Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix recorder HTTPS, close #884

  • Loading branch information...
commit 5ce59e00bfe7d6a7f6ece82e0dff91c7538fe9b2 1 parent cdddb1c
@slandelle slandelle authored
View
38 gatling-recorder/src/main/scala/com/excilys/ebi/gatling/recorder/http/channel/BootstrapFactory.scala
@@ -17,7 +17,7 @@ package com.excilys.ebi.gatling.recorder.http.channel
import org.jboss.netty.bootstrap.{ ServerBootstrap, ClientBootstrap }
import org.jboss.netty.channel.{ ChannelPipelineFactory, ChannelPipeline, ChannelHandlerContext }
-import org.jboss.netty.channel.Channels.pipeline
+import org.jboss.netty.channel.Channels
import org.jboss.netty.channel.socket.nio.{ NioServerSocketChannelFactory, NioClientSocketChannelFactory }
import org.jboss.netty.handler.codec.http.{ HttpResponseEncoder, HttpRequestDecoder, HttpRequest, HttpContentDecompressor, HttpContentCompressor, HttpClientCodec, HttpChunkAggregator }
import org.jboss.netty.handler.ssl.SslHandler
@@ -29,26 +29,28 @@ import com.excilys.ebi.gatling.recorder.http.ssl.{ SSLEngineFactory, FirstEventI
object BootstrapFactory {
+ val SSL_HANDLER_NAME = "ssl"
+
private val CHUNK_MAX_SIZE = 100 * 1024 * 1024; // 100Mo
private val clientChannelFactory = new NioClientSocketChannelFactory
private val serverChannelFactory = new NioServerSocketChannelFactory
- def newClientBootstrap(controller: RecorderController, browserCtx: ChannelHandlerContext, browserRequest: HttpRequest, ssl: Boolean): ClientBootstrap = {
+ def newClientBootstrap(controller: RecorderController, requestContext: ChannelHandlerContext, browserRequest: HttpRequest, ssl: Boolean): ClientBootstrap = {
val bootstrap = new ClientBootstrap(clientChannelFactory)
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
def getPipeline: ChannelPipeline = {
- val tmpPipeline = pipeline()
+ val pipeline = Channels.pipeline
if (ssl)
- tmpPipeline.addLast("ssl", new SslHandler(SSLEngineFactory.newClientSSLEngine))
- tmpPipeline.addLast("codec", new HttpClientCodec)
- tmpPipeline.addLast("inflater", new HttpContentDecompressor)
- tmpPipeline.addLast("aggregator", new HttpChunkAggregator(CHUNK_MAX_SIZE))
- tmpPipeline.addLast("gatling", new ServerHttpResponseHandler(controller, browserCtx, browserRequest))
+ pipeline.addLast(SSL_HANDLER_NAME, new SslHandler(SSLEngineFactory.newClientSSLEngine))
+ pipeline.addLast("codec", new HttpClientCodec)
+ pipeline.addLast("inflater", new HttpContentDecompressor)
+ pipeline.addLast("aggregator", new HttpChunkAggregator(CHUNK_MAX_SIZE))
+ pipeline.addLast("gatling", new ServerHttpResponseHandler(controller, requestContext, browserRequest))
- tmpPipeline
+ pipeline
}
})
@@ -64,19 +66,19 @@ object BootstrapFactory {
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
def getPipeline: ChannelPipeline = {
- val tmpPipeline = pipeline()
+ val pipeline = Channels.pipeline
if (ssl)
- tmpPipeline.addLast("ssl", new FirstEventIsUnsecuredConnectSslHandler(SSLEngineFactory.newServerSSLEngine))
- tmpPipeline.addLast("decoder", new HttpRequestDecoder)
- tmpPipeline.addLast("aggregator", new HttpChunkAggregator(CHUNK_MAX_SIZE))
- tmpPipeline.addLast("encoder", new HttpResponseEncoder)
- tmpPipeline.addLast("deflater", new HttpContentCompressor)
+ pipeline.addLast(SSL_HANDLER_NAME, new FirstEventIsUnsecuredConnectSslHandler(SSLEngineFactory.newServerSSLEngine))
+ pipeline.addLast("decoder", new HttpRequestDecoder)
+ pipeline.addLast("aggregator", new HttpChunkAggregator(CHUNK_MAX_SIZE))
+ pipeline.addLast("encoder", new HttpResponseEncoder)
+ pipeline.addLast("deflater", new HttpContentCompressor)
if (ssl)
- tmpPipeline.addLast("gatling", new BrowserHttpsRequestHandler(controller, proxyConfig))
+ pipeline.addLast("gatling", new BrowserHttpsRequestHandler(controller, proxyConfig))
else
- tmpPipeline.addLast("gatling", new BrowserHttpRequestHandler(controller, proxyConfig))
+ pipeline.addLast("gatling", new BrowserHttpRequestHandler(controller, proxyConfig))
- tmpPipeline
+ pipeline
}
})
View
25 ...ecorder/src/main/scala/com/excilys/ebi/gatling/recorder/http/handler/AbstractBrowserRequestHandler.scala
@@ -31,6 +31,10 @@ import grizzled.slf4j.Logging
abstract class AbstractBrowserRequestHandler(controller: RecorderController, proxyConfig: ProxyConfig) extends SimpleChannelHandler with Logging {
+ implicit def function2ChannelFutureListener(thunk: ChannelFuture => Any) = new ChannelFutureListener {
+ def operationComplete(future: ChannelFuture) { thunk(future) }
+ }
+
override def messageReceived(ctx: ChannelHandlerContext, event: MessageEvent) {
event.getMessage match {
@@ -45,39 +49,26 @@ abstract class AbstractBrowserRequestHandler(controller: RecorderController, pro
}
}.getOrElse(request.removeHeader("Proxy-Connection")) // remove Proxy-Connection header if it's not significant
- val future = connectToServerOnBrowserRequestReceived(ctx, request)
+ propagateRequest(ctx, request)
controller.receiveRequest(request)
- sendRequestToServerAfterConnection(future, request);
-
case unknown => warn("Received unknown message: " + unknown)
}
}
- def connectToServerOnBrowserRequestReceived(ctx: ChannelHandlerContext, request: HttpRequest): ChannelFuture
+ def propagateRequest(requestContext: ChannelHandlerContext, request: HttpRequest)
override def exceptionCaught(ctx: ChannelHandlerContext, e: ExceptionEvent) {
error("Exception caught", e.getCause)
// Properly closing
val future = ctx.getChannel.getCloseFuture
- future.addListener(new ChannelFutureListener {
- def operationComplete(future: ChannelFuture) = future.getChannel.close
- })
+ future.addListener(ChannelFutureListener.CLOSE)
ctx.sendUpstream(e)
}
- private def sendRequestToServerAfterConnection(future: ChannelFuture, request: HttpRequest) {
-
- Option(future).map { future =>
- future.addListener(new ChannelFutureListener {
- def operationComplete(future: ChannelFuture) = future.getChannel.write(buildRequestWithRelativeURI(request))
- })
- }
- }
-
- private def buildRequestWithRelativeURI(request: HttpRequest) = {
+ def buildRequestWithRelativeURI(request: HttpRequest) = {
val uri = new URI(request.getUri)
val newUri = new URI(null, null, null, -1, uri.getPath, uri.getQuery, uri.getFragment).toString
val newRequest = new DefaultHttpRequest(request.getProtocolVersion, request.getMethod, newUri)
View
8 ...ng-recorder/src/main/scala/com/excilys/ebi/gatling/recorder/http/handler/BrowserHttpRequestHandler.scala
@@ -26,9 +26,9 @@ import com.excilys.ebi.gatling.recorder.http.channel.BootstrapFactory.newClientB
class BrowserHttpRequestHandler(controller: RecorderController, proxyConfig: ProxyConfig) extends AbstractBrowserRequestHandler(controller, proxyConfig) {
- def connectToServerOnBrowserRequestReceived(ctx: ChannelHandlerContext, request: HttpRequest): ChannelFuture = {
+ def propagateRequest(requestContext: ChannelHandlerContext, request: HttpRequest) {
- val bootstrap = newClientBootstrap(controller, ctx, request, false)
+ val bootstrap = newClientBootstrap(controller, requestContext, request, false)
val (proxyHost, proxyPort) = (for {
host <- proxyConfig.host
@@ -40,6 +40,8 @@ class BrowserHttpRequestHandler(controller: RecorderController, proxyConfig: Pro
(uri.getHost, port)
}
- bootstrap.connect(new InetSocketAddress(proxyHost, proxyPort))
+ bootstrap
+ .connect(new InetSocketAddress(proxyHost, proxyPort))
+ .addListener { future: ChannelFuture => future.getChannel.write(buildRequestWithRelativeURI(request)) }
}
}
View
37 ...g-recorder/src/main/scala/com/excilys/ebi/gatling/recorder/http/handler/BrowserHttpsRequestHandler.scala
@@ -19,9 +19,11 @@ import java.net.{ InetSocketAddress, URI }
import org.jboss.netty.channel.{ ChannelFuture, ChannelHandlerContext }
import org.jboss.netty.handler.codec.http.{ DefaultHttpResponse, HttpMethod, HttpRequest, HttpResponseStatus, HttpVersion }
+import org.jboss.netty.handler.ssl.SslHandler
import com.excilys.ebi.gatling.recorder.config.ProxyConfig
import com.excilys.ebi.gatling.recorder.controller.RecorderController
+import com.excilys.ebi.gatling.recorder.http.channel.BootstrapFactory
import com.excilys.ebi.gatling.recorder.http.channel.BootstrapFactory.newClientBootstrap
import grizzled.slf4j.Logging
@@ -30,34 +32,37 @@ class BrowserHttpsRequestHandler(controller: RecorderController, proxyConfig: Pr
@volatile var targetHostURI: URI = _
- def connectToServerOnBrowserRequestReceived(ctx: ChannelHandlerContext, request: HttpRequest): ChannelFuture = {
-
- info("Received " + request.getMethod + " on " + request.getUri)
-
- if (request.getMethod == HttpMethod.CONNECT) {
-
- targetHostURI = new URI("https://" + request.getUri());
+ def propagateRequest(requestContext: ChannelHandlerContext, request: HttpRequest) {
+ def handleConnect {
+ targetHostURI = new URI("https://" + request.getUri)
warn("Trying to connect to " + targetHostURI + ", make sure you've accepted the recorder certificate for this site")
-
controller.secureConnection(targetHostURI)
+ requestContext.getChannel.write(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK))
+ }
- ctx.getChannel.write(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK))
-
- null
-
- } else {
- // set full uri so that it's correctly recorded
+ def handlePropagatableRequest {
+ // set full uri so that it's correctly recorded FIXME ugly
request.setUri(targetHostURI + request.getUri)
- val bootstrap = newClientBootstrap(controller, ctx, request, true)
+ val bootstrap = newClientBootstrap(controller, requestContext, request, true)
val (host, port) = (for {
host <- proxyConfig.host
port <- proxyConfig.port
} yield (host, port)).getOrElse(targetHostURI.getHost, targetHostURI.getPort)
- bootstrap.connect(new InetSocketAddress(host, port))
+ bootstrap
+ .connect(new InetSocketAddress(host, port))
+ .addListener { connectFuture: ChannelFuture =>
+ connectFuture.getChannel.getPipeline.get(BootstrapFactory.SSL_HANDLER_NAME).asInstanceOf[SslHandler].handshake.addListener { handshakeFuture: ChannelFuture =>
+ handshakeFuture.getChannel.write(buildRequestWithRelativeURI(request))
+ }
+ }
}
+
+ info("Received " + request.getMethod + " on " + request.getUri)
+ if (request.getMethod == HttpMethod.CONNECT) handleConnect
+ else handlePropagatableRequest
}
}
View
628 gatling-recorder/src/main/scala/com/excilys/ebi/gatling/recorder/ui/frame/ConfigurationFrame.scala
@@ -36,318 +36,318 @@ import javax.swing._
class ConfigurationFrame(controller: RecorderController) extends JFrame with ScalaSwing with Logging {
- private val IS_MAC_OSX = System.getProperty("os.name").startsWith("Mac");
-
- val txtPort = new JTextField(null, 4)
- val txtSslPort = new JTextField(null, 4)
-
- val txtProxyHost = new JTextField(null, 15)
- val txtProxyPort = new JTextField(null, 4)
- txtProxyPort.setEnabled(false)
- val txtProxySslPort = new JTextField(null, 4)
- txtProxySslPort.setEnabled(false)
- val txtProxyUsername = new JTextField(null, 12)
- txtProxyUsername.setEnabled(false)
- val txtProxyPassword = new JTextField(null, 12)
- txtProxyPassword.setEnabled(false)
-
- val cbFilterStrategies = new JComboBox
- val chkSavePref = new JCheckBox("Save preferences")
- val chkFollowRedirect = new JCheckBox("Follow Redirects?")
- val chkAutomaticReferer = new JCheckBox("Automatic Referers?")
- val txtOutputFolder = new JTextField(66)
- val tblFilters = new FilterTable
- val cbOutputEncoding = new JComboBox
- val txtSimulationPackage = new JTextField(30)
- val txtSimulationClassName = new JTextField(30)
-
- private val btnFiltersAdd = new JButton("+")
- private val btnFiltersDel = new JButton("-")
- private val btnOutputFolder = new JButton("Browse")
- private val btnClear = new JButton("Clear")
- val btnStart = new JButton("Start !")
-
- private var pnlTop: JPanel = null
- private var pnlCenter: JPanel = null
- private var pnlBottom: JPanel = null
-
- private var fileDialog: FileDialog = null
- private var fileChooser: JFileChooser = null
-
- /** Initialization of the frame **/
-
- setTitle("Gatling Recorder - Configuration")
- setLayout(new BorderLayout)
- setMinimumSize(new Dimension(1024, 768))
- setResizable(true)
- setLocationRelativeTo(null)
- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
- setIconImages(iconList)
-
- /** Initialization of components **/
- initTopPanel
- initCenterPanel
- initBottomPanel
- initOutputDirectoryChooser
-
- setListeners
-
- setValidationListeners
-
- populateItemsFromConfiguration(configuration)
-
- private def initOutputDirectoryChooser {
-
- if (IS_MAC_OSX) {
- // on mac, use native dialog because JFileChooser is buggy
- System.setProperty("apple.awt.fileDialogForDirectories", "true")
- fileDialog = new FileDialog(ConfigurationFrame.this)
-
- } else {
- fileChooser = new JFileChooser
- fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
- }
- }
-
- private def initTopPanel {
- /***** Creating Top Panel (Network) *****/
- pnlTop = new JPanel(new BorderLayout)
-
- /* Gatling Image */
- val pnlImage = new JPanel
- pnlImage.add(new JLabel(Commons.logoSmall))
-
- /* Network Panel */
- val pnlNetwork = new JPanel(new BorderLayout)
- pnlNetwork.setBorder(BorderFactory.createTitledBorder("Network"))
- pnlNetwork.setLayout(new BorderLayout)
-
- /* Local proxy host panel */
- val localProxyHostPanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
- localProxyHostPanel.add(new JLabel("Listening port* : "))
- localProxyHostPanel.add(new JLabel(" localhost"))
-
- /* Local proxy ports panel */
- val localProxyPortsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT))
- localProxyPortsPanel.add(new JLabel("HTTP"))
- localProxyPortsPanel.add(txtPort)
- localProxyPortsPanel.add(new JLabel("HTTPS"))
- localProxyPortsPanel.add(txtSslPort)
-
- /* Local proxy panel */
- val localProxyPanel = new JPanel(new FlowLayout)
- localProxyPanel.add(localProxyHostPanel)
- localProxyPanel.add(localProxyPortsPanel)
-
- /* Outgoing proxy host panel */
- val outgoingProxyHostPanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
- outgoingProxyHostPanel.add(new JLabel("Outgoing proxy : "))
- outgoingProxyHostPanel.add(new JLabel("host:"))
- outgoingProxyHostPanel.add(txtProxyHost)
- outgoingProxyHostPanel.add(new JLabel("HTTP"))
- outgoingProxyHostPanel.add(txtProxyPort)
- outgoingProxyHostPanel.add(new JLabel("HTTPS"))
- outgoingProxyHostPanel.add(txtProxySslPort)
-
- /* Outgoing proxy ports panel */
- val outgoingProxyCredentialsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT))
- outgoingProxyCredentialsPanel.add(new JLabel("Username"))
- outgoingProxyCredentialsPanel.add(txtProxyUsername)
- outgoingProxyCredentialsPanel.add(new JLabel("Password"))
- outgoingProxyCredentialsPanel.add(txtProxyPassword)
-
- /* Outgoing proxy panel */
- val outgoingProxyPanel = new JPanel(new BorderLayout)
- outgoingProxyPanel.add(outgoingProxyHostPanel, BorderLayout.NORTH)
- outgoingProxyPanel.add(outgoingProxyCredentialsPanel, BorderLayout.SOUTH)
-
- /* Adding panels to newtworkPanel */
- pnlNetwork.add(localProxyPanel, BorderLayout.NORTH)
- pnlNetwork.add(outgoingProxyPanel, BorderLayout.SOUTH)
-
- /* Adding Image and network panel to top panel */
- pnlTop.add(pnlImage, BorderLayout.WEST)
- pnlTop.add(pnlNetwork, BorderLayout.EAST)
-
- /* Adding panel to Frame */
- add(pnlTop, BorderLayout.NORTH)
- }
-
- private def initCenterPanel {
- /***** Creating Center Panel (Output + Start) *****/
- pnlCenter = new JPanel
- pnlCenter.setLayout(new BorderLayout)
-
- /* Output Folder Panel */
- val outputFolderPanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
- outputFolderPanel.add(new JLabel("Output folder* : "))
- outputFolderPanel.add(txtOutputFolder)
- outputFolderPanel.add(btnOutputFolder)
-
- for (c <- Charset.availableCharsets.values)
- cbOutputEncoding.addItem(c)
-
- /* Output Panel */
- val outputPanel = new JPanel(new BorderLayout)
- outputPanel.setBorder(BorderFactory.createTitledBorder("Output"))
-
- val outputFormatPanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
- outputFormatPanel.add(new JLabel("Encoding: "))
- outputFormatPanel.add(cbOutputEncoding)
-
- outputPanel.add(outputFolderPanel, BorderLayout.NORTH)
- outputPanel.add(outputFormatPanel, BorderLayout.CENTER)
-
- /* Simulation information panel */
- val simulationInfoPanel = new JPanel(new BorderLayout)
-
- val packageNamePanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
- packageNamePanel.add(new JLabel("Package: "))
- packageNamePanel.add(txtSimulationPackage)
-
- val simulationNamePanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
- simulationNamePanel.add(new JLabel("Class Name*: "))
- simulationNamePanel.add(txtSimulationClassName)
-
- simulationInfoPanel.add(packageNamePanel, BorderLayout.WEST)
- simulationInfoPanel.add(simulationNamePanel, BorderLayout.EAST)
-
- val simulationConfigPanel = new JPanel(new BorderLayout)
- simulationConfigPanel.setBorder(BorderFactory.createTitledBorder("Simulation Information"))
-
- simulationConfigPanel.add(simulationInfoPanel, BorderLayout.NORTH)
- simulationConfigPanel.add(chkFollowRedirect, BorderLayout.WEST)
- simulationConfigPanel.add(chkAutomaticReferer, BorderLayout.EAST)
-
- /* Filters Panel */
- val filtersPanel = new JPanel(new BorderLayout);
- filtersPanel.setBorder(BorderFactory.createTitledBorder("Filters"))
-
- // Fill Combo Box for Strategies
- for (ft <- FilterStrategy.values)
- cbFilterStrategies.addItem(ft)
-
- /* Filter Actions panel */
- val filterActionsPanel = new JPanel
- filterActionsPanel.add(new JLabel("Strategy"))
- filterActionsPanel.add(cbFilterStrategies)
- filterActionsPanel.add(btnFiltersAdd)
- filterActionsPanel.add(btnFiltersDel)
- filterActionsPanel.add(btnClear)
-
- /* Adding panels to filterPanel */
- filtersPanel.add(tblFilters, BorderLayout.CENTER)
- filtersPanel.add(filterActionsPanel, BorderLayout.SOUTH)
-
- /* Adding panels to bottomPanel */
- pnlCenter.add(simulationConfigPanel, BorderLayout.NORTH)
- pnlCenter.add(outputPanel, BorderLayout.CENTER)
- pnlCenter.add(filtersPanel, BorderLayout.SOUTH)
-
- /* Adding panel to Frame */
- add(pnlCenter, BorderLayout.CENTER)
- }
-
- private def initBottomPanel {
- /***** Creating Bottom Panel (Filters) *****/
- pnlBottom = new JPanel
- pnlBottom.setLayout(new BorderLayout)
-
- /* Start Action Panel */
- val startActionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT))
- startActionPanel.add(chkSavePref)
- startActionPanel.add(btnStart)
-
- chkSavePref.setHorizontalTextPosition(SwingConstants.LEFT);
-
- pnlBottom.add(startActionPanel, BorderLayout.SOUTH);
-
- /* Adding panel to Frame */
- add(pnlBottom, BorderLayout.SOUTH)
- }
-
- private def setListeners {
- // Enables or disables filter edition depending on the selected strategy
- cbFilterStrategies.addItemListener((e: ItemEvent) => {
- if (e.getStateChange == ItemEvent.SELECTED && e.getItem == FilterStrategy.NONE) {
- tblFilters.setEnabled(false)
- tblFilters.setFocusable(false)
- } else {
- tblFilters.setEnabled(true)
- tblFilters.setFocusable(true)
- }
- })
-
- // Adds a filter row when + button clicked
- btnFiltersAdd.addActionListener((e: ActionEvent) => tblFilters.addRow)
-
- // Removes selected filter when - button clicked
- btnFiltersDel.addActionListener((e: ActionEvent) => tblFilters.removeSelectedRow)
-
- // Removes all filters when clear button clicked
- btnClear.addActionListener((e: ActionEvent) => tblFilters.removeAllElements)
-
- // Opens a save dialog when Browse button clicked
- btnOutputFolder.addActionListener((e: ActionEvent) => {
-
- var chosenDirPath: String = null
-
- if (IS_MAC_OSX) {
- fileDialog.setVisible(true)
-
- if (fileDialog.getDirectory == null)
- return
-
- chosenDirPath = fileDialog.getDirectory + fileDialog.getFile
-
- } else {
- if (fileChooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION)
- return
-
- chosenDirPath = fileChooser.getSelectedFile.getPath
- }
-
- txtOutputFolder.setText(chosenDirPath)
- })
-
- // Validates form when Start button clicked
- btnStart.addActionListener(new SaveConfigurationListener(controller, this))
- }
-
- private def setValidationListeners {
- txtPort.addKeyListener(intValidator(this, "port"))
- txtSslPort.addKeyListener(intValidator(this, "sslPort"))
- txtProxyHost.addKeyListener(proxyHostValidator(this))
- txtProxyPort.addKeyListener(intValidator(this, "proxyPort"))
- txtProxySslPort.addKeyListener(intValidator(this, "proxySslPort"))
- txtOutputFolder.addKeyListener(nonEmptyValidator(this, "outputFolder"))
- txtSimulationClassName.addKeyListener(nonEmptyValidator(this, "simulationClassName"))
- }
-
- def populateItemsFromConfiguration(configuration: Configuration) {
- txtPort.setText(configuration.port.toString)
- txtSslPort.setText(configuration.sslPort.toString)
-
- configuration.proxy.host.map { proxyHost =>
- txtProxyHost.setText(proxyHost)
- txtProxyPort.setText(configuration.proxy.port.getOrElse(0).toString)
- txtProxySslPort.setText(configuration.proxy.sslPort.getOrElse(0).toString)
- txtProxyUsername.setText(configuration.proxy.getUsername.getOrElse(null))
- txtProxyPassword.setText(configuration.proxy.getPassword.getOrElse(null))
- txtProxyPort.setEnabled(true)
- txtProxySslPort.setEnabled(true)
- txtProxyUsername.setEnabled(true)
- txtProxyPassword.setEnabled(true)
- }
- configuration.simulationPackage.map(txtSimulationPackage.setText)
- txtSimulationClassName.setText(configuration.simulationClassName)
- cbFilterStrategies.setSelectedItem(configuration.filterStrategy)
- chkFollowRedirect.setSelected(configuration.followRedirect)
- chkAutomaticReferer.setSelected(configuration.automaticReferer)
- for (pattern <- configuration.patterns)
- tblFilters.addRow(pattern)
- txtOutputFolder.setText(configuration.outputFolder)
- chkSavePref.setSelected(configuration.saveConfiguration)
- cbOutputEncoding.setSelectedItem(Charset.forName(configuration.encoding))
- }
+ private val IS_MAC_OSX = System.getProperty("os.name").startsWith("Mac");
+
+ val txtPort = new JTextField(null, 4)
+ val txtSslPort = new JTextField(null, 4)
+
+ val txtProxyHost = new JTextField(null, 15)
+ val txtProxyPort = new JTextField(null, 4)
+ txtProxyPort.setEnabled(false)
+ val txtProxySslPort = new JTextField(null, 4)
+ txtProxySslPort.setEnabled(false)
+ val txtProxyUsername = new JTextField(null, 12)
+ txtProxyUsername.setEnabled(false)
+ val txtProxyPassword = new JTextField(null, 12)
+ txtProxyPassword.setEnabled(false)
+
+ val cbFilterStrategies = new JComboBox
+ val chkSavePref = new JCheckBox("Save preferences")
+ val chkFollowRedirect = new JCheckBox("Follow Redirects?")
+ val chkAutomaticReferer = new JCheckBox("Automatic Referers?")
+ val txtOutputFolder = new JTextField(66)
+ val tblFilters = new FilterTable
+ val cbOutputEncoding = new JComboBox
+ val txtSimulationPackage = new JTextField(30)
+ val txtSimulationClassName = new JTextField(30)
+
+ private val btnFiltersAdd = new JButton("+")
+ private val btnFiltersDel = new JButton("-")
+ private val btnOutputFolder = new JButton("Browse")
+ private val btnClear = new JButton("Clear")
+ val btnStart = new JButton("Start !")
+
+ private var pnlTop: JPanel = null
+ private var pnlCenter: JPanel = null
+ private var pnlBottom: JPanel = null
+
+ private var fileDialog: FileDialog = null
+ private var fileChooser: JFileChooser = null
+
+ /** Initialization of the frame **/
+
+ setTitle("Gatling Recorder - Configuration")
+ setLayout(new BorderLayout)
+ setMinimumSize(new Dimension(1024, 768))
+ setResizable(true)
+ setLocationRelativeTo(null)
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
+ setIconImages(iconList)
+
+ /** Initialization of components **/
+ initTopPanel
+ initCenterPanel
+ initBottomPanel
+ initOutputDirectoryChooser
+
+ setListeners
+
+ setValidationListeners
+
+ populateItemsFromConfiguration(configuration)
+
+ private def initOutputDirectoryChooser {
+
+ if (IS_MAC_OSX) {
+ // on mac, use native dialog because JFileChooser is buggy
+ System.setProperty("apple.awt.fileDialogForDirectories", "true")
+ fileDialog = new FileDialog(ConfigurationFrame.this)
+
+ } else {
+ fileChooser = new JFileChooser
+ fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
+ }
+ }
+
+ private def initTopPanel {
+ /***** Creating Top Panel (Network) *****/
+ pnlTop = new JPanel(new BorderLayout)
+
+ /* Gatling Image */
+ val pnlImage = new JPanel
+ pnlImage.add(new JLabel(Commons.logoSmall))
+
+ /* Network Panel */
+ val pnlNetwork = new JPanel(new BorderLayout)
+ pnlNetwork.setBorder(BorderFactory.createTitledBorder("Network"))
+ pnlNetwork.setLayout(new BorderLayout)
+
+ /* Local proxy host panel */
+ val localProxyHostPanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
+ localProxyHostPanel.add(new JLabel("Listening port* : "))
+ localProxyHostPanel.add(new JLabel(" localhost"))
+
+ /* Local proxy ports panel */
+ val localProxyPortsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT))
+ localProxyPortsPanel.add(new JLabel("HTTP"))
+ localProxyPortsPanel.add(txtPort)
+ localProxyPortsPanel.add(new JLabel("HTTPS"))
+ localProxyPortsPanel.add(txtSslPort)
+
+ /* Local proxy panel */
+ val localProxyPanel = new JPanel(new FlowLayout)
+ localProxyPanel.add(localProxyHostPanel)
+ localProxyPanel.add(localProxyPortsPanel)
+
+ /* Outgoing proxy host panel */
+ val outgoingProxyHostPanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
+ outgoingProxyHostPanel.add(new JLabel("Outgoing proxy : "))
+ outgoingProxyHostPanel.add(new JLabel("host:"))
+ outgoingProxyHostPanel.add(txtProxyHost)
+ outgoingProxyHostPanel.add(new JLabel("HTTP"))
+ outgoingProxyHostPanel.add(txtProxyPort)
+ outgoingProxyHostPanel.add(new JLabel("HTTPS"))
+ outgoingProxyHostPanel.add(txtProxySslPort)
+
+ /* Outgoing proxy ports panel */
+ val outgoingProxyCredentialsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT))
+ outgoingProxyCredentialsPanel.add(new JLabel("Username"))
+ outgoingProxyCredentialsPanel.add(txtProxyUsername)
+ outgoingProxyCredentialsPanel.add(new JLabel("Password"))
+ outgoingProxyCredentialsPanel.add(txtProxyPassword)
+
+ /* Outgoing proxy panel */
+ val outgoingProxyPanel = new JPanel(new BorderLayout)
+ outgoingProxyPanel.add(outgoingProxyHostPanel, BorderLayout.NORTH)
+ outgoingProxyPanel.add(outgoingProxyCredentialsPanel, BorderLayout.SOUTH)
+
+ /* Adding panels to newtworkPanel */
+ pnlNetwork.add(localProxyPanel, BorderLayout.NORTH)
+ pnlNetwork.add(outgoingProxyPanel, BorderLayout.SOUTH)
+
+ /* Adding Image and network panel to top panel */
+ pnlTop.add(pnlImage, BorderLayout.WEST)
+ pnlTop.add(pnlNetwork, BorderLayout.EAST)
+
+ /* Adding panel to Frame */
+ add(pnlTop, BorderLayout.NORTH)
+ }
+
+ private def initCenterPanel {
+ /***** Creating Center Panel (Output + Start) *****/
+ pnlCenter = new JPanel
+ pnlCenter.setLayout(new BorderLayout)
+
+ /* Output Folder Panel */
+ val outputFolderPanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
+ outputFolderPanel.add(new JLabel("Output folder* : "))
+ outputFolderPanel.add(txtOutputFolder)
+ outputFolderPanel.add(btnOutputFolder)
+
+ for (c <- Charset.availableCharsets.values)
+ cbOutputEncoding.addItem(c)
+
+ /* Output Panel */
+ val outputPanel = new JPanel(new BorderLayout)
+ outputPanel.setBorder(BorderFactory.createTitledBorder("Output"))
+
+ val outputFormatPanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
+ outputFormatPanel.add(new JLabel("Encoding: "))
+ outputFormatPanel.add(cbOutputEncoding)
+
+ outputPanel.add(outputFolderPanel, BorderLayout.NORTH)
+ outputPanel.add(outputFormatPanel, BorderLayout.CENTER)
+
+ /* Simulation information panel */
+ val simulationInfoPanel = new JPanel(new BorderLayout)
+
+ val packageNamePanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
+ packageNamePanel.add(new JLabel("Package: "))
+ packageNamePanel.add(txtSimulationPackage)
+
+ val simulationNamePanel = new JPanel(new FlowLayout(FlowLayout.LEFT))
+ simulationNamePanel.add(new JLabel("Class Name*: "))
+ simulationNamePanel.add(txtSimulationClassName)
+
+ simulationInfoPanel.add(packageNamePanel, BorderLayout.WEST)
+ simulationInfoPanel.add(simulationNamePanel, BorderLayout.EAST)
+
+ val simulationConfigPanel = new JPanel(new BorderLayout)
+ simulationConfigPanel.setBorder(BorderFactory.createTitledBorder("Simulation Information"))
+
+ simulationConfigPanel.add(simulationInfoPanel, BorderLayout.NORTH)
+ simulationConfigPanel.add(chkFollowRedirect, BorderLayout.WEST)
+ simulationConfigPanel.add(chkAutomaticReferer, BorderLayout.EAST)
+
+ /* Filters Panel */
+ val filtersPanel = new JPanel(new BorderLayout);
+ filtersPanel.setBorder(BorderFactory.createTitledBorder("Filters"))
+
+ // Fill Combo Box for Strategies
+ for (ft <- FilterStrategy.values)
+ cbFilterStrategies.addItem(ft)
+
+ /* Filter Actions panel */
+ val filterActionsPanel = new JPanel
+ filterActionsPanel.add(new JLabel("Strategy"))
+ filterActionsPanel.add(cbFilterStrategies)
+ filterActionsPanel.add(btnFiltersAdd)
+ filterActionsPanel.add(btnFiltersDel)
+ filterActionsPanel.add(btnClear)
+
+ /* Adding panels to filterPanel */
+ filtersPanel.add(tblFilters, BorderLayout.CENTER)
+ filtersPanel.add(filterActionsPanel, BorderLayout.SOUTH)
+
+ /* Adding panels to bottomPanel */
+ pnlCenter.add(simulationConfigPanel, BorderLayout.NORTH)
+ pnlCenter.add(outputPanel, BorderLayout.CENTER)
+ pnlCenter.add(filtersPanel, BorderLayout.SOUTH)
+
+ /* Adding panel to Frame */
+ add(pnlCenter, BorderLayout.CENTER)
+ }
+
+ private def initBottomPanel {
+ /***** Creating Bottom Panel (Filters) *****/
+ pnlBottom = new JPanel
+ pnlBottom.setLayout(new BorderLayout)
+
+ /* Start Action Panel */
+ val startActionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT))
+ startActionPanel.add(chkSavePref)
+ startActionPanel.add(btnStart)
+
+ chkSavePref.setHorizontalTextPosition(SwingConstants.LEFT);
+
+ pnlBottom.add(startActionPanel, BorderLayout.SOUTH);
+
+ /* Adding panel to Frame */
+ add(pnlBottom, BorderLayout.SOUTH)
+ }
+
+ private def setListeners {
+ // Enables or disables filter edition depending on the selected strategy
+ cbFilterStrategies.addItemListener { e: ItemEvent =>
+ if (e.getStateChange == ItemEvent.SELECTED && e.getItem == FilterStrategy.NONE) {
+ tblFilters.setEnabled(false)
+ tblFilters.setFocusable(false)
+ } else {
+ tblFilters.setEnabled(true)
+ tblFilters.setFocusable(true)
+ }
+ }
+
+ // Adds a filter row when + button clicked
+ btnFiltersAdd.addActionListener { e: ActionEvent => tblFilters.addRow }
+
+ // Removes selected filter when - button clicked
+ btnFiltersDel.addActionListener { e: ActionEvent => tblFilters.removeSelectedRow }
+
+ // Removes all filters when clear button clicked
+ btnClear.addActionListener { e: ActionEvent => tblFilters.removeAllElements }
+
+ // Opens a save dialog when Browse button clicked
+ btnOutputFolder.addActionListener { e: ActionEvent =>
+
+ var chosenDirPath: String = null
+
+ if (IS_MAC_OSX) {
+ fileDialog.setVisible(true)
+
+ if (fileDialog.getDirectory == null)
+ return
+
+ chosenDirPath = fileDialog.getDirectory + fileDialog.getFile
+
+ } else {
+ if (fileChooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION)
+ return
+
+ chosenDirPath = fileChooser.getSelectedFile.getPath
+ }
+
+ txtOutputFolder.setText(chosenDirPath)
+ }
+
+ // Validates form when Start button clicked
+ btnStart.addActionListener(new SaveConfigurationListener(controller, this))
+ }
+
+ private def setValidationListeners {
+ txtPort.addKeyListener(intValidator(this, "port"))
+ txtSslPort.addKeyListener(intValidator(this, "sslPort"))
+ txtProxyHost.addKeyListener(proxyHostValidator(this))
+ txtProxyPort.addKeyListener(intValidator(this, "proxyPort"))
+ txtProxySslPort.addKeyListener(intValidator(this, "proxySslPort"))
+ txtOutputFolder.addKeyListener(nonEmptyValidator(this, "outputFolder"))
+ txtSimulationClassName.addKeyListener(nonEmptyValidator(this, "simulationClassName"))
+ }
+
+ def populateItemsFromConfiguration(configuration: Configuration) {
+ txtPort.setText(configuration.port.toString)
+ txtSslPort.setText(configuration.sslPort.toString)
+
+ configuration.proxy.host.map { proxyHost =>
+ txtProxyHost.setText(proxyHost)
+ txtProxyPort.setText(configuration.proxy.port.getOrElse(0).toString)
+ txtProxySslPort.setText(configuration.proxy.sslPort.getOrElse(0).toString)
+ txtProxyUsername.setText(configuration.proxy.getUsername.getOrElse(null))
+ txtProxyPassword.setText(configuration.proxy.getPassword.getOrElse(null))
+ txtProxyPort.setEnabled(true)
+ txtProxySslPort.setEnabled(true)
+ txtProxyUsername.setEnabled(true)
+ txtProxyPassword.setEnabled(true)
+ }
+ configuration.simulationPackage.map(txtSimulationPackage.setText)
+ txtSimulationClassName.setText(configuration.simulationClassName)
+ cbFilterStrategies.setSelectedItem(configuration.filterStrategy)
+ chkFollowRedirect.setSelected(configuration.followRedirect)
+ chkAutomaticReferer.setSelected(configuration.automaticReferer)
+ for (pattern <- configuration.patterns)
+ tblFilters.addRow(pattern)
+ txtOutputFolder.setText(configuration.outputFolder)
+ chkSavePref.setSelected(configuration.saveConfiguration)
+ cbOutputEncoding.setSelectedItem(Charset.forName(configuration.encoding))
+ }
}
View
16 gatling-recorder/src/main/scala/com/excilys/ebi/gatling/recorder/ui/frame/RunningFrame.scala
@@ -123,7 +123,7 @@ class RunningFrame(controller: RecorderController) extends JFrame with ScalaSwin
private def setListeners {
/* Listeners */
- btnTag.addActionListener((e: ActionEvent) => {
+ btnTag.addActionListener { e: ActionEvent =>
if (!txtTag.getText.isEmpty) {
val tag = new TagInfo(txtTag.getText)
eventsInfo.addElement(tag)
@@ -131,9 +131,9 @@ class RunningFrame(controller: RecorderController) extends JFrame with ScalaSwin
eventsInfoJList.ensureIndexIsVisible(eventsInfo.getSize() - 1)
txtTag.clear
}
- })
+ }
- eventsInfoJList.addListSelectionListener((e: ListSelectionEvent) => {
+ eventsInfoJList.addListSelectionListener { e: ListSelectionEvent =>
if (eventsInfoJList.getSelectedIndex() >= 0) {
val obj = eventsInfo.get(eventsInfoJList.getSelectedIndex());
if (obj.isInstanceOf[RequestInfo]) {
@@ -158,16 +158,16 @@ class RunningFrame(controller: RecorderController) extends JFrame with ScalaSwin
responseBodyInfo.clear
}
}
- })
+ }
- btnClear.addActionListener((e: ActionEvent) => controller.clearRecorderState)
+ btnClear.addActionListener { e: ActionEvent => controller.clearRecorderState }
- btnCancel.addActionListener((e: ActionEvent) => {
+ btnCancel.addActionListener { e: ActionEvent =>
controller.clearRecorderState
controller.stopRecording
- })
+ }
- btnStop.addActionListener((e: ActionEvent) => controller.stopRecording)
+ btnStop.addActionListener { e: ActionEvent => controller.stopRecording }
}
def clearState {
Please sign in to comment.
Something went wrong with that request. Please try again.