<commit_before>package com.ldaniels528.trifecta.web

import java.io.ByteArrayOutputStream

import akka.actor.{Actor, ActorSystem, Props}
import com.ldaniels528.trifecta.util.Resource
import com.ldaniels528.trifecta.util.ResourceHelper._
import com.ldaniels528.trifecta.util.StringHelper._
import com.ldaniels528.trifecta.web.EmbeddedWebServer._
import com.typesafe.config.ConfigFactory
import org.apache.commons.io.IOUtils
import org.mashupbots.socko.events.{HttpRequestEvent, HttpResponseStatus}
import org.mashupbots.socko.infrastructure.Logger
import org.mashupbots.socko.routes.{GET, Routes}
import org.mashupbots.socko.webserver.{WebServer, WebServerConfig}
import org.slf4j.LoggerFactory

import scala.util.Try

/**
 * Embedded Web Server
 * @author <NAME> <<EMAIL>>
 */
class EmbeddedWebServer() extends Logger {
  private val actorSystem = ActorSystem("EmbeddedWebServer", ConfigFactory.parseString(actorConfig))
  private var webServer: Option[WebServer] = None

  Runtime.getRuntime.addShutdownHook(new Thread {
    override def run() = EmbeddedWebServer.this.stop()
  })

  val routes = Routes({
    case GET(request) =>
      actorSystem.actorOf(Props[WebContentHandler]) ! request
  })

  /**
   * Starts the embedded app server
   */
  def start() {
    if (webServer.isEmpty) {
      webServer = Option(new WebServer(WebServerConfig(), routes, actorSystem))
      webServer.foreach(_.start())
    }
  }

  /**
   * Stops the embedded app server
   */
  def stop() {
    Try(webServer.foreach(_.stop()))
    webServer = None
  }

}

/**
 * Embedded Web Server Singleton
 * @author <NAME> <<EMAIL>>
 */
object EmbeddedWebServer {
  private val logger = LoggerFactory.getLogger(getClass)
  private val actorConfig = """
      my-pinned-dispatcher {
        type=PinnedDispatcher
        executor=thread-pool-executor
      }
      akka {
        event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
        loglevel=DEBUG
        actor {
          deployment {
            /static-file-router {
              router = round-robin
              nr-of-instances = 5
            }
            /file-upload-router {
              router = round-robin
              nr-of-instances = 5
            }
          }
        }
      }"""

  /**
   * Application entry point
   * @param args the given command line arguments
   */
  def main(args: Array[String]) {
    new EmbeddedWebServer().start()

    logger.info("Open your browser and navigate to http://localhost:8888")
  }

  /**
   * Web Content Handler
   * @author <NAME> <<EMAIL>>
   */
  class WebContentHandler extends Actor {
    def receive = {
      case event: HttpRequestEvent =>
        val endPoint = event.request.endPoint
        val response = event.response
        val path = translatePath(endPoint.path)

        path match {
          case s => loadContent(s) map { bytes =>
            getMimeType(s) foreach (response.contentType = _)
            response.write(bytes)
          } getOrElse {
            logger.error(s"Resource '$path' not found")
            response.write(HttpResponseStatus.NOT_FOUND)
          }
        }
        context.stop(self)
    }

    /**
     * Returns the MIME type for the given resource
     * @param path the given resource path (e.g. "/images/greenLight.png")
     * @return the option of a MIME type (e.g. "image/png")
     */
    private def getMimeType(path: String): Option[String] = {
      path.lastIndexOptionOf(".") map (index => path.substring(index + 1)) flatMap {
        case "gif" => Some("image/gif")
        case "htm" | "html" => Some("text/html")
        case "jpg" | "jpeg" => Some("image/jpeg")
        case "js" => Some("text/javascript")
        case "png" => Some("image/png")
        case unknown =>
          logger.warn(s"No MIME type for $unknown")
          None
      }
    }<commit_msg>added additional MIME types<commit_after>package com.ldaniels528.trifecta.web

import java.io.ByteArrayOutputStream

import akka.actor.{Actor, ActorSystem, Props}
import com.ldaniels528.trifecta.util.Resource
import com.ldaniels528.trifecta.util.ResourceHelper._
import com.ldaniels528.trifecta.util.StringHelper._
import com.ldaniels528.trifecta.web.EmbeddedWebServer._
import com.typesafe.config.ConfigFactory
import org.apache.commons.io.IOUtils
import org.mashupbots.socko.events.{HttpRequestEvent, HttpResponseStatus}
import org.mashupbots.socko.infrastructure.Logger
import org.mashupbots.socko.routes.{GET, Routes}
import org.mashupbots.socko.webserver.{WebServer, WebServerConfig}
import org.slf4j.LoggerFactory

import scala.util.Try

/**
 * Embedded Web Server
 * @author <NAME> <<EMAIL>>
 */
class EmbeddedWebServer() extends Logger {
  private val actorSystem = ActorSystem("EmbeddedWebServer", ConfigFactory.parseString(actorConfig))
  private var webServer: Option[WebServer] = None

  Runtime.getRuntime.addShutdownHook(new Thread {
    override def run() = EmbeddedWebServer.this.stop()
  })

  val routes = Routes({
    case GET(request) =>
      actorSystem.actorOf(Props[WebContentHandler]) ! request
  })

  /**
   * Starts the embedded app server
   */
  def start() {
    if (webServer.isEmpty) {
      webServer = Option(new WebServer(WebServerConfig(), routes, actorSystem))
      webServer.foreach(_.start())
    }
  }

  /**
   * Stops the embedded app server
   */
  def stop() {
    Try(webServer.foreach(_.stop()))
    webServer = None
  }

}

/**
 * Embedded Web Server Singleton
 * @author <NAME> <<EMAIL>>
 */
object EmbeddedWebServer {
  private val logger = LoggerFactory.getLogger(getClass)
  private val actorConfig = """
      my-pinned-dispatcher {
        type=PinnedDispatcher
        executor=thread-pool-executor
      }
      akka {
        event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
        loglevel=DEBUG
        actor {
          deployment {
            /static-file-router {
              router = round-robin
              nr-of-instances = 5
            }
            /file-upload-router {
              router = round-robin
              nr-of-instances = 5
            }
          }
        }
      }"""

  /**
   * Application entry point
   * @param args the given command line arguments
   */
  def main(args: Array[String]) {
    new EmbeddedWebServer().start()

    logger.info("Open your browser and navigate to http://localhost:8888")
  }

  /**
   * Web Content Handler
   * @author <NAME> <<EMAIL>>
   */
  class WebContentHandler extends Actor {
    def receive = {
      case event: HttpRequestEvent =>
        val endPoint = event.request.endPoint
        val response = event.response
        val path = translatePath(endPoint.path)

        path match {
          case s => loadContent(s) map { bytes =>
            getMimeType(s) foreach (response.contentType = _)
            response.write(bytes)
          } getOrElse {
            logger.error(s"Resource '$path' not found")
            response.write(HttpResponseStatus.NOT_FOUND)
          }
        }
        context.stop(self)
    }

    /**
     * Returns the MIME type for the given resource
     * @param path the given resource path (e.g. "/images/greenLight.png")
     * @return the option of a MIME type (e.g. "image/png")
     */
    private def getMimeType(path: String): Option[String] = {
      path.lastIndexOptionOf(".") map (index => path.substring(index + 1)) flatMap {
        case "css" => Some("text/css")
        case "gif" => Some("image/gif")
        case "htm" | "html" => Some("text/html")
        case "jpg" | "jpeg" => Some("image/jpeg")
        case "js" => Some("text/javascript")
        case "json" => Some("application/json")
        case "png" => Some("image/png")
        case "xml" => Some("application/xml")
        case unknown =>
          logger.warn(s"No MIME type found for '$unknown' ($path)")
          None
      }
    }
{'fraction_non_alphanumeric': 0.1194639438417358, 'fraction_numerical': 0.006381620931716656, 'mean_word_length': 2.5829903978052124, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5107792', 'n_tokens_mistral': 2451, 'n_tokens_neox': 2389, 'n_words': 520}