From 7fae4b5f8c3775c7e48901799cb51dd2661d193e Mon Sep 17 00:00:00 2001 From: Patrick Schmitz Date: Fri, 17 Sep 2010 20:55:22 +0000 Subject: [PATCH] CSPACE-2021 - Updated to use more recent version of the RestEasy, that fixes a problem encoding non-latin1 Unicode chars as parameters. This caused search tests to pass unicode search terms and terms with punctuation incorrectly. Changed the handling of partial-term and keyword search to properly escape punctuation, allowing for search on names like O'Hara. Added beginnings of logic to support search on partial-keyword (keywords with wildcards) and search on keyword phrases (in quotes). --- .../services/client/AccountClient.java | 3 +- .../services/client/AccountRoleClient.java | 3 +- .../services/client/AcquisitionClient.java | 4 +- .../services/client/PermissionClient.java | 3 +- .../services/client/PermissionRoleClient.java | 3 +- .../services/client/RoleClient.java | 3 +- .../services/client/RolePermissionClient.java | 3 +- .../client/CollectionObjectClient.java | 3 +- .../src/main/config/log/jboss-log4j.xml | 1 + .../services/common/query/IQueryManager.java | 10 + .../services/common/query/QueryManager.java | 13 ++ .../query/nuxeo/QueryManagerNuxeoImpl.java | 98 +++++++-- .../common/vocabulary/AuthorityResource.java | 8 +- .../services/client/ContactClient.java | 3 +- .../services/client/DimensionClient.java | 3 +- .../services/client/IdClient.java | 3 +- .../services/client/IntakeClient.java | 3 +- .../services/client/LoaninClient.java | 3 +- .../services/client/LoanoutClient.java | 3 +- .../client/LocationAuthorityClient.java | 3 +- .../services/client/MovementClient.java | 3 +- .../services/client/NoteClient.java | 3 +- .../services/client/ObjectExitClient.java | 3 +- .../services/client/OrgAuthorityClient.java | 3 +- .../client/PersonAuthorityClient.java | 5 +- .../services/client/PersonAuthorityProxy.java | 5 +- .../test/PersonAuthoritySearchTest.java | 192 ++++++++++++++---- .../test/PersonAuthorityServiceTest.java | 18 +- .../src/test/resources/log4j.properties | 2 + services/pom.xml | 8 +- .../services/client/RelationClient.java | 3 +- .../services/client/ReportClient.java | 3 +- .../services/client/VocabularyClient.java | 4 +- 33 files changed, 333 insertions(+), 95 deletions(-) diff --git a/services/account/client/src/main/java/org/collectionspace/services/client/AccountClient.java b/services/account/client/src/main/java/org/collectionspace/services/client/AccountClient.java index efad64555..8c0b0bd8e 100644 --- a/services/account/client/src/main/java/org/collectionspace/services/client/AccountClient.java +++ b/services/account/client/src/main/java/org/collectionspace/services/client/AccountClient.java @@ -34,6 +34,7 @@ import org.collectionspace.services.account.AccountsCommonList; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.spi.ResteasyProviderFactory; /** @@ -78,7 +79,7 @@ public class AccountClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { accountProxy = ProxyFactory.create(AccountProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { accountProxy = ProxyFactory.create(AccountProxy.class, getBaseURL()); diff --git a/services/account/client/src/main/java/org/collectionspace/services/client/AccountRoleClient.java b/services/account/client/src/main/java/org/collectionspace/services/client/AccountRoleClient.java index 59cb850eb..265c2c1c4 100644 --- a/services/account/client/src/main/java/org/collectionspace/services/client/AccountRoleClient.java +++ b/services/account/client/src/main/java/org/collectionspace/services/client/AccountRoleClient.java @@ -33,6 +33,7 @@ import org.collectionspace.services.authorization.AccountRole; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.spi.ResteasyProviderFactory; /** @@ -76,7 +77,7 @@ public class AccountRoleClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { accountRoleProxy = ProxyFactory.create(AccountRoleProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { accountRoleProxy = ProxyFactory.create(AccountRoleProxy.class, getBaseURL()); diff --git a/services/acquisition/client/src/main/java/org/collectionspace/services/client/AcquisitionClient.java b/services/acquisition/client/src/main/java/org/collectionspace/services/client/AcquisitionClient.java index 4aedd2722..972716418 100644 --- a/services/acquisition/client/src/main/java/org/collectionspace/services/client/AcquisitionClient.java +++ b/services/acquisition/client/src/main/java/org/collectionspace/services/client/AcquisitionClient.java @@ -4,10 +4,10 @@ import javax.ws.rs.core.Response; import org.collectionspace.services.acquisition.AcquisitionsCommonList; import org.collectionspace.services.common.authorityref.AuthorityRefList; -//import org.collectionspace.services.common.context.ServiceContext; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; import org.jboss.resteasy.spi.ResteasyProviderFactory; @@ -57,7 +57,7 @@ public class AcquisitionClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { acquisitionProxy = ProxyFactory.create(AcquisitionProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { acquisitionProxy = ProxyFactory.create(AcquisitionProxy.class, getBaseURL()); diff --git a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionClient.java b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionClient.java index 88b01e92b..7cdf5e2c3 100644 --- a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionClient.java +++ b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionClient.java @@ -34,6 +34,7 @@ import org.collectionspace.services.authorization.PermissionsList; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.spi.ResteasyProviderFactory; /** @@ -77,7 +78,7 @@ public class PermissionClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { permissionProxy = ProxyFactory.create(PermissionProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { permissionProxy = ProxyFactory.create(PermissionProxy.class, getBaseURL()); diff --git a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleClient.java b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleClient.java index 8a56491bf..dd83a6fa6 100644 --- a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleClient.java +++ b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleClient.java @@ -33,6 +33,7 @@ import org.collectionspace.services.authorization.PermissionRole; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.spi.ResteasyProviderFactory; /** @@ -77,7 +78,7 @@ public class PermissionRoleClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { permissionRoleProxy = ProxyFactory.create(PermissionRoleProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { permissionRoleProxy = ProxyFactory.create(PermissionRoleProxy.class, getBaseURL()); diff --git a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/RoleClient.java b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/RoleClient.java index 5514859d7..e57ffa932 100644 --- a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/RoleClient.java +++ b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/RoleClient.java @@ -34,6 +34,7 @@ import org.collectionspace.services.authorization.RolesList; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.spi.ResteasyProviderFactory; /** @@ -77,7 +78,7 @@ public class RoleClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { roleProxy = ProxyFactory.create(RoleProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { roleProxy = ProxyFactory.create(RoleProxy.class, getBaseURL()); diff --git a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/RolePermissionClient.java b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/RolePermissionClient.java index ce1930f75..00bfe0958 100644 --- a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/RolePermissionClient.java +++ b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/RolePermissionClient.java @@ -33,6 +33,7 @@ import org.collectionspace.services.authorization.PermissionRole; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.spi.ResteasyProviderFactory; // TODO: Auto-generated Javadoc @@ -78,7 +79,7 @@ public class RolePermissionClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { rolePermissionProxy = ProxyFactory.create(RolePermissionProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { rolePermissionProxy = ProxyFactory.create(RolePermissionProxy.class, getBaseURL()); diff --git a/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectClient.java b/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectClient.java index 84c576468..d98b520c9 100644 --- a/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectClient.java +++ b/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectClient.java @@ -35,6 +35,7 @@ import org.collectionspace.services.common.authorityref.AuthorityRefList; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; import org.jboss.resteasy.spi.ResteasyProviderFactory; @@ -78,7 +79,7 @@ public class CollectionObjectClient extends AbstractServiceClientImpl { public void setProxy() { if(useAuth()){ collectionObjectProxy = ProxyFactory.create(CollectionObjectProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); }else{ collectionObjectProxy = ProxyFactory.create(CollectionObjectProxy.class, getBaseURL()); diff --git a/services/common/src/main/config/log/jboss-log4j.xml b/services/common/src/main/config/log/jboss-log4j.xml index c765e2831..d1cd342a9 100644 --- a/services/common/src/main/config/log/jboss-log4j.xml +++ b/services/common/src/main/config/log/jboss-log4j.xml @@ -140,6 +140,7 @@ + diff --git a/services/common/src/main/java/org/collectionspace/services/common/query/IQueryManager.java b/services/common/src/main/java/org/collectionspace/services/common/query/IQueryManager.java index e7c1cabea..c4174fadd 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/query/IQueryManager.java +++ b/services/common/src/main/java/org/collectionspace/services/common/query/IQueryManager.java @@ -50,4 +50,14 @@ public interface IQueryManager { */ public String createWhereClauseFromKeywords(String keywords); + /** + * Creates the where clause for partial term match. + * + * @param field the qualified field to match on + * @param partialTerm the term to match against + * + * @return the string + */ + public String createWhereClauseForPartialMatch(String field, String partialTerm); + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/query/QueryManager.java b/services/common/src/main/java/org/collectionspace/services/common/query/QueryManager.java index ec22822bc..040d04f68 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/query/QueryManager.java +++ b/services/common/src/main/java/org/collectionspace/services/common/query/QueryManager.java @@ -45,4 +45,17 @@ public class QueryManager { static public String createWhereClauseFromKeywords(String keywords) { return queryManager.createWhereClauseFromKeywords(keywords); } + + /** + * Creates the where clause for partial term match. + * + * @param field the qualified field to match on + * @param partialTerm the term to match against + * + * @return the string + */ + static public String createWhereClauseForPartialMatch(String field, String partialTerm) { + return queryManager.createWhereClauseForPartialMatch(field, partialTerm); + } + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/query/nuxeo/QueryManagerNuxeoImpl.java b/services/common/src/main/java/org/collectionspace/services/common/query/nuxeo/QueryManagerNuxeoImpl.java index d6bd14f20..aba6d1d6d 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/query/nuxeo/QueryManagerNuxeoImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/query/nuxeo/QueryManagerNuxeoImpl.java @@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory; import java.util.Map; import java.util.HashMap; import java.util.StringTokenizer; +import java.util.regex.Pattern; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; @@ -44,12 +45,18 @@ import org.collectionspace.services.nuxeo.client.java.NuxeoConnector; import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.query.IQueryManager; +import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema; public class QueryManagerNuxeoImpl implements IQueryManager { private final Logger logger = LoggerFactory .getLogger(RepositoryJavaClientImpl.class); + // Consider that letters, letter-markers, numbers, '_' and apostrophe are words + private static Pattern nonWordChars = Pattern.compile("[^\\p{L}\\p{M}\\p{N}_']"); + private static Pattern unescapedDblQuotes = Pattern.compile("(?readItemList( @PathParam("csid") String parentcsid, - @QueryParam (IQueryManager.SEARCH_TYPE_PARTIALTERM) String partialTerm, - @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords); + @QueryParam (IQueryManager.SEARCH_TYPE_PARTIALTERM) @Encoded String partialTerm, + @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) @Encoded String keywords); /** * @param parentcsid diff --git a/services/person/client/src/test/java/org/collectionspace/services/client/test/PersonAuthoritySearchTest.java b/services/person/client/src/test/java/org/collectionspace/services/client/test/PersonAuthoritySearchTest.java index 115e1552a..96f561f19 100644 --- a/services/person/client/src/test/java/org/collectionspace/services/client/test/PersonAuthoritySearchTest.java +++ b/services/person/client/src/test/java/org/collectionspace/services/client/test/PersonAuthoritySearchTest.java @@ -22,6 +22,10 @@ */ package org.collectionspace.services.client.test; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -58,6 +62,8 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { /** The service path component. */ final String SERVICE_PATH_COMPONENT = "personauthorities"; + final String UTF8_CHARSET_NAME = "UTF-8"; + // Test name for partial term matching: Lech Wałęsa // // For details regarding the łę characters in the last name, see: @@ -67,18 +73,40 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { // Forename final String TEST_PARTIAL_TERM_FORE_NAME = "Lech"; // + // Surname (contains single quote character) + final String TEST_PARTIAL_TERM_SUR_NAME_QUOTE = "O'Hara"; + // // Surname (contains two non-USASCII range Unicode UTF-8 characters) - final String TEST_PARTIAL_TERM_SUR_NAME = "Wa" + '\u0142' + '\u0119' + "sa"; + final String TEST_PARTIAL_TERM_SUR_NAME_UNICODE = "Wałęsa"; + // Wrong: "Wa" + "\u0142" + "\u0119" + "sa"; + // Should also work: "Wa" + '\u0142' + '\u0119' + "sa"; + // Should also work: "Wa\u0142\u0119sa"; + // + // + // Displayname + final String TEST_PARTIAL_TERM_DISPLAY_NAME_UNICODE = + TEST_PARTIAL_TERM_FORE_NAME + " " + TEST_PARTIAL_TERM_SUR_NAME_UNICODE; // // Displayname - final String TEST_PARTIAL_TERM_DISPLAY_NAME = - TEST_PARTIAL_TERM_FORE_NAME + " " + TEST_PARTIAL_TERM_SUR_NAME; + final String TEST_PARTIAL_TERM_DISPLAY_NAME_QUOTE = + TEST_PARTIAL_TERM_FORE_NAME + " " + TEST_PARTIAL_TERM_SUR_NAME_QUOTE; // // shortId - final String TEST_SHORT_ID = "lechWalesa"; + final String TEST_SHORT_ID_UNICODE = "lechWalesa"; + // + // shortId + final String TEST_SHORT_ID_QUOTE = "lechOHara"; final String TEST_KWD_BIRTH_PLACE = "Popowo, Poland"; + final String TEST_KWD_UTF8_STYLE = "Appliqu"+'\u00e8'+"d Arts"; + + final String TEST_KWD_BIO_NOTE_NO_QUOTES = + "This is a silly bionote with no so-called quotes."; + + final String TEST_KWD_BIO_NOTE_DBL_QUOTES = + "This is a silly \"bionote\" for testing so called quote_handling"; + final String TEST_KWD_NO_MATCH = "Foobar"; // Non-existent partial term name (first letters of each of the words @@ -104,7 +132,8 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { new HashMap(); // The number of matches expected on each partial term. - final int NUM_MATCHES_EXPECTED = 1; + final int NUM_MATCHES_EXPECTED_COMMON = 2; + final int NUM_MATCHES_EXPECTED_SPECIFIC = 1; // The minimum number of characters that must be included // a partial term, in order to permit matching to occur. @@ -127,12 +156,16 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { return response.getEntity(PersonsCommonList.class); } - private String getPartialTerm() { + private String getPartialTermCommon() { return TEST_PARTIAL_TERM_FORE_NAME; } private String getPartialTermUtf8() { - return TEST_PARTIAL_TERM_SUR_NAME; + return TEST_PARTIAL_TERM_SUR_NAME_UNICODE; + } + + private String getPartialTermQuote() { + return TEST_PARTIAL_TERM_SUR_NAME_QUOTE; } private String getPartialTermNonExistent() { @@ -140,11 +173,11 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { } private String getPartialTermMinimumLength() { - String partialTerm = getPartialTerm(); + String partialTerm = getPartialTermCommon(); if (partialTerm == null || partialTerm.trim().isEmpty()) { return partialTerm; } - if (getPartialTerm().length() > PARTIAL_TERM_MIN_LENGTH) { + if (partialTerm.length() > PARTIAL_TERM_MIN_LENGTH) { return partialTerm.substring(0, PARTIAL_TERM_MIN_LENGTH); } else { return partialTerm; @@ -155,6 +188,10 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { return TEST_KWD_BIRTH_PLACE; } + private String getKwdTermUTF8() { + return TEST_KWD_UTF8_STYLE; + } + private String getKwdTermNonExistent() { return TEST_KWD_NO_MATCH; } @@ -167,7 +204,7 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { Assert.fail("Could not create new Authority for search tests.", e); } try { - createItemInAuthorityForPartialTermMatch(knownResourceId, knownResourceRefName); + createItemsInAuthorityForPartialTermMatch(knownResourceId, knownResourceRefName); } catch (Exception e) { Assert.fail("Could not create new item in Authority for search tests.", e); } @@ -189,16 +226,16 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { logger.debug(testBanner(testName, CLASS_NAME)); } int numMatchesFound = 0; - String partialTerm = getPartialTerm(); + String partialTerm = getPartialTermCommon(); if (logger.isDebugEnabled()) { logger.debug("Attempting match on partial term '" + partialTerm + "' ..."); } numMatchesFound = readItemListWithFilters(testName, knownResourceId, partialTerm, null); if (logger.isDebugEnabled()) { logger.debug("Found " + numMatchesFound + " match(es), expected " + - NUM_MATCHES_EXPECTED + " match(es)."); + NUM_MATCHES_EXPECTED_COMMON + " match(es)."); } - Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED); + Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON); } /** @@ -214,7 +251,7 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { } int numMatchesFound = 0; - final String partialTerm = getPartialTerm().toLowerCase(); + final String partialTerm = getPartialTermCommon().toLowerCase(); if (logger.isDebugEnabled()) { logger.debug("Attempting match on partial term '" + partialTerm + "' ..."); } @@ -222,9 +259,9 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { readItemListWithFilters(testName, knownResourceId, partialTerm, null); if (logger.isDebugEnabled()) { logger.debug("Found " + numMatchesFound + " match(es), expected " + - NUM_MATCHES_EXPECTED + " match(es)."); + NUM_MATCHES_EXPECTED_COMMON + " match(es)."); } - Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED); + Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON); } /** @@ -240,7 +277,7 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { } int numMatchesFound = 0; - final String partialTerm = getPartialTerm().toUpperCase(); + final String partialTerm = getPartialTermCommon().toUpperCase(); if (logger.isDebugEnabled()) { logger.debug("Attempting match on partial term '" + partialTerm + "' ..."); } @@ -248,9 +285,9 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { readItemListWithFilters(testName, knownResourceId, partialTerm, null); if (logger.isDebugEnabled()) { logger.debug("Found " + numMatchesFound + " match(es), expected " + - NUM_MATCHES_EXPECTED + " match(es)."); + NUM_MATCHES_EXPECTED_COMMON + " match(es)."); } - Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED); + Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON); } /** @@ -272,18 +309,15 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { // Zero matches are expected on a non-existent term. if (logger.isDebugEnabled()) { logger.debug("Found " + numMatchesFound + " match(es), expected " + - NUM_MATCHES_EXPECTED + " match(es)."); + NUM_MATCHES_EXPECTED_COMMON + " match(es)."); } - Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED); + Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON); } /** * Reads an item list by partial term, with a partial term that contains * at least one Unicode UTF-8 character (outside the USASCII range). */ - // FIXME: Test currently fails with a true UTF-8 String - need to investigate why. - // Will be commented out for now until we get this working ... -/* @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"}) public void partialTermMatchUTF8(String testName) { @@ -292,23 +326,54 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { } int numMatchesFound = 0; String partialTerm = getPartialTermUtf8(); + String ptEncoded; + try { + ptEncoded = URLEncoder.encode(partialTerm, UTF8_CHARSET_NAME); + } + catch (UnsupportedEncodingException ex) { + throw new RuntimeException("Broken VM does not support UTF-8"); + } + if (logger.isDebugEnabled()) { + logger.debug("Attempting match on partial term '" + partialTerm + "', Encoded:'"+ptEncoded+"' ..."); + } + numMatchesFound = + readItemListWithFilters(testName, knownResourceId, partialTerm, null); + if (logger.isDebugEnabled()) { + logger.debug("Found " + numMatchesFound + " match(es), expected " + + NUM_MATCHES_EXPECTED_SPECIFIC + " match(es)."); + } + Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_SPECIFIC); + } + + /** + * Reads an item list by partial term, with a partial term that contains + * at least one Unicode UTF-8 character (outside the USASCII range). + */ + @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, + groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"}) + public void partialTermMatchQuote(String testName) { + if (logger.isDebugEnabled()) { + logger.debug(testBanner(testName, CLASS_NAME)); + } + int numMatchesFound = 0; + String partialTerm = getPartialTermQuote(); if (logger.isDebugEnabled()) { logger.debug("Attempting match on partial term '" + partialTerm + "' ..."); } numMatchesFound = - readItemListByPartialTerm(knownResourceId, partialTerm); + readItemListWithFilters(testName, knownResourceId, partialTerm, null); if (logger.isDebugEnabled()) { logger.debug("Found " + numMatchesFound + " match(es), expected " + - NUM_MATCHES_EXPECTED + " match(es)."); + NUM_MATCHES_EXPECTED_SPECIFIC + " match(es)."); } - Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED); + Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_SPECIFIC); } -*/ + /** - * Reads an item list by partial term. + * Finds terms by keywords. */ @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - groups = {"readListByKwdTerm"}, dependsOnGroups = {"readListByPartialTerm"}) + groups = {"readListByKwdTerm"}) public void keywordTermMatch(String testName) { if (logger.isDebugEnabled()) { logger.debug(testBanner(testName, CLASS_NAME)); @@ -321,12 +386,35 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { numMatchesFound = readItemListWithFilters(testName, knownResourceId, null, kwdTerm); if (logger.isDebugEnabled()) { logger.debug("Found " + numMatchesFound + " match(es), expected " + - NUM_MATCHES_EXPECTED + " match(es)."); + NUM_MATCHES_EXPECTED_COMMON + " match(es)."); + } + Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON); + } + + /** + * Finds terms by keywords. + */ + @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, + groups = {"readListByKwdTerm"}, dependsOnMethods = {"keywordTermMatch"}) + public void keywordTermMatchUTF8(String testName) { + if (logger.isDebugEnabled()) { + logger.debug(testBanner(testName, CLASS_NAME)); + } + int numMatchesFound = 0; + String kwdTerm = getKwdTermUTF8(); + if (logger.isDebugEnabled()) { + logger.debug("Attempting match on kwd term '" + kwdTerm + "' ..."); + } + numMatchesFound = readItemListWithFilters(testName, knownResourceId, null, kwdTerm); + if (logger.isDebugEnabled()) { + logger.debug("Found " + numMatchesFound + " match(es), expected " + + NUM_MATCHES_EXPECTED_COMMON + " match(es)."); } - Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED); + Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON); } + // Failure outcomes /** @@ -495,6 +583,9 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { public void createAuthority() throws Exception { String testName = "createAuthority"; + if (logger.isDebugEnabled()) { + logger.debug(testBanner(testName, CLASS_NAME)); + } // Perform setup. int expectedStatusCode = Response.Status.CREATED.getStatusCode(); @@ -547,11 +638,11 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { * @param authorityCsid The CSID of the Authority in which the term will be created. * @param authRefName The refName of the Authority in which the term will be created. */ - private void createItemInAuthorityForPartialTermMatch( + private void createItemsInAuthorityForPartialTermMatch( String authorityCsid, String authRefName) throws Exception { - String testName = "createItemInAuthorityForPartialTermMatch"; + String testName = "createItemsInAuthorityForPartialTermMatch"; int expectedStatusCode = Response.Status.CREATED.getStatusCode(); ServiceRequestType requestType = ServiceRequestType.CREATE; @@ -561,18 +652,43 @@ public class PersonAuthoritySearchTest extends BaseServiceTest { PersonAuthorityClient client = new PersonAuthorityClient(); Map partialTermPersonMap = new HashMap(); // - // Fill the property map + // Fill the property map for the UNICODE item // - partialTermPersonMap.put(PersonJAXBSchema.SHORT_IDENTIFIER, TEST_SHORT_ID ); + partialTermPersonMap.put(PersonJAXBSchema.SHORT_IDENTIFIER, TEST_SHORT_ID_UNICODE ); partialTermPersonMap.put(PersonJAXBSchema.DISPLAY_NAME_COMPUTED, "false"); - partialTermPersonMap.put(PersonJAXBSchema.DISPLAY_NAME, TEST_PARTIAL_TERM_DISPLAY_NAME); + partialTermPersonMap.put(PersonJAXBSchema.DISPLAY_NAME, TEST_PARTIAL_TERM_DISPLAY_NAME_UNICODE); partialTermPersonMap.put(PersonJAXBSchema.FORE_NAME, TEST_PARTIAL_TERM_FORE_NAME); - partialTermPersonMap.put(PersonJAXBSchema.SUR_NAME, TEST_PARTIAL_TERM_SUR_NAME); + partialTermPersonMap.put(PersonJAXBSchema.SUR_NAME, TEST_PARTIAL_TERM_SUR_NAME_UNICODE); partialTermPersonMap.put(PersonJAXBSchema.BIRTH_PLACE, TEST_KWD_BIRTH_PLACE); partialTermPersonMap.put(PersonJAXBSchema.GENDER, "male"); + partialTermPersonMap.put(PersonJAXBSchema.BIO_NOTE, TEST_KWD_BIO_NOTE_NO_QUOTES); Map> partialTermRepeatablesMap = new HashMap>(); + ArrayList styles = new ArrayList(); + styles.add(TEST_KWD_UTF8_STYLE); + partialTermRepeatablesMap.put(PersonJAXBSchema.SCHOOLS_OR_STYLES, styles); + + createItem(testName, authorityCsid, authRefName, client, + partialTermPersonMap, partialTermRepeatablesMap); + // + // Adjust the property map for the QUOTE item + // + partialTermPersonMap.put(PersonJAXBSchema.SHORT_IDENTIFIER, TEST_SHORT_ID_QUOTE ); + partialTermPersonMap.put(PersonJAXBSchema.DISPLAY_NAME, TEST_PARTIAL_TERM_DISPLAY_NAME_QUOTE); + partialTermPersonMap.put(PersonJAXBSchema.SUR_NAME, TEST_PARTIAL_TERM_SUR_NAME_QUOTE); + partialTermPersonMap.put(PersonJAXBSchema.BIO_NOTE, TEST_KWD_BIO_NOTE_DBL_QUOTES); + createItem(testName, authorityCsid, authRefName, client, + partialTermPersonMap, partialTermRepeatablesMap); + } + + private void createItem( + String testName, + String authorityCsid, + String authRefName, + PersonAuthorityClient client, + Map partialTermPersonMap, + Map> partialTermRepeatablesMap) throws Exception { MultipartOutput multipart = PersonAuthorityClientUtils.createPersonInstance(authorityCsid, authRefName, partialTermPersonMap, partialTermRepeatablesMap, client.getItemCommonPartName() ); diff --git a/services/person/client/src/test/java/org/collectionspace/services/client/test/PersonAuthorityServiceTest.java b/services/person/client/src/test/java/org/collectionspace/services/client/test/PersonAuthorityServiceTest.java index e93c4460f..e4a298d9f 100644 --- a/services/person/client/src/test/java/org/collectionspace/services/client/test/PersonAuthorityServiceTest.java +++ b/services/person/client/src/test/java/org/collectionspace/services/client/test/PersonAuthorityServiceTest.java @@ -573,8 +573,8 @@ public class PersonAuthorityServiceTest extends AbstractServiceTestImpl { * @throws Exception the exception */ @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - groups = {"read"}, dependsOnGroups = {"create"}) - public void readByName(String testName) throws Exception { + groups = {"read"}, dependsOnMethods = {"read"}) + public void readByName(String testName) throws Exception { readInternal(testName, null, knownResourceShortIdentifer); } @@ -638,7 +638,7 @@ public class PersonAuthorityServiceTest extends AbstractServiceTestImpl { * @throws Exception the exception */ @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - groups = {"readItem"}, dependsOnGroups = {"read"}) + groups = {"readItem"}, dependsOnMethods = {"readItem"}) public void readItemInNamedAuth(String testName) throws Exception { readItemInternal(testName, null, knownResourceShortIdentifer, knownItemResourceId, null); } @@ -650,7 +650,7 @@ public class PersonAuthorityServiceTest extends AbstractServiceTestImpl { * @throws Exception the exception */ @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - groups = {"readItem"}, dependsOnGroups = {"read"}) + groups = {"readItem"}, dependsOnMethods = {"readItem"}) public void readNamedItem(String testName) throws Exception { readItemInternal(testName, knownResourceId, null, null, knownItemResourceShortIdentifer); } @@ -662,7 +662,7 @@ public class PersonAuthorityServiceTest extends AbstractServiceTestImpl { * @throws Exception the exception */ @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - groups = {"readItem"}, dependsOnGroups = {"read"}) + groups = {"readItem"}, dependsOnMethods = {"readItem"}) public void readNamedItemInNamedAuth(String testName) throws Exception { readItemInternal(testName, null, knownResourceShortIdentifer, null, knownItemResourceShortIdentifer); } @@ -745,7 +745,7 @@ public class PersonAuthorityServiceTest extends AbstractServiceTestImpl { * @throws Exception the exception */ @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - dependsOnMethods = {"readItem", "updateItem"}) + groups = {"update"}, dependsOnMethods = {"updateItem"}) public void verifyItemDisplayName(String testName) throws Exception { if (logger.isDebugEnabled()) { @@ -878,7 +878,7 @@ public class PersonAuthorityServiceTest extends AbstractServiceTestImpl { * @throws Exception the exception */ @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - dependsOnMethods = {"verifyItemDisplayName"}) + groups = {"update"}, dependsOnMethods = {"verifyItemDisplayName"}) public void verifyIllegalItemDisplayName(String testName) throws Exception { if (logger.isDebugEnabled()) { @@ -1332,7 +1332,7 @@ public class PersonAuthorityServiceTest extends AbstractServiceTestImpl { */ @Override @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - groups = {"update"}, dependsOnGroups = {"read", "readList", "readListByPartialTerm"}) + groups = {"update"}, dependsOnGroups = {"readItem", "readList"}) public void update(String testName) throws Exception { if (logger.isDebugEnabled()) { @@ -1809,7 +1809,7 @@ public class PersonAuthorityServiceTest extends AbstractServiceTestImpl { * @throws Exception the exception */ @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, - groups = {"delete"}, dependsOnGroups = {"create", "read", "readList", "readListByPartialTerm", "update"}) + groups = {"delete"}, dependsOnGroups = {"update"}) public void deleteContact(String testName) throws Exception { if (logger.isDebugEnabled()) { diff --git a/services/person/client/src/test/resources/log4j.properties b/services/person/client/src/test/resources/log4j.properties index 18c510350..4519e9992 100644 --- a/services/person/client/src/test/resources/log4j.properties +++ b/services/person/client/src/test/resources/log4j.properties @@ -2,12 +2,14 @@ log4j.rootLogger=debug, stdout, R log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.encoding=UTF-8 # Pattern to output the caller's file name and line number. log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] [%c:%L] %m%n log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=target/test-client.log +log4j.appender.R.encoding=UTF-8 log4j.appender.R.MaxFileSize=100KB # Keep one backup file diff --git a/services/pom.xml b/services/pom.xml index e8b649779..0cb75bbaa 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -258,22 +258,22 @@ org.jboss.resteasy jaxrs-api - 1.2.GA + 1.2.1.GA org.jboss.resteasy resteasy-jaxrs - 1.2.GA + 1.2.1.GA org.jboss.resteasy resteasy-jaxb-provider - 1.2.GA + 1.2.1.GA org.jboss.resteasy resteasy-multipart-provider - 1.2.GA + 1.2.1.GA commons-httpclient diff --git a/services/relation/client/src/main/java/org/collectionspace/services/client/RelationClient.java b/services/relation/client/src/main/java/org/collectionspace/services/client/RelationClient.java index 38aafe195..85eda922a 100644 --- a/services/relation/client/src/main/java/org/collectionspace/services/client/RelationClient.java +++ b/services/relation/client/src/main/java/org/collectionspace/services/client/RelationClient.java @@ -34,6 +34,7 @@ import org.collectionspace.services.relation.RelationsCommonList; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; import org.jboss.resteasy.spi.ResteasyProviderFactory; @@ -79,7 +80,7 @@ public class RelationClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { relationProxy = ProxyFactory.create(RelationProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { relationProxy = ProxyFactory.create(RelationProxy.class, getBaseURL()); diff --git a/services/report/client/src/main/java/org/collectionspace/services/client/ReportClient.java b/services/report/client/src/main/java/org/collectionspace/services/client/ReportClient.java index 841a80480..042e1b44d 100644 --- a/services/report/client/src/main/java/org/collectionspace/services/client/ReportClient.java +++ b/services/report/client/src/main/java/org/collectionspace/services/client/ReportClient.java @@ -36,6 +36,7 @@ import org.collectionspace.services.report.ReportsCommonList; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; import org.jboss.resteasy.spi.ResteasyProviderFactory; @@ -85,7 +86,7 @@ public class ReportClient extends AbstractServiceClientImpl { public void setProxy() { if (useAuth()) { reportProxy = ProxyFactory.create(ReportProxy.class, - getBaseURL(), getHttpClient()); + getBaseURL(), new ApacheHttpClientExecutor(getHttpClient())); } else { reportProxy = ProxyFactory.create(ReportProxy.class, getBaseURL()); diff --git a/services/vocabulary/client/src/main/java/org/collectionspace/services/client/VocabularyClient.java b/services/vocabulary/client/src/main/java/org/collectionspace/services/client/VocabularyClient.java index cb1177dc5..d69fb6f44 100644 --- a/services/vocabulary/client/src/main/java/org/collectionspace/services/client/VocabularyClient.java +++ b/services/vocabulary/client/src/main/java/org/collectionspace/services/client/VocabularyClient.java @@ -34,6 +34,7 @@ import org.collectionspace.services.client.VocabularyProxy; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.client.ProxyFactory; +import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; @@ -89,7 +90,8 @@ public class VocabularyClient extends AbstractServiceClientImpl { */ public void setProxy() { if (useAuth()) { - vocabularyProxy = ProxyFactory.create(VocabularyProxy.class, getBaseURL(), getHttpClient()); + vocabularyProxy = ProxyFactory.create(VocabularyProxy.class, getBaseURL(), + new ApacheHttpClientExecutor(getHttpClient())); } else { vocabularyProxy = ProxyFactory.create(VocabularyProxy.class, getBaseURL()); } -- 2.47.3