From 9b51936bac9871a83498553a03097ef18d6109f2 Mon Sep 17 00:00:00 2001 From: "Logan Mauzaize (T524467)" Date: Mon, 19 Dec 2016 18:17:03 +0100 Subject: [PATCH 1/6] POW-322 Adds encoding selection for JMS publishing --- .../apache/jorphan/gui/JLabeledChoice.java | 4 ++ .../jms/control/gui/JMSPublisherGui.java | 21 ++++++++ .../jms/sampler/PublisherSampler.java | 51 ++++++++++++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/jorphan/org/apache/jorphan/gui/JLabeledChoice.java b/src/jorphan/org/apache/jorphan/gui/JLabeledChoice.java index 44a20d1dfd3..4c1e8535850 100644 --- a/src/jorphan/org/apache/jorphan/gui/JLabeledChoice.java +++ b/src/jorphan/org/apache/jorphan/gui/JLabeledChoice.java @@ -173,6 +173,10 @@ public void itemStateChanged(ItemEvent e) { } + public void setChoiceListEnabled(boolean enabled) { + choiceList.setEnabled(enabled); + } + /** * Set the text displayed in the label. * diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/control/gui/JMSPublisherGui.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/control/gui/JMSPublisherGui.java index 9e28e2e9c88..8351c636e28 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/control/gui/JMSPublisherGui.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/control/gui/JMSPublisherGui.java @@ -39,6 +39,7 @@ import org.apache.jmeter.samplers.gui.AbstractSamplerGui; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; +import org.apache.jorphan.gui.JLabeledChoice; import org.apache.jorphan.gui.JLabeledPasswordField; import org.apache.jorphan.gui.JLabeledTextField; @@ -108,6 +109,8 @@ public class JMSPublisherGui extends AbstractSamplerGui implements ChangeListene private final JLabeledRadioI18N msgChoice = new JLabeledRadioI18N("jms_message_type", MSGTYPES_ITEMS, TEXT_MSG_RSC); //$NON-NLS-1$ + private JLabeledChoice fileEncoding; + private final JCheckBox useNonPersistentDelivery = new JCheckBox(JMeterUtils.getResString("jms_use_non_persistent_delivery"),false); //$NON-NLS-1$ // These are the names of properties used to define the labels @@ -176,6 +179,7 @@ private void setupSamplerProperties(final PublisherSampler sampler) { sampler.setInputFile(messageFile.getFilename()); sampler.setRandomPath(randomFile.getFilename()); sampler.setConfigChoice(configChoice.getText()); + sampler.setFileEncoding(fileEncoding.getText()); sampler.setMessageChoice(msgChoice.getText()); sampler.setIterations(iterations.getText()); sampler.setUseAuth(useAuth.isSelected()); @@ -213,6 +217,13 @@ private void init() { // WARNING: called from ctor so must not be overridden (i. mainPanel.add(configChoice); msgChoice.setLayout(new BoxLayout(msgChoice, BoxLayout.X_AXIS)); mainPanel.add(msgChoice); + + fileEncoding = new JLabeledChoice(JMeterUtils.getResString("content_encoding") + "\u00A0\u00A0", // $NON-NLS-1$ + PublisherSampler.getSupportedEncodings(), true, false); + fileEncoding.setLayout(new BoxLayout(fileEncoding, BoxLayout.X_AXIS)); + fileEncoding.add(Box.createHorizontalGlue()); + mainPanel.add(fileEncoding); + mainPanel.add(messageFile); mainPanel.add(randomFile); @@ -243,6 +254,7 @@ public void clearGui(){ messageFile.setFilename(""); // $NON-NLS-1$ randomFile.setFilename(""); // $NON-NLS-1$ msgChoice.setText(""); // $NON-NLS-1$ + fileEncoding.setSelectedIndex(0); configChoice.setText(USE_TEXT_RSC); updateConfig(USE_TEXT_RSC); msgChoice.setText(TEXT_MSG_RSC); @@ -275,6 +287,7 @@ public void configure(TestElement el) { randomFile.setFilename(sampler.getRandomPath()); configChoice.setText(sampler.getConfigChoice()); msgChoice.setText(sampler.getMessageChoice()); + fileEncoding.setText(sampler.getFileEncoding()); iterations.setText(sampler.getIterations()); expiration.setText(sampler.getExpiration()); priority.setText(sampler.getPriority()); @@ -308,6 +321,12 @@ public void stateChanged(ChangeEvent event) { jmsPwd.setEnabled(useAuth.isSelected() && useAuth.isEnabled()); } } + + private void updateFileEncoding() { + boolean isTextMode = USE_TEXT_RSC.equals(configChoice.getText()); + boolean isObjectType = OBJECT_MSG_RSC.equals(msgChoice.getText()); + fileEncoding.setChoiceListEnabled(!isTextMode && !isObjectType); + } /** * Update choice contains the actual logic for hiding or showing Textarea if Bytes message * is selected @@ -326,6 +345,7 @@ private void updateChoice(String command) { configChoice.resetButtons(CONFIG_ITEMS, oldChoice); textMessage.setEnabled(true); } + updateFileEncoding(); validate(); } /** @@ -348,6 +368,7 @@ private void updateConfig(String command) { messageFile.enableFile(true); randomFile.enableFile(false); } + updateFileEncoding(); } /** diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java index 53725446b83..7387a407602 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java @@ -24,9 +24,17 @@ import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; import javax.jms.DeliveryMode; import javax.jms.JMSException; @@ -57,6 +65,31 @@ */ public class PublisherSampler extends BaseJMSSampler implements TestStateListener { + public static final String RAW_DATA = ""; + public static final String DEFAULT_ENCODING = ""; + + public static final Set NO_ENCODING = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(RAW_DATA, DEFAULT_ENCODING))); + + public static String[] getSupportedEncodings() { + // Only get JVM standard charsets + return Stream.concat( + NO_ENCODING.stream(), + Arrays + .stream(StandardCharsets.class.getDeclaredFields()) + .filter(f -> Modifier.isStatic(f.getModifiers()) && Modifier.isPublic(f.getModifiers()) && f.getType() == Charset.class) + .map(f -> { + try { + return (Charset) f.get(null); + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + }) + .map(Charset::displayName) + .sorted() + ) + .toArray(size -> new String[size]); + } + private static final long serialVersionUID = 233L; private static final Logger log = LoggingManager.getLoggerForClass(); @@ -80,6 +113,8 @@ public class PublisherSampler extends BaseJMSSampler implements TestStateListene private static final String JMS_EXPIRATION = "jms.expiration"; // $NON-NLS-1$ + private static final String JMS_FILE_ENCODING = "jms.file_encoding"; // $NON-NLS-1$ + //-- // Does not need to be synch. because it is only accessed from the sampler thread @@ -279,7 +314,13 @@ private String getMessageContent() { * @return the contents of the file */ public String getFileContent(String path) { - TextFile tf = new TextFile(path); + TextFile tf; + String fileEncoding = getFileEncoding(); + if (NO_ENCODING.contains(fileEncoding)) { + tf = new TextFile(path); + } else { + tf = new TextFile(path, fileEncoding); + } return tf.getText(); } @@ -588,4 +629,12 @@ public JMSProperties getJMSProperties() { public void setJMSProperties(JMSProperties jmsProperties) { setProperty(new TestElementProperty(JMS_PROPERTIES, jmsProperties)); } + + public String getFileEncoding() { + return getPropertyAsString(JMS_FILE_ENCODING, RAW_DATA); + } + + public void setFileEncoding(String fileEncoding) { + setProperty(JMS_FILE_ENCODING, fileEncoding, RAW_DATA); + } } From 800192846c4abe0b1055cbd58ae31c2b4fbd31cc Mon Sep 17 00:00:00 2001 From: "Logan Mauzaize (T524467)" Date: Wed, 21 Dec 2016 11:50:39 +0100 Subject: [PATCH 2/6] POW-322 Adds variable support for file source with JMS publishing --- .../jms/control/gui/JMSPublisherGui.java | 2 +- .../jms/sampler/PublisherSampler.java | 332 +++++------------- .../protocol/jms/sampler/cache/Cache.java | 42 +++ .../protocol/jms/sampler/cache/NoopCache.java | 37 ++ .../jms/sampler/cache/SimpleCache.java | 31 ++ .../jms/sampler/cache/package-info.java | 23 ++ .../sampler/render/BinaryMessageRenderer.java | 68 ++++ .../protocol/jms/sampler/render/FileKey.java | 56 +++ .../sampler/render/MapMessageRenderer.java | 73 ++++ .../jms/sampler/render/MessageRenderer.java | 27 ++ .../sampler/render/ObjectMessageRenderer.java | 106 ++++++ .../jms/sampler/render/RendererFactory.java | 72 ++++ .../jms/sampler/render/Renderers.java | 47 +++ .../sampler/render/TextMessageRenderer.java | 46 +++ .../jms/sampler/render/package-info.java | 23 ++ .../protocol/jms/sampler/render/cp1252.txt | 1 + .../protocol/jms/sampler/render/noVar.txt | 1 + .../jms/sampler/render/object_cp1252.xml | 1 + .../jms/sampler/render/object_doe.xml | 1 + .../sampler/render/object_prolog_cp1252.xml | 2 + .../jms/sampler/render/object_utf8.xml | 1 + .../protocol/jms/sampler/render/oneVar.txt | 1 + .../protocol/jms/sampler/render/utf8.txt | 1 + .../jms/sampler/cache/SimpleCacheTest.java | 48 +++ .../render/BinaryMessageRendererTest.java | 123 +++++++ .../sampler/render/MessageRendererTest.java | 74 ++++ .../render/ObjectMessageRendererTest.java | 99 ++++++ .../protocol/jms/sampler/render/Person.java | 32 ++ .../render/TextMessageRendererTest.java | 94 +++++ .../threads/JMeterContextServiceHelper.java | 41 +++ 30 files changed, 1263 insertions(+), 242 deletions(-) create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/NoopCache.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCache.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRenderer.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/FileKey.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MapMessageRenderer.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MessageRenderer.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRenderer.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/RendererFactory.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/Renderers.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRenderer.java create mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/package-info.java create mode 100644 test/resources/org/apache/jmeter/protocol/jms/sampler/render/cp1252.txt create mode 100644 test/resources/org/apache/jmeter/protocol/jms/sampler/render/noVar.txt create mode 100644 test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_cp1252.xml create mode 100644 test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_doe.xml create mode 100644 test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_prolog_cp1252.xml create mode 100644 test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_utf8.xml create mode 100644 test/resources/org/apache/jmeter/protocol/jms/sampler/render/oneVar.txt create mode 100644 test/resources/org/apache/jmeter/protocol/jms/sampler/render/utf8.txt create mode 100644 test/src/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCacheTest.java create mode 100644 test/src/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRendererTest.java create mode 100644 test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java create mode 100644 test/src/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRendererTest.java create mode 100644 test/src/org/apache/jmeter/protocol/jms/sampler/render/Person.java create mode 100644 test/src/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRendererTest.java create mode 100644 test/src/org/apache/jmeter/threads/JMeterContextServiceHelper.java diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/control/gui/JMSPublisherGui.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/control/gui/JMSPublisherGui.java index 8351c636e28..59f2d43edd7 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/control/gui/JMSPublisherGui.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/control/gui/JMSPublisherGui.java @@ -57,7 +57,7 @@ public class JMSPublisherGui extends AbstractSamplerGui implements ChangeListene /** Take source from a random file */ public static final String USE_RANDOM_RSC = "jms_use_random_file"; //$NON-NLS-1$ /** Take source from the text area */ - private static final String USE_TEXT_RSC = "jms_use_text"; //$NON-NLS-1$ + public static final String USE_TEXT_RSC = "jms_use_text"; //$NON-NLS-1$ /** Create a TextMessage */ public static final String TEXT_MSG_RSC = "jms_text_message"; //$NON-NLS-1$ diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java index 7387a407602..70747e2155b 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java @@ -17,22 +17,14 @@ package org.apache.jmeter.protocol.jms.sampler; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.stream.Stream; @@ -41,35 +33,37 @@ import javax.jms.Message; import javax.naming.NamingException; -import org.apache.commons.io.IOUtils; import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.jms.Utils; import org.apache.jmeter.protocol.jms.client.ClientPool; import org.apache.jmeter.protocol.jms.client.InitialContextFactory; import org.apache.jmeter.protocol.jms.client.Publisher; import org.apache.jmeter.protocol.jms.control.gui.JMSPublisherGui; +import org.apache.jmeter.protocol.jms.sampler.cache.Cache; +import org.apache.jmeter.protocol.jms.sampler.render.MessageRenderer; +import org.apache.jmeter.protocol.jms.sampler.render.Renderers; import org.apache.jmeter.samplers.SampleResult; import org.apache.jmeter.services.FileServer; import org.apache.jmeter.testelement.TestStateListener; import org.apache.jmeter.testelement.property.TestElementProperty; import org.apache.jmeter.util.JMeterUtils; -import org.apache.jorphan.io.TextFile; import org.apache.jorphan.logging.LoggingManager; -import org.apache.jorphan.util.JOrphanUtils; import org.apache.log.Logger; -import com.thoughtworks.xstream.XStream; - /** * This class implements the JMS Publisher sampler. */ public class PublisherSampler extends BaseJMSSampler implements TestStateListener { + /** Encoding value to sent data as is (no variabilisation) **/ public static final String RAW_DATA = ""; + /** Encoding value to sent parsed data but read with default system encoding **/ public static final String DEFAULT_ENCODING = ""; + /** Constant for system default encodings **/ public static final Set NO_ENCODING = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(RAW_DATA, DEFAULT_ENCODING))); + /** Init available encoding using constants, then JVM standard ones **/ public static String[] getSupportedEncodings() { // Only get JVM standard charsets return Stream.concat( @@ -104,9 +98,9 @@ public static String[] getSupportedEncodings() { private static final String CONFIG_CHOICE = "jms.config_choice"; //$NON-NLS-1$ private static final String MESSAGE_CHOICE = "jms.config_msg_type"; //$NON-NLS-1$ - + private static final String NON_PERSISTENT_DELIVERY = "jms.non_persistent"; //$NON-NLS-1$ - + private static final String JMS_PROPERTIES = "jms.jmsProperties"; // $NON-NLS-1$ private static final String JMS_PRIORITY = "jms.priority"; // $NON-NLS-1$ @@ -115,6 +109,11 @@ public static String[] getSupportedEncodings() { private static final String JMS_FILE_ENCODING = "jms.file_encoding"; // $NON-NLS-1$ + /** File extensions for text files **/ + private static final String[] EXT_FILE_TEXT = { ".txt", ".obj" }; + /** File extensions for binary files **/ + private static final String[] EXT_FILE_BIN = { ".dat" }; + //-- // Does not need to be synch. because it is only accessed from the sampler thread @@ -123,19 +122,8 @@ public static String[] getSupportedEncodings() { private static final FileServer FSERVER = FileServer.getFileServer(); - // Cache for file. Only used by sample() in a single thread - private String file_contents = null; - // Cache for object-message, only used when parsing from a file because in text-area - // property replacement might have been used - private Serializable object_msg_file_contents = null; - // Cache for bytes-message, only used when parsing from a file - private byte[] bytes_msg_file_contents = null; - - // Cached file name - private String cachedFileName; - - public PublisherSampler() { - } + /** File cache handler **/ + private Cache fileCache = null; /** * the implementation calls testStarted() without any parameters. @@ -169,12 +157,12 @@ public void testStarted() { /** * initialize the Publisher client. - * @throws JMSException - * @throws NamingException + * @throws JMSException + * @throws NamingException * */ private void initClient() throws JMSException, NamingException { - publisher = new Publisher(getUseJNDIPropertiesAsBoolean(), getJNDIInitialContextFactory(), + publisher = new Publisher(getUseJNDIPropertiesAsBoolean(), getJNDIInitialContextFactory(), getProviderUrl(), getConnectionFactory(), getDestination(), isUseAuth(), getUsername(), getPassword(), isDestinationStatic()); ClientPool.addClient(publisher); @@ -189,6 +177,16 @@ private void initClient() throws JMSException, NamingException { */ @Override public SampleResult sample() { + if (fileCache == null) { + switch (getConfigChoice()) { + case JMSPublisherGui.USE_FILE_RSC: + fileCache = Cache.newSingleInstance(); + break; + default: + fileCache = Cache.getNoopCache(); + } + } + SampleResult result = new SampleResult(); result.setSampleLabel(getName()); result.setSuccessful(false); // Assume it will fail @@ -209,34 +207,34 @@ public SampleResult sample() { int loop = getIterationCount(); result.sampleStart(); String type = getMessageChoice(); - + try { Map msgProperties = getJMSProperties().getJmsPropertysAsMap(); - int deliveryMode = getUseNonPersistentDelivery() ? DeliveryMode.NON_PERSISTENT : DeliveryMode.PERSISTENT; + int deliveryMode = getUseNonPersistentDelivery() ? DeliveryMode.NON_PERSISTENT : DeliveryMode.PERSISTENT; int priority = Integer.parseInt(getPriority()); long expiration = Long.parseLong(getExpiration()); - + for (int idx = 0; idx < loop; idx++) { + Message msg; if (JMSPublisherGui.TEXT_MSG_RSC.equals(type)){ - String tmsg = getMessageContent(); - Message msg = publisher.publish(tmsg, getDestination(), msgProperties, deliveryMode, priority, expiration); + String tmsg = getRenderedContent(String.class, EXT_FILE_TEXT); + msg = publisher.publish(tmsg, getDestination(), msgProperties, deliveryMode, priority, expiration); buffer.append(tmsg); - Utils.messageProperties(propBuffer, msg); } else if (JMSPublisherGui.MAP_MSG_RSC.equals(type)){ - Map m = getMapContent(); - Message msg = publisher.publish(m, getDestination(), msgProperties, deliveryMode, priority, expiration); - Utils.messageProperties(propBuffer, msg); + @SuppressWarnings("unchecked") + Map map = getRenderedContent(Map.class, EXT_FILE_TEXT); + Map m = map; + msg = publisher.publish(m, getDestination(), msgProperties, deliveryMode, priority, expiration); } else if (JMSPublisherGui.OBJECT_MSG_RSC.equals(type)){ - Serializable omsg = getObjectContent(); - Message msg = publisher.publish(omsg, getDestination(), msgProperties, deliveryMode, priority, expiration); - Utils.messageProperties(propBuffer, msg); + Serializable omsg = getRenderedContent(Serializable.class, EXT_FILE_TEXT); + msg = publisher.publish(omsg, getDestination(), msgProperties, deliveryMode, priority, expiration); } else if (JMSPublisherGui.BYTES_MSG_RSC.equals(type)){ - byte[] bmsg = getBytesContent(); - Message msg = publisher.publish(bmsg, getDestination(), msgProperties, deliveryMode, priority, expiration); - Utils.messageProperties(propBuffer, msg); + byte[] bmsg = getRenderedContent(byte[].class, EXT_FILE_BIN); + msg = publisher.publish(bmsg, getDestination(), msgProperties, deliveryMode, priority, expiration); } else { - throw new JMSException(type+ " is not recognised"); + throw new JMSException(type+ " is not recognised"); } + Utils.messageProperties(propBuffer, msg); } result.setResponseCodeOK(); result.setResponseMessage(loop + " messages published"); @@ -245,211 +243,49 @@ public SampleResult sample() { result.setSampleCount(loop); result.setRequestHeaders(propBuffer.toString()); } catch (Exception e) { + log.error(String.format("Can't sent %s message from %s", type, getConfigChoice()), e); result.setResponseMessage(e.toString()); } finally { - result.sampleEnd(); + result.sampleEnd(); } return result; } - private Map getMapContent() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { - Map m = new HashMap<>(); - String text = getMessageContent(); - String[] lines = text.split("\n"); - for (String line : lines){ - String[] parts = line.split(",",3); - if (parts.length != 3) { - throw new IllegalArgumentException("line must have 3 parts: "+line); - } - String name = parts[0]; - String type = parts[1]; - if (!type.contains(".")){// Allow shorthand names - type = "java.lang."+type; - } - String value = parts[2]; - Object obj; - if (type.equals("java.lang.String")){ - obj = value; - } else { - Class clazz = Class.forName(type); - Method method = clazz.getMethod("valueOf", new Class[]{String.class}); - obj = method.invoke(clazz, value); - } - m.put(name, obj); + /** Gets file path to use **/ + private String getFilePath(String... ext) { + switch (getConfigChoice()) { + case JMSPublisherGui.USE_FILE_RSC: + return getInputFile(); + case JMSPublisherGui.USE_RANDOM_RSC: + String fname = FSERVER.getRandomFile(getRandomPath(), ext).getAbsolutePath(); + return fname; + default: + throw new IllegalArgumentException("Type of input not handled:" + getConfigChoice()); } - return m; } - /** - * Method will check the setting and get the contents for the message. + /** Look-up renderer and get appropriate value * - * @return the contents for the message - */ - private String getMessageContent() { - if (getConfigChoice().equals(JMSPublisherGui.USE_FILE_RSC)) { - // in the case the test uses a file, we set it locally and - // prevent loading the file repeatedly - // if the file name changes we reload it - if (file_contents == null || !Objects.equals(cachedFileName, getInputFile())) { - cachedFileName = getInputFile(); - file_contents = getFileContent(getInputFile()); - } - return file_contents; - } else if (getConfigChoice().equals(JMSPublisherGui.USE_RANDOM_RSC)) { - // Maybe we should consider creating a global cache for the - // random files to make JMeter more efficient. - String fname = FSERVER.getRandomFile(getRandomPath(), new String[] { ".txt", ".obj" }) - .getAbsolutePath(); - return getFileContent(fname); + * @param type Message type to render + * @param fileExts File extensions for directory mode. + **/ + private T getRenderedContent(Class type, String[] fileExts) { + MessageRenderer renderer = Renderers.getInstance(type); + if (getConfigChoice().equals(JMSPublisherGui.USE_TEXT_RSC)) { + return renderer.getValueFromText(getTextMessage()); } else { - return getTextMessage(); + return renderer.getValueFromFile(getFilePath(fileExts), getFileEncoding(), !isRaw(), fileCache); } } /** - * The implementation uses TextFile to load the contents of the file and - * returns a string. - * - * @param path path to the file to read in - * @return the contents of the file + * Specified if value must be parsed or not. + * @return true if value must be sent as-is. */ - public String getFileContent(String path) { - TextFile tf; - String fileEncoding = getFileEncoding(); - if (NO_ENCODING.contains(fileEncoding)) { - tf = new TextFile(path); - } else { - tf = new TextFile(path, fileEncoding); - } - return tf.getText(); + private boolean isRaw() { + return RAW_DATA.equals(getFileEncoding()); } - /** - * This method will load the contents for the JMS Object Message. - * The contents are either loaded from file (might be cached), random file - * or from the GUI text-area. - * - * @return Serialized object as loaded from the specified input file - */ - private Serializable getObjectContent() { - if (getConfigChoice().equals(JMSPublisherGui.USE_FILE_RSC)) { - // in the case the test uses a file, we set it locally and - // prevent loading the file repeatedly - // if the file name changes we reload it - if (object_msg_file_contents == null || !Objects.equals(cachedFileName, getInputFile())) { - cachedFileName = getInputFile(); - object_msg_file_contents = getFileObjectContent(getInputFile()); - } - - return object_msg_file_contents; - } else if (getConfigChoice().equals(JMSPublisherGui.USE_RANDOM_RSC)) { - // Maybe we should consider creating a global cache for the - // random files to make JMeter more efficient. - final String fname = FSERVER.getRandomFile(getRandomPath(), new String[] {".txt", ".obj"}) - .getAbsolutePath(); - - return getFileObjectContent(fname); - } else { - final String xmlMessage = getTextMessage(); - return transformXmlToObjectMessage(xmlMessage); - } - } - - /** - * This method will load the contents for the JMS BytesMessage. - * The contents are either loaded from file (might be cached), random file - * - * @return byte[] as loaded from the specified input file - * @since 2.9 - */ - private byte[] getBytesContent() { - if (getConfigChoice().equals(JMSPublisherGui.USE_FILE_RSC)) { - // in the case the test uses a file, we set it locally and - // prevent loading the file repeatedly - // if the file name changes we reload it - if (bytes_msg_file_contents == null || !Objects.equals(cachedFileName, getInputFile())) { - cachedFileName = getInputFile(); - bytes_msg_file_contents = getFileBytesContent(getInputFile()); - } - - return bytes_msg_file_contents; - } else if (getConfigChoice().equals(JMSPublisherGui.USE_RANDOM_RSC)) { - final String fname = FSERVER.getRandomFile(getRandomPath(), new String[] {".dat"}) - .getAbsolutePath(); - - return getFileBytesContent(fname); - } else { - throw new IllegalArgumentException("Type of input not handled:" + getConfigChoice()); - } - } - - /** - * Try to load an object from a provided file, so that it can be used as body - * for a JMS message. - * An {@link IllegalStateException} will be thrown if loading the object fails. - * - * @param path Path to the file that will be serialized - * @return byte[] instance - * @since 2.9 - */ - private static byte[] getFileBytesContent(final String path) { - InputStream inputStream = null; - try { - File file = new File(path); - inputStream = new BufferedInputStream(new FileInputStream(file)); - return IOUtils.toByteArray(inputStream, (int)file.length()); - } catch (Exception e) { - log.error(e.getLocalizedMessage(), e); - throw new IllegalStateException("Unable to load file:'"+path+"'", e); - } finally { - JOrphanUtils.closeQuietly(inputStream); - } - } - - /** - * Try to load an object from a provided file, so that it can be used as body - * for a JMS message. - * An {@link IllegalStateException} will be thrown if loading the object fails. - * - * @param path Path to the file that will be serialized - * @return Serialized object instance - */ - private static Serializable getFileObjectContent(final String path) { - Serializable readObject = null; - InputStream inputStream = null; - try { - inputStream = new BufferedInputStream(new FileInputStream(path)); - XStream xstream = new XStream(); - readObject = (Serializable) xstream.fromXML(inputStream, readObject); - } catch (Exception e) { - log.error(e.getLocalizedMessage(), e); - throw new IllegalStateException("Unable to load object instance from file:'"+path+"'", e); - } finally { - JOrphanUtils.closeQuietly(inputStream); - } - return readObject; - } - - /** - * Try to load an object via XStream from XML text, so that it can be used as body - * for a JMS message. - * An {@link IllegalStateException} will be thrown if transforming the XML to an object fails. - * - * @param xmlMessage String containing XML text as input for the transformation - * @return Serialized object instance - */ - private static Serializable transformXmlToObjectMessage(final String xmlMessage) { - Serializable readObject = null; - try { - XStream xstream = new XStream(); - readObject = (Serializable) xstream.fromXML(xmlMessage, readObject); - } catch (Exception e) { - log.error(e.getLocalizedMessage(), e); - throw new IllegalStateException("Unable to load object instance from text", e); - } - return readObject; - } - // ------------- get/set properties ----------------------// /** * set the source of the message @@ -477,7 +313,7 @@ public void setConfigChoice(String choice) { public String getConfigChoice() { // Allow for the old JMX file which used the local language string String config = getPropertyAsString(CONFIG_CHOICE); - if (config.equals(USE_FILE_LOCALNAME) + if (config.equals(USE_FILE_LOCALNAME) || config.equals(JMSPublisherGui.USE_FILE_RSC)){ return JMSPublisherGui.USE_FILE_RSC; } @@ -573,7 +409,7 @@ public String getPriority() { return priority; } } - + public void setPriority(String s) { // Bug 59173 if (Utils.DEFAULT_PRIORITY_4.equals(s)) { @@ -581,7 +417,7 @@ public void setPriority(String s) { } setProperty(JMS_PRIORITY, s); // always need to save the field } - + public void setExpiration(String s) { // Bug 59173 if (Utils.DEFAULT_NO_EXPIRY.equals(s)) { @@ -589,14 +425,14 @@ public void setExpiration(String s) { } setProperty(JMS_EXPIRATION, s); // always need to save the field } - + /** * @param value boolean use NON_PERSISTENT */ public void setUseNonPersistentDelivery(boolean value) { setProperty(NON_PERSISTENT_DELIVERY, value, false); } - + /** * @return true if NON_PERSISTENT delivery must be used */ @@ -604,7 +440,7 @@ public boolean getUseNonPersistentDelivery() { return getPropertyAsBoolean(NON_PERSISTENT_DELIVERY, false); } - /** + /** * @return {@link JMSProperties} JMS Properties */ public JMSProperties getJMSProperties() { @@ -622,7 +458,7 @@ public JMSProperties getJMSProperties() { } return jmsProperties; } - + /** * @param jmsProperties JMS Properties */ @@ -630,10 +466,24 @@ public void setJMSProperties(JMSProperties jmsProperties) { setProperty(new TestElementProperty(JMS_PROPERTIES, jmsProperties)); } + /** + * Gets file encoding to use. If {@value #RAW_DATA}, content isn't parsed. + * @return File encoding. + * @see #RAW_DATA + * @see #DEFAULT_ENCODING + * @see #getSupportedEncodings() + */ public String getFileEncoding() { return getPropertyAsString(JMS_FILE_ENCODING, RAW_DATA); } + /** + * Sets file encoding to use. If {@value #RAW_DATA}, content isn't parsed. + * @param fileEncoding File encoding. + * @see #RAW_DATA + * @see #DEFAULT_ENCODING + * @see #getSupportedEncodings() + */ public void setFileEncoding(String fileEncoding) { setProperty(JMS_FILE_ENCODING, fileEncoding, RAW_DATA); } diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java new file mode 100644 index 00000000000..b334b582ecd --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java @@ -0,0 +1,42 @@ +/* + * 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.jmeter.protocol.jms.sampler.cache; + +import java.util.function.Function; + +/** + * Basic cache interface. + */ +public interface Cache { + + /** Force a cache value **/ + void put(Object key, Object value); + + /** Check if key is already cached, or execute function and cache value **/ + R get(T key, Function get); + + /** Non-caching implementation **/ + static Cache getNoopCache() { + return NoopCache.getInstance(); + } + + /** Caching a single value, if key change, cached value is thrown away. null key is supported. **/ + static Cache newSingleInstance() { + return new SimpleCache(); + } +} \ No newline at end of file diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/NoopCache.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/NoopCache.java new file mode 100644 index 00000000000..a2d89beb7a3 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/NoopCache.java @@ -0,0 +1,37 @@ +/* + * 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.jmeter.protocol.jms.sampler.cache; + +import java.util.function.Function; + +/** Non-Caching singleton **/ +enum NoopCache implements Cache { + INSTANCE; + + public static NoopCache getInstance() { + return INSTANCE; + } + + @Override + public void put(Object key, Object value) {} + + @Override + public R get(T key, Function get) { + return get.apply(key); + } +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCache.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCache.java new file mode 100644 index 00000000000..c76e3301902 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCache.java @@ -0,0 +1,31 @@ +package org.apache.jmeter.protocol.jms.sampler.cache; + +import java.io.Serializable; +import java.util.Objects; +import java.util.function.Function; + +/** Caching a single value, if key change, cached value is thrown away. null key is supported. **/ +class SimpleCache implements Cache, Serializable { + /** Unique version identifier **/ + private static final long serialVersionUID = 1L; + + private transient Object value; + private transient Object key; + + + @Override + public void put(Object key, Object value) { + this.key = key; + this.value = value; + } + + @Override + @SuppressWarnings("unchecked") + public R get(T key, Function get) { + if (!Objects.equals(this.key, key)) { + this.value = get.apply(key); + this.key = key; + } + return (R) this.value; + } +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java new file mode 100644 index 00000000000..611f6c6a044 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * Basic cache API for JMS. + * + * @See Cache + */ +package org.apache.jmeter.protocol.jms.sampler.cache; \ No newline at end of file diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRenderer.java new file mode 100644 index 00000000000..b2277d8ea90 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRenderer.java @@ -0,0 +1,68 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import static java.lang.String.format; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.apache.jmeter.protocol.jms.control.gui.JMSPublisherGui; +import org.apache.jmeter.protocol.jms.sampler.cache.Cache; + +class BinaryMessageRenderer implements MessageRenderer { + + private TextMessageRenderer delegate; + + public BinaryMessageRenderer(TextMessageRenderer delegate) { + this.delegate = delegate; + } + + @Override + public byte[] getValueFromText(String text) { + throw new UnsupportedOperationException(format("Type of input not handled: %s", JMSPublisherGui.USE_TEXT_RSC)); + } + + @Override + public byte[] getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { + byte[] bytes; + + if (hasVariable) { + String stringValue = delegate.getValueFromFile(filename, encoding, hasVariable, cache); + try { + bytes = stringValue.getBytes(encoding); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } else { + bytes = cache.get(filename, this::getContent); + } + + return bytes; + } + + byte[] getContent(String filename) { + try { + return Files.readAllBytes(Paths.get(filename)); + } catch (IOException e) { + throw new RuntimeException(format("Can't read content of %s", filename), e); + } + } +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/FileKey.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/FileKey.java new file mode 100644 index 00000000000..b6c20d930b3 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/FileKey.java @@ -0,0 +1,56 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import java.util.Objects; + +/** File specification for {@link TextMessageRenderer} **/ +class FileKey { + + private final String filename; + private final String encoding; + + public FileKey(String filename, String encoding) { + this.filename = filename; + this.encoding = encoding; + } + + public String getFilename() { + return filename; + } + + public String getEncoding() { + return encoding; + } + + @Override + public int hashCode() { + return Objects.hashCode(filename); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (!(obj instanceof FileKey)) return false; + + FileKey that = (FileKey) obj; + + return Objects.equals(this.filename, that.filename); + + } +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MapMessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MapMessageRenderer.java new file mode 100644 index 00000000000..b9ee7891fe7 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MapMessageRenderer.java @@ -0,0 +1,73 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.apache.jmeter.protocol.jms.sampler.cache.Cache; + +public class MapMessageRenderer implements MessageRenderer> { + + private TextMessageRenderer delegate; + + public MapMessageRenderer(TextMessageRenderer delegate) { + this.delegate = delegate; + } + + @Override + public Map getValueFromText(String text) { + Map m = new HashMap<>(); + String[] lines = text.split("\n"); + for (String line : lines){ + String[] parts = line.split(",",3); + if (parts.length != 3) { + throw new IllegalArgumentException("line must have 3 parts: "+line); + } + String name = parts[0]; + String type = parts[1]; + if (!type.contains(".")){// Allow shorthand names + type = "java.lang."+type; + } + String value = parts[2]; + Object obj; + if (type.equals("java.lang.String")){ + obj = value; + } else { + try { + Class clazz = Class.forName(type); + Method method = clazz.getMethod("valueOf", new Class[]{String.class}); + obj = method.invoke(clazz, value); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + throw new RuntimeException(String.format("Can't convert %s to object", line), e); + } + } + m.put(name, obj); + } + return m; + } + + @Override + public Map getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { + String text = delegate.getValueFromFile(filename, encoding, hasVariable, cache); + return getValueFromText(text); + } +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MessageRenderer.java new file mode 100644 index 00000000000..059911381ce --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MessageRenderer.java @@ -0,0 +1,27 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import org.apache.jmeter.protocol.jms.sampler.cache.Cache; + +public interface MessageRenderer { + /** Convert text to expected type **/ + T getValueFromText(String text); + /** Read text from file, eventually replace variables, then convert it. Cached content depends if variabilisation is active or not. **/ + T getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache); +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRenderer.java new file mode 100644 index 00000000000..e5029a42561 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRenderer.java @@ -0,0 +1,106 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import static java.lang.String.format; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.Serializable; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.jmeter.protocol.jms.sampler.PublisherSampler; +import org.apache.jmeter.protocol.jms.sampler.cache.Cache; + +import com.thoughtworks.xstream.XStream; + +class ObjectMessageRenderer implements MessageRenderer { + + TextMessageRenderer delegate; + + public ObjectMessageRenderer(TextMessageRenderer delegate) { + this.delegate = delegate; + } + + @Override + public Serializable getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { + Serializable value; + if (hasVariable) { + value = getInterpretedContent(filename, encoding, hasVariable, cache); + } else { + value = cache.get(filename, this::getContent); + } + + return value; + } + + /** + * Try to load an object via XStream from XML text, so that it can be used as body + * for a JMS message. + * An {@link IllegalStateException} will be thrown if transforming the XML to an object fails. + * + * @param xmlMessage String containing XML text as input for the transformation + * @return Serialized object instance + */ + @Override + public Serializable getValueFromText(final String xmlMessage) { + Serializable readObject = null; + try { + XStream xstream = new XStream(); + readObject = (Serializable) xstream.fromXML(xmlMessage, readObject); + } catch (Exception e) { + throw new IllegalStateException("Unable to load object instance from text", e); + } + return readObject; + } + + /** + *

Gets content with variable replaced.

+ *

If encoding {@link PublisherSampler#DEFAULT_ENCODING isn't provided}, try to find it.

+ *

Only raw text is cached, neither interpreted text, neither parsed object.

+ */ + protected Serializable getInterpretedContent(String filename, String encoding, boolean hasVariable, Cache cache) { + Serializable value; + if (PublisherSampler.DEFAULT_ENCODING.equals(encoding)) { + encoding = findEncoding(filename); + } + String stringValue = delegate.getValueFromFile(filename, encoding, hasVariable, cache); + value = (Serializable) new XStream().fromXML(stringValue); + return value; + } + + /** Try to determine encoding based on XML prolog, if none null is returned. **/ + protected String findEncoding(String filename) { + XMLInputFactory factory = XMLInputFactory.newFactory(); + try (FileInputStream input = new FileInputStream(filename)) { + XMLStreamReader reader = factory.createXMLStreamReader(input); + return reader.getEncoding(); + } catch (IOException|XMLStreamException e) { + throw new RuntimeException(format("Unable to read %s", filename), e); + } + } + + protected Serializable getContent(String filename) { + Serializable object = (Serializable) new XStream().fromXML(new File(filename)); + return object; + } +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/RendererFactory.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/RendererFactory.java new file mode 100644 index 00000000000..e8ba1288c89 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/RendererFactory.java @@ -0,0 +1,72 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import java.io.Serializable; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Renderer singleton. + */ +enum RendererFactory { + + INSTANCE; + + public static RendererFactory getInstance() { + return INSTANCE; + } + + private TextMessageRenderer text = new TextMessageRenderer(); + private BinaryMessageRenderer binary = new BinaryMessageRenderer(text); + private ObjectMessageRenderer object = new ObjectMessageRenderer(text); + private MapMessageRenderer map = new MapMessageRenderer(text); + + /** Registred renderers **/ + private Map, MessageRenderer> renderers; + { + Map, MessageRenderer> writable = new LinkedHashMap<>(); + writable.put(String.class, text); + writable.put(byte[].class, binary); + writable.put(Serializable.class, object); + writable.put(Map.class, map); + renderers = Collections.unmodifiableMap(writable); + } + + public TextMessageRenderer getText() { + return text; + } + + public BinaryMessageRenderer getBinary() { + return binary; + } + + public ObjectMessageRenderer getObject() { + return object; + } + + public MapMessageRenderer getMap() { + return map; + } + + @SuppressWarnings("unchecked") + public MessageRenderer getInstance(Class type) { + return (MessageRenderer) renderers.get(type); + } +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/Renderers.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/Renderers.java new file mode 100644 index 00000000000..7fd328ecd8e --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/Renderers.java @@ -0,0 +1,47 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import java.io.Serializable; +import java.util.Map; + +/** + * Renderer API entry point. + */ +public interface Renderers { + + public static MessageRenderer getText() { + return RendererFactory.getInstance().getText(); + } + + public static MessageRenderer getBinary() { + return RendererFactory.getInstance().getBinary(); + } + + public static MessageRenderer getObject() { + return RendererFactory.getInstance().getObject(); + } + + public static MessageRenderer> getMap() { + return RendererFactory.getInstance().getMap(); + } + + public static MessageRenderer getInstance(Class type) { + return RendererFactory.getInstance().getInstance(type); + } +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRenderer.java new file mode 100644 index 00000000000..455edc0884b --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRenderer.java @@ -0,0 +1,46 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import org.apache.jmeter.engine.util.CompoundVariable; +import org.apache.jmeter.protocol.jms.sampler.cache.Cache; +import org.apache.jorphan.io.TextFile; + +class TextMessageRenderer implements MessageRenderer { + + @Override + public String getValueFromText(String text) { + return text; + } + + @Override + public String getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { + String text = cache.get(new FileKey(filename, encoding), this::getContent); + if (hasVariable) { + text = new CompoundVariable(text).execute(); + } + + return text; + } + + String getContent(FileKey key) { + return new TextFile(key.getFilename(), key.getEncoding()).getText(); + } + + +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/package-info.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/package-info.java new file mode 100644 index 00000000000..464839e9ac3 --- /dev/null +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/package-info.java @@ -0,0 +1,23 @@ +/* + * 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 contains all renderer for JMS publisher. + * @see Renderers + * @see MessageRenderer + */ +package org.apache.jmeter.protocol.jms.sampler.render; \ No newline at end of file diff --git a/test/resources/org/apache/jmeter/protocol/jms/sampler/render/cp1252.txt b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/cp1252.txt new file mode 100644 index 00000000000..33d642f7ca3 --- /dev/null +++ b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/cp1252.txt @@ -0,0 +1 @@ +éè€ \ No newline at end of file diff --git a/test/resources/org/apache/jmeter/protocol/jms/sampler/render/noVar.txt b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/noVar.txt new file mode 100644 index 00000000000..98c541790c0 --- /dev/null +++ b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/noVar.txt @@ -0,0 +1 @@ +noVar \ No newline at end of file diff --git a/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_cp1252.xml b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_cp1252.xml new file mode 100644 index 00000000000..df8b3749a05 --- /dev/null +++ b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_cp1252.xml @@ -0,0 +1 @@ +eéè€ \ No newline at end of file diff --git a/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_doe.xml b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_doe.xml new file mode 100644 index 00000000000..ef6eeda1e7a --- /dev/null +++ b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_doe.xml @@ -0,0 +1 @@ +Doe \ No newline at end of file diff --git a/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_prolog_cp1252.xml b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_prolog_cp1252.xml new file mode 100644 index 00000000000..83997f05fb5 --- /dev/null +++ b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_prolog_cp1252.xml @@ -0,0 +1,2 @@ + +eéè€ \ No newline at end of file diff --git a/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_utf8.xml b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_utf8.xml new file mode 100644 index 00000000000..7a1d21b7464 --- /dev/null +++ b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/object_utf8.xml @@ -0,0 +1 @@ +eéè€ \ No newline at end of file diff --git a/test/resources/org/apache/jmeter/protocol/jms/sampler/render/oneVar.txt b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/oneVar.txt new file mode 100644 index 00000000000..88fa4155b49 --- /dev/null +++ b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/oneVar.txt @@ -0,0 +1 @@ +${oneVar} \ No newline at end of file diff --git a/test/resources/org/apache/jmeter/protocol/jms/sampler/render/utf8.txt b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/utf8.txt new file mode 100644 index 00000000000..179993d71b3 --- /dev/null +++ b/test/resources/org/apache/jmeter/protocol/jms/sampler/render/utf8.txt @@ -0,0 +1 @@ +éè€ \ No newline at end of file diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCacheTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCacheTest.java new file mode 100644 index 00000000000..43d89180b10 --- /dev/null +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCacheTest.java @@ -0,0 +1,48 @@ +/* + * 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.jmeter.protocol.jms.sampler.cache; + +import static org.junit.Assert.assertSame; + +import org.junit.Test; + +public class SimpleCacheTest { + + private SimpleCache cache = new SimpleCache(); + + @Test + public void put() { + String value = "banana"; + String key = "key"; + cache.put(key, value); + + String actual = cache.get(key, k -> "none"); + + assertSame(value, actual); + } + + @Test + public void getWithNoCacheValue() { + String value = "banana"; + String key = "key"; + + String actual = cache.get(key, k -> value); + + assertSame(value, actual); + } +} diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRendererTest.java new file mode 100644 index 00000000000..59ce910ef5a --- /dev/null +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRendererTest.java @@ -0,0 +1,123 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import static java.lang.String.format; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class BinaryMessageRendererTest extends MessageRendererTest { + + @Rule + public ExpectedException error = ExpectedException.none(); + + BinaryMessageRenderer render = RendererFactory.getInstance().getBinary(); + @Override + protected MessageRenderer getRenderer() { + return render; + } + + @Test(expected=UnsupportedOperationException.class) + public void getValueFromText() { + render.getValueFromText(""); + } + + @Test + public void readUTF8File() { + assertContent("utf8.txt", "UTF-8"); + } + + @Test + public void readCP1252File() { + assertContent("cp1252.txt", "Cp1252"); + } + + private void assertContent(String resource, String encoding) { + String filename = getResourceFile(resource); + byte[] actual = render.getContent(filename); + try { + assertArrayEquals("éè€".getBytes(encoding), actual); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + @Test + public void readNonExistingContent() { + error.expect(RuntimeException.class); + error.expectCause(instanceOf(IOException.class)); + error.expectMessage("Can't read content of __file_that_may_not_exists_else_it_will_fail"); + render.getContent("__file_that_may_not_exists_else_it_will_fail"); + } + + @Test + public void getValueFromFile_withNoVar() { + String text = format("éè€%n"); + assertValueFromFile(text, "utf8.txt", true); + assertCacheContentInString(text); + + } + + @Test + public void getValueFromFile_withOneVar() { + String value = "éè€"; + jmeterCtxService.get().getVariables().put("oneVar", value); + assertValueFromFile(format("%s%n", value), "oneVar.txt", true); + assertCacheContentInString(format("${oneVar}%n")); + } + + + + @Test + public void getValueFromFile_withInvalidEncoding() { + error.expect(RuntimeException.class); + error.expectCause(instanceOf(UnsupportedEncodingException.class)); + + render.getValueFromFile(getResourceFile("utf8.txt"), "banana", true, cache); + } + + @Test + public void getValueFromFile_inRawMode() { + String text = "${oneVar}"; + assertValueFromFile(text, "oneVar.txt", false); + assertCacheContentInBytes(text); + } + + protected void assertValueFromFile(String expected, String resource, boolean hasVariable) { + assertValueFromFile(actual -> assertBytesEquals(expected, actual), resource, hasVariable); + } + + protected void assertCacheContentInBytes(String expected) { + assertBytesEquals(expected, (byte[]) cacheContent.getValue()); + } + protected void assertCacheContentInString(String expected) { + assertEquals(expected, cacheContent.getValue()); + } + protected void assertBytesEquals(String expected, byte[] actual) { + assertArrayEquals(expected.getBytes(StandardCharsets.UTF_8), actual); + } +} diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java new file mode 100644 index 00000000000..883171f61d2 --- /dev/null +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java @@ -0,0 +1,74 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import static java.lang.String.format; + +import java.util.AbstractMap; +import java.util.Map.Entry; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.apache.jmeter.protocol.jms.sampler.cache.Cache; +import org.apache.jmeter.threads.JMeterContext; +import org.apache.jmeter.threads.JMeterContextServiceHelper; +import org.apache.jmeter.threads.JMeterVariables; +import org.junit.Rule; + +/** + * + */ +public abstract class MessageRendererTest { + + @SuppressWarnings("rawtypes") + protected Entry cacheContent; + protected Cache cache = new Cache() { + @Override + public void put(Object key, Object value) { + cacheContent = new AbstractMap.SimpleImmutableEntry<>(key, value); + } + + @Override + public V get(K key, Function get) { + V value = get.apply(key); + cacheContent = new AbstractMap.SimpleImmutableEntry<>(key, value); + return value; + } + }; + + @Rule + public JMeterContextServiceHelper jmeterCtxService = new JMeterContextServiceHelper() { + @Override + protected void initContext(JMeterContext jMeterContext) { + jMeterContext.setVariables(new JMeterVariables()); + } + }; + + protected abstract MessageRenderer getRenderer(); + + protected String getResourceFile(String resource) { + return format("test/resources/%s/%s", getClass().getPackage().getName().replace('.', '/'), resource); + } + + protected void assertValueFromFile(Consumer assertion, String resource, boolean hasVariable) { + String filename = getResourceFile(resource); + T actual = getRenderer().getValueFromFile(filename, "UTF-8", hasVariable, cache); + assertion.accept(actual); + } + +} diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRendererTest.java new file mode 100644 index 00000000000..b62043f6ec1 --- /dev/null +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRendererTest.java @@ -0,0 +1,99 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import static java.lang.String.format; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + +import java.io.Serializable; + +import org.apache.jmeter.protocol.jms.sampler.PublisherSampler; +import org.junit.Test; + +/** + * + */ +public class ObjectMessageRendererTest extends MessageRendererTest { + + private ObjectMessageRenderer render = RendererFactory.getInstance().getObject(); + @Override + public ObjectMessageRenderer getRenderer() { + return render; + } + + @Test + public void getValueFromText() { + Serializable object = render.getValueFromText(getDoeContent()); + assertObject(object, "Doe"); + } + + private void assertObject(Serializable object, String name) { + assertNotNull("object", object); + assertEquals("object.class", Person.class, object.getClass()); + Person p = (Person) object; + assertEquals("object.name", name, p.getName()); + } + + @Test + public void getValueFromFile_inRawMode() { + assertValueFromFile(object -> { + assertObject(object, "Doe"); + Person p = (Person) object; + assertSame("cache", p, cacheContent.getValue()); + }, "object_doe.xml", false); + } + + @Test + public void getValueFromFile_withForcedEncoding() { + String filename = getResourceFile("object_cp1252.xml"); + Serializable object = getRenderer().getValueFromFile(filename, "Cp1252", true, cache); + assertObject(object, "eéè€"); + assertEquals("cache", format("%s%n", getUnicodeContent()), cacheContent.getValue()); + + } + + @Test + public void getValueFromFile_withDefaultEncodingAndNoProlog() { + String filename = getResourceFile("object_utf8.xml"); + Serializable object = getRenderer().getValueFromFile(filename, PublisherSampler.DEFAULT_ENCODING, true, cache); + assertObject(object, "eéè€"); + assertEquals("cache", format("%s%n", getUnicodeContent()), cacheContent.getValue()); + + } + + @Test + public void getValueFromFile_withDefaultEncodingAndProlog() { + String filename = getResourceFile("object_prolog_cp1252.xml"); + Serializable object = getRenderer().getValueFromFile(filename, PublisherSampler.DEFAULT_ENCODING, true, cache); + assertObject(object, "eéè€"); + Person p = (Person) object; + assertEquals("object.name", "eéè€", p.getName()); + assertEquals("cache", format("%n%s%n", getUnicodeContent()), cacheContent.getValue()); + + } + + private String getUnicodeContent() { + return "eéè€"; + } + + private String getDoeContent() { + return "Doe"; + } +} diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/Person.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/Person.java new file mode 100644 index 00000000000..12076f4eb47 --- /dev/null +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/Person.java @@ -0,0 +1,32 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import java.io.Serializable; + +class Person implements Serializable { + private static final long serialVersionUID = 1L; + + private String name; + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRendererTest.java new file mode 100644 index 00000000000..8706cdda200 --- /dev/null +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRendererTest.java @@ -0,0 +1,94 @@ +/* + * 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.jmeter.protocol.jms.sampler.render; + +import static java.lang.String.format; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.util.Arrays; + +import org.junit.Test; + +/** + * + */ +public class TextMessageRendererTest extends MessageRendererTest { + + private TextMessageRenderer render = RendererFactory.getInstance().getText(); + @Override + protected MessageRenderer getRenderer() { + return render; + } + + @Test + public void readUTF8File() { + assertContent("utf8.txt", "UTF-8"); + } + + @Test + public void readCP1252File() { + assertContent("cp1252.txt", "Cp1252"); + } + + private void assertContent(String resource, String encoding) { + String filename = getResourceFile(resource); + String actual = render.getContent(new FileKey(filename, encoding)); + assertEquals(format("éè€%n"), actual); + } + + + @Test + public void getValueFromFileWithNoVar() { + assertValueFromFile(format("noVar%n"), "noVar.txt", true); + } + + @Test + public void getValueFromFileWithOneVar() { + jmeterCtxService.get().getVariables().put("oneVar", "foobar"); + assertValueFromFile(format("foobar%n"), "oneVar.txt", true); + } + + @Test + public void checkCache() { + jmeterCtxService.get().getVariables().put("oneVar", "foo"); + assertValueFromFile(format("foo%n"), "oneVar.txt", true); + assertEquals(format("${oneVar}%n"), cacheContent.getValue()); + + jmeterCtxService.get().getVariables().put("oneVar", "bar"); + assertValueFromFile(format("bar%n"), "oneVar.txt", true); + assertEquals(format("${oneVar}%n"), cacheContent.getValue()); + } + + @Test + public void checkNoVariable() { + jmeterCtxService.get().getVariables().put("oneVar", "RAW"); + assertValueFromFile(format("${oneVar}%n"), "oneVar.txt", false); + } + + @Test + public void getValueFromText() { + for (String text : Arrays.asList("a", null, "b", "")) { + assertSame(text, render.getValueFromText(text)); + } + } + + protected void assertValueFromFile(String expected, String resource, boolean hasVariable) { + assertValueFromFile(actual -> assertEquals(expected, actual), resource, hasVariable); + } +} diff --git a/test/src/org/apache/jmeter/threads/JMeterContextServiceHelper.java b/test/src/org/apache/jmeter/threads/JMeterContextServiceHelper.java new file mode 100644 index 00000000000..316142c0d28 --- /dev/null +++ b/test/src/org/apache/jmeter/threads/JMeterContextServiceHelper.java @@ -0,0 +1,41 @@ +/* + * 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.jmeter.threads; + +import org.junit.rules.ExternalResource; + +public class JMeterContextServiceHelper extends ExternalResource { + + @Override + protected void after() { + JMeterContextService.removeContext(); + } + + private JMeterContext instance; + public JMeterContext get() { + if (instance == null) { + JMeterContext jMeterContext = new JMeterContext(); + JMeterContextService.replaceContext(jMeterContext); + initContext(jMeterContext); + instance = jMeterContext; + } + return instance; + } + + protected void initContext(JMeterContext jMeterContext) {} +} From 2be5fd3013ff0851d747ef6df6d2b40a68718bd5 Mon Sep 17 00:00:00 2001 From: "Logan Mauzaize (T524467)" Date: Thu, 22 Dec 2016 09:22:52 +0100 Subject: [PATCH 3/6] POW-322 Fixes resource lookup --- .../sampler/render/MessageRendererTest.java | 5 +- .../apache/jmeter/test/ResourceLocator.java | 51 +++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 test/src/org/apache/jmeter/test/ResourceLocator.java diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java index 883171f61d2..a56d471fa3c 100644 --- a/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java @@ -17,14 +17,13 @@ package org.apache.jmeter.protocol.jms.sampler.render; -import static java.lang.String.format; - import java.util.AbstractMap; import java.util.Map.Entry; import java.util.function.Consumer; import java.util.function.Function; import org.apache.jmeter.protocol.jms.sampler.cache.Cache; +import org.apache.jmeter.test.ResourceLocator; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextServiceHelper; import org.apache.jmeter.threads.JMeterVariables; @@ -62,7 +61,7 @@ protected void initContext(JMeterContext jMeterContext) { protected abstract MessageRenderer getRenderer(); protected String getResourceFile(String resource) { - return format("test/resources/%s/%s", getClass().getPackage().getName().replace('.', '/'), resource); + return ResourceLocator.getResource(this, resource); } protected void assertValueFromFile(Consumer assertion, String resource, boolean hasVariable) { diff --git a/test/src/org/apache/jmeter/test/ResourceLocator.java b/test/src/org/apache/jmeter/test/ResourceLocator.java new file mode 100644 index 00000000000..a39e7ab4afe --- /dev/null +++ b/test/src/org/apache/jmeter/test/ResourceLocator.java @@ -0,0 +1,51 @@ +/* + * 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.jmeter.test; + +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +public interface ResourceLocator { + + public static String getResource(Object instance, String path) { + return getResource(instance.getClass(), path); + } + + public static String getResource(Class basetype, String path) { + Path nioPath = getResourcePath(basetype, path); + return nioPath.toString(); + } + + public static Path getResourcePath(Object instance, String path) { + return getResourcePath(instance.getClass(), path); + } + + public static Path getResourcePath(Class basetype, String path) { + URL url = basetype.getResource(path); + if (url == null) return null; + Path nioPath; + try { + nioPath = Paths.get(url.toURI()); + } catch (URISyntaxException e) { + throw new IllegalStateException(e); + } + return nioPath; + } +} From 44b4bd9a2f83b1cbbc47f0dfef5fa98bfb9e211d Mon Sep 17 00:00:00 2001 From: "Logan Mauzaize (T524467)" Date: Thu, 22 Dec 2016 09:46:38 +0100 Subject: [PATCH 4/6] POW-322 Uses HTTPS for checkstyle location --- build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.properties b/build.properties index db0d945f4d0..bb3446751f4 100644 --- a/build.properties +++ b/build.properties @@ -386,7 +386,7 @@ jdom.md5 = 140bfed13341fe2039eee0f26a16d705 # Optional for use by checkstyle checkstyle-all.version = 6.13 checkstyle-all.jar = checkstyle-${checkstyle-all.version}-all.jar -checkstyle-all.loc = http://downloads.sourceforge.net/checkstyle/checkstyle/${checkstyle-all.version}/checkstyle-${checkstyle-all.version}-all.jar?ts=${EPOCHSECONDS}&use_mirror=autoselect +checkstyle-all.loc = https://downloads.sourceforge.net/checkstyle/checkstyle/${checkstyle-all.version}/checkstyle-${checkstyle-all.version}-all.jar?ts=${EPOCHSECONDS}&use_mirror=autoselect checkstyle-all.md5 = ac6e1e81d09bcaf4c0c22181e9bda1d9 # Optional for use by rat From 674ac84830f77a8707975f91732824de8834fe06 Mon Sep 17 00:00:00 2001 From: "Logan Mauzaize (T524467)" Date: Thu, 22 Dec 2016 09:50:32 +0100 Subject: [PATCH 5/6] POW-322 Fixes checkstyle errors --- .../apache/jmeter/protocol/jms/sampler/cache/Cache.java | 2 +- .../jmeter/protocol/jms/sampler/cache/package-info.java | 2 +- .../jmeter/protocol/jms/sampler/render/FileKey.java | 8 ++++++-- .../jmeter/protocol/jms/sampler/render/package-info.java | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java index b334b582ecd..bd686950d9f 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java @@ -39,4 +39,4 @@ static Cache getNoopCache() { static Cache newSingleInstance() { return new SimpleCache(); } -} \ No newline at end of file +} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java index 611f6c6a044..bb681fdf64e 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java @@ -20,4 +20,4 @@ * * @See Cache */ -package org.apache.jmeter.protocol.jms.sampler.cache; \ No newline at end of file +package org.apache.jmeter.protocol.jms.sampler.cache; diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/FileKey.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/FileKey.java index b6c20d930b3..b7a62cff68d 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/FileKey.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/FileKey.java @@ -45,8 +45,12 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (obj == this) return true; - if (!(obj instanceof FileKey)) return false; + if (obj == this) { + return true; + } + if (!(obj instanceof FileKey)) { + return false; + } FileKey that = (FileKey) obj; diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/package-info.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/package-info.java index 464839e9ac3..dd61060de2c 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/package-info.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/package-info.java @@ -20,4 +20,4 @@ * @see Renderers * @see MessageRenderer */ -package org.apache.jmeter.protocol.jms.sampler.render; \ No newline at end of file +package org.apache.jmeter.protocol.jms.sampler.render; From d265a6dc3ca5c8fba51e6cdf9fe85b113d2392b4 Mon Sep 17 00:00:00 2001 From: Logan Mzz Date: Thu, 5 Jan 2017 13:45:57 +0100 Subject: [PATCH 6/6] POW-322 Replaces simple cache API by Caffeine --- .../jms/sampler/PublisherSampler.java | 32 ++++++---- .../protocol/jms/sampler/cache/Cache.java | 42 ------------- .../protocol/jms/sampler/cache/NoopCache.java | 37 ------------ .../jms/sampler/cache/SimpleCache.java | 31 ---------- .../jms/sampler/cache/package-info.java | 23 ------- .../sampler/render/BinaryMessageRenderer.java | 7 ++- .../sampler/render/MapMessageRenderer.java | 4 +- .../jms/sampler/render/MessageRenderer.java | 4 +- .../sampler/render/ObjectMessageRenderer.java | 8 +-- .../sampler/render/TextMessageRenderer.java | 7 ++- .../jms/sampler/PublisherSamplerTest.java | 60 +++++++++++++++++++ .../jms/sampler/cache/SimpleCacheTest.java | 48 --------------- .../render/BinaryMessageRendererTest.java | 4 +- .../sampler/render/MessageRendererTest.java | 25 +++----- .../render/ObjectMessageRendererTest.java | 8 +-- .../render/TextMessageRendererTest.java | 4 +- 16 files changed, 113 insertions(+), 231 deletions(-) delete mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java delete mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/NoopCache.java delete mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCache.java delete mode 100644 src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java create mode 100644 test/src/org/apache/jmeter/protocol/jms/sampler/PublisherSamplerTest.java delete mode 100644 test/src/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCacheTest.java diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java index 70747e2155b..1e5077f34d6 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/PublisherSampler.java @@ -26,6 +26,7 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.stream.Stream; import javax.jms.DeliveryMode; @@ -39,7 +40,6 @@ import org.apache.jmeter.protocol.jms.client.InitialContextFactory; import org.apache.jmeter.protocol.jms.client.Publisher; import org.apache.jmeter.protocol.jms.control.gui.JMSPublisherGui; -import org.apache.jmeter.protocol.jms.sampler.cache.Cache; import org.apache.jmeter.protocol.jms.sampler.render.MessageRenderer; import org.apache.jmeter.protocol.jms.sampler.render.Renderers; import org.apache.jmeter.samplers.SampleResult; @@ -50,6 +50,9 @@ import org.apache.jorphan.logging.LoggingManager; import org.apache.log.Logger; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + /** * This class implements the JMS Publisher sampler. */ @@ -123,7 +126,7 @@ public static String[] getSupportedEncodings() { private static final FileServer FSERVER = FileServer.getFileServer(); /** File cache handler **/ - private Cache fileCache = null; + private Cache fileCache = null; /** * the implementation calls testStarted() without any parameters. @@ -177,14 +180,10 @@ private void initClient() throws JMSException, NamingException { */ @Override public SampleResult sample() { + String configChoice = getConfigChoice(); if (fileCache == null) { - switch (getConfigChoice()) { - case JMSPublisherGui.USE_FILE_RSC: - fileCache = Cache.newSingleInstance(); - break; - default: - fileCache = Cache.getNoopCache(); - } + Cache newCache = buildCache(configChoice); + fileCache = newCache; } SampleResult result = new SampleResult(); @@ -243,7 +242,7 @@ public SampleResult sample() { result.setSampleCount(loop); result.setRequestHeaders(propBuffer.toString()); } catch (Exception e) { - log.error(String.format("Can't sent %s message from %s", type, getConfigChoice()), e); + log.error(String.format("Can't sent %s message from %s", type, configChoice), e); result.setResponseMessage(e.toString()); } finally { result.sampleEnd(); @@ -251,6 +250,19 @@ public SampleResult sample() { return result; } + protected static Cache buildCache(String configChoice) { + Caffeine cacheBuilder = Caffeine.newBuilder(); + switch (configChoice) { + case JMSPublisherGui.USE_FILE_RSC: + cacheBuilder.maximumSize(1); + break; + default: + cacheBuilder.expireAfterWrite(0, TimeUnit.MILLISECONDS).maximumSize(0); + } + Cache newCache = cacheBuilder.build(); + return newCache; + } + /** Gets file path to use **/ private String getFilePath(String... ext) { switch (getConfigChoice()) { diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java deleted file mode 100644 index bd686950d9f..00000000000 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/Cache.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.jmeter.protocol.jms.sampler.cache; - -import java.util.function.Function; - -/** - * Basic cache interface. - */ -public interface Cache { - - /** Force a cache value **/ - void put(Object key, Object value); - - /** Check if key is already cached, or execute function and cache value **/ - R get(T key, Function get); - - /** Non-caching implementation **/ - static Cache getNoopCache() { - return NoopCache.getInstance(); - } - - /** Caching a single value, if key change, cached value is thrown away. null key is supported. **/ - static Cache newSingleInstance() { - return new SimpleCache(); - } -} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/NoopCache.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/NoopCache.java deleted file mode 100644 index a2d89beb7a3..00000000000 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/NoopCache.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.jmeter.protocol.jms.sampler.cache; - -import java.util.function.Function; - -/** Non-Caching singleton **/ -enum NoopCache implements Cache { - INSTANCE; - - public static NoopCache getInstance() { - return INSTANCE; - } - - @Override - public void put(Object key, Object value) {} - - @Override - public R get(T key, Function get) { - return get.apply(key); - } -} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCache.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCache.java deleted file mode 100644 index c76e3301902..00000000000 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCache.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apache.jmeter.protocol.jms.sampler.cache; - -import java.io.Serializable; -import java.util.Objects; -import java.util.function.Function; - -/** Caching a single value, if key change, cached value is thrown away. null key is supported. **/ -class SimpleCache implements Cache, Serializable { - /** Unique version identifier **/ - private static final long serialVersionUID = 1L; - - private transient Object value; - private transient Object key; - - - @Override - public void put(Object key, Object value) { - this.key = key; - this.value = value; - } - - @Override - @SuppressWarnings("unchecked") - public R get(T key, Function get) { - if (!Objects.equals(this.key, key)) { - this.value = get.apply(key); - this.key = key; - } - return (R) this.value; - } -} diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java deleted file mode 100644 index bb681fdf64e..00000000000 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/cache/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - */ - -/** - * Basic cache API for JMS. - * - * @See Cache - */ -package org.apache.jmeter.protocol.jms.sampler.cache; diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRenderer.java index b2277d8ea90..d2e57dbc478 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRenderer.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRenderer.java @@ -25,7 +25,8 @@ import java.nio.file.Paths; import org.apache.jmeter.protocol.jms.control.gui.JMSPublisherGui; -import org.apache.jmeter.protocol.jms.sampler.cache.Cache; + +import com.github.benmanes.caffeine.cache.Cache; class BinaryMessageRenderer implements MessageRenderer { @@ -41,7 +42,7 @@ public byte[] getValueFromText(String text) { } @Override - public byte[] getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { + public byte[] getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { byte[] bytes; if (hasVariable) { @@ -52,7 +53,7 @@ public byte[] getValueFromFile(String filename, String encoding, boolean hasVari throw new RuntimeException(e); } } else { - bytes = cache.get(filename, this::getContent); + bytes = (byte[]) cache.get(filename, _p -> getContent(filename)); } return bytes; diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MapMessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MapMessageRenderer.java index b9ee7891fe7..ddfb08e14fe 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MapMessageRenderer.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MapMessageRenderer.java @@ -22,7 +22,7 @@ import java.util.HashMap; import java.util.Map; -import org.apache.jmeter.protocol.jms.sampler.cache.Cache; +import com.github.benmanes.caffeine.cache.Cache; public class MapMessageRenderer implements MessageRenderer> { @@ -66,7 +66,7 @@ public Map getValueFromText(String text) { } @Override - public Map getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { + public Map getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { String text = delegate.getValueFromFile(filename, encoding, hasVariable, cache); return getValueFromText(text); } diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MessageRenderer.java index 059911381ce..a19e7452a17 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MessageRenderer.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/MessageRenderer.java @@ -17,11 +17,11 @@ package org.apache.jmeter.protocol.jms.sampler.render; -import org.apache.jmeter.protocol.jms.sampler.cache.Cache; +import com.github.benmanes.caffeine.cache.Cache; public interface MessageRenderer { /** Convert text to expected type **/ T getValueFromText(String text); /** Read text from file, eventually replace variables, then convert it. Cached content depends if variabilisation is active or not. **/ - T getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache); + T getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache); } diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRenderer.java index e5029a42561..e6c31d9e5d7 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRenderer.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRenderer.java @@ -29,8 +29,8 @@ import javax.xml.stream.XMLStreamReader; import org.apache.jmeter.protocol.jms.sampler.PublisherSampler; -import org.apache.jmeter.protocol.jms.sampler.cache.Cache; +import com.github.benmanes.caffeine.cache.Cache; import com.thoughtworks.xstream.XStream; class ObjectMessageRenderer implements MessageRenderer { @@ -42,12 +42,12 @@ public ObjectMessageRenderer(TextMessageRenderer delegate) { } @Override - public Serializable getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { + public Serializable getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { Serializable value; if (hasVariable) { value = getInterpretedContent(filename, encoding, hasVariable, cache); } else { - value = cache.get(filename, this::getContent); + value = (Serializable) cache.get(filename, _p -> getContent(filename)); } return value; @@ -78,7 +78,7 @@ public Serializable getValueFromText(final String xmlMessage) { *

If encoding {@link PublisherSampler#DEFAULT_ENCODING isn't provided}, try to find it.

*

Only raw text is cached, neither interpreted text, neither parsed object.

*/ - protected Serializable getInterpretedContent(String filename, String encoding, boolean hasVariable, Cache cache) { + protected Serializable getInterpretedContent(String filename, String encoding, boolean hasVariable, Cache cache) { Serializable value; if (PublisherSampler.DEFAULT_ENCODING.equals(encoding)) { encoding = findEncoding(filename); diff --git a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRenderer.java b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRenderer.java index 455edc0884b..332dde23235 100644 --- a/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRenderer.java +++ b/src/protocol/jms/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRenderer.java @@ -18,9 +18,10 @@ package org.apache.jmeter.protocol.jms.sampler.render; import org.apache.jmeter.engine.util.CompoundVariable; -import org.apache.jmeter.protocol.jms.sampler.cache.Cache; import org.apache.jorphan.io.TextFile; +import com.github.benmanes.caffeine.cache.Cache; + class TextMessageRenderer implements MessageRenderer { @Override @@ -29,8 +30,8 @@ public String getValueFromText(String text) { } @Override - public String getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { - String text = cache.get(new FileKey(filename, encoding), this::getContent); + public String getValueFromFile(String filename, String encoding, boolean hasVariable, Cache cache) { + String text = (String) cache.get(new FileKey(filename, encoding), key -> getContent((FileKey)key)); if (hasVariable) { text = new CompoundVariable(text).execute(); } diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/PublisherSamplerTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/PublisherSamplerTest.java new file mode 100644 index 00000000000..feb4072cb9b --- /dev/null +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/PublisherSamplerTest.java @@ -0,0 +1,60 @@ +/* + * 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.jmeter.protocol.jms.sampler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.util.Locale; + +import org.apache.jmeter.protocol.jms.control.gui.JMSPublisherGui; +import org.apache.jmeter.util.JMeterUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.github.benmanes.caffeine.cache.Cache; + +/** + * + */ +public class PublisherSamplerTest { + + @Before + public void initJMeter() { + JMeterUtils.setLocale(new Locale("ignoreResources")); + } + + @After + public void resetJMeter() { + JMeterUtils.setLocale(Locale.ENGLISH); + } + + @Test + public void noopCache() { + Cache noopCache = PublisherSampler.buildCache(JMSPublisherGui.USE_RANDOM_RSC); + assertEquals(0, noopCache.estimatedSize()); + + String key = "key"; + String val1 = "1st time"; + assertSame(val1, noopCache.get(key, k -> val1)); + + String val2 = "2nd call"; + assertSame(val2, noopCache.get(key, k -> val2)); + } +} diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCacheTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCacheTest.java deleted file mode 100644 index 43d89180b10..00000000000 --- a/test/src/org/apache/jmeter/protocol/jms/sampler/cache/SimpleCacheTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.jmeter.protocol.jms.sampler.cache; - -import static org.junit.Assert.assertSame; - -import org.junit.Test; - -public class SimpleCacheTest { - - private SimpleCache cache = new SimpleCache(); - - @Test - public void put() { - String value = "banana"; - String key = "key"; - cache.put(key, value); - - String actual = cache.get(key, k -> "none"); - - assertSame(value, actual); - } - - @Test - public void getWithNoCacheValue() { - String value = "banana"; - String key = "key"; - - String actual = cache.get(key, k -> value); - - assertSame(value, actual); - } -} diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRendererTest.java index 59ce910ef5a..29005fb1cb3 100644 --- a/test/src/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRendererTest.java +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/BinaryMessageRendererTest.java @@ -112,10 +112,10 @@ protected void assertValueFromFile(String expected, String resource, boolean has } protected void assertCacheContentInBytes(String expected) { - assertBytesEquals(expected, (byte[]) cacheContent.getValue()); + assertBytesEquals(expected, (byte[]) getFirstCachedValue()); } protected void assertCacheContentInString(String expected) { - assertEquals(expected, cacheContent.getValue()); + assertEquals(expected, getFirstCachedValue()); } protected void assertBytesEquals(String expected, byte[] actual) { assertArrayEquals(expected.getBytes(StandardCharsets.UTF_8), actual); diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java index a56d471fa3c..e3ab48e724e 100644 --- a/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/MessageRendererTest.java @@ -17,38 +17,27 @@ package org.apache.jmeter.protocol.jms.sampler.render; -import java.util.AbstractMap; -import java.util.Map.Entry; import java.util.function.Consumer; -import java.util.function.Function; -import org.apache.jmeter.protocol.jms.sampler.cache.Cache; import org.apache.jmeter.test.ResourceLocator; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextServiceHelper; import org.apache.jmeter.threads.JMeterVariables; import org.junit.Rule; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; + /** * */ public abstract class MessageRendererTest { - @SuppressWarnings("rawtypes") - protected Entry cacheContent; - protected Cache cache = new Cache() { - @Override - public void put(Object key, Object value) { - cacheContent = new AbstractMap.SimpleImmutableEntry<>(key, value); - } + protected Cache cache = Caffeine.newBuilder().build(); - @Override - public V get(K key, Function get) { - V value = get.apply(key); - cacheContent = new AbstractMap.SimpleImmutableEntry<>(key, value); - return value; - } - }; + protected Object getFirstCachedValue() { + return cache.asMap().values().stream().findFirst().get(); + } @Rule public JMeterContextServiceHelper jmeterCtxService = new JMeterContextServiceHelper() { diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRendererTest.java index b62043f6ec1..635314631e7 100644 --- a/test/src/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRendererTest.java +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/ObjectMessageRendererTest.java @@ -56,7 +56,7 @@ public void getValueFromFile_inRawMode() { assertValueFromFile(object -> { assertObject(object, "Doe"); Person p = (Person) object; - assertSame("cache", p, cacheContent.getValue()); + assertSame("cache", p, getFirstCachedValue()); }, "object_doe.xml", false); } @@ -65,7 +65,7 @@ public void getValueFromFile_withForcedEncoding() { String filename = getResourceFile("object_cp1252.xml"); Serializable object = getRenderer().getValueFromFile(filename, "Cp1252", true, cache); assertObject(object, "eéè€"); - assertEquals("cache", format("%s%n", getUnicodeContent()), cacheContent.getValue()); + assertEquals("cache", format("%s%n", getUnicodeContent()), getFirstCachedValue()); } @@ -74,7 +74,7 @@ public void getValueFromFile_withDefaultEncodingAndNoProlog() { String filename = getResourceFile("object_utf8.xml"); Serializable object = getRenderer().getValueFromFile(filename, PublisherSampler.DEFAULT_ENCODING, true, cache); assertObject(object, "eéè€"); - assertEquals("cache", format("%s%n", getUnicodeContent()), cacheContent.getValue()); + assertEquals("cache", format("%s%n", getUnicodeContent()), getFirstCachedValue()); } @@ -85,7 +85,7 @@ public void getValueFromFile_withDefaultEncodingAndProlog() { assertObject(object, "eéè€"); Person p = (Person) object; assertEquals("object.name", "eéè€", p.getName()); - assertEquals("cache", format("%n%s%n", getUnicodeContent()), cacheContent.getValue()); + assertEquals("cache", format("%n%s%n", getUnicodeContent()), getFirstCachedValue()); } diff --git a/test/src/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRendererTest.java b/test/src/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRendererTest.java index 8706cdda200..9c7417a3b27 100644 --- a/test/src/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRendererTest.java +++ b/test/src/org/apache/jmeter/protocol/jms/sampler/render/TextMessageRendererTest.java @@ -68,11 +68,11 @@ public void getValueFromFileWithOneVar() { public void checkCache() { jmeterCtxService.get().getVariables().put("oneVar", "foo"); assertValueFromFile(format("foo%n"), "oneVar.txt", true); - assertEquals(format("${oneVar}%n"), cacheContent.getValue()); + assertEquals(format("${oneVar}%n"), getFirstCachedValue()); jmeterCtxService.get().getVariables().put("oneVar", "bar"); assertValueFromFile(format("bar%n"), "oneVar.txt", true); - assertEquals(format("${oneVar}%n"), cacheContent.getValue()); + assertEquals(format("${oneVar}%n"), getFirstCachedValue()); } @Test