You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/04/23 02:26:18 UTC

[incubator-servicecomb-java-chassis] 04/05: [SCB-487] add download consumer demo

This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git

commit afb77b3110bb7508c27f40408ecab59b12be0d63
Author: wujimin <wu...@huawei.com>
AuthorDate: Sun Apr 22 17:59:56 2018 +0800

    [SCB-487] add download consumer demo
---
 .../java/org/apache/servicecomb/demo/TestMgr.java  |  10 +-
 .../client/CodeFirstRestTemplateSpringmvc.java     |   4 +
 .../demo/springmvc/client/DownloadSchemaIntf.java  |  37 ++++++
 .../demo/springmvc/client/TestDownload.java        | 124 +++++++++++++++++++++
 .../demo/springmvc/server/DownloadSchema.java      |  91 ++++++++++++---
 5 files changed, 247 insertions(+), 19 deletions(-)

diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
index c72bb36..b0086f6 100644
--- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
@@ -40,6 +40,10 @@ public class TestMgr {
   }
 
   public static void check(Object expect, Object real) {
+    check(expect, real, null);
+  }
+
+  public static void check(Object expect, Object real, Throwable error) {
     if (expect == real) {
       return;
     }
@@ -48,7 +52,11 @@ public class TestMgr {
     String strReal = String.valueOf(real);
 
     if (!strExpect.equals(strReal)) {
-      errorList.add(new Error(msg + " | Expect " + strExpect + ", but " + strReal));
+      Error newError = new Error(msg + " | Expect " + strExpect + ", but " + strReal);
+      if (error != null) {
+        newError.setStackTrace(error.getStackTrace());
+      }
+      errorList.add(newError);
     }
   }
 
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
index f23e882..2303cc0 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
@@ -70,8 +70,12 @@ public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate {
 
   private TestGeneric testGeneric = new TestGeneric();
 
+  private TestDownload testDownload = new TestDownload();
+
   @Override
   protected void testOnlyRest(RestTemplate template, String cseUrlPrefix) {
+    testDownload.runRest();
+
     try {
       testUpload(template, cseUrlPrefix);
     } catch (IOException e) {
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/DownloadSchemaIntf.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/DownloadSchemaIntf.java
new file mode 100644
index 0000000..48b9a0f
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/DownloadSchemaIntf.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.demo.springmvc.client;
+
+import org.apache.servicecomb.foundation.vertx.http.ReadStreamPart;
+
+public interface DownloadSchemaIntf {
+  ReadStreamPart tempFileEntity(String content);
+
+  ReadStreamPart tempFilePart(String content);
+
+  ReadStreamPart file(String content);
+
+  ReadStreamPart chineseAndSpaceFile(String content);
+
+  ReadStreamPart resource(String content);
+
+  ReadStreamPart entityResource(String content);
+
+  ReadStreamPart entityInputStream(String content);
+
+  ReadStreamPart netInputStream(String content);
+}
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownload.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownload.java
new file mode 100644
index 0000000..303c001
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownload.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.demo.springmvc.client;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.foundation.vertx.http.ReadStreamPart;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate;
+import org.springframework.web.client.RestTemplate;
+
+public class TestDownload {
+  private File dir = new File("target/download");
+
+  private DownloadSchemaIntf intf = Invoker.createProxy("springmvc", "download", DownloadSchemaIntf.class);
+
+  private RestTemplate restTemplate = new CseRestTemplate();
+
+  private String prefix = "cse://springmvc/download";
+
+  private List<CompletableFuture<?>> futures = new ArrayList<>();
+
+  private String content = "file content";
+
+  public TestDownload() {
+    FileUtils.deleteQuietly(dir);
+  }
+
+  private String readFileToString(File file) {
+    try {
+      return FileUtils.readFileToString(file);
+    } catch (IOException e) {
+      return "read file failed:" + e.getMessage();
+    }
+  }
+
+  private CompletableFuture<File> checkFile(ReadStreamPart part) {
+    CompletableFuture<File> future = part.saveToFile("target/download/"
+        + UUID.randomUUID().toString()
+        + "-"
+        + part.getSubmittedFileName());
+    return checkFuture(future);
+  }
+
+  private <T> CompletableFuture<T> checkFuture(CompletableFuture<T> future) {
+    Error error = new Error();
+    future.whenComplete((result, e) -> {
+      Object value = result;
+      if (File.class.isInstance(value)) {
+        value = readFileToString((File) value);
+        ((File) value).delete();
+      } else if (byte[].class.isInstance(value)) {
+        value = new String((byte[]) value);
+      }
+
+      TestMgr.check(content, value, error);
+    });
+
+    return future;
+  }
+
+  private ReadStreamPart templateGet(String methodPath) {
+    return restTemplate
+        .getForObject(prefix + "/" + methodPath + "?content={content}",
+            ReadStreamPart.class,
+            content);
+  }
+
+  public void runRest() {
+    futures.add(checkFile(intf.tempFileEntity(content)));
+    futures.add(checkFuture(templateGet("tempFileEntity").saveAsBytes()));
+
+    futures.add(checkFile(intf.tempFilePart(content)));
+    futures.add(checkFuture(templateGet("tempFilePart").saveAsString()));
+
+    futures.add(checkFile(intf.file(content)));
+    futures.add(checkFuture(templateGet("file").saveAsString()));
+
+    // fix in next PR
+    //    futures.add(checkFile(intf.chineseAndSpaceFile(content)));
+    //    futures.add(checkFuture(templateGet("chineseAndSpaceFile").saveAsString()));
+
+    futures.add(checkFile(intf.resource(content)));
+    futures.add(checkFuture(templateGet("resource").saveAsString()));
+
+    futures.add(checkFile(intf.entityResource(content)));
+    futures.add(checkFuture(templateGet("entityResource").saveAsString()));
+
+    futures.add(checkFile(intf.entityInputStream(content)));
+    futures.add(checkFuture(templateGet("entityInputStream").saveAsString()));
+
+    futures.add(checkFile(intf.netInputStream(content)));
+    futures.add(checkFuture(templateGet("netInputStream").saveAsString()));
+
+    try {
+      CompletableFuture
+          .allOf(futures.toArray(new CompletableFuture[futures.size()]))
+          .get();
+    } catch (InterruptedException | ExecutionException e1) {
+    }
+  }
+}
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/DownloadSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/DownloadSchema.java
index 7125511..c6124d2 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/DownloadSchema.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/DownloadSchema.java
@@ -20,17 +20,26 @@ import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.UUID;
 
 import javax.servlet.http.Part;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.bootstrap.HttpServer;
+import org.apache.http.impl.bootstrap.ServerBootstrap;
 import org.apache.servicecomb.foundation.common.part.FilePart;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.springframework.core.io.ByteArrayResource;
 import org.springframework.core.io.Resource;
 import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -41,24 +50,45 @@ import io.swagger.annotations.ApiResponses;
 @RestSchema(schemaId = "download")
 @RequestMapping(path = "/download")
 public class DownloadSchema {
-  File tempDir = new File("downloadTemp");
+  File tempDir = new File("target/downloadTemp");
 
   public DownloadSchema() throws IOException {
+    FileUtils.deleteQuietly(tempDir);
     FileUtils.forceMkdir(tempDir);
+
+    // for download from net stream case
+    HttpServer server = ServerBootstrap
+        .bootstrap()
+        .setListenerPort(9000)
+        .registerHandler("/download/netInputStream", (req, resp, context) -> {
+          String uri = req.getRequestLine().getUri();
+          String query = URI.create(uri).getQuery();
+          int idx = query.indexOf('=');
+          String content = query.substring(idx + 1);
+          content = URLDecoder.decode(content, StandardCharsets.UTF_8.name());
+          resp.setEntity(new StringEntity(content, StandardCharsets.UTF_8.name()));
+        })
+        .create();
+    server.start();
+  }
+
+  protected File createTempFile(String content) throws IOException {
+    return createTempFile(null, content);
   }
 
-  // content is file name
-  protected File createTempFile() throws IOException {
-    String name = "download-" + UUID.randomUUID().toString() + ".txt";
+  protected File createTempFile(String name, String content) throws IOException {
+    if (name == null) {
+      name = "download-" + UUID.randomUUID().toString() + ".txt";
+    }
     File file = new File(tempDir, name);
-    FileUtils.write(file, name);
+    FileUtils.write(file, content);
     return file;
   }
 
   // customize HttpHeaders.CONTENT_DISPOSITION to be "attachment;filename=tempFileEntity.txt"
   @GetMapping(path = "/tempFileEntity")
-  public ResponseEntity<Part> downloadTempFileEntity() throws IOException {
-    File file = createTempFile();
+  public ResponseEntity<Part> tempFileEntity(String content) throws IOException {
+    File file = createTempFile(content);
 
     return ResponseEntity
         .ok()
@@ -69,8 +99,8 @@ public class DownloadSchema {
 
   // generate HttpHeaders.CONTENT_DISPOSITION to be "attachment;filename=tempFilePart.txt" automatically
   @GetMapping(path = "/tempFilePart")
-  public Part downloadTempFilePart() throws IOException {
-    File file = createTempFile();
+  public Part tempFilePart(String content) throws IOException {
+    File file = createTempFile(content);
 
     return new FilePart(null, file)
         .setDeleteAfterFinished(true)
@@ -78,19 +108,27 @@ public class DownloadSchema {
   }
 
   @GetMapping(path = "/file")
-  public File downloadFile() throws IOException {
-    return new File(this.getClass().getClassLoader().getResource("microservice.yaml").getFile());
+  public File file(String content) throws IOException {
+    return createTempFile("file.txt", content);
+  }
+
+  @GetMapping(path = "/chineseAndSpaceFile")
+  public Part chineseAndSpaceFile(String content) throws IOException {
+    File file = createTempFile(content);
+    return new FilePart(null, file)
+        .setDeleteAfterFinished(true)
+        .setSubmittedFileName("测 试.test.txt");
   }
 
   @GetMapping(path = "/resource")
   @ApiResponses({
       @ApiResponse(code = 200, response = File.class, message = ""),
   })
-  public Resource downloadResource() throws IOException {
-    return new ByteArrayResource("abc".getBytes(StandardCharsets.UTF_8)) {
+  public Resource resource(String content) throws IOException {
+    return new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8)) {
       @Override
       public String getFilename() {
-        return "abc.txt";
+        return "resource.txt";
       }
     };
   }
@@ -99,21 +137,38 @@ public class DownloadSchema {
   @ApiResponses({
       @ApiResponse(code = 200, response = File.class, message = ""),
   })
-  public ResponseEntity<Resource> downloadEntityResource() throws IOException {
+  public ResponseEntity<Resource> entityResource(String content) throws IOException {
     return ResponseEntity
         .ok()
+        .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
         .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=entityResource.txt")
-        .body(new ByteArrayResource("entityResource".getBytes(StandardCharsets.UTF_8)));
+        .body(new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8)));
   }
 
   @GetMapping(path = "/entityInputStream")
   @ApiResponses({
       @ApiResponse(code = 200, response = File.class, message = ""),
   })
-  public ResponseEntity<InputStream> downloadEntityInputStream() throws IOException {
+  public ResponseEntity<InputStream> entityInputStream(String content) throws IOException {
     return ResponseEntity
         .ok()
+        .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
         .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=entityInputStream.txt")
-        .body(new ByteArrayInputStream("entityInputStream".getBytes(StandardCharsets.UTF_8)));
+        .body(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
+  }
+
+  @GetMapping(path = "/netInputStream")
+  @ApiResponses({
+      @ApiResponse(code = 200, response = File.class, message = ""),
+  })
+  public ResponseEntity<InputStream> netInputStream(String content) throws IOException {
+    URL url = new URL("http://localhost:9000/download/netInputStream?content="
+        + URLEncoder.encode(content, StandardCharsets.UTF_8.name()));
+    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+    return ResponseEntity
+        .ok()
+        .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=netInputStream.txt")
+        .body(conn.getInputStream());
   }
 }

-- 
To stop receiving notification emails like this one, please contact
liubao@apache.org.