From ec40a184c75a1801802e47f14efb3e96e4a57ba3 Mon Sep 17 00:00:00 2001 From: David Maus <maus@hab.de> Date: Wed, 22 May 2013 12:47:31 +0200 Subject: [PATCH] Implement SOLR 3.x error listener --- .../VuFind/Search/Solr/V3/ErrorListener.php | 90 ++++++++++++++ .../response/solr/solr3-alphabrowse-error | 93 +++++++++++++++ .../fixtures/response/solr/solr3-parse-error | 77 ++++++++++++ .../response/solr/solr3-undefined-field-error | 33 ++++++ .../src/Search/Solr/V3/ErrorListenerTest.php | 110 ++++++++++++++++++ 5 files changed, 403 insertions(+) create mode 100644 module/VuFind/src/VuFind/Search/Solr/V3/ErrorListener.php create mode 100644 module/VuFind/tests/fixtures/response/solr/solr3-alphabrowse-error create mode 100644 module/VuFind/tests/fixtures/response/solr/solr3-parse-error create mode 100644 module/VuFind/tests/fixtures/response/solr/solr3-undefined-field-error create mode 100644 module/VuFind/tests/unit-tests/src/Search/Solr/V3/ErrorListenerTest.php diff --git a/module/VuFind/src/VuFind/Search/Solr/V3/ErrorListener.php b/module/VuFind/src/VuFind/Search/Solr/V3/ErrorListener.php new file mode 100644 index 00000000000..ae97c12d679 --- /dev/null +++ b/module/VuFind/src/VuFind/Search/Solr/V3/ErrorListener.php @@ -0,0 +1,90 @@ +<?php + +/** + * SOLR 3.x error listener. + * + * PHP version 5 + * + * Copyright (C) Villanova University 2013. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category VuFind2 + * @package Search + * @author David Maus <maus@hab.de> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org Main Site + */ + +namespace VuFind\Search\Solr\V3; + +use VuFindSearch\Backend\Exception\BackendException; + +use Zend\EventManager\EventInterface; + +/** + * SOLR 3.x error listener. + * + * @category VuFind2 + * @package Search + * @author David Maus <maus@hab.de> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org Main Site + */ +class ErrorListener +{ + + /** + * Backends ot listen on. + * + * @var array + */ + protected $backends; + + /** + * Constructor. + * + * @param array $backends Name of backends to listen on + * + * @return void + */ + public function __construct(array $backends) + { + $this->backends = $backends; + } + + /** + * VuFindSearch.error + * + * @param EventInterface $event Event + * + * @return EventInterface + */ + public function onSearchError(EventInterface $event) + { + $backend = $event->getParam('backend'); + if (in_array($backend, $this->backends)) { + $error = $event->getTarget(); + if ($error instanceOf BackendException) { + $reason = $error->getResponse()->getReasonPhrase(); + if (stristr($error, 'org.apache.lucene.queryParser.ParseException') + || stristr($error, 'undefined field') + ) { + $error->addTag('VuFind\Search\ParserError'); + } + } + } + return $event; + } +} \ No newline at end of file diff --git a/module/VuFind/tests/fixtures/response/solr/solr3-alphabrowse-error b/module/VuFind/tests/fixtures/response/solr/solr3-alphabrowse-error new file mode 100644 index 00000000000..f5402ef94e9 --- /dev/null +++ b/module/VuFind/tests/fixtures/response/solr/solr3-alphabrowse-error @@ -0,0 +1,93 @@ +HTTP/1.1 Error 500 I couldn't find a browse index +Date: Wed, 22 May 2013 10:08:23 GMT +Content-Type: text/html + +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>Error 500 I couldn't find a browse index at: /home/dkatz/vufind3/solr/alphabetical_browse/author_browse.db. +Maybe you need to create your browse indexes? + +java.lang.Exception: I couldn't find a browse index at: /home/dkatz/vufind3/solr/alphabetical_browse/author_browse.db. +Maybe you need to create your browse indexes? + at au.gov.nla.solr.handler.HeadingsDB.openDB(BrowseRequestHandler.java:72) + at au.gov.nla.solr.handler.HeadingsDB.reopenIfUpdated(BrowseRequestHandler.java:127) + at au.gov.nla.solr.handler.Browse.reopenDatabasesIfUpdated(BrowseRequestHandler.java:553) + at au.gov.nla.solr.handler.BrowseRequestHandler.handleRequestBody(BrowseRequestHandler.java:752) + at org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:129) + at org.apache.solr.core.SolrCore.execute(SolrCore.java:1372) + at org.apache.solr.servlet.SolrDispatchFilter.execute(SolrDispatchFilter.java:356) + at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:252) + at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088) + at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360) + at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) + at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181) + at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729) + at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405) + at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206) + at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114) + at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) + at org.mortbay.jetty.Server.handle(Server.java:324) + at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505) + at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829) + at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513) + at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211) + at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380) + at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395) + at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488) +</title> +</head> +<body><h2>HTTP ERROR: 500</h2><pre>I couldn't find a browse index at: /home/dkatz/vufind3/solr/alphabetical_browse/author_browse.db. +Maybe you need to create your browse indexes? + +java.lang.Exception: I couldn't find a browse index at: /home/dkatz/vufind3/solr/alphabetical_browse/author_browse.db. +Maybe you need to create your browse indexes? + at au.gov.nla.solr.handler.HeadingsDB.openDB(BrowseRequestHandler.java:72) + at au.gov.nla.solr.handler.HeadingsDB.reopenIfUpdated(BrowseRequestHandler.java:127) + at au.gov.nla.solr.handler.Browse.reopenDatabasesIfUpdated(BrowseRequestHandler.java:553) + at au.gov.nla.solr.handler.BrowseRequestHandler.handleRequestBody(BrowseRequestHandler.java:752) + at org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:129) + at org.apache.solr.core.SolrCore.execute(SolrCore.java:1372) + at org.apache.solr.servlet.SolrDispatchFilter.execute(SolrDispatchFilter.java:356) + at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:252) + at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1088) + at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360) + at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) + at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181) + at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729) + at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405) + at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206) + at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114) + at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) + at org.mortbay.jetty.Server.handle(Server.java:324) + at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505) + at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829) + at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513) + at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211) + at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380) + at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395) + at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488) +</pre> +<p>RequestURI=/solr/biblio/browse</p><p><i><small><a href="http://jetty.mortbay.org/">Powered by Jetty://</a></small></i></p><br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> + +</body> +</html> diff --git a/module/VuFind/tests/fixtures/response/solr/solr3-parse-error b/module/VuFind/tests/fixtures/response/solr/solr3-parse-error new file mode 100644 index 00000000000..e2d465743d1 --- /dev/null +++ b/module/VuFind/tests/fixtures/response/solr/solr3-parse-error @@ -0,0 +1,77 @@ +HTTP/1.1 400 org.apache.lucene.queryParser.ParseException +Date: Wed, 22 May 2013 10:08:23 GMT +Content-Type: text/html + +<html><head> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> +<title>Error 400 org.apache.lucene.queryParser.ParseException: Cannot +parse '((title_short:("~~~")^750 OR title_full_unstemmed:("~~~")^600 +OR title_full_unstemmed:(~~~)^500 OR title_full:("~~~")^400 OR +title:("~~~")^300 OR title:(~~~)^250 OR title_alt:(~~~)^200 OR +title_new:(~~~)^100)^50 OR series:(~~~)^50 OR series2:(~~~)^30 OR +author:("~~~")^300 OR author:(~~~)^250 OR author_fuller:("~~~")^150 OR +author_fuller:(~~~)^125 OR author2:(~~~)^50 OR +author_additional:(~~~)^50 OR contents:(~~~)^10 OR +topic_unstemmed:("~~~")^550 OR topic_unstemmed:(~~~)^500 OR +topic:("~~~")^500 OR geographic:("~~~")^300 OR genre:("~~~")^300 OR +allfields_unstemmed:(~~~)^10 OR fulltext_unstemmed:(~~~)^10 OR +allfields:(~~~) OR fulltext:(~~~))': Encountered " <FUZZY_SLOP> "~ + "" at line 1, column 91. +Was expecting one of: + <NOT> ... + "+" ... + "-" ... + "(" ... + "*" ... + <QUOTED> ... + <TERM> ... + <PREFIXTERM> ... + <WILDTERM> ... + "[" ... + "{" ... + <NUMBER> ... + <TERM> ... + "*" ... + </title> +</head> +<body><h2>HTTP ERROR: 400</h2><pre>org.apache.lucene.queryParser.ParseException: Cannot parse '((title_short:("~~~")^750 OR title_full_unstemmed:("~~~")^600 OR title_full_unstemmed:(~~~)^500 OR title_full:("~~~")^400 OR title:("~~~")^300 OR title:(~~~)^250 OR title_alt:(~~~)^200 OR title_new:(~~~)^100)^50 OR series:(~~~)^50 OR series2:(~~~)^30 OR author:("~~~")^300 OR author:(~~~)^250 OR author_fuller:("~~~")^150 OR author_fuller:(~~~)^125 OR author2:(~~~)^50 OR author_additional:(~~~)^50 OR contents:(~~~)^10 OR topic_unstemmed:("~~~")^550 OR topic_unstemmed:(~~~)^500 OR topic:("~~~")^500 OR geographic:("~~~")^300 OR genre:("~~~")^300 OR allfields_unstemmed:(~~~)^10 OR fulltext_unstemmed:(~~~)^10 OR allfields:(~~~) OR fulltext:(~~~))': Encountered " <FUZZY_SLOP> "~ "" at line 1, column 91. +Was expecting one of: + <NOT> ... + "+" ... + "-" ... + "(" ... + "*" ... + <QUOTED> ... + <TERM> ... + <PREFIXTERM> ... + <WILDTERM> ... + "[" ... + "{" ... + <NUMBER> ... + <TERM> ... + "*" ... + </pre> +<p>RequestURI=/solr/biblio/select</p><p><i><small><a href="http://jetty.mortbay.org/">Powered by Jetty://</a></small></i></p><br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> +<br> + + + +</body></html> diff --git a/module/VuFind/tests/fixtures/response/solr/solr3-undefined-field-error b/module/VuFind/tests/fixtures/response/solr/solr3-undefined-field-error new file mode 100644 index 00000000000..6d0614956dc --- /dev/null +++ b/module/VuFind/tests/fixtures/response/solr/solr3-undefined-field-error @@ -0,0 +1,33 @@ +HTTP/1.1 400 undefined field test +Date: Wed, 22 May 2013 10:08:23 GMT +Content-Type: text/html + +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>Error 400 undefined field test</title> +</head> +<body><h2>HTTP ERROR: 400</h2><pre>undefined field test</pre> +<p>RequestURI=/solr/biblio/select</p><p><i><small><a href="http://jetty.mortbay.org/">Powered by Jetty://</a></small></i></p><br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> +<br/> + +</body> +</html> diff --git a/module/VuFind/tests/unit-tests/src/Search/Solr/V3/ErrorListenerTest.php b/module/VuFind/tests/unit-tests/src/Search/Solr/V3/ErrorListenerTest.php new file mode 100644 index 00000000000..dfe867b0af5 --- /dev/null +++ b/module/VuFind/tests/unit-tests/src/Search/Solr/V3/ErrorListenerTest.php @@ -0,0 +1,110 @@ +<?php + +/** + * Unit tests for SOLR 3.x error listener. + * + * PHP version 5 + * + * Copyright (C) Villanova University 2013. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category VuFind2 + * @package Search + * @author David Maus <maus@hab.de> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org Main Site + */ + +namespace VuFindTest\Search\Solr\V3; + +use VuFind\Search\Solr\V3\ErrorListener; + +use VuFindSearch\Backend\Exception\BackendException; + +use Zend\EventManager\Event; +use Zend\Http\Response; + +use PHPUnit_Framework_TestCase as TestCase; + +use RuntimeException; + +/** + * Unit tests for SOLR 3.x error listener. + * + * @category VuFind2 + * @package Search + * @author David Maus <maus@hab.de> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org Main Site + */ +class ErrorListenerTest extends TestCase +{ + /** + * Detect parser error response. + * + * @return void + */ + public function testDetectParseError() + { + $response = $this->createResponse('solr3-parse-error'); + + $exception = BackendException::createFromResponse($response); + $params = array('backend' => 'test'); + $event = new Event(null, $exception, $params); + $listener = new ErrorListener(array('test')); + $listener->onSearchError($event); + $this->assertTrue($exception->hasTag('VuFind\Search\ParserError')); + } + + /** + * Detect parser error response. + * + * @return void + */ + public function testDetectUndefinedFieldError() + { + $response = $this->createResponse('solr3-undefined-field-error'); + + $exception = BackendException::createFromResponse($response); + $params = array('backend' => 'test'); + $event = new Event(null, $exception, $params); + $listener = new ErrorListener(array('test')); + $listener->onSearchError($event); + $this->assertTrue($exception->hasTag('VuFind\Search\ParserError')); + } + + /// Internal API + + /** + * Return response fixture + * + * @param string $name Name of fixture + * + * @return Response Response + */ + protected function createResponse($name) + { + $file = realpath( + \VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/response/solr/' . $name + ); + if (!$file) { + throw new RuntimeException( + sprintf('Unable to resolve fixture to fixture file: %s', $name) + ); + } + $response = Response::fromString(file_get_contents($file)); + return $response; + } +} \ No newline at end of file -- GitLab