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

org.scaladebugger.api.lowlevel.watchpoints.StandardAccessWatchpointManager.scala Maven / Gradle / Ivy

package org.scaladebugger.api.lowlevel.watchpoints

import com.sun.jdi.request.{AccessWatchpointRequest, EventRequestManager}
import org.scaladebugger.api.lowlevel.classes.ClassManager
import org.scaladebugger.api.lowlevel.requests.JDIRequestArgument
import org.scaladebugger.api.lowlevel.requests.properties.{SuspendPolicyProperty, EnabledProperty}
import org.scaladebugger.api.utils.{MultiMap, Logging}

import scala.collection.JavaConverters._
import scala.util.{Failure, Try}

/**
 * Represents the manager for access watchpoint requests.
 *
 * @param eventRequestManager The manager used to create access watchpoint
 *                            requests
 * @param classManager The manager used to retrieve information about classes
 *                     and their respective fields
 */
class StandardAccessWatchpointManager(
  private val eventRequestManager: EventRequestManager,
  private val classManager: ClassManager
) extends AccessWatchpointManager with Logging {
  import org.scaladebugger.api.lowlevel.requests.Implicits._

  private val accessWatchpointRequests =
    new MultiMap[AccessWatchpointRequestInfo, AccessWatchpointRequest]

  /**
   * Retrieves the list of access watchpoints contained by this manager.
   *
   * @return The collection of access watchpoint request information
   */
  override def accessWatchpointRequestList: Seq[AccessWatchpointRequestInfo] =
    accessWatchpointRequests.keys

  /**
   * Retrieves the list of access watchpoints contained by this manager.
   *
   * @return The collection of access watchpoints by id
   */
  override def accessWatchpointRequestListById: Seq[String] =
    accessWatchpointRequests.ids

  /**
   * Creates a new access watchpoint request for the specified field using the
   * field's name.
   *
   * @param requestId The id of the request used to retrieve and delete it
   * @param className The name of the class containing the field
   * @param fieldName The name of the field to watch
   * @param extraArguments Any additional arguments to provide to the request
   * @return Success(id) if successful, otherwise Failure
   */
  override def createAccessWatchpointRequestWithId(
    requestId: String,
    className: String,
    fieldName: String,
    extraArguments: JDIRequestArgument*
  ): Try[String] = {
    val fields = classManager.fieldsWithName(className, fieldName)

    if (fields.isEmpty) return Failure(NoFieldFound(className, fieldName))

    val request = Try(eventRequestManager.createAccessWatchpointRequest(
      fields.head,
      Seq(
        EnabledProperty(value = true),
        SuspendPolicyProperty.EventThread
      ) ++ extraArguments: _*
    ))

    if (request.isSuccess) {
      val l = s"$className.$fieldName"
      val i = requestId
      logger.trace(s"Created access watchpoint request for $l with id '$i'")
      accessWatchpointRequests.putWithId(
        requestId,
        AccessWatchpointRequestInfo(
          requestId,
          isPending = false,
          className,
          fieldName,
          extraArguments
        ),
        request.get
      )
    }

    // If no exception was thrown, assume that we succeeded
    request.map(_ => requestId)
  }

  /**
   * Determines if a access watchpoint request with the specified field.
   *
   * @param className The name of the class containing the field
   * @param fieldName The name of the field to watch
   * @return True if a access watchpoint request with the id exists,
   *         otherwise false
   */
  override def hasAccessWatchpointRequest(
    className: String,
    fieldName: String
  ): Boolean = {
    accessWatchpointRequests.hasWithKeyPredicate(w =>
      w.className == className && w.fieldName == fieldName
    )
  }

  /**
   * Determines if a access watchpoint request with the specified id.
   *
   * @param id The id of the Access Watchpoint Request
   * @return True if a access watchpoint request with the id exists,
   *         otherwise false
   */
  override def hasAccessWatchpointRequestWithId(id: String): Boolean = {
    accessWatchpointRequests.hasWithId(id)
  }

  /**
   * Returns the collection of access watchpoint requests representing the
   * access watchpoint for the specified field.
   *
   * @param className The name of the class containing the field
   * @param fieldName The name of the field to watch
   * @return Some collection of access watchpoints for the field, or None if
   *         the specified field has no access watchpoints
   */
  override def getAccessWatchpointRequest(
    className: String,
    fieldName: String
  ): Option[Seq[AccessWatchpointRequest]] = {
    val requests = accessWatchpointRequests.getWithKeyPredicate(w =>
      w.className == className && w.fieldName == fieldName
    )

    if (requests.nonEmpty) Some(requests) else None
  }

  /**
   * Retrieves the access watchpoint request using the specified id.
   *
   * @param id The id of the Access Watchpoint Request
   * @return Some access watchpoint request if it exists, otherwise None
   */
  override def getAccessWatchpointRequestWithId(
    id: String
  ): Option[AccessWatchpointRequest] = {
    accessWatchpointRequests.getWithId(id)
  }

  /**
   * Returns the information for an access watchpoint request with the
   * specified id.
   *
   * @param requestId The id of the request
   * @return Some access watchpoint information if found, otherwise None
   */
  override def getAccessWatchpointRequestInfoWithId(
    requestId: String
  ): Option[AccessWatchpointRequestInfo] = {
    accessWatchpointRequestList.find(_.requestId == requestId)
  }

  /**
   * Removes the access watchpoint for the specified field.
   *
   * @param className The name of the class containing the field
   * @param fieldName The name of the field to watch
   * @return True if successfully removed access watchpoint, otherwise false
   */
  override def removeAccessWatchpointRequest(
    className: String,
    fieldName: String
  ): Boolean = {
    val ids = accessWatchpointRequests.getIdsWithKeyPredicate(w =>
      w.className == className && w.fieldName == fieldName
    )

    ids.nonEmpty && ids.forall(removeAccessWatchpointRequestWithId)
  }

  /**
   * Removes the access watchpoint request with the specified id.
   *
   * @param id The id of the Access Watchpoint Request
   * @return True if the access watchpoint request was removed (if it existed),
   *         otherwise false
   */
  override def removeAccessWatchpointRequestWithId(id: String): Boolean = {
    val request = accessWatchpointRequests.removeWithId(id)

    request.foreach(eventRequestManager.deleteEventRequest)

    request.nonEmpty
  }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy