Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.staticcdn.sdk.client.StaticCdnClient Maven / Gradle / Ivy
package io.staticcdn.sdk.client;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import io.staticcdn.sdk.client.model.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class StaticCdnClient {
private static Logger logger = Logger.getLogger(StaticCdnClient.class.getName());
private HttpResponse lastResponse;
private String lastResponseTextBody;
private HttpClient httpClient;
private ServerConfig serverConfig;
private List apiServerList;
private String clientUserAgent;
public StaticCdnClient() {
this(null, null);
}
public StaticCdnClient(String apiKey, String apiSecret) {
BasicHttpParams httpParams = new BasicHttpParams();
httpParams.setParameter(ClientPNames.HANDLE_REDIRECTS, false);
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
DefaultHttpClient defaultHttpClient = new DefaultHttpClient(httpParams);
httpClient = defaultHttpClient;
setupCredentials(apiKey, apiSecret, defaultHttpClient);
setupUserAgent();
setupServerConfig();
}
public OptimizeResponse optimize(
List inputWwwRoots,
File outputWwwRoot,
String filePath,
OptimizerOptions optimizerOptions,
String originalFileNameSuffix, String refsFileNameSuffix
) throws Exception {
if (outputWwwRoot == null) {
outputWwwRoot = inputWwwRoots.get(0);
}
backupExistingInputFile(inputWwwRoots, outputWwwRoot, filePath, originalFileNameSuffix);
Map path2fileMapping = new HashMap();
OptimizeRequest optimizeRequest = new OptimizeRequestBuilder(path2fileMapping).options(optimizerOptions).collectFiles(serverConfig.getOptimizeScanRules(), inputWwwRoots, filePath).build();
OptimizeResponse optimizeResponse = optimize(inputWwwRoots, optimizeRequest);
writeOptimizedResultToFile(outputWwwRoot, filePath, optimizeResponse,refsFileNameSuffix);
return optimizeResponse;
}
public OptimizeResponse optimize(List inputWwwRoots, OptimizeRequest optimizeRequest) throws Exception {
long startTimestamp = System.currentTimeMillis();
OptimizeResponse optimizeResponse;
try {
optimizeResponse = performOptimize(inputWwwRoots, optimizeRequest);
} catch (Throwable ex) {
if (ex.getMessage() == null || ex instanceof JsonSyntaxException) {
logger.severe("last response was " + lastResponse.getStatusLine().getReasonPhrase() + " body: " + readTextBody());
}
throw new Exception("Failed to optimize files: " + ex.getMessage(), ex);
}
logger.info("optimized " + optimizeRequest.getPaths().keySet().iterator().next() + " in " + ((System.currentTimeMillis() - startTimestamp) / 1000.0) + " seconds");
return optimizeResponse;
}
private ServerConfig apiCallConfig() {
for (String apiServerUrl : apiServerList) {
try {
executeRequest(new HttpGet(apiServerUrl + "/v1/config"), true);
Gson gson = new Gson();
return gson.fromJson(readTextBody(), ServerConfig.class);
} catch (Exception ex) {
logger.log(Level.WARNING, "failed to retrieve server config from " + apiServerUrl + ": " + ex.getMessage());
}
}
throw new RuntimeException("failed to retrieve server config");
}
private OptimizeResponse apiCallOptimize(OptimizeRequest optimizeRequest, Gson gson) throws Exception {
Exception lastException = null;
for (String apiServerUrl : apiServerList) {
try {
HttpPost request = new HttpPost(apiServerUrl + "/v1/optimizer/optimize");
String requestBody = gson.toJson(optimizeRequest);
if (logger.isLoggable(Level.FINE)) {
logger.fine("request body: " + requestBody);
}
request.setEntity(new StringEntity(requestBody, ContentType.create("application/json", "UTF-8")));
executeRequest(request, true);
return gson.fromJson(readTextBody(), OptimizeResponse.class);
} catch (Exception ex) {
if (lastResponse != null && lastResponse.getStatusLine().getStatusCode() < 500) {
throw ex;
}
logger.log(Level.WARNING, "failed to optimize with server " + apiServerUrl + ": " + ex.getMessage());
lastException = ex;
}
}
throw lastException;
}
private FilesInfoResponse apiCallUpload(List inputWwwRoots, Map path2keyMapping, List keys, Gson gson) throws Exception {
Map key2pathMapping = new HashMap();
for (Map.Entry pathAndKey : path2keyMapping.entrySet()) {
key2pathMapping.put(pathAndKey.getValue(), pathAndKey.getKey());
}
Exception lastException = null;
for (String apiServerUrl : apiServerList) {
try {
HttpPost request = new HttpPost(apiServerUrl + "/v1/files/upload");
MultipartEntity multipartEntity = new MultipartEntity();
List missingPaths = new ArrayList();
for (String missingKey : keys) {
for (File inputWwwRoot : inputWwwRoots) {
String filePath = key2pathMapping.get(missingKey);
File localFile = new File(inputWwwRoot, filePath);
if (localFile.isFile()) {
missingPaths.add(filePath);
multipartEntity.addPart("file", new FileBody(localFile));
multipartEntity.addPart("key", new StringBody(missingKey));
break;
}
}
}
request.setEntity(multipartEntity);
executeRequest(request, true);
logger.info("uploaded " + StringUtils.join(missingPaths, ','));
return gson.fromJson(readTextBody(), FilesInfoResponse.class);
} catch (Exception ex) {
if (lastResponse != null && lastResponse.getStatusLine().getStatusCode() < 500) {
throw ex;
}
logger.log(Level.WARNING, "failed upload to server " + apiServerUrl + ": " + ex.getMessage());
lastException = ex;
}
}
throw lastException;
}
private OptimizeResponse performOptimize(List inputWwwRoots, OptimizeRequest optimizeRequest) throws Exception {
Gson gson = new Gson();
OptimizeResponse optimizeResponse = apiCallOptimize(optimizeRequest, gson);
if (optimizeResponse.getCreatedAt() == null) {
if (optimizeResponse.getMissingKeys() != null) {
apiCallUpload(inputWwwRoots, optimizeRequest.getPaths(), optimizeResponse.getMissingKeys(), gson);
optimizeResponse = apiCallOptimize(optimizeRequest, gson);
}
if (optimizeResponse.getCreatedAt() == null) {
throw new RuntimeException(optimizeResponse.getMessage());
}
}
return optimizeResponse;
}
private void writeOptimizedResultToFile(File outputWwwRoot, String filePath, OptimizeResponse optimizeResponse,String refsFileNameSuffix) throws Exception {
String fileExtension = FilenameUtils.getExtension(filePath);
String fileBaseName = FilenameUtils.getBaseName(filePath);
File outputFile = buildOutputFile(outputWwwRoot, filePath);
FileUtils.writeStringToFile(outputFile, optimizeResponse.getOptimized(), "UTF-8");
System.out.println("optimized session " + optimizeResponse.getSignature() + " to " + outputFile.getCanonicalPath());
if(!refsFileNameSuffix.equals("skip")){
StringBuilder refText = new StringBuilder();
refText.append("session=" + optimizeResponse.getSignature() + "\n");
if (optimizeResponse.getReferences() != null) {
for (String referenceKey : optimizeResponse.getReferences().keySet()) {
refText.append(referenceKey + "=" + optimizeResponse.getReferences().get(referenceKey) + "\n");
}
}
File refOutputFile = new File(outputFile.getAbsolutePath() +refsFileNameSuffix);
FileUtils.writeStringToFile(refOutputFile, refText.toString());
}
}
private void backupExistingInputFile(List inputWwwRoots, File outputWwwRoot, String filePath, String originalFileNameSuffix) throws Exception {
if (!originalFileNameSuffix.equals("skip")) {
for (File inputWwwRoot : inputWwwRoots) {
File inputFile = new File(inputWwwRoot, filePath);
if (inputFile.exists()) {
File outputFile = buildOutputFile(outputWwwRoot, filePath);
File backupOriginFile = new File(outputFile.getAbsolutePath() + originalFileNameSuffix);
if (!backupOriginFile.exists()) {
FileUtils.copyFile(inputFile, backupOriginFile);
logger.fine("back up existing output file as:" + backupOriginFile.getAbsolutePath());
}
return;
}
}
}
}
private File buildOutputFile(File outputWwwRoot, String filePath) throws Exception {
File outputFile = new File(outputWwwRoot, filePath);
return outputFile;
}
public synchronized HttpResponse executeGet(String path) throws Exception {
return executeRequest(new HttpGet(apiServerList.get(0) + path), false);
}
public synchronized HttpResponse executeRequest(HttpUriRequest request, boolean verifyStatusOk) throws Exception {
if (lastResponse != null) {
if (lastResponseTextBody == null) {
try {
lastResponse.getEntity().getContent().close();
} catch (Exception ex) {
logger.warning("close previous connection failed with message: " + ex.getMessage());
}
}
lastResponse = null;
}
lastResponseTextBody = null;
URI uri = request.getURI();
if (logger.isLoggable(Level.FINE)) {
logger.fine("executing request " + request.getMethod() + ": " + uri);
}
AuthCache authCache = new BasicAuthCache();
HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
authCache.put(targetHost, new BasicScheme());
BasicHttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.AUTH_CACHE, authCache);
request.setHeader(HttpHeaders.USER_AGENT, clientUserAgent);
lastResponse = httpClient.execute(targetHost, request, localContext);
if (logger.isLoggable(Level.FINE)) {
logger.fine("executed request with response " + lastResponse.getStatusLine().getReasonPhrase() + " body: " + readTextBody());
}
if (verifyStatusOk && lastResponse.getStatusLine().getStatusCode() != 200) {
String errorMessage = null;
try {
ErrorResponse errorResponse = new Gson().fromJson(readTextBody(), ErrorResponse.class);
if (errorResponse.getMessage() != null) {
errorMessage = errorResponse.getMessage();
}
} catch (Throwable ignore) {
}
if (errorMessage == null) {
errorMessage = request.getMethod() + " : " + uri + " failed with status code " + lastResponse.getStatusLine().getStatusCode();
}
throw new RuntimeException(errorMessage);
}
return lastResponse;
}
private void setupCredentials(String apiKey, String apiSecret, DefaultHttpClient defaultHttpClient) {
if (StringUtils.isEmpty(apiKey)) {
apiKey = System.getenv("STATICO_API_KEY");
if (StringUtils.isEmpty(apiKey)) {
apiKey = System.getProperty("staticoApiKey");
if (StringUtils.isEmpty(apiKey)) {
Properties prop = new Properties();
File credentialFile = new File(System.getProperty("user.home"), ".statico/credentials");
if(credentialFile.isFile()){
InputStream input = null;
try {
input = new FileInputStream(credentialFile);
prop.load(input);
apiKey=prop.getProperty("apiKey");
apiSecret=prop.getProperty("apiSecret");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
if (StringUtils.isEmpty(apiKey)) {
apiKey = "anonymous";
}
}
}
}
if (StringUtils.isEmpty(apiSecret)) {
apiSecret = System.getenv("STATICO_API_SECRET");
if (StringUtils.isEmpty(apiSecret)) {
apiSecret = System.getProperty("staticoApiSecret");
if (StringUtils.isEmpty(apiSecret)) {
apiSecret = "none";
}
}
}
defaultHttpClient.getCredentialsProvider().setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
new UsernamePasswordCredentials(apiKey, apiSecret)
);
}
private void setupUserAgent() {
String clientVersion = "unknown";
try {
for (String line : IOUtils.readLines(this.getClass().getClassLoader().getResourceAsStream("META-INF/maven/io.staticcdn.sdk/staticcdn-sdk-client/pom.properties"))) {
if (line.startsWith("version=")) {
clientVersion = line.substring(line.indexOf("=") + 1);
}
}
} catch (Exception ex) {
}
clientUserAgent = "staticcdn-sdk-client " + clientVersion + " (" + System.getProperty("os.name") + " " + System.getProperty("os.version") + "/" + System.getProperty("java.vm.name") + " " + System.getProperty("java.runtime.version") + ")";
}
private void setupServerConfig() {
this.apiServerList = new ArrayList();
if (System.getProperty("staticCdnApiServerBaseUrl") != null) {
this.apiServerList.add(System.getProperty("staticCdnApiServerBaseUrl"));
serverConfig = apiCallConfig();
} else {
this.apiServerList.add("https://api.statico.io");
this.apiServerList.add("https://primary-api.statico.io");
this.apiServerList.add("https://backup-api.statico.io");
this.apiServerList.add("https://raw.githubusercontent.com/mrduguo/staticcdn-sdk/master");
serverConfig = apiCallConfig();
this.apiServerList = serverConfig.getApiServerList();
}
}
public HttpResponse getLastResponse() {
return lastResponse;
}
public List getApiServerList() {
return apiServerList;
}
public String readTextBody() throws Exception {
if (lastResponseTextBody == null) {
lastResponseTextBody = EntityUtils.toString(lastResponse.getEntity());
}
return lastResponseTextBody;
}
}