Skip to content

Commit daa39f3

Browse files
committed
Merge branch 'release-5.1.0' into 4.0-master
2 parents 603e23f + 7284a1a commit daa39f3

File tree

105 files changed

+5260
-2810
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+5260
-2810
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# CHANGELOG
22

3+
## 5.1.0
4+
#### New Functionality
5+
- New package to make it easy to implement connectors for dataflow frameworks. Refer to https://github.com/marklogic/java-client-api/wiki/Bulk-Data-Services page for details.
6+
- Two new splitters complementing JacksonCSVSplitter. LineSplitter for line-delimited payloads (JSON) and ZipSplitter splitter for entries in a zipfile
7+
8+
#### Improvements and Bug Fixes
9+
- [#1163](https://github.com/marklogic/java-client-api/issues/1163) - Eliminated potential for deadlocks between batches with URI sort and support for multibyte characters within uris
10+
- [#1177](https://github.com/marklogic/java-client-api/issues/1177) - Addressed security vulnerability in Jackson by upgrading Jackson dependency
11+
312
## 5.0.1
413
#### New Functionality
514
- [#636](https://github.com/marklogic/java-client-api/issues/636) - Support for debugging connection issues

NOTICE.txt

Lines changed: 108 additions & 2440 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,19 @@ The Java API supports the following core features of the MarkLogic database:
2424
* Query data structure trees, marked-up text, and all the hybrids in between those extremes.
2525
* Project values, tuples, and triples from hierarchical documents and aggregate over them.
2626
* Patch documents with partial updates.
27-
* Match documents against alerting rules expressed as queries.
2827
* Use Optimistic Locking to detect contention without creating locks on the server.
2928
* Execute ACID modifications so the change either succeeds or throws an exception.
3029
* Execute multi-statement transactions so changes to multiple documents succeed or fail together.
30+
* Call Data Services by means of a Java interface on the client for data functionality
31+
implemented by an endpoint on the server.
32+
33+
### What's New in Java Client API 5
34+
35+
* Splitters for CSV records, for entries in a ZipInputStream, and for line-delimited JSON or XML
36+
for streaming to WriteBatcher.
37+
* Support for Bulk IO Data Services to make it easy to implement connectors for dataflow
38+
frameworks - see https://github.com/marklogic/java-client-api/wiki/Bulk-Data-Services for more
39+
detail.
3140

3241
### What's New in Java Client API 4
3342

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
group=com.marklogic
2-
version=5.0.1
3-
releaseVersion=5.0.1
2+
version=5.1.0
3+
releaseVersion=5.1.0
44
describedName=MarkLogic Java Client API
55
publishUrl=file:../marklogic-java/releases

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/datamovement/functionaltests/StringQueryHostBatcherTest.java

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 MarkLogic Corporation
2+
* Copyright 2014-2020 MarkLogic Corporation
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -2221,4 +2221,109 @@ public void testQueryBatcherWithIterator() throws Exception {
22212221
clearDB();
22222222
}
22232223
}
2224+
2225+
// Verify UTF-8 char in URI. Refer to Git Issue 1163.
2226+
2227+
@Test
2228+
public void testUTF8InUri() throws Exception
2229+
{
2230+
System.out.println("Running testUTF8InUri");
2231+
DatabaseClient clientTmp = null;
2232+
DataMovementManager dmManagerTmp = null;
2233+
2234+
try {
2235+
System.out.println("Running testUTF8InUri");
2236+
2237+
String[] filenames = { "constraint1.xml", "constraint2.xml", "constraint3.xml", "constraint4.xml", "constraint5.xml" };
2238+
String combinedQueryFileName = "combinedQueryOptionJSON.json";
2239+
2240+
clientTmp = getDatabaseClient("eval-user", "x", getConnType());
2241+
dmManagerTmp = clientTmp.newDataMovementManager();
2242+
2243+
QueryManager queryMgr = clientTmp.newQueryManager();
2244+
String dataFileDir = dataConfigDirPath + "/data/";
2245+
String combQueryFileDir = dataConfigDirPath + "/combined/";
2246+
2247+
// Use WriteBatcher to write the same files.
2248+
WriteBatcher wbatcher = dmManagerTmp.newWriteBatcher();
2249+
2250+
wbatcher.withBatchSize(2);
2251+
InputStreamHandle contentHandle1 = new InputStreamHandle();
2252+
contentHandle1.set(new FileInputStream(dataFileDir + filenames[0]));
2253+
InputStreamHandle contentHandle2 = new InputStreamHandle();
2254+
contentHandle2.set(new FileInputStream(dataFileDir + filenames[1]));
2255+
InputStreamHandle contentHandle3 = new InputStreamHandle();
2256+
contentHandle3.set(new FileInputStream(dataFileDir + filenames[2]));
2257+
InputStreamHandle contentHandle4 = new InputStreamHandle();
2258+
contentHandle4.set(new FileInputStream(dataFileDir + filenames[3]));
2259+
InputStreamHandle contentHandle5 = new InputStreamHandle();
2260+
contentHandle5.set(new FileInputStream(dataFileDir + filenames[4]));
2261+
2262+
wbatcher.add(filenames[0], contentHandle1);
2263+
wbatcher.add(filenames[1], contentHandle2);
2264+
wbatcher.add(filenames[2], contentHandle3);
2265+
wbatcher.add(filenames[3], contentHandle4);
2266+
wbatcher.add("/CXXXX_Ü_testqa.xml", contentHandle5);
2267+
2268+
wbatcher.flushAndWait();
2269+
2270+
// get the combined query
2271+
File file = new File(combQueryFileDir + combinedQueryFileName);
2272+
2273+
// create a handle for the search criteria
2274+
FileHandle rawHandle = (new FileHandle(file)).withFormat(Format.JSON);
2275+
// create a search definition based on the handle
2276+
RawCombinedQueryDefinition querydef = queryMgr.newRawCombinedQueryDefinition(rawHandle);
2277+
2278+
StringBuilder batchResults = new StringBuilder();
2279+
StringBuilder batchFailResults = new StringBuilder();
2280+
2281+
// Run a QueryBatcher on the new URIs.
2282+
QueryBatcher queryBatcher1 = dmManagerTmp.newQueryBatcher(querydef);
2283+
2284+
queryBatcher1.onUrisReady(batch -> {
2285+
for (String str : batch.getItems()) {
2286+
batchResults.append(str)
2287+
.append('|');
2288+
}
2289+
});
2290+
queryBatcher1.onQueryFailure(throwable -> {
2291+
System.out.println("Exceptions thrown from callback onQueryFailure");
2292+
throwable.printStackTrace();
2293+
batchFailResults.append("Test has Exceptions");
2294+
});
2295+
2296+
dmManagerTmp.startJob(queryBatcher1);
2297+
boolean bJobFinished = queryBatcher1.awaitCompletion(3, TimeUnit.MINUTES);
2298+
2299+
if (bJobFinished) {
2300+
2301+
if (!batchFailResults.toString().isEmpty() && batchFailResults.toString().contains("Exceptions")) {
2302+
fail("Test failed due to exceptions");
2303+
}
2304+
2305+
// Verify the batch results now.
2306+
String[] res = batchResults.toString().split("\\|");
2307+
assertEquals("Number of reults returned is incorrect", 1, res.length);
2308+
assertTrue("URI returned not correct", res[0].trim().contains("/CXXXX_Ü_testqa.xml"));
2309+
2310+
// Read the document and assert on the value
2311+
DOMHandle contentHandle = new DOMHandle();
2312+
contentHandle = readDocumentUsingDOMHandle(clientTmp, "/CXXXX_Ü_testqa.xml", "XML");
2313+
Document readDoc = contentHandle.get();
2314+
System.out.println(convertXMLDocumentToString(readDoc));
2315+
2316+
assertTrue("Document content returned not correct", readDoc.getElementsByTagName("id").item(0).getTextContent().contains("0026"));
2317+
assertTrue("Document content returned not correct", readDoc.getElementsByTagName("title").item(0).getTextContent().contains("The memex"));
2318+
assertTrue("Document content returned not correct", readDoc.getElementsByTagName("date").item(0).getTextContent().contains("2009-05-05"));
2319+
}
2320+
} catch (Exception e) {
2321+
System.out.println("Exceptions thrown from testUTF8InUri");
2322+
System.out.println(e.getMessage());
2323+
fail("testUTF8InUri mathod failed");
2324+
} finally {
2325+
clientTmp.release();
2326+
clearDB();
2327+
}
2328+
}
22242329
}

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/datamovement/functionaltests/WriteHostBatcherTest.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 MarkLogic Corporation
2+
* Copyright 2014-2020 MarkLogic Corporation
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -246,14 +246,22 @@ private void replenishStream() throws Exception {
246246
// the callback receives the output stream
247247
public void write(OutputStream out) throws IOException {
248248
// acquire the content
249-
InputStream docStreamwrongjson = new FileInputStream(
250-
WriteHostBatcherTest.class.getResource(TEST_DIR_PREFIX + "WrongFormat.json").getPath());
249+
InputStream docStreamwrongjson = null;
250+
try {
251+
docStreamwrongjson = new FileInputStream(
252+
WriteHostBatcherTest.class.getResource(TEST_DIR_PREFIX + "WrongFormat.json").getPath());
251253

252-
// copy content to the output stream
253-
byte[] buf = new byte[1024];
254-
int byteCount = 0;
255-
while ((byteCount = docStreamwrongjson.read(buf)) != -1) {
256-
out.write(buf, 0, byteCount);
254+
// copy content to the output stream
255+
byte[] buf = new byte[1024];
256+
int byteCount = 0;
257+
while ((byteCount = docStreamwrongjson.read(buf)) != -1) {
258+
out.write(buf, 0, byteCount);
259+
}
260+
} catch (Exception e) {
261+
e.printStackTrace();
262+
}
263+
finally {
264+
docStreamwrongjson.close();
257265
}
258266

259267
}
@@ -1434,7 +1442,7 @@ public void run() {
14341442
// TODO Auto-generated catch block
14351443
e.printStackTrace();
14361444
}
1437-
Set threads = Thread.getAllStackTraces().keySet();
1445+
Set<Thread> threads = Thread.getAllStackTraces().keySet();
14381446
Iterator<Thread> iter = threads.iterator();
14391447
while (iter.hasNext()) {
14401448
Thread t = iter.next();
@@ -1519,7 +1527,7 @@ public void run() {
15191527
// TODO Auto-generated catch block
15201528
e.printStackTrace();
15211529
}
1522-
Set threads = Thread.getAllStackTraces().keySet();
1530+
Set<Thread> threads = Thread.getAllStackTraces().keySet();
15231531
Iterator<Thread> iter = threads.iterator();
15241532
while (iter.hasNext()) {
15251533
Thread t = iter.next();
@@ -1611,7 +1619,7 @@ public void run() {
16111619
// TODO Auto-generated catch block
16121620
e.printStackTrace();
16131621
}
1614-
Set threads = Thread.getAllStackTraces().keySet();
1622+
Set<Thread> threads = Thread.getAllStackTraces().keySet();
16151623
Iterator<Thread> iter = threads.iterator();
16161624
while (iter.hasNext()) {
16171625
Thread t = iter.next();
@@ -1762,7 +1770,7 @@ public void run() {
17621770
}
17631771
Iterator<Entry<String, Integer>> it = threadMap.entrySet().iterator();
17641772
while (it.hasNext()) {
1765-
Map.Entry<String, Integer> pair = (Map.Entry) it.next();
1773+
Map.Entry<String, Integer> pair = (Entry<String, Integer>) it.next();
17661774
System.out.println("Thread pool: " + pair.getKey() + " = " + pair.getValue() + " Threads");
17671775
if (pair.getValue() == 20) {
17681776
count.set(true);
@@ -1823,6 +1831,7 @@ public void testNPESuccessCallBack() throws Exception {
18231831
System.out.println("Job writes " + batch.getJobWritesSoFar());
18241832
successCount.getAndAdd(batch.getItems().length);
18251833
String s = null;
1834+
// s.length is called purposefully to set off NEE.
18261835
s.length();
18271836

18281837
}).onBatchFailure((batch, throwable) -> {
@@ -2364,8 +2373,6 @@ public void testNullConfig() throws Exception {
23642373

23652374
final String query1 = "fn:count(fn:doc())";
23662375

2367-
DocumentMetadataHandle meta6 = new DocumentMetadataHandle().withCollections("NoHost").withQuality(0);
2368-
23692376
Assert.assertTrue(dbClient.newServerEval().xquery(query1).eval().next().getNumber().intValue() == 0);
23702377

23712378
WriteBatcher ihb2 = dmManager.newWriteBatcher();
@@ -2910,7 +2917,7 @@ public void testDocumentWriteOperationAdd() throws Exception {
29102917

29112918
metadataHandle.setQuality(23);
29122919
DocumentWriteOperationImpl docWriteOpsImp4 = new DocumentWriteOperationImpl(
2913-
OperationType.DISABLE_METADATA_DEFAULT,
2920+
OperationType.DOCUMENT_WRITE,
29142921
docId[4],
29152922
metadataHandle,
29162923
contHandle5

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/functionaltest/TestEvalJavaScript.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 MarkLogic Corporation
2+
* Copyright 2014-2020 MarkLogic Corporation
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -78,22 +78,22 @@ public static void setUpBeforeClass() throws Exception {
7878
configureRESTServer(dbName, fNames, false);
7979
TestEvalXquery.createUserRolesWithPrevilages("test-js-eval", "xdbc:eval", "xdbc:eval-in", "xdmp:eval-in", "xdmp:invoke-in", "xdmp:invoke", "xdbc:invoke-in", "any-uri",
8080
"xdbc:invoke");
81-
TestEvalXquery.createRESTUser("eval-user", "x", "test-js-eval");
81+
TestEvalXquery.createRESTUser("eval-userJS", "x", "test-js-eval");
8282
appServerHostname = getRestAppServerHostName();
8383
}
8484

8585
@AfterClass
8686
public static void tearDownAfterClass() throws Exception {
8787
System.out.println("In tear down");
8888
cleanupRESTServer(dbName, fNames);
89-
TestEvalXquery.deleteRESTUser("eval-user");
89+
TestEvalXquery.deleteRESTUser("eval-userJS");
9090
TestEvalXquery.deleteUserRole("test-js-eval");
9191
}
9292

9393
@Before
9494
public void setUp() throws KeyManagementException, NoSuchAlgorithmException, Exception {
9595
int restPort = getRestServerPort();
96-
client = getDatabaseClientOnDatabase(appServerHostname, restPort, dbName, "eval-user", "x", getConnType());
96+
client = getDatabaseClientOnDatabase(appServerHostname, restPort, dbName, "eval-userJS", "x", getConnType());
9797
}
9898

9999
@After
@@ -579,8 +579,8 @@ public void testJSReturningDifferentTypesOrder3fromModules() throws Exception {
579579
Capability.UPDATE, Capability.READ, Capability.EXECUTE);
580580
DocumentManager dm = moduleClient.newDocumentManager();
581581
dm.write("/data/javascriptQueries.sjs", metadataHandle, ish);
582-
DocumentBuilder db = DocumentBuilderFactory.newInstance()
583-
.newDocumentBuilder();
582+
/*DocumentBuilder db = DocumentBuilderFactory.newInstance()
583+
.newDocumentBuilder();*/
584584
InputSource is = new InputSource();
585585
is.setCharacterStream(new StringReader(
586586
"<foo attr=\"attribute\"><?processing instruction?><!--comment-->test1</foo>"));

marklogic-client-api/build.gradle

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ dependencies {
1818
compile group: 'com.sun.mail', name: 'javax.mail', version:'1.6.1'
1919
compile group: 'javax.ws.rs', name: 'javax.ws.rs-api', version:'2.1'
2020
compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.25'
21-
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version:'2.9.8'
22-
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version:'2.9.8'
23-
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version:'2.9.8'
24-
compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-csv', version:'2.9.8'
21+
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version:'2.10.1'
22+
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version:'2.10.1'
23+
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version:'2.10.1'
24+
compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-csv', version:'2.10.1'
2525
testCompile group: 'org.mockito', name: 'mockito-all', version:'1.10.19'
26-
testCompile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version:'2.9.8'
26+
testCompile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version:'2.10.1'
2727
testCompile group: 'ch.qos.logback', name: 'logback-classic', version:'1.2.3'
2828
testCompile group: 'org.hsqldb', name: 'hsqldb', version:'2.4.0'
2929
compileOnly group: 'org.jdom', name: 'jdom2', version:'2.0.6'

marklogic-client-api/src/main/java/com/marklogic/client/DatabaseClientFactory.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,17 @@ public HostnameVerifierAdapter(SSLHostnameVerifier verifier) {
158158
/**
159159
* verify method verifies the incoming hostname and SSLSession.
160160
* @param hostname denotes the hostname.
161-
* @param session represents the SSLSession containing the pper certificates.
161+
* @param session represents the SSLSession containing the peer certificates.
162162
* @return true if the hostname and peer certificates are valid and false if they are invalid.
163163
* */
164164
@Override
165165
public boolean verify(String hostname, SSLSession session) {
166166
try {
167167
Certificate[] certificates = session.getPeerCertificates();
168-
verify(hostname, (X509Certificate) certificates[0]);
168+
verify(
169+
hostname,
170+
(X509Certificate) ((certificates == null || certificates.length == 0) ? null : certificates[0])
171+
);
169172
return true;
170173
} catch(SSLException e) {
171174
return false;
@@ -1496,11 +1499,11 @@ static public class Bean implements Serializable {
14961499
private String password;
14971500
private Authentication authentication;
14981501
private String externalName;
1499-
private SecurityContext securityContext;
15001502
private DatabaseClient.ConnectionType connectionType;
1501-
private HandleFactoryRegistry handleRegistry =
1502-
HandleFactoryRegistryImpl.newDefault();
15031503

1504+
transient private SecurityContext securityContext;
1505+
transient private HandleFactoryRegistry handleRegistry =
1506+
HandleFactoryRegistryImpl.newDefault();
15041507
transient private SSLContext context;
15051508
transient private SSLHostnameVerifier verifier;
15061509

marklogic-client-api/src/main/java/com/marklogic/client/bitemporal/TemporalDocumentManager.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@
2121
import javax.xml.bind.DatatypeConverter;
2222
import javax.xml.datatype.Duration;
2323

24-
import com.marklogic.client.FailedRequestException;
25-
import com.marklogic.client.ForbiddenUserException;
26-
import com.marklogic.client.ResourceNotFoundException;
27-
import com.marklogic.client.Transaction;
24+
import com.marklogic.client.*;
2825
import com.marklogic.client.bitemporal.TemporalDescriptor;
2926
import com.marklogic.client.document.DocumentDescriptor;
3027
import com.marklogic.client.document.DocumentManager;
@@ -68,8 +65,9 @@ public String toString() {
6865
return "noWipe";
6966
case NOUPDATE:
7067
return "noUpdate";
68+
default:
69+
throw new MarkLogicInternalException("Unknown enumeration");
7170
}
72-
return null;
7371
}
7472
}
7573

0 commit comments

Comments
 (0)