/**
* Handles errors caused by singleRequest and multiRequest
*
* For transport level errors, tries to figure out what went wrong to
* throw the most appropriate exception.
*
* @param curl $curl
* @param string $response the response body
* @param int $httpCode the http response code
*
* @throws NoSuchWorkspaceException if it was not possible to reach the server (resolve host or connect)
* @throws ItemNotFoundException if the object was not found
* @throws RepositoryException on any other error.
* @throws PathNotFoundException if the path was not found (server returned 404 without xml response)
*/
protected function handleError(curl $curl, $response, $httpCode)
{
// first: check if the backend is too old for us
if (!self::$versionChecked) {
// avoid endless loops.
self::$versionChecked = true;
try {
// getting the descriptors triggers a version check
$this->client->getRepositoryDescriptors();
} catch (\Exception $e) {
if ($e instanceof \PHPCR\UnsupportedRepositoryOperationException) {
throw $e;
}
//otherwise ignore exception here as to not confuse what happened
}
}
switch ($curl->errno()) {
case CURLE_COULDNT_RESOLVE_HOST:
case CURLE_COULDNT_CONNECT:
$info = $curl->getinfo();
throw new NoSuchWorkspaceException($curl->error() . ' "' . $info['url'] . '"');
case CURLE_RECV_ERROR:
throw new RepositoryException(sprintf('CURLE_RECV_ERROR (errno 56) encountered. This has been known to happen intermittently with ' . 'some versions of libcurl (see https://github.com/jackalope/jackalope-jackrabbit/issues/89). ' . 'You can use the "jackalope.jackrabbit_force_http_version_10" option to force HTTP 1.0 as a workaround'));
}
// use XML error response if it's there
if (substr($response, 0, 2) === '<?') {
$dom = new DOMDocument();
$dom->loadXML($response);
$err = $dom->getElementsByTagNameNS(Client::NS_DCR, 'exception');
if ($err->length > 0) {
$err = $err->item(0);
$errClass = $err->getElementsByTagNameNS(Client::NS_DCR, 'class')->item(0)->textContent;
$errMsg = $err->getElementsByTagNameNS(Client::NS_DCR, 'message')->item(0)->textContent;
$exceptionMsg = 'HTTP ' . $httpCode . ': ' . $errMsg;
switch ($errClass) {
case 'javax.jcr.NoSuchWorkspaceException':
throw new NoSuchWorkspaceException($exceptionMsg);
case 'javax.jcr.nodetype.NoSuchNodeTypeException':
throw new NoSuchNodeTypeException($exceptionMsg);
case 'javax.jcr.ItemNotFoundException':
throw new ItemNotFoundException($exceptionMsg);
case 'javax.jcr.nodetype.ConstraintViolationException':
throw new ConstraintViolationException($exceptionMsg);
case 'javax.jcr.ReferentialIntegrityException':
throw new ReferentialIntegrityException($exceptionMsg);
//TODO: Two more errors needed for Transactions. How does the corresponding Jackrabbit response look like?
// javax.transaction.RollbackException => \PHPCR\Transaction\RollbackException
// java.lang.SecurityException => \PHPCR\AccessDeniedException
//TODO: map more errors here?
//TODO: Two more errors needed for Transactions. How does the corresponding Jackrabbit response look like?
// javax.transaction.RollbackException => \PHPCR\Transaction\RollbackException
// java.lang.SecurityException => \PHPCR\AccessDeniedException
//TODO: map more errors here?
default:
// try to generically "guess" the right exception class name
$class = substr($errClass, strlen('javax.jcr.'));
$class = explode('.', $class);
array_walk($class, function (&$ns) {
$ns = ucfirst(str_replace('nodetype', 'NodeType', $ns));
});
$class = '\\PHPCR\\' . implode('\\', $class);
if (class_exists($class)) {
throw new $class($exceptionMsg);
}
throw new RepositoryException($exceptionMsg . " ({$errClass})");
}
}
}
if (401 == $httpCode) {
throw new LoginException("HTTP 401 Unauthorized\n" . $this->getShortErrorString());
}
if (404 == $httpCode) {
throw new PathNotFoundException("HTTP 404 Path Not Found: {$this->method} \n" . $this->getShortErrorString());
}
if (405 == $httpCode) {
throw new HTTPErrorException("HTTP 405 Method Not Allowed: {$this->method} \n" . $this->getShortErrorString(), 405);
}
if (412 == $httpCode) {
throw new LockException("Unable to lock the non-lockable node '" . reset($this->uri) . "\n" . $this->getShortErrorString());
}
if ($httpCode >= 500) {
$msg = "HTTP {$httpCode} Error from backend on: {$this->method} \n" . $this->getLongErrorString($curl, $response);
try {
$workspaceUri = array($this->client->getWorkSpaceUri());
if (!$this->errorHandlingMode && ($workspaceUri !== $this->uri || self::GET !== $this->method)) {
$this->errorHandlingMode = true;
$this->setUri($workspaceUri);
$this->setMethod(self::GET);
$this->executeDom();
}
} catch (PathNotFoundException $e) {
$msg = "Error likely caused by incorrect server URL configuration '" . reset($this->uri) . "' resulted in:\n{$msg}";
}
$this->errorHandlingMode = false;
throw new RepositoryException($msg);
}
$curlError = $curl->error();
$msg = "Unexpected error: \nCURL Error: {$curlError} \nResponse (HTTP {$httpCode}): {$this->method} \n" . $this->getLongErrorString($curl, $response);
throw new RepositoryException($msg);
}