diff --git a/src/main/java/com/arangodb/entity/CursorEntity.java b/src/main/java/com/arangodb/entity/CursorEntity.java index 24405fd0f..9e0e6a185 100644 --- a/src/main/java/com/arangodb/entity/CursorEntity.java +++ b/src/main/java/com/arangodb/entity/CursorEntity.java @@ -21,6 +21,9 @@ package com.arangodb.entity; import java.util.Collection; +import java.util.Map; + +import org.apache.http.protocol.HTTP; import com.arangodb.velocypack.VPackSlice; @@ -30,7 +33,7 @@ * @see API * Documentation */ -public class CursorEntity implements Entity { +public class CursorEntity implements Entity, MetaAware { private String id; private Integer count; @@ -38,6 +41,8 @@ public class CursorEntity implements Entity { private Boolean cached; private Boolean hasMore; private VPackSlice result; + + private Map meta; public String getId() { return id; @@ -83,6 +88,23 @@ public Boolean getHasMore() { public VPackSlice getResult() { return result; } + + public Map getMeta() { + return meta; + } + + /** + * @return remove not allowed (valid storable) meta information + */ + public Map cleanupMeta(Map meta) { + meta.remove(HTTP.CONTENT_LEN); + meta.remove(HTTP.TRANSFER_ENCODING); + return meta; + } + + public void setMeta(Map meta) { + this.meta = cleanupMeta(meta); + } public static class Warning { diff --git a/src/main/java/com/arangodb/entity/MetaAware.java b/src/main/java/com/arangodb/entity/MetaAware.java new file mode 100644 index 000000000..fe22725d6 --- /dev/null +++ b/src/main/java/com/arangodb/entity/MetaAware.java @@ -0,0 +1,15 @@ +package com.arangodb.entity; + +import java.util.Map; + +/** + * @author Mark Vollmary + * + */ +public interface MetaAware { + + public Map getMeta(); + + public void setMeta(final Map meta); + +} diff --git a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java index fc8edd784..21fb01cff 100644 --- a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java +++ b/src/main/java/com/arangodb/internal/ArangoCursorExecute.java @@ -20,6 +20,8 @@ package com.arangodb.internal; +import java.util.Map; + import com.arangodb.ArangoDBException; import com.arangodb.entity.CursorEntity; @@ -29,8 +31,8 @@ */ public interface ArangoCursorExecute { - CursorEntity next(String id) throws ArangoDBException; + CursorEntity next(String id, Map meta) throws ArangoDBException; - void close(String id) throws ArangoDBException; + void close(String id, Map meta) throws ArangoDBException; } diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 66666d9d1..c99a886e0 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -192,10 +192,13 @@ public ArangoCursor query( final Map bindVars, final AqlQueryOptions options, final Class type) throws ArangoDBException { + final Request request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); final CursorEntity result = executor.execute(request, CursorEntity.class, hostHandle); + return createCursor(result, type, options, hostHandle); + } @Override @@ -218,7 +221,7 @@ public ArangoCursor query(final String query, final Class type) throws @Override public ArangoCursor cursor(final String cursorId, final Class type) throws ArangoDBException { final HostHandle hostHandle = new HostHandle(); - final CursorEntity result = executor.execute(queryNextRequest(cursorId, null), CursorEntity.class, hostHandle); + final CursorEntity result = executor.execute(queryNextRequest(cursorId, null, null), CursorEntity.class, hostHandle); return createCursor(result, type, null, hostHandle); } @@ -227,17 +230,19 @@ private ArangoCursor createCursor( final Class type, final AqlQueryOptions options, final HostHandle hostHandle) { + final ArangoCursorExecute execute = new ArangoCursorExecute() { @Override - public CursorEntity next(final String id) { - return executor.execute(queryNextRequest(id, options), CursorEntity.class, hostHandle); + public CursorEntity next(final String id, Map meta) { + return executor.execute(queryNextRequest(id, options, meta), CursorEntity.class, hostHandle); } @Override - public void close(final String id) { - executor.execute(queryCloseRequest(id, options), Void.class, hostHandle); + public void close(final String id, Map meta) { + executor.execute(queryCloseRequest(id, options, meta), Void.class, hostHandle); } }; + return cursorInitializer != null ? cursorInitializer.createInstance(this, execute, type, result) : new ArangoCursorImpl(this, execute, type, result); } diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 9436ab047..b52562284 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -23,7 +23,11 @@ import java.io.IOException; import java.lang.reflect.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.arangodb.ArangoDBException; +import com.arangodb.entity.MetaAware; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.ArangoSerializationFactory; @@ -36,6 +40,8 @@ * */ public class ArangoExecutorSync extends ArangoExecutor { + + private static final Logger LOG = LoggerFactory.getLogger(ArangoExecutorSync.class); private final CommunicationProtocol protocol; @@ -73,6 +79,11 @@ public T execute( final Response response = protocol.execute(request, hostHandle); T deserialize = responseDeserializer.deserialize(response); + if(deserialize instanceof MetaAware) { + LOG.debug("Respone is MetaAware " + deserialize.getClass().getName()); + ((MetaAware) deserialize).setMeta(response.getMeta()); + } + return deserialize; } catch (final VPackException e) { diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java index 45d1e0389..d1379a088 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -136,7 +136,7 @@ protected void loadProperties(final Properties properties) { user = loadUser(properties, user); password = loadPassword(properties, password); useSsl = loadUseSsl(properties, useSsl); - httpCookieSpec = loadhttpCookieSpec(properties, useSsl); + httpCookieSpec = loadhttpCookieSpec(properties, httpCookieSpec); chunksize = loadChunkSize(properties, chunksize); maxConnections = loadMaxConnections(properties, maxConnections); connectionTtl = loadConnectionTtl(properties, connectionTtl); @@ -203,7 +203,7 @@ protected void setSerializer(final ArangoSerialization serializer) { protected HostResolver createHostResolver(final Collection hosts, final int maxConnections,final ConnectionFactory connectionFactory) { - if(acquireHostList) { + if(acquireHostList != null && acquireHostList) { LOG.debug("acquireHostList -> Use ExtendedHostResolver"); return new ExtendedHostResolver(new ArrayList(hosts), maxConnections, connectionFactory, acquireHostListInterval); } else { @@ -288,7 +288,7 @@ private static Boolean loadUseSsl(final Properties properties, final Boolean cur getProperty(properties, PROPERTY_KEY_USE_SSL, currentValue, ArangoDefaults.DEFAULT_USE_SSL)); } - private static String loadhttpCookieSpec(final Properties properties, final Boolean currentValue) { + private static String loadhttpCookieSpec(final Properties properties, final String currentValue) { return getProperty(properties, PROPERTY_KEY_COOKIE_SPEC, currentValue, ""); } @@ -330,8 +330,16 @@ protected static String getProperty( final String key, final T currentValue, final T defaultValue) { - return properties.getProperty(key, - currentValue != null ? currentValue.toString() : defaultValue != null ? defaultValue.toString() : null); + + String overrideDefaultValue = null; + + if(currentValue != null) { + overrideDefaultValue = currentValue.toString(); + } else if(defaultValue != null) { + overrideDefaultValue = defaultValue.toString(); + } + + return properties.getProperty(key, overrideDefaultValue); } protected Collection createHostList( diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java index bc3be8a37..daad3e2fc 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -208,21 +208,36 @@ protected Request queryRequest( return request; } - protected Request queryNextRequest(final String id, final AqlQueryOptions options) { + protected Request queryNextRequest(final String id, final AqlQueryOptions options, Map meta) { + final Request request = request(name, RequestType.PUT, PATH_API_CURSOR, id); + + if(meta != null) { + request.getHeaderParam().putAll(meta); + } + final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); + if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); } return request; } - protected Request queryCloseRequest(final String id, final AqlQueryOptions options) { + protected Request queryCloseRequest(final String id, final AqlQueryOptions options, Map meta) { + final Request request = request(name, RequestType.DELETE, PATH_API_CURSOR, id); + + if(meta != null) { + request.getHeaderParam().putAll(meta); + } + final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); + if (opt.getAllowDirtyRead() == Boolean.TRUE) { RequestUtils.allowDirtyRead(request); } + return request; } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index e105518c1..0342d466c 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -98,7 +98,7 @@ public boolean isCached() { @Override public void close() { if (id != null && hasNext()) { - execute.close(id); + execute.close(id, iterator.getResult().getMeta()); } } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index 7f1f2ebf4..1ffeb03b4 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -66,7 +66,7 @@ public boolean hasNext() { @Override public T next() { if (pos >= result.getResult().size() && result.getHasMore()) { - result = execute.next(cursor.getId()); + result = execute.next(cursor.getId(), result.getMeta()); pos = 0; } if (!hasNext()) { diff --git a/src/test/java/com/arangodb/ArangoCursorTest.java b/src/test/java/com/arangodb/ArangoCursorTest.java index b986d3c01..a8de88f9a 100644 --- a/src/test/java/com/arangodb/ArangoCursorTest.java +++ b/src/test/java/com/arangodb/ArangoCursorTest.java @@ -36,6 +36,7 @@ import org.junit.runners.Parameterized; import com.arangodb.ArangoDB.Builder; +import com.arangodb.model.AqlQueryOptions; import com.arangodb.velocypack.VPackSlice; /** @@ -57,6 +58,17 @@ public void first() { assertThat(first.isInteger(), is(true)); assertThat(first.getAsLong(), is(0L)); } + + @Test + public void next() { + + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), VPackSlice.class); + + while(cursor.hasNext()) { + cursor.next(); + } + + } @Test public void mapFilterCount() {