mirror of
https://github.com/Alfresco/SearchServices.git
synced 2025-09-17 14:21:20 +00:00
Merge branch 'master' of git.alfresco.com:search_discovery/insightengine into fix/SEARCH-1994
This commit is contained in:
@@ -11,9 +11,9 @@
|
||||
<name>Search Analytics E2E Tests</name>
|
||||
<description>Test Project to test Search Service and Analytics Features on a complete setup of Alfresco, Share</description>
|
||||
<properties>
|
||||
<tas.rest.api.version>1.18</tas.rest.api.version>
|
||||
<tas.cmis.api.version>1.10</tas.cmis.api.version>
|
||||
<tas.utility.version>3.0.15</tas.utility.version>
|
||||
<tas.rest.api.version>1.20</tas.rest.api.version>
|
||||
<tas.cmis.api.version>1.11</tas.cmis.api.version>
|
||||
<tas.utility.version>3.0.16</tas.utility.version>
|
||||
<rm.version>3.2.0</rm.version>
|
||||
<suiteXmlFile>src/test/resources/SearchSuite.xml</suiteXmlFile>
|
||||
<test.exclude></test.exclude>
|
||||
|
@@ -38,6 +38,7 @@ public class TestGroup
|
||||
public static final String ACS_61n = "ACS_61n"; // Alfresco Content Services 6.1 or above
|
||||
public static final String ACS_611n = "ACS_611n"; // Alfresco Content Services 6.1.1 or above
|
||||
public static final String ACS_62n = "ACS_62n"; // Alfresco Content Services 6.2 or above
|
||||
public static final String ACS_63n = "ACS_63n"; // Alfresco Content Services 6.3 or above
|
||||
|
||||
public static final String AGS_302 = "AGS_302"; // Alfresco governance Services 3.0.2 or above
|
||||
|
||||
|
@@ -6,6 +6,16 @@
|
||||
*/
|
||||
package org.alfresco.test.search.functional;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
import static lombok.AccessLevel.PROTECTED;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.alfresco.cmis.CmisWrapper;
|
||||
import org.alfresco.dataprep.ContentService;
|
||||
import org.alfresco.dataprep.SiteService.Visibility;
|
||||
@@ -38,11 +48,6 @@ import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.BeforeSuite;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static lombok.AccessLevel.PROTECTED;
|
||||
|
||||
/**
|
||||
* @author meenal bhave
|
||||
*/
|
||||
@@ -424,28 +429,76 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
|
||||
|
||||
/**
|
||||
* Helper method to test if the search query works and count matches where provided
|
||||
*
|
||||
* @param query: AFTS or cmis query string
|
||||
* @param expectedCount: Only successful response is checked, when expectedCount is null (can not be exactly specified),
|
||||
* @return SearchResponse
|
||||
*/
|
||||
protected SearchResponse testSearchQuery(String query, Integer expectedCount, SearchLanguage queryLanguage)
|
||||
{
|
||||
SearchResponse response = performSearch(testUser, query, queryLanguage);
|
||||
|
||||
if (ofNullable(expectedCount).isPresent())
|
||||
{
|
||||
restClient.onResponse().assertThat().body("list.pagination.count", Matchers.equalTo(expectedCount));
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to test if the search query returns the expected results in the order given.
|
||||
*
|
||||
* @param query: AFTS or cmis query string
|
||||
* @param expectedNames: The ordered list of names expected to be returned,
|
||||
* @return SearchResponse
|
||||
*/
|
||||
protected SearchResponse testSearchQueryOrdered(String query, List<String> expectedNames, SearchLanguage queryLanguage)
|
||||
{
|
||||
SearchResponse response = performSearch(testUser, query, queryLanguage);
|
||||
|
||||
List<String> names = response.getEntries().stream().map(s -> s.getModel().getName()).collect(Collectors.toList());
|
||||
|
||||
// Include lists in failure message as TestNG won't do this for lists.
|
||||
assertEquals(names, expectedNames, "Unexpected results for query: " + query + " Expected: " + expectedNames + " but got " + names);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to test if the search query returns the expected set of results.
|
||||
*
|
||||
* @param query: AFTS or cmis query string
|
||||
* @param expectedNames: The ordered list of names expected to be returned,
|
||||
* @return SearchResponse
|
||||
*/
|
||||
protected SearchResponse testSearchQueryUnordered(String query, Set<String> expectedNames, SearchLanguage queryLanguage)
|
||||
{
|
||||
SearchResponse response = performSearch(testUser, query, queryLanguage);
|
||||
|
||||
Set<String> names = response.getEntries().stream().map(s -> s.getModel().getName()).collect(Collectors.toSet());
|
||||
|
||||
assertEquals(names, expectedNames, "Unexpected results for query: " + query);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private SearchResponse performSearch(UserModel asUser, String query, SearchLanguage queryLanguage)
|
||||
{
|
||||
RestRequestQueryModel queryModel = new RestRequestQueryModel();
|
||||
queryModel.setQuery(query);
|
||||
|
||||
if (!ofNullable(asUser).isPresent())
|
||||
{
|
||||
asUser = testUser;
|
||||
}
|
||||
|
||||
if (ofNullable(queryLanguage).isPresent())
|
||||
{
|
||||
queryModel.setLanguage(queryLanguage.toString());
|
||||
}
|
||||
|
||||
SearchResponse response = queryAsUser(testUser, queryModel);
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
|
||||
if (ofNullable(expectedCount).isPresent())
|
||||
{
|
||||
restClient.onResponse().assertThat().body("list.pagination.count", Matchers.equalTo(expectedCount));
|
||||
}
|
||||
SearchResponse response = queryAsUser(asUser, queryModel);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright 2019 Alfresco Software, Ltd. All rights reserved.
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
|
||||
package org.alfresco.test.search.functional.searchServices.search;
|
||||
|
||||
import static java.util.List.of;
|
||||
|
||||
import static jersey.repackaged.com.google.common.collect.Sets.newHashSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.alfresco.rest.model.RestNodeAssociationModelCollection;
|
||||
import org.alfresco.rest.model.RestNodeChildAssociationModel;
|
||||
import org.alfresco.rest.search.SearchResponse;
|
||||
import org.alfresco.search.TestGroup;
|
||||
import org.alfresco.test.search.functional.AbstractE2EFunctionalTest;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.FileType;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Test class tests AFTS Search In Field works
|
||||
* Created for Search-840
|
||||
*
|
||||
* @author Meenal Bhave
|
||||
*/
|
||||
public class SearchAFTSInFieldTest extends AbstractE2EFunctionalTest
|
||||
{
|
||||
private FolderModel folder1, folder2;
|
||||
private FileModel file1, file2, file3, file4, file5;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void dataPreparation()
|
||||
{
|
||||
// Create Folders:
|
||||
// Folder1: Expected to be found with file.txt
|
||||
folder1 = new FolderModel("file txt folder");
|
||||
dataContent.usingUser(testUser).usingSite(testSite).createFolder(folder1);
|
||||
|
||||
// Folder2: Not expected to be found with file.txt
|
||||
folder2 = new FolderModel("txt files folder");
|
||||
dataContent.usingUser(testUser).usingSite(testSite).createFolder(folder2);
|
||||
|
||||
// Create File(s): Expected to be found with file.txt
|
||||
file1 = new FileModel("file.txt", "file.txt", "", FileType.TEXT_PLAIN, "file.txt");
|
||||
|
||||
file2 = new FileModel("1-file.txt", "1-file.txt", "", FileType.TEXT_PLAIN, "1-file.txt");
|
||||
|
||||
file3 = new FileModel("file1.txt", "file1.txt", "", FileType.TEXT_PLAIN, "file1.txt");
|
||||
|
||||
file4 = new FileModel("txt file", "txt file", "", FileType.TEXT_PLAIN, "txt file");
|
||||
|
||||
// Not Expected to be found with file.txt
|
||||
file5 = new FileModel("txt files", "txt files", "", FileType.TEXT_PLAIN, "txt files");
|
||||
|
||||
of(file1, file2, file3, file4, file5).forEach(
|
||||
f -> dataContent.usingUser(testUser).usingSite(testSite).usingResource(folder1).createContent(f));
|
||||
|
||||
waitForContentIndexing(file5.getContent(), true);
|
||||
}
|
||||
|
||||
@Test(priority = 1, groups = { TestGroup.ACS_63n })
|
||||
public void testSearchInFieldName()
|
||||
{
|
||||
// Field names in various formats
|
||||
Stream<String> fieldNames = Stream.of("{http://www.alfresco.org/model/content/1.0}name",
|
||||
"@{http://www.alfresco.org/model/content/1.0}name",
|
||||
"cm_name",
|
||||
"cm:name",
|
||||
"@cm:name",
|
||||
"name");
|
||||
|
||||
// For each field name, check that queries return consistent results with / out ''
|
||||
fieldNames.forEach(fieldName ->
|
||||
{
|
||||
// Query string without quotes
|
||||
String query = fieldName + ":file.txt";
|
||||
|
||||
Set<String> expectedNames = newHashSet();
|
||||
expectedNames.add("file.txt"); // file1
|
||||
expectedNames.add("1-file.txt"); // file2
|
||||
expectedNames.add("file1.txt"); // file3
|
||||
expectedNames.add("txt file"); // file4
|
||||
expectedNames.add("file txt folder"); // folder1
|
||||
|
||||
testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
|
||||
|
||||
// Query string in single quotes
|
||||
query = fieldName + ":'file.txt'";
|
||||
testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
|
||||
});
|
||||
}
|
||||
|
||||
@Test(priority = 2, groups = { TestGroup.ACS_63n })
|
||||
public void testSearchInFieldTitle()
|
||||
{
|
||||
// Field names in various formats
|
||||
Stream<String> fieldNames = Stream.of("{http://www.alfresco.org/model/content/1.0}title",
|
||||
"@{http://www.alfresco.org/model/content/1.0}title",
|
||||
"cm_title",
|
||||
"cm:title",
|
||||
"@cm:title");
|
||||
|
||||
// For each field name, check that queries return consistent results with / out ''
|
||||
fieldNames.forEach(fieldName ->
|
||||
{
|
||||
String query = fieldName + ":" + file2.getName();
|
||||
boolean fileFound = isContentInSearchResults(query, file2.getName(), true);
|
||||
Assert.assertTrue(fileFound, "File Not found for query: " + query);
|
||||
|
||||
testSearchQuery(query, 1, SearchLanguage.AFTS);
|
||||
|
||||
query = fieldName + ":'" + file2.getName() + "\'";
|
||||
fileFound = isContentInSearchResults(query, file2.getName(), true);
|
||||
Assert.assertTrue(fileFound, "File Not found for query: " + query);
|
||||
|
||||
testSearchQuery(query, 1, SearchLanguage.AFTS);
|
||||
});
|
||||
}
|
||||
|
||||
@Test(priority = 3, groups = { TestGroup.ACS_63n })
|
||||
public void testSearchInFieldContent()
|
||||
{
|
||||
// Field names in various formats
|
||||
List<String> fieldNames = new ArrayList<>();
|
||||
fieldNames.add("TEXT");
|
||||
fieldNames.add("{http://www.alfresco.org/model/dictionary/1.0}content");
|
||||
fieldNames.add("cm:content");
|
||||
fieldNames.add("d:content");
|
||||
|
||||
// For each field name, check that queries return consistent results with / out ''
|
||||
fieldNames.forEach(fieldName ->
|
||||
{
|
||||
String query = fieldName + ":" + file3.getContent();
|
||||
boolean fileFound = isContentInSearchResults(query, file3.getName(), true);
|
||||
Assert.assertTrue(fileFound, "File Not found for query: " + query);
|
||||
|
||||
Integer resultCount1 = testSearchQuery(query, null, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
|
||||
query = fieldName + ":'" + file3.getContent() + "\'";
|
||||
fileFound = isContentInSearchResults(query, file3.getName(), true);
|
||||
Assert.assertTrue(fileFound, "File Not found for query: " + query);
|
||||
|
||||
testSearchQuery(query, resultCount1, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
});
|
||||
}
|
||||
|
||||
@Test(priority = 4)
|
||||
public void testSearchInFieldSITE()
|
||||
{
|
||||
String query = "SITE:" + testSite.getId();
|
||||
boolean fileFound = isContentInSearchResults(query, folder1.getName(), true);
|
||||
Assert.assertTrue(fileFound, "Site Not found for query: " + query);
|
||||
|
||||
Integer resultCount1 = testSearchQuery(query, 8, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
|
||||
query = "SITE:'" + testSite.getId() + "\'";
|
||||
fileFound = isContentInSearchResults(query, folder1.getName(), true);
|
||||
Assert.assertTrue(fileFound, "Site Not found for query: " + query);
|
||||
|
||||
testSearchQuery(query, resultCount1, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
}
|
||||
|
||||
@Test(priority = 5)
|
||||
public void testSearchInFieldTYPE()
|
||||
{
|
||||
// Field names in various formats
|
||||
List<String> fieldNames = new ArrayList<>();
|
||||
fieldNames.add("TYPE");
|
||||
fieldNames.add("EXACTTYPE");
|
||||
|
||||
// For each field name, check that queries return consistent results with / out ''
|
||||
fieldNames.forEach(fieldName -> {
|
||||
|
||||
String query = fieldName + ":cm\\:content" + " and =cm:name:" + file1.getName();
|
||||
boolean fileFound = isContentInSearchResults(query, file1.getName(), true);
|
||||
Assert.assertTrue(fileFound, "Content Not found for query: " + query);
|
||||
|
||||
Integer resultCount1 = testSearchQuery(query, 1, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
|
||||
query = fieldName + ":'cm:content'" + " and =cm:name:" + file1.getName();
|
||||
fileFound = isContentInSearchResults(query, file1.getName(), true);
|
||||
Assert.assertTrue(fileFound, "Content Not found for query: " + query);
|
||||
|
||||
testSearchQuery(query, resultCount1, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
});
|
||||
}
|
||||
|
||||
@Test(priority = 6)
|
||||
public void testSearchInFieldID() throws Exception
|
||||
{
|
||||
String query = "ID:'workspace://SpacesStore/" + file1.getNodeRefWithoutVersion() + "'";
|
||||
boolean fileFound = isContentInSearchResults(query, file1.getName(), true);
|
||||
Assert.assertTrue(fileFound, "Content Not found for query: " + query);
|
||||
|
||||
testSearchQuery(query, 1, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
}
|
||||
|
||||
@Test(priority = 7)
|
||||
public void testSearchInFieldPARENT()
|
||||
{
|
||||
String query = "PARENT:" + folder1.getNodeRefWithoutVersion();
|
||||
|
||||
Set<String> expectedNames = newHashSet();
|
||||
expectedNames.add(file1.getName());
|
||||
expectedNames.add(file2.getName());
|
||||
expectedNames.add(file3.getName());
|
||||
expectedNames.add(file4.getName());
|
||||
expectedNames.add(file5.getName());
|
||||
|
||||
testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
|
||||
|
||||
query = "PARENT:'" + folder1.getNodeRefWithoutVersion() + "\'";
|
||||
|
||||
testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
|
||||
}
|
||||
|
||||
@Test(priority = 8)
|
||||
public void testSearchInFieldPRIMARYPARENT() throws Exception
|
||||
{
|
||||
// Create Secondary association in testFolder2
|
||||
RestNodeChildAssociationModel childAssoc1 = new RestNodeChildAssociationModel(file1.getNodeRefWithoutVersion(), "cm:contains");
|
||||
String secondaryChildrenBody = "[" + childAssoc1.toJson() + "]";
|
||||
|
||||
restClient.authenticateUser(testUser).withCoreAPI().usingResource(folder2).createSecondaryChildren(secondaryChildrenBody);
|
||||
RestNodeAssociationModelCollection secondaryChildren = restClient.authenticateUser(testUser).withCoreAPI().usingResource(folder2).getSecondaryChildren();
|
||||
secondaryChildren.getEntryByIndex(0).assertThat().field("id").is(file1.getNodeRefWithoutVersion());
|
||||
|
||||
String query = "PRIMARYPARENT:'workspace://SpacesStore/" + folder1.getNodeRef() + "'";
|
||||
|
||||
Set<String> expectedNames = newHashSet();
|
||||
expectedNames.add(file1.getName());
|
||||
expectedNames.add(file2.getName());
|
||||
expectedNames.add(file3.getName());
|
||||
expectedNames.add(file4.getName());
|
||||
expectedNames.add(file5.getName());
|
||||
|
||||
testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
|
||||
|
||||
query = "PARENT:'workspace://SpacesStore/" + folder2.getNodeRef() + "'";
|
||||
boolean fileFound = isContentInSearchResults(query, file1.getName(), true);
|
||||
Assert.assertTrue(fileFound, "Expected Content Not found for query: " + query);
|
||||
|
||||
testSearchQuery(query, 1, SearchLanguage.AFTS);
|
||||
}
|
||||
|
||||
@Test(priority = 9, groups = { TestGroup.ACS_63n })
|
||||
public void testSearchInFieldNameExactMatch()
|
||||
{
|
||||
// Check that queries return consistent results with / out ''
|
||||
String query = "=name:" + file1.getName();
|
||||
boolean fileFound = isContentInSearchResults(query, file1.getName(), true);
|
||||
Assert.assertTrue(fileFound, "File Not found for query: " + query);
|
||||
|
||||
Integer resultCount1 = testSearchQuery(query, 1, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
Assert.assertSame(resultCount1, 1, "File count does not match for query: " + query);
|
||||
|
||||
query = "=name:'" + file1.getName() + "\'";
|
||||
fileFound = isContentInSearchResults(query, file1.getName(), true);
|
||||
Assert.assertTrue(fileFound, "File Not found for query: " + query);
|
||||
|
||||
testSearchQuery(query, resultCount1, SearchLanguage.AFTS).getPagination().getTotalItems();
|
||||
}
|
||||
|
||||
@Test(priority = 10, groups = { TestGroup.ACS_63n })
|
||||
public void testSearchInFieldNameQueryExpansion()
|
||||
{
|
||||
// Check that queries return consistent results with / out ''
|
||||
String query = "~name:" + file1.getName();
|
||||
|
||||
Set<String> expectedNames = newHashSet();
|
||||
expectedNames.add(file1.getName());
|
||||
expectedNames.add(file2.getName());
|
||||
expectedNames.add(file3.getName());
|
||||
expectedNames.add(file4.getName());
|
||||
expectedNames.add(folder1.getName());
|
||||
|
||||
testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
|
||||
|
||||
query = "~name:'" + file1.getName() + "\'";
|
||||
testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
|
||||
}
|
||||
|
||||
@Test(priority = 11, groups = { TestGroup.ACS_63n })
|
||||
public void testWithConjunctionDisjunctionAndNegation()
|
||||
{
|
||||
// Query string to include Conjunction, Disjunction and Negation
|
||||
|
||||
String query1 = "~name:" + file1.getName(); // Query expected to return 5 results
|
||||
String query2 = "=name:" + file2.getName(); // Query expected to return 1 result
|
||||
String query3 = "=name:" + file3.getName(); // Query expected to return 1 result
|
||||
|
||||
// Check Query with Conjunction, Negation, Disjunction: returns right results
|
||||
// "~name:file.txt and ! (=name:1-file.txt or =name:file1.txt)"
|
||||
String query = query1 + " and ! (" + query2 + " or " + query3 + ")";
|
||||
|
||||
// Check that expected files are included in the results
|
||||
Set<String> expectedNames = newHashSet();
|
||||
expectedNames.add("file.txt"); // file1
|
||||
expectedNames.add("txt file"); // file4
|
||||
expectedNames.add("file txt folder"); // folder1
|
||||
|
||||
SearchResponse response = testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
|
||||
|
||||
// Check result count is 5-(1+1)=3
|
||||
int resultCount = response.getPagination().getTotalItems();
|
||||
Assert.assertEquals(resultCount, 3, "File count does not match for query: " + query);
|
||||
|
||||
// Check that file2 and file3 are excluded from the results
|
||||
boolean fileFound = isContentInSearchResponse(response, file2.getName());
|
||||
Assert.assertFalse(fileFound, "File2 found for query: " + query);
|
||||
|
||||
fileFound = isContentInSearchResponse(response, file3.getName());
|
||||
Assert.assertFalse(fileFound, "File3 found for query: " + query);
|
||||
}
|
||||
}
|
@@ -22,7 +22,7 @@
|
||||
</distributionManagement>
|
||||
|
||||
<properties>
|
||||
<dependency.alfresco-data-model.version>8.57</dependency.alfresco-data-model.version>
|
||||
<dependency.alfresco-data-model.version>8.60</dependency.alfresco-data-model.version>
|
||||
<dependency.jackson.version>2.10.1</dependency.jackson.version>
|
||||
</properties>
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Alfresco Search Services ${project.version} Docker Image
|
||||
|
||||
FROM alfresco/alfresco-base-java:11.0.1-openjdk-centos-7-6784d76a7b81
|
||||
FROM alfresco/alfresco-base-java:11.0.1-openjdk-centos-7-7a6031154417
|
||||
LABEL creator="Gethin James" maintainer="Alfresco Search Services Team"
|
||||
|
||||
ENV DIST_DIR /opt/alfresco-search-services
|
||||
|
@@ -58,16 +58,16 @@ jackson-core-2.10.1.jar https://github.com/FasterXML/jackson
|
||||
jackson-annotations-2.10.1.jar https://github.com/FasterXML/jackson
|
||||
jackson-databind-2.10.1.jar https://github.com/FasterXML/jackson
|
||||
commons-httpclient-3.1-HTTPCLIENT-1265.jar http://jakarta.apache.org/commons/
|
||||
spring-aop-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-beans-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-context-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-context-support-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-core-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-expression-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-jdbc-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-orm-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-tx-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-web-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-aop-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-beans-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-context-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-context-support-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-core-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-expression-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-jdbc-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-orm-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-tx-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
spring-web-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
|
||||
xercesImpl-2.12.0-alfresco-patched-20191004.jar http://xerces.apache.org/xerces2-j
|
||||
guessencoding-1.4.jar http://docs.codehaus.org/display/GUESSENC/
|
||||
xml-apis-1.4.01.jar https://github.com/FasterXML/jackson
|
||||
|
Reference in New Issue
Block a user