Skip to content

Commit

Permalink
Added Java source files. #2
Browse files Browse the repository at this point in the history
  • Loading branch information
zhoub committed Nov 4, 2022
1 parent 04e4b6e commit 1caa2a4
Show file tree
Hide file tree
Showing 7 changed files with 439 additions and 0 deletions.
91 changes: 91 additions & 0 deletions rest/java/src/main/java/io/werender/examples/App.java
@@ -0,0 +1,91 @@
package io.werender.examples;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openapitools.client.ApiClient;
import org.openapitools.client.Configuration;
import org.openapitools.client.model.StorageFile;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;

public class App {
private static Log log = LogFactory.getLog(App.class);

private static final String APP_NAME = "werender-example-rest-java";

private static final String COMMAND_UPLOAD_FILE = "upload_file";
private static final String COMMAND_HELP = "help";

public static void handleUploadFile(CommandLine cmdLine) {
// Retrieve configuration.
Config config = Config.create();
log.info(String.format("Using server %s", config.getAddress()));

// Create API client.
ApiClient apiClient = Configuration.getDefaultApiClient();
apiClient.setBasePath(config.getAddress());
apiClient.setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15.7) WeRender/0.4.0");

OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new SignatureInterceptor(config.getPublicKey(), config.getPrivateKey()))
.addInterceptor(new HttpLoggingInterceptor()).build();
apiClient.setHttpClient(client);

// Upload the local file to remote directory.
try {
// Get local file path and remote directory path.
String[] optionValues = cmdLine.getOptionValues(COMMAND_UPLOAD_FILE);
String localFilePath = optionValues[0];
String remoteDirPath = optionValues[1];
log.info(String.format("Start to upload file from %s to %s", localFilePath, remoteDirPath));

// Create command to do the actual work.
CommandContext commandContext = new CommandContext(apiClient);
UploadFileCommand command = new UploadFileCommand(localFilePath, remoteDirPath);
StorageFile file = command.execute(commandContext);

log.info(String.format("Uploaded file from %s to %s with id %s", localFilePath, remoteDirPath,
file.getId()));
} catch (Exception e) {
e.printStackTrace();
}
}

public static void handleHelp(Options options) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(APP_NAME, options);
}

public static void main(String[] args) {
// Prepare command line options.
Option uploadFileOption = Option.builder(COMMAND_UPLOAD_FILE).hasArgs()
.desc("upload a file from local path to remote directory").build();
Option helpOption = Option.builder(COMMAND_HELP).desc("print help").build();

Options options = new Options();
options.addOption(uploadFileOption);
options.addOption(helpOption);

// Process command line.
try {
CommandLineParser parser = new DefaultParser();
CommandLine cmdLine = parser.parse(options, args);
if (cmdLine.hasOption(COMMAND_HELP)) {
handleHelp(options);
} else if (cmdLine.hasOption(COMMAND_UPLOAD_FILE)) {
handleUploadFile(cmdLine);
} else {
handleHelp(options);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
7 changes: 7 additions & 0 deletions rest/java/src/main/java/io/werender/examples/Command.java
@@ -0,0 +1,7 @@
package io.werender.examples;

public interface Command<T> {

public T execute(CommandContext context) throws Exception;

}
24 changes: 24 additions & 0 deletions rest/java/src/main/java/io/werender/examples/CommandContext.java
@@ -0,0 +1,24 @@
package io.werender.examples;

import org.openapitools.client.ApiClient;
import org.openapitools.client.api.StorageApi;

public class CommandContext {

private ApiClient apiClient;
private StorageApi storageApi;

public CommandContext(ApiClient apiClient) {
this.apiClient = apiClient;
storageApi = new StorageApi(apiClient);
}

public ApiClient getApiClient() {
return apiClient;
}

public StorageApi getStorageApi() {
return storageApi;
}

}
109 changes: 109 additions & 0 deletions rest/java/src/main/java/io/werender/examples/Config.java
@@ -0,0 +1,109 @@
package io.werender.examples;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import org.apache.commons.lang3.SystemUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class Config {
private static Log log = LogFactory.getLog(Config.class);

public static final String DEFAULT_SERVER_ADDRESS = "https://api-us-east-2.werender.io/v1";
public static final String DEFAULT_SERVER_VERSION = "v1";

private String address;
private String publicKey;
private String privateKey;

public static Config create() {
/* Create instance. */
Config config = new Config();

/* Get home folder and configuration folder. */
String homeDirPath = SystemUtils.getUserHome().getAbsolutePath();
String configDirPath = new String(homeDirPath);
if (SystemUtils.IS_OS_MAC_OSX) {
configDirPath += "/Library/Application Support/werender";
} else {
log.fatal(String.format("Unsupported platform"));
}

/* Read werender.config file. */
try {
String serverAddress = Config.DEFAULT_SERVER_ADDRESS;

String configFilePath = configDirPath + "/werender.config";
FileReader reader = new FileReader(configFilePath);
JsonParser parser = new JsonParser();
JsonElement rootElement = parser.parse(reader);
JsonObject rootObject = rootElement.getAsJsonObject();
if (rootObject.has("internal")) {
JsonObject internalObject = rootObject.get("internal").getAsJsonObject();
if (internalObject.has("server")) {
JsonObject serverObject = internalObject.get("server").getAsJsonObject();
if (serverObject.has("server_address")) {
serverAddress = serverObject.get("server_address").getAsString();
}
}
}

if (!serverAddress.endsWith(DEFAULT_SERVER_VERSION)) {
serverAddress += String.format("/%s", DEFAULT_SERVER_VERSION);
}
config.setAddress(serverAddress);
} catch (FileNotFoundException e) {
e.printStackTrace();
}

/* Read werender.key file. */
try {
String keyFilePath = configDirPath + "/werender.key";
String key = Files.readString(Paths.get(keyFilePath));
String[] keyTokens = key.split(",");
config.setPublicKey(keyTokens[0]);
config.setPrivateKey(keyTokens[1].trim());
} catch (IOException e) {
e.printStackTrace();
}

/* Return instance. */
return config;
}

private Config() {
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public String getPublicKey() {
return publicKey;
}

public void setPublicKey(String publicKey) {
this.publicKey = publicKey;
}

public String getPrivateKey() {
return privateKey;
}

public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}

}
59 changes: 59 additions & 0 deletions rest/java/src/main/java/io/werender/examples/FileUtil.java
@@ -0,0 +1,59 @@
package io.werender.examples;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

public final class FileUtil {

public static final String MODE_STRICT = "strict";
public static final String MODE_UNIQUE = "unique";

public static final String EXT_FBX = "fbx";
public static final String EXT_USD = "usd";

public static final String CONTENT_TYPE_BINARY = "application/octet-stream";
public static final String CONTENT_TYPE_MODEL_FBX = "model/fbx";
public static final String CONTENT_TYPE_MODEL_USD = "model/usd";

public static String computeFileChecksum(File file) throws Exception {
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
try (InputStream input = new FileInputStream(file)) {

byte[] buffer = new byte[8192];
int len = input.read(buffer);

while (len != -1) {
sha1.update(buffer, 0, len);
len = input.read(buffer);
}

String checksum = new HexBinaryAdapter().marshal(sha1.digest());
checksum = "sha1:" + checksum.toLowerCase();
return checksum;
}
}

public static String getContentType(String filePath) {
String contentType = CONTENT_TYPE_BINARY;
String[] tokens = filePath.split("\\.");
if (tokens.length > 0) {
String lastToken = tokens[tokens.length - 1];
switch (lastToken) {
case EXT_FBX:
contentType = CONTENT_TYPE_MODEL_FBX;
break;
case EXT_USD:
contentType = CONTENT_TYPE_MODEL_USD;
break;
default:
break;
}
}
return contentType;
}

}
@@ -0,0 +1,67 @@
package io.werender.examples;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

public class SignatureInterceptor implements Interceptor {
private static final String SIGNATURE_ALGORITHM = "HmacSHA1";

private String publicKey;
private String privateKey;

private static String getDate() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return dateFormat.format(calendar.getTime());
}

private static String getSignature(String method, String host, String date, String privateKey) {
String message = String.format("%s\n%s\n%s", method, host, date);
String signature = null;
try {
SecretKeySpec signingKey = new SecretKeySpec(privateKey.getBytes(), SIGNATURE_ALGORITHM);
Mac mac = Mac.getInstance(SIGNATURE_ALGORITHM);
mac.init(signingKey);
byte[] macOutput = mac.doFinal(message.getBytes());
signature = Base64.getEncoder().encodeToString(macOutput);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return signature;
}

public SignatureInterceptor(String publicKey, String privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
}

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String method = request.method();
String date = getDate();
String host = request.url().host();
String signature = getSignature(method, host, date, privateKey);
Request newRequest = request.newBuilder()
.addHeader("Authorization", String.format("WR %s:%s", publicKey, signature))
.addHeader("Date", getDate()).addHeader("Host", host).build();
return chain.proceed(newRequest);
}

}

0 comments on commit 1caa2a4

Please sign in to comment.