package com.baidu.disconf.core.common.restful.impl;
import java.io.File;
import java.net.URL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baidu.disconf.core.common.restful.RestfulMgr;
import com.baidu.disconf.core.common.restful.core.RemoteUrl;
import com.baidu.disconf.core.common.restful.core.UnreliableInterface;
import com.baidu.disconf.core.common.restful.retry.RetryStrategy;
import com.baidu.disconf.core.common.restful.type.FetchConfFile;
import com.baidu.disconf.core.common.restful.type.RestfulGet;
import com.baidu.disconf.core.common.utils.ClassLoaderUtil;
import com.baidu.disconf.core.common.utils.MyStringUtils;
import com.baidu.disconf.core.common.utils.OsUtil;
import com.baidu.disconf.core.common.utils.http.HttpClientUtil;
/**
* RestFul的一个实现, 独立模块
*
* @author liaoqiqi
* @version 2014-6-10
*/
public class RestfulMgrImpl implements RestfulMgr {
protected static final Logger LOGGER = LoggerFactory.getLogger(RestfulMgrImpl.class);
/**
* 重试策略
*/
private RetryStrategy retryStrategy;
public RestfulMgrImpl(RetryStrategy retryStrategy) {
this.retryStrategy = retryStrategy;
HttpClientUtil.init();
}
/**
* 获取JSON数据
*
* @param clazz
* @param remoteUrl
*
* @return
*
* @throws Exception
*/
public <T> T getJsonData(Class<T> clazz, RemoteUrl remoteUrl, int retryTimes, int retrySleepSeconds)
throws Exception {
Exception ex = null;
for (URL url : remoteUrl.getUrls()) {
// 可重试的下载
UnreliableInterface unreliableImpl = new RestfulGet<T>(clazz, url);
try {
T t = retryStrategy.retry(unreliableImpl, retryTimes, retrySleepSeconds);
return t;
} catch (Exception e) {
ex = e;
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
LOGGER.info("pass");
}
}
}
throw new Exception("cannot get: " + remoteUrl, ex);
}
/**
* @param remoteUrl 远程地址
* @param fileName 文件名
* @param localFileDir 本地文件地址
* @param targetDirPath 下载完后,配置文件指定的文件目录
* @param retryTimes
* @param retrySleepSeconds
*
* @return
*
* @throws Exception
*/
@Override
public String downloadFromServer(RemoteUrl remoteUrl, String fileName, String localFileDir, String localFileDirTemp,
String targetDirPath, boolean enableLocalDownloadDirInClassPath,
int retryTimes, int retrySleepSeconds)
throws Exception {
// 目标地址文件
File localFile = null;
//
// 进行下载、mv、copy
//
try {
// 可重试的下载
File tmpFilePathUniqueFile = retryDownload(localFileDirTemp, fileName, remoteUrl, retryTimes,
retrySleepSeconds);
// 将 tmp file copy localFileDir
localFile = transfer2SpecifyDir(tmpFilePathUniqueFile, localFileDir, fileName, false);
// mv 到指定目录
if (targetDirPath != null) {
//
if (enableLocalDownloadDirInClassPath || !targetDirPath.equals(ClassLoaderUtil.getClassPath
())) {
localFile = transfer2SpecifyDir(tmpFilePathUniqueFile, targetDirPath, fileName, true);
}
}
LOGGER.debug("Move to: " + localFile.getAbsolutePath());
} catch (Exception e) {
LOGGER.warn("download file failed, using previous download file.", e);
}
//
// 判断是否下载失败
//
if (localFile == null || !localFile.exists()) {
throw new Exception("target file cannot be found! " + fileName);
}
//
// 下面为下载成功
//
// 返回相对路径
String relativePathString = OsUtil.getRelativePath(localFile, new File(localFileDir));
if (relativePathString != null) {
if (new File(relativePathString).isFile()) {
return relativePathString;
}
}
// 否则, 返回全路径
return localFile.getAbsolutePath();
}
@Override
public void close() {
HttpClientUtil.close();
}
/**
* 可重试的下载
*
* @param fileName
* @param remoteUrl
* @param retryTimes
* @param retrySleepSeconds
*
* @throws Exception
*/
private File retryDownload(String localFileDirTemp, String fileName, RemoteUrl remoteUrl, int retryTimes, int
retrySleepSeconds)
throws Exception {
if (localFileDirTemp == null) {
localFileDirTemp = "./disconf/download";
}
String tmpFilePath = OsUtil.pathJoin(localFileDirTemp, fileName);
String tmpFilePathUnique = MyStringUtils.getRandomName(tmpFilePath);
File tmpFilePathUniqueFile = new File(tmpFilePathUnique);
retry4ConfDownload(remoteUrl, tmpFilePathUniqueFile, retryTimes, retrySleepSeconds);
return tmpFilePathUniqueFile;
}
/**
* copy/mv 到指定目录
*
* @param srcFile
* @param targetDirPath
* @param fileName
*
* @return
*
* @throws Exception
*/
private File transfer2SpecifyDir(File srcFile, String targetDirPath, String fileName,
boolean isMove) throws Exception {
// make dir
OsUtil.makeDirs(targetDirPath);
File targetPath = new File(OsUtil.pathJoin(targetDirPath, fileName));
// 从下载文件 复制/mv 到targetPath 原子性的做转移
OsUtil.transferFileAtom(srcFile, targetPath, isMove);
return targetPath;
}
/**
* Retry封装 RemoteUrl 支持多Server的下载
*
* @param remoteUrl
* @param localTmpFile
* @param retryTimes
* @param sleepSeconds
*
* @return
*/
private Object retry4ConfDownload(RemoteUrl remoteUrl, File localTmpFile, int retryTimes, int sleepSeconds)
throws Exception {
Exception ex = null;
for (URL url : remoteUrl.getUrls()) {
// 可重试的下载
UnreliableInterface unreliableImpl = new FetchConfFile(url, localTmpFile);
try {
return retryStrategy.retry(unreliableImpl, retryTimes, sleepSeconds);
} catch (Exception e) {
ex = e;
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
LOGGER.info("pass");
}
}
}
throw new Exception("download failed.", ex);
}
}