All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.perfcake.message.sender.CommandSender Maven / Gradle / Ivy

There is a newer version: 7.5
Show newest version
/*
 * -----------------------------------------------------------------------\
 * PerfCake
 *  
 * Copyright (C) 2010 - 2013 the original author or authors.
 *  
 * Licensed 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.perfcake.message.sender;

import java.io.BufferedOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.perfcake.message.Message;
import org.perfcake.reporting.MeasurementUnit;
import org.perfcake.util.Utils;

/**
 * The sender that can invoke external command (specified by {@link #target} property)
 * in a separate process to send the message payload passed to the standard input of
 * the process or as the command argument.
 *
 * @author Martin Večeřa 
 * @author Pavel Macík 
 */
public class CommandSender extends AbstractSender {

   /**
    * Reference to a process where the command is executed.
    */
   private Process process;

   /**
    * The writer that is used to pass the message payload to the command's process standard input stream.
    */
   private PrintWriter writer;

   /**
    * The message payload that is passed to the command to send it.
    */
   private String messagePayload;

   /**
    * The reader that is used to read the response from the command's process standard output stream.
    */
   private InputStreamReader reader;

   /**
    * Specifies from where the message to send is taken.
    */
   private MessageFrom messageFrom = MessageFrom.STDIN;

   /**
    * The prefix for the command.
    */
   private String commandPrefix = "";

   /**
    * The actual command that is executed;
    */
   private String command = "";

   /**
    * The array of environment variables passed to the command.
    */
   private String[] environmentVariables;

   public static enum MessageFrom {
      STDIN, ARGUMENTS;
   }

   /*
    * (non-Javadoc)
    *
    * @see org.perfcake.message.sender.AbstractSender#init()
    */
   @Override
   public void init() throws Exception {
      // nop
   }

   /*
    * (non-Javadoc)
    *
    * @see org.perfcake.message.sender.AbstractSender#close()
    */
   @Override
   public void close() {
      // nop
   }

   /*
    * (non-Javadoc)
    *
    * @see org.perfcake.message.sender.AbstractSender#preSend(org.perfcake.message.Message, java.util.Map)
    */
   @Override
   public void preSend(final Message message, final Map properties) throws Exception {
      super.preSend(message, properties);
      this.messagePayload = message.getPayload().toString();
      command = (commandPrefix + " " + target + (messageFrom == MessageFrom.ARGUMENTS ? " " + message.getPayload() : "")).trim();

      Set> propertiesEntrySet = properties.entrySet();
      String[] environmentVariables = new String[propertiesEntrySet.size()];
      int i = 0;
      for (Entry entry : propertiesEntrySet) {
         environmentVariables[i++] = entry.getKey() + "=" + entry.getValue();
      }
   }

   /*
    * (non-Javadoc)
    *
    * @see org.perfcake.message.sender.AbstractSender#doSend(org.perfcake.message.Message, java.util.Map)
    */
   @Override
   public Serializable doSend(final Message message, final Map properties, final MeasurementUnit mu) throws Exception {
      process = Runtime.getRuntime().exec(command, environmentVariables);
      if (messageFrom == MessageFrom.STDIN) {
         writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(process.getOutputStream()), Utils.getDefaultEncoding()), true);
         writer.write(messagePayload);
         writer.flush();
         writer.close();
      }

      process.waitFor();
      char[] cbuf = new char[10 * 1024];
      this.reader = new InputStreamReader(process.getInputStream(), Utils.getDefaultEncoding());
      // note that Content-Length is available at this point
      StringBuilder sb = new StringBuilder();
      int ch = reader.read(cbuf);
      while (ch != -1) {
         sb.append(cbuf, 0, ch);
         ch = reader.read(cbuf);
      }

      String result = sb.toString();
      return result;
   }

   /*
    * (non-Javadoc)
    *
    * @see org.perfcake.message.sender.AbstractSender#postSend(org.perfcake.message.Message)
    */
   @Override
   public void postSend(final Message message) throws Exception {
      super.postSend(message);
      reader.close();
      process.getInputStream().close();
   }

   /**
    * Used to read the value of messageFrom property.
    *
    * @return The messageFrom.
    */
   public MessageFrom getMessageFrom() {
      return messageFrom;
   }

   /**
    * Sets the value of messageFrom property.
    *
    * @param messageFrom
    *           The messageFrom to set.
    */
   public void setMessageFrom(final MessageFrom messageFrom) {
      this.messageFrom = messageFrom;
   }

   /**
    * Used to read the value of commandPrefix.
    *
    * @return The commandPrefix.
    */
   protected String getCommandPrefix() {
      return commandPrefix;
   }

   /**
    * Sets the value of commandPrefix.
    *
    * @param commandPrefix
    *           The commandPrefix to set.
    */
   protected void setCommandPrefix(final String commandPrefix) {
      this.commandPrefix = commandPrefix;
   }

   /**
    * @return the environmentVariables
    */
   public String[] getEnvironmentVariables() {
      return Arrays.copyOf(environmentVariables, environmentVariables.length); // do not allow external modifications
   }

   /**
    * @param environmentVariables
    *           the environmentVariables to set
    */
   public void setEnvironmentVariables(String[] environmentVariables) {
      this.environmentVariables = Arrays.copyOf(environmentVariables, environmentVariables.length); // ignore any later external modifications
   }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy