From a400f156925a046e7e3a7a8446134a973a736837 Mon Sep 17 00:00:00 2001
From: ccx1024cc <1261138729@qq.com>
Date: Thu, 2 Dec 2021 14:41:28 +0800
Subject: [PATCH] feat(java-sdk): java sdk support File API (#325)
---
sdk/java-sdk/README-zh.md | 1 +
sdk/java-sdk/README.md | 1 +
sdk/java-sdk/examples/pom.xml | 2 +-
.../io/mosn/layotto/examples/file/File.java | 132 +++++
sdk/java-sdk/pom.xml | 2 +-
sdk/java-sdk/sdk/pom.xml | 2 +-
.../io/mosn/layotto/v1/RuntimeClientGrpc.java | 494 +++++++++++++++++-
.../sdk/runtime/v1/domain/FileRuntime.java | 48 ++
.../v1/domain/file/DelFileRequest.java | 56 ++
.../v1/domain/file/DelFileResponse.java | 18 +
.../sdk/runtime/v1/domain/file/FileInfo.java | 69 +++
.../v1/domain/file/GetFileRequest.java | 55 ++
.../v1/domain/file/GetFileResponse.java | 34 ++
.../v1/domain/file/GetMetaRequest.java | 55 ++
.../v1/domain/file/GetMeteResponse.java | 53 ++
.../v1/domain/file/ListFileRequest.java | 73 +++
.../v1/domain/file/ListFileResponse.java | 52 ++
.../v1/domain/file/PutFileRequest.java | 66 +++
.../v1/domain/file/PutFileResponse.java | 18 +
.../java/io/mosn/layotto/v1/FileTest.java | 360 +++++++++++++
.../layotto/v1/FileTestWithRealServer.java | 366 +++++++++++++
.../mosn/layotto/v1/mock/MyFileService.java | 143 +++++
22 files changed, 2095 insertions(+), 5 deletions(-)
create mode 100644 sdk/java-sdk/examples/src/test/java/io/mosn/layotto/examples/file/File.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java
create mode 100644 sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java
create mode 100644 sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTest.java
create mode 100644 sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java
create mode 100644 sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java
diff --git a/sdk/java-sdk/README-zh.md b/sdk/java-sdk/README-zh.md
index 4c80e9fb67..bffda113df 100644
--- a/sdk/java-sdk/README-zh.md
+++ b/sdk/java-sdk/README-zh.md
@@ -78,6 +78,7 @@ mvn clean install
* [Hello world](./examples/src/test/java/io/mosn/layotto/examples/helloworld)
* [State management](./examples/src/test/java/io/mosn/layotto/examples/state)
* [Pubsub API](./examples/src/test/java/io/mosn/layotto/examples/pubsub)
+* [File API](./examples/src/test/java/io/mosn/layotto/examples/file)
## java sdk开发指南
### java sdk职责
diff --git a/sdk/java-sdk/README.md b/sdk/java-sdk/README.md
index 66a34ad8e2..ad241c07d8 100644
--- a/sdk/java-sdk/README.md
+++ b/sdk/java-sdk/README.md
@@ -49,6 +49,7 @@ Try the following examples to learn more about this SDK:
* [Hello world](./examples/src/test/java/io/mosn/layotto/examples/helloworld)
* [State management](./examples/src/test/java/io/mosn/layotto/examples/state)
* [Pubsub API](./examples/src/test/java/io/mosn/layotto/examples/pubsub)
+* [File API](./examples/src/test/java/io/mosn/layotto/examples/file)
## java sdk developer guide
### How to format java sdk code
diff --git a/sdk/java-sdk/examples/pom.xml b/sdk/java-sdk/examples/pom.xml
index 039d2dbef8..015e86ba45 100644
--- a/sdk/java-sdk/examples/pom.xml
+++ b/sdk/java-sdk/examples/pom.xml
@@ -7,7 +7,7 @@
runtime-sdk-parent
io.mosn.layotto
- 1.0.0
+ 1.1.0-SNAPSHOT
examples
diff --git a/sdk/java-sdk/examples/src/test/java/io/mosn/layotto/examples/file/File.java b/sdk/java-sdk/examples/src/test/java/io/mosn/layotto/examples/file/File.java
new file mode 100644
index 0000000000..d5ccd1acae
--- /dev/null
+++ b/sdk/java-sdk/examples/src/test/java/io/mosn/layotto/examples/file/File.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.examples.file;
+
+import io.mosn.layotto.v1.RuntimeClientBuilder;
+import io.mosn.layotto.v1.config.RuntimeProperties;
+import spec.sdk.runtime.v1.client.RuntimeClient;
+import spec.sdk.runtime.v1.domain.file.PutFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetFileRequest;
+import spec.sdk.runtime.v1.domain.file.ListFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetMetaRequest;
+import spec.sdk.runtime.v1.domain.file.DelFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetFileResponse;
+import spec.sdk.runtime.v1.domain.file.ListFileResponse;
+import spec.sdk.runtime.v1.domain.file.FileInfo;
+import spec.sdk.runtime.v1.domain.file.GetMeteResponse;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * Specially
+ *
+ * 1. add `"local:{}` to "files" node in layotto/configs/config_file.json
+ * 2. start server by `./layotto start -c ../../configs/config_file.json`
+ */
+public class File {
+
+ private static final Logger logger = Logger.getLogger(File.class.getName());
+
+ static String storeName = "local";
+ static String fileName = "/tmp/test.log";
+
+ public static void main(String[] args) throws Exception {
+
+ RuntimeClient client = new RuntimeClientBuilder()
+ .withPort(RuntimeProperties.DEFAULT_PORT)
+ .build();
+
+ putFile(client);
+ getFile(client);
+ listFile(client);
+ getFileMeta(client);
+ delFile(client);
+ }
+
+ public static void putFile(RuntimeClient client) throws Exception {
+
+ PutFileRequest request = new PutFileRequest();
+ request.setStoreName(storeName);
+ request.setFileName(fileName);
+
+ Map meta = new HashMap<>();
+ meta.put("FileMode", "521");
+ meta.put("FileFlag", "0777");
+ request.setMetaData(meta);
+
+ request.setIn(new ByteArrayInputStream("hello world".getBytes()));
+
+ client.putFile(request, 3000);
+ }
+
+ public static void getFile(RuntimeClient client) throws Exception {
+
+ GetFileRequest request = new GetFileRequest();
+ request.setStoreName(storeName);
+ request.setFileName(fileName);
+
+ Map meta = new HashMap<>();
+ meta.put("k1", "v1");
+ request.setMetaData(meta);
+
+ GetFileResponse resp = client.getFile(request, 3000);
+
+ InputStream reader = resp.getIn();
+
+ byte[] buf = new byte[128];
+ for (int len = reader.read(buf); len > 0; len = reader.read(buf)) {
+ logger.info(new String(buf, 0, len));
+ }
+ }
+
+ public static void delFile(RuntimeClient client) throws Exception {
+
+ DelFileRequest request = new DelFileRequest();
+ request.setStoreName(storeName);
+ request.setFileName(fileName);
+
+ client.delFile(request, 3000);
+ }
+
+ public static void listFile(RuntimeClient client) throws Exception {
+
+ ListFileRequest request = new ListFileRequest();
+ request.setStoreName(storeName);
+ request.setMarker("test.log");
+ request.setName("/tmp");
+ request.setPageSize(10);
+
+ ListFileResponse resp = client.listFile(request, 3000);
+
+ for (FileInfo f : resp.getFiles()) {
+ logger.info(f.getFileName());
+ }
+ }
+
+ public static void getFileMeta(RuntimeClient client) throws Exception {
+
+ GetMetaRequest request = new GetMetaRequest();
+ request.setStoreName(storeName);
+ request.setFileName(fileName);
+
+ GetMeteResponse response = client.getFileMeta(request, 3000);
+ logger.info(response.getLastModified());
+ logger.info("" + response.getMeta().size());
+ }
+}
diff --git a/sdk/java-sdk/pom.xml b/sdk/java-sdk/pom.xml
index 800fcc5d1d..8539decf36 100644
--- a/sdk/java-sdk/pom.xml
+++ b/sdk/java-sdk/pom.xml
@@ -5,7 +5,7 @@
io.mosn.layotto
runtime-sdk-parent
- 1.0.0
+ 1.1.0-SNAPSHOT
pom
runtime-sdk-parent
diff --git a/sdk/java-sdk/sdk/pom.xml b/sdk/java-sdk/sdk/pom.xml
index c1a567ccc6..57e8d51182 100644
--- a/sdk/java-sdk/sdk/pom.xml
+++ b/sdk/java-sdk/sdk/pom.xml
@@ -6,7 +6,7 @@
io.mosn.layotto
runtime-sdk-parent
- 1.0.0
+ 1.1.0-SNAPSHOT
runtime-sdk
diff --git a/sdk/java-sdk/sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java b/sdk/java-sdk/sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java
index 31b5a1b444..fdc14dda2b 100644
--- a/sdk/java-sdk/sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java
+++ b/sdk/java-sdk/sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java
@@ -17,8 +17,11 @@
import com.google.common.base.Strings;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
+import com.google.protobuf.Empty;
import io.grpc.Metadata;
+import io.grpc.StatusRuntimeException;
import io.grpc.stub.MetadataUtils;
+import io.grpc.stub.StreamObserver;
import io.mosn.layotto.v1.config.RuntimeProperties;
import io.mosn.layotto.v1.exceptions.RuntimeClientException;
import io.mosn.layotto.v1.grpc.GrpcRuntimeClient;
@@ -27,13 +30,37 @@
import org.slf4j.Logger;
import spec.proto.runtime.v1.RuntimeGrpc;
import spec.proto.runtime.v1.RuntimeProto;
+import spec.sdk.runtime.v1.domain.file.GetFileRequest;
+import spec.sdk.runtime.v1.domain.file.PutFileRequest;
+import spec.sdk.runtime.v1.domain.file.DelFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetFileResponse;
+import spec.sdk.runtime.v1.domain.file.PutFileResponse;
+import spec.sdk.runtime.v1.domain.file.DelFileResponse;
+import spec.sdk.runtime.v1.domain.file.ListFileResponse;
+import spec.sdk.runtime.v1.domain.file.ListFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetMeteResponse;
+import spec.sdk.runtime.v1.domain.file.GetMetaRequest;
+import spec.sdk.runtime.v1.domain.file.FileInfo;
import spec.sdk.runtime.v1.domain.invocation.InvokeResponse;
-import spec.sdk.runtime.v1.domain.state.*;
+import spec.sdk.runtime.v1.domain.state.DeleteStateRequest;
+import spec.sdk.runtime.v1.domain.state.SaveStateRequest;
+import spec.sdk.runtime.v1.domain.state.State;
+import spec.sdk.runtime.v1.domain.state.StateOptions;
+import spec.sdk.runtime.v1.domain.state.ExecuteStateTransactionRequest;
+import spec.sdk.runtime.v1.domain.state.TransactionalStateOperation;
+import spec.sdk.runtime.v1.domain.state.GetStateRequest;
+import spec.sdk.runtime.v1.domain.state.GetBulkStateRequest;
import java.io.IOException;
+import java.io.PipedOutputStream;
+import java.io.PipedInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class RuntimeClientGrpc extends AbstractRuntimeClient implements GrpcRuntimeClient {
@@ -108,7 +135,7 @@ public InvokeResponse invokeMethod(String appId, String methodName, byte
// 3. parse result
InvokeResponse result = new InvokeResponse<>();
result.setContentType(resp.getContentType());
- byte[] bytes = new byte[] {};
+ byte[] bytes = new byte[]{};
result.setData(bytes);
if (resp.getData() == null) {
return result;
@@ -501,4 +528,467 @@ public StubManager get
public void shutdown() {
stubManager.destroy();
}
+
+ @Override
+ public PutFileResponse putFile(PutFileRequest request, int timeoutMs) throws Exception {
+
+ checkParamOfPutFile(request);
+
+ PutFileFuture putFuture = new PutFileFuture(request.getFileName());
+ StreamObserver observer = createPutFileObserver(putFuture, timeoutMs);
+
+ observer.onNext(buildPutFileMetaDataRequest(request.getStoreName(), request.getFileName(),
+ request.getMetaData()));
+
+ byte[] buf = new byte[4096];
+ for (int size = request.getIn().read(buf); size > 0; size = request.getIn().read(buf)) {
+ observer.onNext(buildPutFileDataRequest(buf, size));
+ }
+
+ observer.onCompleted();
+
+ putFuture.awaitDone(timeoutMs);
+
+ return new PutFileResponse();
+ }
+
+ @Override
+ public GetFileResponse getFile(GetFileRequest request, int timeoutMs) throws Exception {
+
+ checkParamOfGetFile(request);
+
+ GetFilePipe pipe = new GetFilePipe(request.getFileName());
+
+ stubManager.
+ getAsyncStub().
+ getFile(
+ buildGetFileRequest(
+ request.getStoreName(),
+ request.getFileName(),
+ request.getMetaData()),
+ pipe);
+
+ return new GetFileResponse(pipe.getReader());
+ }
+
+ @Override
+ public ListFileResponse listFile(ListFileRequest request, int timeoutMs) throws Exception {
+
+ checkParamOfListFile(request);
+
+ RuntimeProto.ListFileResp response = stubManager.
+ getBlockingStub().
+ withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS).
+ listFile(
+ buildListFileRequest(
+ request.getStoreName(),
+ request.getName(),
+ request.getMarker(),
+ request.getPageSize(),
+ request.getMetaData()));
+
+ return buildListFileResponse(response);
+ }
+
+ @Override
+ public DelFileResponse delFile(DelFileRequest request, int timeoutMs) throws Exception {
+
+ checkParamOfDeleteFile(request);
+
+ stubManager.
+ getBlockingStub().
+ withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS).
+ delFile(
+ buildDelFileRequest(request.getStoreName(), request.getFileName(), request.getMetaData()));
+
+ return new DelFileResponse();
+ }
+
+ @Override
+ public GetMeteResponse getFileMeta(GetMetaRequest request, int timeoutMs) throws Exception {
+
+ checkParamOfGetFileMeta(request);
+
+ RuntimeProto.GetFileMetaResponse resp = stubManager.
+ getBlockingStub().
+ withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS).
+ getFileMeta(
+ buildGetFileMetaRequest(request.getStoreName(), request.getFileName(), request.getMetaData()));
+
+ return buildGetFileMetaResponse(resp);
+ }
+
+ private void checkParamOfGetFile(GetFileRequest request) {
+
+ // check request
+ if (request == null) {
+ throw new IllegalArgumentException("miss request");
+ }
+
+ // check store name
+ if (request.getStoreName() == null) {
+ throw new IllegalArgumentException("miss store name");
+ }
+
+ // check file name
+ if (request.getFileName() == null) {
+ throw new IllegalArgumentException("miss file name");
+ }
+ }
+
+ private void checkParamOfPutFile(PutFileRequest request) {
+
+ // check request
+ if (request == null) {
+ throw new IllegalArgumentException("miss request");
+ }
+
+ // check store name
+ if (request.getStoreName() == null) {
+ throw new IllegalArgumentException("miss store name");
+ }
+
+ // check file name
+ if (request.getFileName() == null) {
+ throw new IllegalArgumentException("miss file name");
+ }
+
+ // check input stream
+ if (request.getIn() == null) {
+ throw new IllegalArgumentException("miss file stream");
+ }
+ }
+
+ private void checkParamOfListFile(ListFileRequest request) {
+
+ // check request
+ if (request == null) {
+ throw new IllegalArgumentException("miss request");
+ }
+
+ // check store name
+ if (request.getStoreName() == null) {
+ throw new IllegalArgumentException("miss store name");
+ }
+ }
+
+ private void checkParamOfDeleteFile(DelFileRequest request) {
+
+ // check request
+ if (request == null) {
+ throw new IllegalArgumentException("miss request");
+ }
+
+ // check file name
+ if (request.getFileName() == null) {
+ throw new IllegalArgumentException("miss file name");
+ }
+
+ // check store name
+ if (request.getStoreName() == null) {
+ throw new IllegalArgumentException("miss store name");
+ }
+ }
+
+ private void checkParamOfGetFileMeta(GetMetaRequest request) {
+
+ // check request
+ if (request == null) {
+ throw new IllegalArgumentException("miss request");
+ }
+
+ // check store name
+ if (request.getStoreName() == null) {
+ throw new IllegalArgumentException("miss store name");
+ }
+
+ // check file name
+ if (request.getFileName() == null) {
+ throw new IllegalArgumentException("miss file name");
+ }
+ }
+
+ private class PutFileFuture implements StreamObserver {
+
+ private final String fileName;
+ private final CountDownLatch latch;
+
+ private volatile Throwable t;
+
+ PutFileFuture(String fileName) {
+ this.fileName = fileName;
+ this.latch = new CountDownLatch(1);
+ }
+
+ @Override
+ public void onNext(Empty value) {
+ logger.info(String.format("put File %s successfully", this.fileName));
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ logger.error(String.format("put File error, file=%s", this.fileName), t);
+ this.t = t;
+ this.latch.countDown();
+ }
+
+ @Override
+ public void onCompleted() {
+ logger.info(String.format("put File %s complete", this.fileName));
+ latch.countDown();
+ }
+
+ public void awaitDone(int timeoutMs) throws Exception {
+
+ boolean finished = latch.await(timeoutMs, TimeUnit.MILLISECONDS);
+ if (!finished) {
+ String tip = String.format("put file timeout, file=%s", fileName);
+ throw new RuntimeClientException("PUT_FILE", tip);
+ }
+
+ // do not wrap for grpc Exception
+ if (t instanceof StatusRuntimeException) {
+ throw (StatusRuntimeException) t;
+ }
+
+ // wrap exception for non grpc Exception
+ if (t != null) {
+ throw new RuntimeClientException(t);
+ }
+ }
+ }
+
+ private class PipeFileInputStream extends PipedInputStream {
+
+ private volatile Throwable cause;
+
+ PipeFileInputStream(PipedOutputStream out) throws IOException {
+ super(out);
+ }
+
+ @Override
+ public synchronized int read() throws IOException {
+
+ checkCause();
+
+ return super.read();
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+
+ checkCause();
+
+ return super.read(b);
+ }
+
+ @Override
+ public synchronized int read(byte[] b, int off, int len) throws IOException {
+
+ checkCause();
+
+ return super.read(b, off, len);
+ }
+
+ private void checkCause() throws IOException {
+ if (this.cause != null) {
+ this.close();
+ throw new IOException(this.cause);
+ }
+ }
+
+ public void setCause(Throwable cause) {
+ this.cause = cause;
+ }
+ }
+
+ private class GetFilePipe implements StreamObserver {
+
+ private final String fileName;
+ private final PipeFileInputStream reader;
+ private final PipedOutputStream dataSource;
+
+ GetFilePipe(String fileName) throws IOException {
+ this.fileName = fileName;
+ this.dataSource = new PipedOutputStream();
+ this.reader = new PipeFileInputStream(this.dataSource);
+ }
+
+ @Override
+ public void onNext(RuntimeProto.GetFileResponse value) {
+
+ logger.info(String.format("get File %s successfully", this.fileName));
+
+ pipe(value.getData().toByteArray());
+ }
+
+ @Override
+ public void onError(Throwable t) {
+
+ logger.error(String.format("get File error, file=%s", this.fileName), t);
+
+ reader.setCause(t);
+
+ pipe(t.getMessage().getBytes());
+ }
+
+ @Override
+ public void onCompleted() {
+
+ logger.info(String.format("get File %s complete", this.fileName));
+
+ close();
+ }
+
+ private void pipe(byte[] data) {
+ try {
+ dataSource.write(data);
+ } catch (IOException e) {
+ logger.error("get File transform err", e);
+ }
+ }
+
+ private void close() {
+ try {
+ dataSource.close();
+ } catch (IOException e) {
+ logger.error("get File close stream err", e);
+ }
+ }
+
+ public InputStream getReader() {
+ return this.reader;
+ }
+ }
+
+ private StreamObserver createPutFileObserver(
+ StreamObserver callBackObserver,
+ int timeoutMs) {
+
+ return stubManager.
+ getAsyncStub().
+ withDeadlineAfter(timeoutMs, TimeUnit.MILLISECONDS).
+ putFile(callBackObserver);
+ }
+
+ private RuntimeProto.PutFileRequest buildPutFileMetaDataRequest(String storeName,
+ String fileName,
+ Map meta) {
+ return RuntimeProto.PutFileRequest.
+ newBuilder().
+ setStoreName(storeName).
+ setName(fileName).
+ putAllMetadata(meta).
+ build();
+ }
+
+ private RuntimeProto.PutFileRequest buildPutFileDataRequest(byte[] bytes, int size) {
+
+ return RuntimeProto.PutFileRequest.
+ newBuilder().
+ setData(ByteString.copyFrom(bytes, 0, size)).
+ build();
+ }
+
+ private RuntimeProto.GetFileRequest buildGetFileRequest(String storeName,
+ String fileName,
+ Map meta) {
+
+ return RuntimeProto.GetFileRequest.
+ newBuilder().
+ setStoreName(storeName).
+ setName(fileName).
+ putAllMetadata(meta).
+ build();
+ }
+
+ private RuntimeProto.ListFileRequest buildListFileRequest(String storeName, String name, String marker,
+ int pageSize, Map meta) {
+
+ RuntimeProto.FileRequest fileRequest = RuntimeProto.FileRequest.
+ newBuilder().
+ setStoreName(storeName).
+ setName(name).
+ putAllMetadata(meta).
+ build();
+
+ return RuntimeProto.ListFileRequest.
+ newBuilder().
+ setRequest(fileRequest).
+ setMarker(marker).
+ setPageSize(pageSize).
+ build();
+ }
+
+ private RuntimeProto.DelFileRequest buildDelFileRequest(String storeName,
+ String fileName,
+ Map meta) {
+
+ RuntimeProto.FileRequest fileRequest = RuntimeProto.FileRequest.
+ newBuilder().
+ setStoreName(storeName).
+ setName(fileName).
+ putAllMetadata(meta).
+ build();
+
+ return RuntimeProto.DelFileRequest.
+ newBuilder().
+ setRequest(fileRequest).
+ build();
+ }
+
+ private RuntimeProto.GetFileMetaRequest buildGetFileMetaRequest(String storeName,
+ String fileName,
+ Map meta) {
+
+ RuntimeProto.FileRequest fileRequest = RuntimeProto.FileRequest.
+ newBuilder().
+ setStoreName(storeName).
+ setName(fileName).
+ putAllMetadata(meta).
+ build();
+
+ return RuntimeProto.GetFileMetaRequest.
+ newBuilder().
+ setRequest(fileRequest).
+ build();
+ }
+
+ private GetMeteResponse buildGetFileMetaResponse(RuntimeProto.GetFileMetaResponse resp) {
+
+ Map metas = new HashMap<>();
+ resp.getResponse().
+ getMetadataMap().
+ forEach(
+ (s, fileMetaValue) ->
+ metas.put(s, fileMetaValue.getValueList().toArray(new String[0])));
+
+ GetMeteResponse result = new GetMeteResponse();
+ result.setSize(resp.getSize());
+ result.setLastModified(resp.getLastModified());
+ result.setMeta(metas);
+
+ return result;
+ }
+
+ private ListFileResponse buildListFileResponse(RuntimeProto.ListFileResp resp) {
+
+ FileInfo[] files = resp.getFilesList().
+ stream().
+ map(
+ fileInfo ->
+ new FileInfo(
+ fileInfo.getFileName(),
+ fileInfo.getSize(),
+ fileInfo.getLastModified(),
+ fileInfo.getMetadataMap())).
+ toArray(FileInfo[]::new);
+
+ ListFileResponse result = new ListFileResponse();
+ result.setFiles(files);
+ result.setTruncated(resp.getIsTruncated());
+ result.setMarker(resp.getMarker());
+
+ return result;
+ }
}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java
index 6d05dfd9ad..ac502ad981 100644
--- a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java
@@ -14,5 +14,53 @@
*/
package spec.sdk.runtime.v1.domain;
+import spec.sdk.runtime.v1.domain.file.GetFileRequest;
+import spec.sdk.runtime.v1.domain.file.PutFileRequest;
+import spec.sdk.runtime.v1.domain.file.DelFileRequest;
+import spec.sdk.runtime.v1.domain.file.ListFileResponse;
+import spec.sdk.runtime.v1.domain.file.ListFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetMetaRequest;
+import spec.sdk.runtime.v1.domain.file.GetMeteResponse;
+import spec.sdk.runtime.v1.domain.file.PutFileResponse;
+import spec.sdk.runtime.v1.domain.file.GetFileResponse;
+import spec.sdk.runtime.v1.domain.file.DelFileResponse;
+
public interface FileRuntime {
+
+ /**
+ * save or update file
+ *
+ * @param request
+ * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all.
+ * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException
+ */
+ PutFileResponse putFile(PutFileRequest request, int timeoutMs) throws Exception;
+
+ /**
+ * @param request
+ * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all.
+ * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException
+ */
+ GetFileResponse getFile(GetFileRequest request, int timeoutMs) throws Exception;
+
+ /**
+ * @param request
+ * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all.
+ * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException
+ */
+ ListFileResponse listFile(ListFileRequest request, int timeoutMs) throws Exception;
+
+ /**
+ * @param request
+ * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all.
+ * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException
+ */
+ DelFileResponse delFile(DelFileRequest request, int timeoutMs) throws Exception;
+
+ /**
+ * @param request
+ * @param timeoutMs If the time is less than or equal to zero, the method will not wait at all.
+ * @throws Exception Instance of RuntimeClientException Or StatusRuntimeException
+ */
+ GetMeteResponse getFileMeta(GetMetaRequest request, int timeoutMs) throws Exception;
}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java
new file mode 100644
index 0000000000..79b8cf0d8f
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class DelFileRequest {
+
+ private String storeName;
+ private String fileName;
+
+ private Map metaData;
+
+ public String getStoreName() {
+ return storeName;
+ }
+
+ public void setStoreName(String storeName) {
+ this.storeName = storeName;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public Map getMetaData() {
+
+ if (metaData == null) {
+ metaData = new HashMap<>();
+ }
+
+ return metaData;
+ }
+
+ public void setMetaData(Map metaData) {
+ this.metaData = metaData;
+ }
+
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java
new file mode 100644
index 0000000000..97dad5a05d
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+public class DelFileResponse {
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java
new file mode 100644
index 0000000000..a3a0ae6fc8
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FileInfo {
+ private String fileName;
+ private long size;
+ private String lastModified;
+ private Map metaData;
+
+ public FileInfo(String fileName, long size, String lastModified, Map metaData) {
+ this.fileName = fileName;
+ this.size = size;
+ this.lastModified = lastModified;
+ this.metaData = metaData;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public void setSize(long size) {
+ this.size = size;
+ }
+
+ public String getLastModified() {
+ return lastModified;
+ }
+
+ public void setLastModified(String lastModified) {
+ this.lastModified = lastModified;
+ }
+
+ public Map getMetaData() {
+
+ if (metaData == null) {
+ metaData = new HashMap<>();
+ }
+
+ return metaData;
+ }
+
+ public void setMetaData(Map metaData) {
+ this.metaData = metaData;
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java
new file mode 100644
index 0000000000..1d8e534778
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GetFileRequest {
+
+ private String storeName;
+ private String fileName;
+
+ private Map metaData;
+
+ public String getStoreName() {
+ return storeName;
+ }
+
+ public void setStoreName(String storeName) {
+ this.storeName = storeName;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public Map getMetaData() {
+
+ if (metaData == null) {
+ metaData = new HashMap<>();
+ }
+
+ return metaData;
+ }
+
+ public void setMetaData(Map metaData) {
+ this.metaData = metaData;
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java
new file mode 100644
index 0000000000..905e55c25e
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+import java.io.InputStream;
+
+public class GetFileResponse {
+
+ private InputStream in;
+
+ public GetFileResponse(InputStream in) {
+ this.in = in;
+ }
+
+ public InputStream getIn() {
+ return in;
+ }
+
+ public void setIn(InputStream in) {
+ this.in = in;
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java
new file mode 100644
index 0000000000..b1f856bf16
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GetMetaRequest {
+
+ private String storeName;
+ private String fileName;
+
+ private Map metaData;
+
+ public String getStoreName() {
+ return storeName;
+ }
+
+ public void setStoreName(String storeName) {
+ this.storeName = storeName;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public Map getMetaData() {
+
+ if (metaData == null) {
+ metaData = new HashMap<>();
+ }
+
+ return metaData;
+ }
+
+ public void setMetaData(Map metaData) {
+ this.metaData = metaData;
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java
new file mode 100644
index 0000000000..38553e786f
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GetMeteResponse {
+ private long size;
+ private String lastModified;
+ private Map meta;
+
+ public long getSize() {
+ return size;
+ }
+
+ public void setSize(long size) {
+ this.size = size;
+ }
+
+ public String getLastModified() {
+ return lastModified;
+ }
+
+ public void setLastModified(String lastModified) {
+ this.lastModified = lastModified;
+ }
+
+ public Map getMeta() {
+
+ if (meta == null) {
+ meta = new HashMap<>();
+ }
+
+ return meta;
+ }
+
+ public void setMeta(Map meta) {
+ this.meta = meta;
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java
new file mode 100644
index 0000000000..86ea4d8fc8
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ListFileRequest {
+
+ private String storeName;
+ private String name;
+ private Map metaData;
+
+ private int pageSize;
+ private String marker;
+
+ public String getStoreName() {
+ return storeName;
+ }
+
+ public void setStoreName(String storeName) {
+ this.storeName = storeName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Map getMetaData() {
+
+ if (metaData == null) {
+ metaData = new HashMap<>();
+ }
+
+ return metaData;
+ }
+
+ public void setMetaData(Map metaData) {
+ this.metaData = metaData;
+ }
+
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(int pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public String getMarker() {
+ return marker;
+ }
+
+ public void setMarker(String marker) {
+ this.marker = marker;
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java
new file mode 100644
index 0000000000..23db57dba5
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+public class ListFileResponse {
+
+ private boolean isTruncated;
+ private String marker;
+
+ private FileInfo[] files;
+
+ public boolean isTruncated() {
+ return isTruncated;
+ }
+
+ public void setTruncated(boolean truncated) {
+ isTruncated = truncated;
+ }
+
+ public String getMarker() {
+ return marker;
+ }
+
+ public void setMarker(String marker) {
+ this.marker = marker;
+ }
+
+ public FileInfo[] getFiles() {
+
+ if (files == null) {
+ files = new FileInfo[0];
+ }
+
+ return files;
+ }
+
+ public void setFiles(FileInfo[] files) {
+ this.files = files;
+ }
+}
\ No newline at end of file
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java
new file mode 100644
index 0000000000..fdef7c75f8
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class PutFileRequest {
+
+ private String storeName;
+ private String fileName;
+
+ private Map metaData;
+
+ private InputStream in;
+
+ public String getStoreName() {
+ return storeName;
+ }
+
+ public void setStoreName(String storeName) {
+ this.storeName = storeName;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public Map getMetaData() {
+
+ if (metaData == null) {
+ metaData = new HashMap<>();
+ }
+
+ return metaData;
+ }
+
+ public void setMetaData(Map metaData) {
+ this.metaData = metaData;
+ }
+
+ public InputStream getIn() {
+ return in;
+ }
+
+ public void setIn(InputStream in) {
+ this.in = in;
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java
new file mode 100644
index 0000000000..44ac87680a
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spec.sdk.runtime.v1.domain.file;
+
+public class PutFileResponse {
+}
diff --git a/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTest.java b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTest.java
new file mode 100644
index 0000000000..0af7c573c9
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTest.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.v1;
+
+import io.grpc.ManagedChannel;
+import io.grpc.inprocess.InProcessChannelBuilder;
+import io.grpc.inprocess.InProcessServerBuilder;
+import io.grpc.testing.GrpcCleanupRule;
+import io.mosn.layotto.v1.mock.MyFileService;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import spec.proto.runtime.v1.RuntimeGrpc;
+import spec.sdk.runtime.v1.client.RuntimeClient;
+import spec.sdk.runtime.v1.domain.file.GetFileRequest;
+import spec.sdk.runtime.v1.domain.file.PutFileRequest;
+import spec.sdk.runtime.v1.domain.file.DelFileRequest;
+import spec.sdk.runtime.v1.domain.file.ListFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetMetaRequest;
+import spec.sdk.runtime.v1.domain.file.GetMeteResponse;
+import spec.sdk.runtime.v1.domain.file.GetFileResponse;
+import spec.sdk.runtime.v1.domain.file.ListFileResponse;
+import spec.sdk.runtime.v1.domain.file.FileInfo;
+
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.AdditionalAnswers.delegatesTo;
+import static org.mockito.Mockito.mock;
+
+@RunWith(JUnit4.class)
+public class FileTest {
+ @Rule
+ public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
+
+ RuntimeGrpc.RuntimeImplBase fileService = new MyFileService();
+
+ private final RuntimeGrpc.RuntimeImplBase serviceImpl = mock(RuntimeGrpc.RuntimeImplBase.class,
+ delegatesTo(fileService));
+
+ private RuntimeClient client;
+
+ @Before
+ public void setUp() throws Exception {
+ String serverName = InProcessServerBuilder.generateName();
+ grpcCleanup.register(InProcessServerBuilder
+ .forName(serverName).directExecutor()
+ .addService(serviceImpl)
+ .build().start());
+ ManagedChannel channel = grpcCleanup.register(
+ InProcessChannelBuilder.forName(serverName).directExecutor().build());
+ client = new RuntimeClientBuilder()
+ .buildGrpcWithExistingChannel(channel);
+ }
+
+ // normal case
+ @Test
+ public void testPutFile1() throws Exception {
+
+ PutFileRequest req = new PutFileRequest();
+ req.setIn(new ByteArrayInputStream("hello world".getBytes()));
+ req.setStoreName( "oss");
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.putFile(req, 10000);
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testPutFile2() throws Exception {
+ client.putFile(null, 10000);
+ }
+
+ // miss in stream
+ @Test(expected = IllegalArgumentException.class)
+ public void testPutFile3() throws Exception {
+
+ PutFileRequest req = new PutFileRequest();
+ req.setStoreName("oss");
+ req.setFileName("test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.putFile(req, 10000);
+ }
+
+ // miss file name
+ @Test(expected = IllegalArgumentException.class)
+ public void testPutFile4() throws Exception {
+
+ PutFileRequest req = new PutFileRequest();
+ req.setIn(new ByteArrayInputStream("hello world".getBytes()));
+ req.setStoreName( "oss");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.putFile(req, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testPutFile5() throws Exception {
+
+ PutFileRequest req = new PutFileRequest();
+ req.setIn(new ByteArrayInputStream("hello world".getBytes()));
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.putFile(req, 10000);
+ }
+
+ // normal case
+ @Test
+ public void testGetFile1() throws Exception {
+
+ GetFileRequest req = new GetFileRequest();
+ req.setStoreName( "oss");
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ GetFileResponse resp = client.getFile(req, 10000);
+
+ byte[] buf = new byte[126];
+ int len = resp.getIn().read(buf);
+
+ String echo = new String(buf,0,len);
+ Assert.assertEquals("get file store name oss, meta 2, file name test.log", echo);
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFile2() throws Exception {
+ client.getFile(null, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFile3() throws Exception {
+
+ GetFileRequest req = new GetFileRequest();
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.getFile(req, 10000);
+ }
+
+ // miss file name
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFile4() throws Exception {
+
+ GetFileRequest req = new GetFileRequest();
+ req.setStoreName( "oss");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.getFile(req, 10000);
+ }
+
+ // normal case
+ @Test
+ public void testDelFile1() throws Exception {
+
+ DelFileRequest req = new DelFileRequest();
+ req.setStoreName( "oss");
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.delFile(req, 10000);
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testDelFile2() throws Exception {
+ client.delFile(null, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testDelFile3() throws Exception {
+
+ DelFileRequest req = new DelFileRequest();
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.delFile(req, 10000);
+ }
+
+ // miss file name
+ @Test(expected = IllegalArgumentException.class)
+ public void testDelFile4() throws Exception {
+
+ DelFileRequest req = new DelFileRequest();
+ req.setStoreName( "oss");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.delFile(req, 10000);
+ }
+
+ // normal
+ @Test
+ public void testListFile1() throws Exception {
+
+ ListFileRequest req = new ListFileRequest();
+ req.setStoreName( "oss");
+ req.setName("dir");
+ req.setMarker("test.log");
+ req.setPageSize(10);
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ ListFileResponse resp = client.listFile(req, 10000);
+
+ Assert.assertTrue(resp.isTruncated());
+ Assert.assertEquals("marker", resp.getMarker());
+ Assert.assertEquals(1, resp.getFiles().length);
+
+ FileInfo f = resp.getFiles()[0];
+ Assert.assertEquals("put file store name oss, meta 2", f.getFileName());
+ Assert.assertEquals(100L, f.getSize());
+ Assert.assertEquals("2021-11-23 10:24:11", f.getLastModified());
+ Assert.assertEquals("v1", f.getMetaData().get("k1"));
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testListFile2() throws Exception {
+ client.listFile(null, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testListFile3() throws Exception {
+
+ ListFileRequest req = new ListFileRequest();
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ ListFileResponse notUsed = client.listFile(req, 10000);
+ }
+
+ // normal
+ @Test
+ public void testGetFileMeta1() throws Exception {
+
+ GetMetaRequest req = new GetMetaRequest();
+ req.setStoreName( "oss");
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ GetMeteResponse res = client.getFileMeta(req, 10000);
+
+ Assert.assertEquals(100L, res.getSize());
+ Assert.assertEquals("2021-11-22 10:24:11", res.getLastModified());
+ Assert.assertArrayEquals(new String[]{"v1", "v2"}, res.getMeta().get("k1"));
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFileMeta2() throws Exception {
+ client.getFileMeta(null, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFileMeta3() throws Exception {
+
+ GetMetaRequest req = new GetMetaRequest();
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ GetMeteResponse res = client.getFileMeta(req, 10000);
+
+ Assert.assertEquals(100L, res.getSize());
+ Assert.assertEquals("2021-11-22 10:24:11", res.getLastModified());
+ Assert.assertArrayEquals(new String[]{"v1", "v2"}, res.getMeta().get("k1"));
+ }
+
+ // miss file name
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFileMeta4() throws Exception {
+
+ GetMetaRequest req = new GetMetaRequest();
+ req.setStoreName( "oss");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.getFileMeta(req, 10000);
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java
new file mode 100644
index 0000000000..15402b2fb5
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.v1;
+
+import io.grpc.Server;
+import io.grpc.ServerBuilder;
+import io.mosn.layotto.v1.grpc.ExceptionHandler;
+import io.mosn.layotto.v1.grpc.GrpcRuntimeClient;
+import io.mosn.layotto.v1.mock.MyFileService;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import spec.proto.runtime.v1.RuntimeGrpc;
+import spec.sdk.runtime.v1.domain.file.GetFileRequest;
+import spec.sdk.runtime.v1.domain.file.PutFileRequest;
+import spec.sdk.runtime.v1.domain.file.DelFileRequest;
+import spec.sdk.runtime.v1.domain.file.ListFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetMetaRequest;
+import spec.sdk.runtime.v1.domain.file.GetMeteResponse;
+import spec.sdk.runtime.v1.domain.file.GetFileResponse;
+import spec.sdk.runtime.v1.domain.file.ListFileResponse;
+import spec.sdk.runtime.v1.domain.file.FileInfo;
+
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(JUnit4.class)
+public class FileTestWithRealServer {
+
+ private final RuntimeGrpc.RuntimeImplBase fileService = new MyFileService();
+
+ private Server srv;
+ private GrpcRuntimeClient client;
+
+ int port = 9999;
+ String ip = "127.0.0.1";
+
+ @Before
+ public void setUp() throws Exception {
+ // start grpc server
+ /* The port on which the server should run */
+ srv = ServerBuilder.forPort(port)
+ .addService(fileService)
+ .intercept(new ExceptionHandler())
+ .build()
+ .start();
+
+ // build a client
+ client = new RuntimeClientBuilder()
+ .withIp(ip)
+ .withPort(port)
+ .withConnectionPoolSize(4)
+ .withTimeout(1000)
+ .buildGrpc();
+ }
+
+ @After
+ public void shutdown() {
+ client.shutdown();
+ srv.shutdownNow();
+ }
+
+ // normal case
+ @Test
+ public void testPutFile1() throws Exception {
+
+ PutFileRequest req = new PutFileRequest();
+ req.setIn( new ByteArrayInputStream("hello world".getBytes()));
+ req.setStoreName("oss");
+ req.setFileName("test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.putFile(req, 10000);
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testPutFile2() throws Exception {
+ client.putFile(null, 10000);
+ }
+
+ // miss in stream
+ @Test(expected = IllegalArgumentException.class)
+ public void testPutFile3() throws Exception {
+
+ PutFileRequest req = new PutFileRequest();
+ req.setStoreName( "oss");
+ req.setFileName("test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.putFile(req, 10000);
+ }
+
+ // miss file name
+ @Test(expected = IllegalArgumentException.class)
+ public void testPutFile4() throws Exception {
+
+ PutFileRequest req = new PutFileRequest();
+ req.setIn( new ByteArrayInputStream("hello world".getBytes()));
+ req.setStoreName( "oss");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.putFile(req, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testPutFile5() throws Exception {
+
+ PutFileRequest req = new PutFileRequest();
+ req.setIn( new ByteArrayInputStream("hello world".getBytes()));
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.putFile(req, 10000);
+ }
+
+ // normal case
+ @Test
+ public void testGetFile1() throws Exception {
+
+ GetFileRequest req = new GetFileRequest();
+ req.setStoreName( "oss");
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ GetFileResponse resp = client.getFile(req, 10000);
+
+ byte[] buf = new byte[126];
+ int len = resp.getIn().read(buf);
+
+ String echo = new String(buf,0,len);
+ Assert.assertEquals("get file store name oss, meta 2, file name test.log", echo);
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFile2() throws Exception {
+ client.getFile(null, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFile3() throws Exception {
+
+ GetFileRequest req = new GetFileRequest();
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.getFile(req, 10000);
+ }
+
+ // miss file name
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFile4() throws Exception {
+
+ GetFileRequest req = new GetFileRequest();
+ req.setStoreName( "oss");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.getFile(req, 10000);
+ }
+
+ // normal case
+ @Test
+ public void testDelFile1() throws Exception {
+
+ DelFileRequest req = new DelFileRequest();
+ req.setStoreName( "oss");
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.delFile(req, 10000);
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testDelFile2() throws Exception {
+ client.delFile(null, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testDelFile3() throws Exception {
+
+ DelFileRequest req = new DelFileRequest();
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.delFile(req, 10000);
+ }
+
+ // miss file name
+ @Test(expected = IllegalArgumentException.class)
+ public void testDelFile4() throws Exception {
+
+ DelFileRequest req = new DelFileRequest();
+ req.setStoreName( "oss");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.delFile(req, 10000);
+ }
+
+ // normal
+ @Test
+ public void testListFile1() throws Exception {
+
+ ListFileRequest req = new ListFileRequest();
+ req.setStoreName( "oss");
+ req.setName("dir");
+ req.setMarker("test.log");
+ req.setPageSize(10);
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ ListFileResponse resp = client.listFile(req, 10000);
+
+ Assert.assertTrue(resp.isTruncated());
+ Assert.assertEquals("marker", resp.getMarker());
+ Assert.assertEquals(1, resp.getFiles().length);
+
+ FileInfo f = resp.getFiles()[0];
+ Assert.assertEquals("put file store name oss, meta 2", f.getFileName());
+ Assert.assertEquals(100L, f.getSize());
+ Assert.assertEquals("2021-11-23 10:24:11", f.getLastModified());
+ Assert.assertEquals("v1", f.getMetaData().get("k1"));
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testListFile2() throws Exception {
+ client.listFile(null, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testListFile3() throws Exception {
+
+ ListFileRequest req = new ListFileRequest();
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ ListFileResponse resp = client.listFile(req, 10000);
+ }
+
+ // normal
+ @Test
+ public void testGetFileMeta1() throws Exception {
+
+ GetMetaRequest req = new GetMetaRequest();
+ req.setStoreName( "oss");
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ GetMeteResponse res = client.getFileMeta(req, 10000);
+
+ Assert.assertEquals(100L,res.getSize());
+ Assert.assertEquals("2021-11-22 10:24:11",res.getLastModified());
+ Assert.assertArrayEquals(new String[]{"v1","v2"},res.getMeta().get("k1"));
+ }
+
+ // miss request
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFileMeta2() throws Exception {
+ client.getFileMeta(null, 10000);
+ }
+
+ // miss store name
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFileMeta3() throws Exception {
+
+ GetMetaRequest req = new GetMetaRequest();
+ req.setFileName( "test.log");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ GetMeteResponse res = client.getFileMeta(req, 10000);
+
+ Assert.assertEquals(100L,res.getSize());
+ Assert.assertEquals("2021-11-22 10:24:11",res.getLastModified());
+ Assert.assertArrayEquals(new String[]{"v1","v2"},res.getMeta().get("k1"));
+ }
+
+ // miss file name
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFileMeta4() throws Exception {
+
+ GetMetaRequest req = new GetMetaRequest();
+ req.setStoreName( "oss");
+
+ Map metaData = new HashMap<>();
+ metaData.put("k1", "v1");
+ metaData.put("k2", "v2");
+ req.setMetaData(metaData);
+
+ client.getFileMeta(req, 10000);
+ }
+}
diff --git a/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java
new file mode 100644
index 0000000000..106423c0e7
--- /dev/null
+++ b/sdk/java-sdk/sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.v1.mock;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.Empty;
+import io.grpc.stub.StreamObserver;
+import spec.proto.runtime.v1.RuntimeGrpc;
+import spec.proto.runtime.v1.RuntimeProto;
+
+public class MyFileService extends RuntimeGrpc.RuntimeImplBase {
+
+ @Override
+ public StreamObserver putFile(StreamObserver responseObserver) {
+
+ return new StreamObserver() {
+
+ @Override
+ public void onNext(RuntimeProto.PutFileRequest putFileRequest) {
+
+ String log = String.format("put file store name %s, meta %d, file name %s, data size %d",
+ putFileRequest.getStoreName(),
+ putFileRequest.getMetadataCount(),
+ putFileRequest.getName(),
+ putFileRequest.getData().size());
+
+ System.out.println(log);
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ if (throwable != null) {
+ System.err.println("put file err: " + throwable);
+ }
+ }
+
+ @Override
+ public void onCompleted() {
+ System.out.println("finished put file");
+ responseObserver.onNext(Empty.newBuilder().build());
+ responseObserver.onCompleted();
+ }
+ };
+ }
+
+ @Override
+ public void getFile(RuntimeProto.GetFileRequest request,
+ StreamObserver responseObserver) {
+
+ String echo = String.format("get file store name %s, meta %d, file name %s",
+ request.getStoreName(),
+ request.getMetadataCount(),
+ request.getName());
+
+ responseObserver.onNext(
+ RuntimeProto.GetFileResponse.newBuilder().
+ setData(
+ ByteString.copyFrom(echo.getBytes())).
+ build());
+
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void delFile(RuntimeProto.DelFileRequest request, StreamObserver responseObserver) {
+
+ String log = String.format("del file store name %s, meta %d, file name %s",
+ request.getRequest().getStoreName(),
+ request.getRequest().getMetadataCount(),
+ request.getRequest().getName());
+
+ System.out.println(log);
+
+ responseObserver.onNext(Empty.newBuilder().build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void listFile(RuntimeProto.ListFileRequest request,
+ StreamObserver responseObserver) {
+
+ String echo = String.format("put file store name %s, meta %d",
+ request.getRequest().getStoreName(),
+ request.getRequest().getMetadataCount());
+
+ responseObserver.onNext(
+ RuntimeProto.ListFileResp.newBuilder().
+ addFiles(
+ RuntimeProto.FileInfo.newBuilder().
+ setFileName(echo).
+ setSize(100).
+ setLastModified("2021-11-23 10:24:11").
+ putMetadata("k1", "v1").
+ build()).
+ setMarker("marker").
+ setIsTruncated(true).
+ build()
+ );
+
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getFileMeta(RuntimeProto.GetFileMetaRequest request,
+ StreamObserver responseObserver) {
+
+ String log = String.format("get file meta store name %s, meta %d, file name %s",
+ request.getRequest().getStoreName(),
+ request.getRequest().getMetadataCount(),
+ request.getRequest().getName());
+
+ System.out.println(log);
+
+ responseObserver.onNext(
+ RuntimeProto.GetFileMetaResponse.newBuilder().
+ setSize(100).
+ setLastModified("2021-11-22 10:24:11").
+ setResponse(
+ RuntimeProto.FileMeta.newBuilder().
+ putMetadata(
+ "k1",
+ RuntimeProto.FileMetaValue.newBuilder().
+ addValue("v1").
+ addValue("v2").
+ build()).
+ build()).
+ build());
+
+ responseObserver.onCompleted();
+ }
+}