/**
 * 
 * Copyright zkyg 
 */
package com.upyuns.platform.rs.gtdata;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.*;
import java.nio.file.FileSystem;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 
 * Description:GTDATA接口客户端(详情请查看gtdata相关的api文档)
 *
 * @author JhYao 2014年11月11日
 * 
 * @version v1.0
 *
 */
@Service("gtDataRestClient")
@Conditional(GtdataCondition.class)
@Scope("singleton")
public class GtDataRestClient {

	private static Logger logger = LoggerFactory
			.getLogger(GtDataRestClient.class);

	@Autowired
	private RestTemplate restTemplate;
//
//	@Value("#{gtdataProperty[baseUrl]}")
//	protected String baseUrl;
//
//	@Value("#{gtdataProperty[gtDataUrl]}")
//	protected String gtDataUrl;
//
//	@Value("#{gtdataProperty[gtDataUsername]}")
//	protected String gtDataUsername;
//
//	@Value("#{gtdataProperty[gtDataPassword]}")
//	protected String gtDataPassword;

    @Value("${gtdata.baseUrl}")
    public String baseUrl;

    @Value("${gtdata.gtDataUrl}")
    public String gtDataUrl;

    @Value("${gtdata.gtDataUsername}")
    protected String gtDataUsername;

    @Value("${gtdata.gtDataPassword}")
    protected String gtDataPassword;

	@Value("${gtdata.outUrl}")
	public String outUrl;

	public String getOutUrl() {
		return outUrl;
	}

	public String getBaseUrl() {
		return baseUrl;
	}

	private String defaultToken;
	private String defaultSign;
	private String defaultTime;

	private static JsonMapper jsonMapper = JsonMapper.buildNormalMapper();

	private ScheduledExecutorService scheduler;

	@PostConstruct
	public void init() {
		try {
			login();// 第一次更新认证信息,在初始化时执行
		} catch (GtDataRestException e) {
			logger.warn("GtData login error. try again...", e);
			logout(defaultToken);
			login(); // 异常时，再试一次更新认证信息
		}
		int cpuCoreNumber = Runtime.getRuntime().availableProcessors();// cpu内核数
		scheduler = Executors.newScheduledThreadPool(cpuCoreNumber);
		Runnable task = new Runnable() {
			@Override
			public void run() {
				try {
					updateAuth(); // 更新认证信息
				} catch (GtDataRestException e) {
					logger.warn("GtData getSign error. try relogin...", e);
					logout(defaultToken);
					login(); // 异常时，重新登陆
				}
			}
		};
		Thread thread = new Thread(task);
		thread.setDaemon(true);
		scheduler.scheduleAtFixedRate(thread, 5L, 5L, TimeUnit.MINUTES);// 每5分钟执行一次

	}

	@PreDestroy
	public void dostory() {
		scheduler.shutdown();
	}

	public boolean isSign() {
		return defaultSign == null ? false : true;
	}

	/**
	 * 
	 * Description：取token
	 * 
	 * @return
	 *
	 */
	public Map<String, Object> getToken() {
		return getToken(gtDataUsername, "");
	}

	/**
	 * 
	 * Description：取token
	 * 
	 * @param username
	 * @return
	 *
	 */
	public Map<String, Object> getToken(String username, String rsign) {
		if(StrUtil.isNotBlank(rsign)){
			rsign = "&rsign="+ rsign;
		}else {
			rsign = "";
		}
		String resourceUrl = MessageFormat.format("{0}?op=GETTOKEN&user={1}{2}",
				baseUrl, username, rsign);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：登录
	 * 
	 * @param token
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> login(String token, String time) {
		return login(gtDataUsername, gtDataPassword, token, time, "");
	}

	/**
	 * 
	 * Description：登录
	 * 
	 * @param username
	 * @param password
	 * @param token
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> login(String username, String password,
			String token, String time, String rsign) {
		String resourceUrl = "";
		if(StrUtil.isNotBlank(rsign)){
			rsign = "&rsign="+ rsign;
		}else {
			rsign = "";
		}
		try {
			resourceUrl = MessageFormat.format(
					"{0}?op=LOGIN&user={1}&pass={2}&token={3}&time={4}{5}",
					baseUrl, username,
					Encodes.encodeHex(Digests.md5((Encodes.encodeHex(Digests
							.md5(password.getBytes())) + token).getBytes())),
					token, time, rsign);
		} catch (IOException e) {
			logger.error("password to md5 error.", e);
		}
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：获取sign
	 * 
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> getSign(String sign, String time) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=GETSIGN&sign={1}&time={2}", baseUrl, sign, time);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：登出
	 * 
	 * @param token
	 * @return
	 *
	 */
	public Map<String, Object> logout(String token) {
		String resourceUrl = MessageFormat.format("{0}?op=LOGOUT&token={1}",
				baseUrl, token);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：组用户注册普通用户
	 * 
	 * @param username
	 *            普通用户名
	 * @param password
	 *            MD5(密码)
	 * @param totalSize
	 *            普通用户空间的总大小(bytes)
	 * @return
	 *
	 */
	public Map<String, Object> register(String username, String password,
			String totalSize) {
		return register(username, password, totalSize, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：组用户注册普通用户
	 * 
	 * @param username
	 *            普通用户名
	 * @param password
	 *            MD5(密码)
	 * @param totalSize
	 *            普通用户空间的总大小(bytes)
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> register(String username, String password,
			String totalSize, String sign, String time) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=GREG&user={1}&pass={2}&total={3}&sign={4}&time={5}",
				baseUrl, username, password, totalSize, sign, time);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：删除普通用户
	 * 
	 * @param username
	 *            普通用户名
	 * @return
	 *
	 */
	public Map<String, Object> deleteUser(String username) {
		return deleteUser(username, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：删除普通用户
	 * 
	 * @param username
	 *            普通用户名
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> deleteUser(String username, String sign,
			String time) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=GDELUSER&user={1}&sign={2}&time={3}", baseUrl,
				username, sign, time);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：组用户修改自己的密码
	 * 
	 * @param newPassword
	 *            MD5(新密码)
	 * @return
	 *
	 */
	public Map<String, Object> changePassword(String newPassword) {
		return changePassword(newPassword, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：组用户修改自己的密码
	 * 
	 * @param newPassword
	 *            MD5(新密码)
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> changePassword(String newPassword, String sign,
			String time) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=CHANGEPWD&newpass={1}&sign={2}&time={3}", baseUrl,
				newPassword, sign, time);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：组用户修改普通用户的密码
	 * 
	 * @param username
	 *            普通用户名
	 * @param newPassword
	 *            MD5(新密码)
	 * @return
	 *
	 */
	public Map<String, Object> changeUserPassword(String username,
			String newPassword) {
		return changeUserPassword(username, newPassword, defaultSign,
				defaultTime);
	}

	/**
	 * 
	 * Description：组用户修改普通用户的密码
	 * 
	 * @param username
	 *            普通用户名
	 * @param newPassword
	 *            MD5(新密码)
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> changeUserPassword(String username,
			String newPassword, String sign, String time) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=GCHANGEPWD&user={1}&newpass={2}&sign={3}&time={4}",
				baseUrl, username, newPassword, sign, time);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：组用户修改普通用户容量
	 * 
	 * @param username
	 *            普通用户名
	 * @param newSize
	 *            修改后的空间的总大小(bytes)
	 * @return
	 *
	 */
	public Map<String, Object> changeUserSize(String username, long newSize) {
		return changeUserSize(username, newSize, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：组用户修改普通用户容量
	 * 
	 * @param username
	 *            普通用户名
	 * @param newSize
	 *            修改后的空间的总大小(bytes)
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> changeUserSize(String username, long newSize,
			String sign, String time) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=GCHANGESIZE&user={1}&newsize={2}&sign={3}&time={4}",
				baseUrl, username, newSize + "", sign, time);
		return restGet(resourceUrl);
	}

	/**
	 * 修改文件目录的权限
	 * 
	 * @param path
	 * @param newpermisson
	 * @return
	 */
	public Map<String, Object> changePermisson(String path, String newpermisson) {
		return changePermisson(path, newpermisson, defaultSign, defaultTime);
	}

	/**
	 * 修改文件目录的权限
	 * 
	 * @param path
	 * @param newpermisson
	 * @param sign
	 * @param time
	 * @return
	 */
	public Map<String, Object> changePermisson(String path,
			String newpermisson, String sign, String time) {
		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=CHANGEPERMISSON&newpermisson={2}&sign={3}&time={4}",
				gtDataUrl, path, newpermisson, sign, time);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：组用户获取普通用户容量等信息
	 * 
	 * @param username
	 *            普通用户名
	 * @return
	 *
	 */
	public Map<String, Object> userInfo(String username) {
		return userInfo(username, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：组用户获取普通用户容量等信息
	 * 
	 * @param username
	 *            普通用户名
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> userInfo(String username, String sign,
			String time) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=GGETUSERINFO&user={1}&sign={2}&time={3}", baseUrl,
				username, sign, time);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：根据路径创建文件夹
	 * 
	 * @param path
	 * @return
	 *
	 */
	public Map<String, Object> mkdirOnly(String path) {
		return mkdirOnly(path, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：根据路径创建文件夹
	 * 
	 * @param path
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> mkdirOnly(String path, String sign, String time) {
		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=MKDIRS&sign={2}&time={3}", gtDataUrl, path, sign,
				time);
		return rest(resourceUrl, HttpMethod.PUT, null);
	}

	/**
	 * Description：根据路径递归创建多级文件夹
	 * 
	 * @param path
	 */
	public Map<String, Object> mkdirs(String path) {
		String parentPath = StringUtils.substringBeforeLast(path, "/");
		if (logger.isInfoEnabled()) {
			logger.info("path:{},parentPath:{},isExist(parentPath):{},", path,parentPath,isExist(parentPath).get("exist"));
		}
		if ( isExist(parentPath).get("exist").toString().equals("true")) {
			return mkdirOnly(path);
			
		} else {
			mkdirs(parentPath);
			return mkdirOnly(path);
		}
	}

	/**
	 * 
	 * Description：文件或文件夹重命名
	 * 
	 * @param path
	 * @param newPath
	 * @return
	 *
	 */
	public Map<String, Object> move(String path, String newPath) {
		return move(path, newPath, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：文件或文件夹重命名
	 * 
	 * @param path
	 * @param newPath
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> move(String path, String newPath, String sign,
			String time) {
		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=MOVE&destination={2}&sign={3}&time={4}", gtDataUrl,
				path, newPath, sign, time);
		return rest(resourceUrl, HttpMethod.PUT, null);
	}

	/**
	 * 
	 * Description：删除文件或文件夹
	 * 
	 * @param path
	 * @return
	 *
	 */
	public Map<String, Object> delete(String path) {
		return delete(path, true, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：删除文件或文件夹
	 * 
	 * @param path
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> delete(String path, boolean recursive,
			String sign, String time) {

		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=DELETE&recursive={2}&sign={3}&time={4}", gtDataUrl,
				path, recursive, sign, time);
		return rest(resourceUrl, HttpMethod.DELETE, null);

	}

	/**
	 * 
	 * Description：复制文件或文件夹到指定路径
	 * 
	 * @param path
	 * @param newPath
	 * @return
	 *
	 */
	public Map<String, Object> copy(String path, String newPath) {
		return copy(path, newPath, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：复制文件或文件夹到指定路径
	 * 
	 * @param path
	 * @param newPath
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> copy(String path, String newPath, String sign,
			String time) {

		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=COPY&destination={2}&sign={3}&time={4}", gtDataUrl,
				path, newPath, sign, time);
		return rest(resourceUrl, HttpMethod.PUT, null);

	}

	/**
	 * 复制文件或文件夹到指定路径(带权限)
	 * 
	 * @param path
	 * @param newPath
	 * @param newcapflag
	 * @param newpermisson
	 * @return
	 */
	public Map<String, Object> copyWithPermisson(String path, String newPath,
			String newcapflag, String newpermisson) {

		String resourceUrl = MessageFormat
				.format("{0}{1}?op=COPY&destination={2}&sign={3}&time={4}&newcapflag={5}&newpermisson={6}",
						gtDataUrl, path, newPath, defaultSign, defaultTime,
						newcapflag, newpermisson);
		return rest(resourceUrl, HttpMethod.PUT, null);

	}

	/**
	 * 
	 * Description：显示指定路径[文件/文件夹(包括子文件)]的属性
	 * 
	 * @param path
	 * @return 
	 *         成功({key:HttpStatusCode,value:200},{key:files,value:List<GtdataFile
	 *         >})
	 *
	 */
	public Map<String, Object> list(String path) {
		return list(path, gtDataUsername, true, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：显示指定路径[文件/文件夹(包括子文件)]的属性
	 * 
	 * @param path
	 * @param username
	 * @param recursive
	 * @param sign
	 * @param time
	 * @return 
	 *         成功({key:HttpStatusCode,value:200},{key:files,value:List<GtdataFile
	 *         >})
	 *
	 */
	public Map<String, Object> list(String path, String username,
			boolean recursive, String sign, String time) {
		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=LIST&user={2}&recursive={3}&sign={4}&time={5}",
				gtDataUrl, path, username, recursive, sign, time);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			List<GtdataFile> gtdataFiles = mapToGtdataFiles(responseMap);
			myResponseMap.put("files", gtdataFiles);
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;

	}

	/**
	 *
	 * Description：显示指定路径[文件/文件夹(包括子文件)]的属性
	 *
	 * @param path
	 * @return
	 *         成功({key:HttpStatusCode,value:200},{key:files,value:List<GtdataFile
	 *         >})
	 *
	 */
	public Map<String, Object> showFileInfo(String path) {
		//路径 和 文件分离
//		Integer indexNum  = StrUtil.lastIndexOfIgnoreCase(path, "/");
//		String fpath = path.substring(0, indexNum);
//		String filename = path.substring(indexNum, path.length());
		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=LIST&sign={2}&time={3}",
				gtDataUrl, path, defaultSign, defaultTime);
		return restGet(resourceUrl);
	}

	/**
	 * 
	 * Description：(只能在Linux环境使用)根据路径读取文件内容(支持大文件)
	 * 
	 * @param filePath
	 * @param path
	 * @return
	 *
	 */
	public Map<String, Object> openLarge(String filePath, String path) {
		return openLarge(filePath, path, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：(只能在Linux环境使用)根据路径读取文件内容(支持大文件)
	 * 
	 * @param filePath
	 *            文件保存的路径
	 * @param path
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> openLarge(String filePath, String path,
			String sign, String time) {

		String resourceUrl = MessageFormat
				.format("{0}{1}?op=OPEN&sign={2}&time={3}", gtDataUrl, path,
						sign, time);

		try {
			// TODO 调curl进行下载,只能在Linux环境使用
			String curlString = MessageFormat.format("curl -o {0} {1}",
					filePath, "\"" + resourceUrl + "\"");
			String jsonResult = ExecLinuxCmd.exec(curlString);
			if (jsonResult != null && !"".equals(jsonResult)) {
				Map<String, Object> responseMap = jsonMapper.fromJson(
						jsonResult, HashMap.class);
				return responseMap;
			}
			Map<String, Object> success = new HashMap<String, Object>();
			success.put("HttpStatusCode", 200);// 调用成功
			return success;

		} catch (Exception e) {
			String message = MessageFormat.format(
					"call gtdata rest api [{0}] by linux curl throw exception",
					resourceUrl);
			logger.error(message, e);

			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 500);// 调用失败
			return error;

		}

	}

	/**
	 * 
	 * Description：根据路径读取文件内容 如果出现内存溢出,请使用openLarge(只能在Linux环境使用)
	 * 
	 * @see #openLarge(String, String)
	 * 
	 * @param path
	 * @return 
	 *         成功({key:HttpStatusCode,value:200},{key:file,value:ByteArrayInputStream
	 *         })
	 *
	 */
	public Map<String, Object> open(String path) {
		return open(path, defaultSign, defaultTime);
	}

	/**
	 *
	 * Description：根据路径读取文件内容的请求地址 如果出现内存溢出,请使用openLarge(只能在Linux环境使用)
	 *
	 * @see #openLarge(String, String)
	 *
	 * @param path
	 * @return url
	 *
	 */
	public String openUrl(String path, String sign, String time, String rsign) {
		if(StrUtil.isNotBlank(rsign)){
			rsign = "&rsign="+ rsign;
		}else {
			rsign = "";
		}
		String resourceUrl = MessageFormat
				.format("{0}{1}?op=OPEN&sign={2}&time={3}{4}", gtDataUrl, path,
						sign, time, rsign);
		return resourceUrl;
	}

	/**
	 * 
	 * Description：根据路径读取文件内容(小文件,1G以内的) 如果出现内存溢出,请使用openLarge(只能在Linux环境使用)
	 * 
	 * @see #openLarge(String, String, String, String)
	 * 
	 * @param path
	 * @param sign
	 * @param time
	 * @return 成功({key:HttpStatusCode,value:200},{key:file,value:byte[]})
	 *
	 */
	public Map<String, Object> open(String path, String sign, String time) {
		String resourceUrl = MessageFormat
				.format("{0}{1}?op=OPEN&sign={2}&time={3}", gtDataUrl, path,
						sign, time);

		try {
			ResponseEntity<byte[]> responseEntity = rest(resourceUrl,
					HttpMethod.GET, null, byte[].class);
			Map<String, Object> success = new HashMap<String, Object>();
			success.put("HttpStatusCode", 200);// 调用成功
			if (responseEntity.getBody() != null
					&& 0 < responseEntity.getBody().length) {
				success.put("file", responseEntity.getBody());
			}
			return success;

		} catch (HttpStatusCodeException e) {
			String message = MessageFormat
					.format("call gtdata rest api [{0}] throw exception: http status code {1}, response body {2}",
							resourceUrl, e.getStatusCode().value(),
							e.getResponseBodyAsString());
			logger.error(message, e);

			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", e.getStatusCode().value());// 调用失败
			if (e.getResponseBodyAsString() != null
					&& !"".equals(e.getResponseBodyAsString())) {
				Map<String, Object> exceptionMap = jsonMapper.fromJson(
						e.getResponseBodyAsString(), HashMap.class);
				if (exceptionMap != null && !exceptionMap.isEmpty()) {
					error.putAll(exceptionMap);
				}
			}
			return error;
		}

	}

	/**
	 * 通过httpclient下载数据，并输入到outputstream中
	 * 
	 * @param path
	 * @param output
	 * @return
	 */
	public Map<String, Object> openByHttpClient(String path, OutputStream output) {
		return openByHttpClient(path, output, defaultSign, defaultTime);
	}

	public Map<String, Object> openByHttpClient(String path,
			OutputStream output, String sign, String time) {
		String resourceUrl = MessageFormat
				.format("{0}{1}?op=OPEN&sign={2}&time={3}", gtDataUrl, path,
						sign, time);
		Map<String, Object> result = new HashMap<String, Object>();
		try {
			result = HttpUtils.GetFile(resourceUrl, output);
			if ((Integer) result.get("HttpStatusCode") != HttpStatus.SC_OK) {
				String message = MessageFormat
						.format("call gtdata rest api [{0}] throw exception: http status code {1}, response body {2}",
								resourceUrl, result.get("HttpStatusCode"),
								result);
				logger.error(message);
			}
			return result;

		} catch (IOException e) {
			String message = MessageFormat.format(
					"call gtdata rest api [{0}] throw IOException: {1}",
					resourceUrl, e.getMessage());
			logger.error(message, e);
			result.put("HttpStatusCode", 500);
		} finally {
			IOUtils.closeQuietly(output);
		}
		return result;
	}

	/**
	 * 
	 * Description：单独上传文件的MD5值
	 * 
	 * @param path
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> md5(String path, String sign,
			String time, String md5) {// xsx modified

		String resourceUrlMd5 = MessageFormat.format(
				"{0}{1}?op=MD5&value={2}&sign={3}&time={4}", gtDataUrl, path,
				md5, sign, time);
		return rest(resourceUrlMd5, HttpMethod.PUT, null);

	}

	/**
	 * 
	 * Description：(只能在Linux环境使用)根据路径创建并写入文件(包含上传文件的MD5、覆盖旧文件)
	 * 
	 * @param filePath
	 * @param path
	 * @return
	 *
	 */
	public Map<String, Object> createLarge(String filePath, String path) {
		return createLarge(filePath, path, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：(只能在Linux环境使用)根据路径创建并写入文件(包含上传文件的MD5、覆盖旧文件)
	 * 
	 * @param filePath
	 * @param path
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> createLarge(String filePath, String path,
			String sign, String time) {
		return createLarge(filePath, path, sign, time, true);// 覆盖旧文件
	}

	/**
	 * 
	 * Description：(只能在Linux环境使用)根据路径创建并写入文件(包含上传文件的MD5)
	 * 
	 * @param filePath
	 * @param path
	 * @param sign
	 * @param time
	 * @param overwrite
	 * @return
	 *
	 */
	public Map<String, Object> createLarge(String filePath, String path,
			String sign, String time, boolean overwrite) {

		String md5 = "";

		try {
			md5 = fileToMd5(filePath);
		} catch (Exception e) {
			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 0);// 上传文件不存在
			return error;
		}

		Map<String, Object> responseMap = md5(path, sign, time, md5);
		if (responseMap != null
				&& (200 == (Integer) responseMap.get("HttpStatusCode") || 404 != (Integer) responseMap
						.get("HttpStatusCode"))) {
			return responseMap;// 已存在该文件,无需上传（秒传） 或 异常
		}

		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=CREATE&md5={2}&sign={3}&time={4}&overwrite={5}",
				gtDataUrl, path, md5, sign, time, overwrite);

		try {
			// TODO 调curl进行上传,只能在Linux环境使用
			String curlString = MessageFormat.format("curl -T {0} -X PUT {1}",
					filePath, "\"" + resourceUrl + "\"");
			String jsonResult = ExecLinuxCmd.exec(curlString);
			Map<String, Object> responseMap2 = jsonMapper.fromJson(jsonResult,
					HashMap.class);
			return responseMap2;

		} catch (Exception e) {
			String message = MessageFormat.format(
					"call gtdata rest api [{0}] by linux curl throw exception",
					resourceUrl);
			logger.error(message, e);

			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 500);// 调用失败
			return error;

		}

	}

	/**
	 * 
	 * Description：(小文件,1G以内的)根据路径创建并写入文件(包含上传文件的MD5)
	 * 如果出现内存溢出,请使用createLarge(只能在Linux环境使用)
	 * 
	 * @see #createLarge(String, String)
	 * 
	 * @param filePath
	 * @param path
	 * @return
	 *
	 */
	public Map<String, Object> create(String filePath, String path) {
		return create(filePath, path, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：(小文件,1G以内的)根据路径创建并写入文件(包含上传文件的MD5)
	 * 如果出现内存溢出,请使用createLarge(只能在Linux环境使用)
	 * 
	 * @see #createLarge(String, String, String, String)
	 * 
	 * @param filePath
	 * @param path
	 * @param sign
	 * @param time
	 * @return
	 *
	 */
	public Map<String, Object> create(String filePath, String path,
			String sign, String time) {
		return create(filePath, path, sign, time, true);// 覆盖旧文件
	}

	/**
	 * 
	 * Description：(小文件,1G以内的)根据路径创建并写入文件(包含上传文件的MD5)
	 * 如果出现内存溢出,请使用createLarge(只能在Linux环境使用)
	 * 
	 * @see #createLarge(String, String, String, String, boolean)
	 * 
	 * @param filePath
	 * @param path
	 * @param sign
	 * @param time
	 * @param overwrite
	 * @return
	 *
	 */
	public Map<String, Object> create(String filePath, String path,
			String sign, String time, boolean overwrite) {

		String md5 = "";

		try {
			md5 = fileToMd5(filePath);
		} catch (Exception e) {
			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 0);// 上传文件不存在
			return error;
		}

		Map<String, Object> responseMap = md5(path, sign, time, md5);
		if (responseMap != null
				&& (200 == (Integer) responseMap.get("HttpStatusCode") || 404 != (Integer) responseMap
						.get("HttpStatusCode"))) {
			return responseMap;// 已存在该文件,无需上传（秒传） 或 异常
		}

		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=CREATE&md5={2}&sign={3}&time={4}&overwrite={5}",
				gtDataUrl, path, md5, sign, time, overwrite);

		try {
			HttpEntity<byte[]> httpEntity = new HttpEntity(
					IOUtils.toByteArray(new FileInputStream(filePath)));
			Map<String, Object> responseMap2 = rest(resourceUrl,
					HttpMethod.PUT, httpEntity);
			return responseMap2;

		} catch (Exception e) {
			String message = MessageFormat.format(
					"call gtdata rest api [{0}] by linux curl throw exception",
					resourceUrl);
			logger.error(message, e);

			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 500);// 调用失败
			return error;

		}

	}

	/**
	 *
	 * Description：(小文件,1G以内的)根据路径创建并写入文件(包含上传文件的MD5)
	 * 如果出现内存溢出,请使用createLarge(只能在Linux环境使用)
	 *
	 * @see #createLarge(String, String, String, String, boolean)
	 *
	 * @param file
	 * @param path
	 * @return
	 *
	 */
	public Map<String, Object> createMultipartFile(MultipartFile file, String path) {
		return createMultipartFile(file, path, defaultSign, defaultTime, Boolean.TRUE);
	}

	/**
	 *
	 * Description：(小文件,1G以内的)根据路径创建并写入文件(包含上传文件的MD5)
	 * 如果出现内存溢出,请使用createLarge(只能在Linux环境使用)
	 *
	 * @see #createLarge(String, String, String, String, boolean)
	 *
	 * @param file
	 * @param path
	 * @param sign
	 * @param time
	 * @param overwrite
	 * @return
	 *
	 */
	public Map<String, Object> createMultipartFile(MultipartFile file, String path,
												 String sign, String time, boolean overwrite) {
		InputStream inputStream = null;
		try {
			byte [] byteArr=file.getBytes();
			inputStream = new ByteArrayInputStream(byteArr);
			return createInputStream(byteArr, inputStream, path, sign, time, overwrite);
		}catch (Exception e){
			logger.error(e.getMessage(), e);
		}finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				}catch (Exception ex) {
					logger.error(ex.getMessage(), ex);
				}
			}
		}
		Map<String, Object> error = CollUtil.newHashMap();
		error.put("HttpStatusCode", 500);// 调用失败
		return error;
	}

	/**
	 *
	 * Description：(小文件,1G以内的)根据路径创建并写入文件(包含上传文件的MD5)
	 * 如果出现内存溢出,请使用createLarge(只能在Linux环境使用)
	 *
	 * @see #createLarge(String, String, String, String, boolean)
	 *
	 * @param file
	 * @param path
	 * @param sign
	 * @param time
	 * @param overwrite
	 * @return
	 *
	 */
	public Map<String, Object> createInputStream(byte [] byteArr, InputStream file, String path,
									  String sign, String time, boolean overwrite) {

		String md5 = "";

		try {
			md5 = fileToMd5(file);
		} catch (Exception e) {
			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 0);// 上传文件不存在
			return error;
		}

		Map<String, Object> responseMap = md5(path, sign, time, md5);
  		if (responseMap != null
				&& (200 == (Integer) responseMap.get("HttpStatusCode") || 404 != (Integer) responseMap
				.get("HttpStatusCode"))) {
			return responseMap;// 已存在该文件,无需上传（秒传） 或 异常
		}


		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=CREATE&md5={2}&sign={3}&time={4}&overwrite={5}",
				gtDataUrl, path, md5, sign, time, overwrite);

		try {
 			HttpEntity<byte[]> httpEntity = null;

			if(null != byteArr && byteArr.length > 0) {
				httpEntity = new HttpEntity(byteArr);
			}else {
				httpEntity = new HttpEntity(
						IoUtil.readBytes(file));
			}

			Map<String, Object> responseMap2 = rest(resourceUrl,
					HttpMethod.PUT, httpEntity);
			return responseMap2;

		} catch (Exception e) {
			String message = MessageFormat.format(
					"call gtdata rest api [{0}] by linux curl throw exception",
					resourceUrl);
			logger.error(message, e);

			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 500);// 调用失败
			return error;

		}

	}

	public Map<String, Object> createByHttpCilent(String filePath, String path) {
		return createByHttpCilent(filePath, path, defaultSign, defaultTime,
				true);
	}

	public Map<String, Object> createByHttpCilent(String filePath, String path,
			String sign, String time, boolean overwrite) {

		String md5 = "";

		try {
			md5 = fileToMd5(filePath);
		} catch (Exception e) {
			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 0);// 上传文件不存在
			return error;
		}

		Map<String, Object> responseMap = md5(path, sign, time, md5);
		if (responseMap != null
				&& (200 == (Integer) responseMap.get("HttpStatusCode") || 404 != (Integer) responseMap
						.get("HttpStatusCode"))) {
			return responseMap;// 已存在该文件,无需上传（秒传） 或 异常
		}

		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=CREATE&md5={2}&sign={3}&time={4}&overwrite={5}",
				gtDataUrl, path, md5, sign, time, overwrite);

		try {
			Map<String, Object> responseMap2 = HttpUtils.putFile(resourceUrl,
					new File(filePath));
			return responseMap2;

		} catch (Exception e) {
			String message = MessageFormat.format(
					"call gtdata rest api [{0}] by linux curl throw exception",
					resourceUrl);
			logger.error(message, e);

			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", 500);// 调用失败
			return error;
		}
	}

	/**
	 * 
	 * Description：统计路径下的文件总大小(包含子目录的文件)
	 * 
	 * @param path
	 * @return 成功({key:HttpStatusCode,value:200},{key:totalSize,value:总大小字节})
	 *
	 */
	public Map<String, Object> countFileSize(String path) {
		return countFileSize(path, gtDataUsername, true, defaultSign,
				defaultTime);
	}

	/**
	 * 
	 * Description：统计路径下的文件总大小
	 * 
	 * @param path
	 * @param username
	 * @param recursive
	 * @param sign
	 * @param time
	 * @return 成功({key:HttpStatusCode,value:200},{key:totalSize,value:总大小字节})
	 *
	 */
	public Map<String, Object> countFileSize(String path, String username,
			boolean recursive, String sign, String time) {
		Map<String, Object> responseMap = list(path, username, recursive, sign,
				time);
		if (responseMap != null && responseMap.containsKey("files")) {
			List<GtdataFile> gtdataFiles = (List<GtdataFile>) responseMap
					.get("files");
			Map<String, Object> success = new HashMap<String, Object>();
			success.put("HttpStatusCode", 200);// 调用成功
			success.put("totalSize", countFileSize(gtdataFiles));
			return success;
		}
		return responseMap;
	}

	/**
	 * 
	 * Description：判断文件或文件夹是否存在
	 * 
	 * @param path
	 * @return 存在(key:exist,value:true),不存在(key:exist,value:true)
	 *
	 */
	public Map<String, Object> isExist(String path) {
		return isExist(path, gtDataUsername, defaultSign, defaultTime);
	}

	/**
	 * 
	 * Description：判断文件或文件夹是否存在
	 * 
	 * @param path
	 * @param username
	 * @param sign
	 * @param time
	 * @return 存在(key:exist,value:true),不存在(key:exist,value:true)
	 *
	 */
	public Map<String, Object> isExist(String path, String username,
			String sign, String time) {
		Map<String, Object> responseMap = list(path, username, false, sign,
				time);

		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			responseMap = new HashMap<String, Object>();
			responseMap.put("HttpStatusCode", 200);
			responseMap.put("exist", true);
			return responseMap;
		}

		if (responseMap != null
				&& 404 == (Integer) responseMap.get("HttpStatusCode")) {
			responseMap = new HashMap<String, Object>();
			responseMap.put("HttpStatusCode", 404);
			responseMap.put("exist", false);
			return responseMap;
		}

		return responseMap;
	}

	/**
	 * 
	 * Description：计算文件总大小
	 * 
	 * @param gtdataFiles
	 * @return
	 *
	 */
	protected long countFileSize(List<GtdataFile> gtdataFiles) {
		long total = 0;
		for (GtdataFile gtdataFile : gtdataFiles) {
			if (!"-1".equals(gtdataFile.getSize())) {
				total += Long.valueOf(gtdataFile.getSize());
			}
			if (gtdataFile.getChild() != null
					&& !gtdataFile.getChild().isEmpty()) {
				total += countFileSize(gtdataFile.getChild());
			}
		}
		return total;
	}
	
	/**
	 * @Description rest方式请求封装(resourceUrl不带sign和time)
	 * @param resourceUrl
	 * @param httpMethod
	 * @return
	 */
	public Map<String, Object> restWithoutSignAndTime(String resourceUrl, HttpMethod httpMethod){
		resourceUrl =gtDataUrl+resourceUrl+ MessageFormat.format("&sign={0}&time={1}",defaultSign, defaultTime);
		return rest(resourceUrl,httpMethod,null);
	}
	
	/**
	 * 
	 * Description：rest方式Get请求封装
	 * 
	 * @param resourceUrl
	 * @return
	 *
	 */
	public Map<String, Object> restGet(String resourceUrl) {
		return rest(resourceUrl, HttpMethod.GET, null);

	}

	/**
	 * 
	 * Description：rest方式请求封装
	 * 
	 * @param resourceUrl
	 * @param httpMethod
	 * @param httpEntity
	 * @return
	 *
	 */
	protected <T> Map<String, Object> rest(String resourceUrl,
                                           HttpMethod httpMethod, HttpEntity<T> httpEntity) {
		try {
			ResponseEntity<HashMap> responseEntity = rest(resourceUrl,
					httpMethod, httpEntity, HashMap.class);
			Map<String, Object> success = new HashMap<String, Object>();
			success.put("HttpStatusCode", responseEntity.getStatusCode()
					.value());// 调用成功
			if (responseEntity.getBody() != null
					&& !responseEntity.getBody().isEmpty()) {
				success.putAll(responseEntity.getBody());
			}
			return success;

		} catch (HttpStatusCodeException e) {
			String message = MessageFormat
					.format("call gtdata rest api [{0}] throw exception: http status code {1}, response body {2}",
							resourceUrl, e.getStatusCode().value(),
							e.getResponseBodyAsString());
			logger.debug(message, e);

			Map<String, Object> error = new HashMap<String, Object>();
			error.put("HttpStatusCode", e.getStatusCode().value());// 调用失败
			if (e.getResponseBodyAsString() != null
					&& !"".equals(e.getResponseBodyAsString())) {
				Map<String, Object> exceptionMap = jsonMapper.fromJson(
						e.getResponseBodyAsString(), HashMap.class);
				if (exceptionMap != null && !exceptionMap.isEmpty()) {
					error.putAll(exceptionMap);
				}
			}
			if (HttpStatus.SC_FORBIDDEN == e.getStatusCode().value()) {
				logger.warn("FORBIDDEN 403, relogin...", e);
				logout(defaultToken);
				login(); // 403时，再试一次更新认证信息
			}
			return error;
		}
	}

	/**
	 * 
	 * Description：rest方式请求封装
	 * 
	 * @param resourceUrl
	 * @param httpMethod
	 * @param httpEntity
	 * @param elementClass
	 * @return
	 *
	 */
	protected <T, E> ResponseEntity<E> rest(String resourceUrl,
                                            HttpMethod httpMethod, HttpEntity<T> httpEntity,
                                            Class<E> elementClass) {
		UriComponents uriComponents = UriComponentsBuilder.fromUriString(
				resourceUrl).build();
		ResponseEntity<E> responseEntity = restTemplate.exchange(
				uriComponents.toUri(), httpMethod, httpEntity, elementClass);
		return responseEntity;
	}

	/**
	 * 
	 * Description：计算文件的md5值
	 * 
	 * @param filePath
	 * @return
	 * @throws IOException
	 *
	 */
	protected String fileToMd5(String filePath) throws IOException {
		File file = new File(filePath);
		return Encodes.encodeHex(Digests.md5(new FileInputStream(file)));
	}

	/**
	 *
	 * Description：计算文件的md5值
	 *
	 * @param file
	 * @return
	 * @throws IOException
	 *
	 */
	protected String fileToMd5(InputStream file) throws IOException {
		return Encodes.encodeHex(Digests.md5(file));
	}

	/**
	 * Description：Map转ShareFile
	 * 
	 * @param responseMap
	 * @return
	 */
	protected List<ShareFile> mapToShareFiles(Map<String, Object> responseMap,
			String keyValue) {
		List<ShareFile> shareFiles = new ArrayList<ShareFile>();
		if (responseMap.containsKey(keyValue)) {
			for (Map fileMap : (List<Map>) responseMap.get(keyValue)) {
				ShareFile shareFile = new ShareFile();
				if (keyValue.equals("friends")) { // 获取所有好友只有name属性

					shareFile.setName((String) fileMap.get("name"));

				} else if (keyValue.equals("groups")) { // 列取用户所属所有组:(包含有id
														// 与name属性)

					shareFile.setId((String) fileMap.get("id"));
					shareFile.setName((String) fileMap.get("name"));

				} else if (keyValue.equals("groupshare")
						|| keyValue.equals("friendshare")) { // 查看组分享 OR 查看好友分享

					shareFile.setId((String) fileMap.get("id"));
					shareFile.setName((String) fileMap.get("name"));
					shareFile.setUser((String) fileMap.get("user"));
					shareFile.setSharetime((String) fileMap.get("sharetime"));
					shareFile.setSize((String) fileMap.get("size"));

				} else if (keyValue.equals("myshare")) { // 查看我的分享

					shareFile.setId((String) fileMap.get("id"));
					shareFile.setName((String) fileMap.get("name"));
					shareFile.setPath((String) fileMap.get("path"));
					shareFile.setSharetime((String) fileMap.get("sharetime"));
					shareFile.setIsdir((String) fileMap.get("isdir"));
				}
				shareFiles.add(shareFile);
			}
		}
		return shareFiles;
	}

	/**
	 * 
	 * Description：Map转GtdataFile 用于查询猎取分享目录
	 * 
	 * @param responseMap
	 * @return
	 *
	 */
	protected List<ShareFile> mapToShareFilesToQueryList(
			Map<String, Object> responseMap) {
		List<ShareFile> shareFiles = new ArrayList<ShareFile>();
		if (responseMap.containsKey("files")) { // 当前属于文件夹
			/*
			 * ShareFile shareFile= new ShareFile();
			 * shareFile.setId((String)responseMap.get("id"));
			 * shareFile.setUser((String)responseMap.get("user"));
			 * shareFile.setPath((String)responseMap.get("path"));
			 * shareFile.setSharetime((String)responseMap.get("sharetime"));
			 * shareFile.setSize((String)responseMap.get("size"));
			 */
			for (Map fileMap : (List<Map>) responseMap.get("files")) {
				ShareFile shareFile0 = new ShareFile();
				shareFile0.setId((String) fileMap.get("id"));
				shareFile0.setUser((String) fileMap.get("user"));
				shareFile0.setPath((String) fileMap.get("path"));
				shareFile0.setSharetime((String) fileMap.get("sharetime"));
				shareFile0.setSize((String) fileMap.get("size"));
				List<ShareFile> child = null;
				if (fileMap.containsKey("files")) {
					child = mapToShareFilesToQueryList(fileMap);// 递归
				}
				shareFile0.setChild(child);
				shareFiles.add(shareFile0);
			}
		} else { // 当前目录属于文件
			ShareFile shareFile = new ShareFile();
			shareFile.setId((String) responseMap.get("id"));
			shareFile.setUser((String) responseMap.get("user"));
			shareFile.setPath((String) responseMap.get("path"));
			shareFile.setSharetime((String) responseMap.get("sharetime"));
			shareFile.setSize((String) responseMap.get("size"));
			shareFiles.add(shareFile);
		}
		return shareFiles;
	}

	protected List<GtdataFile> mapToGtdataFiles(Map<String, Object> responseMap) {
		List<GtdataFile> gtdataFiles = new ArrayList<GtdataFile>();
		if (responseMap.containsKey("files")) {
			for (Map fileMap : (List<Map>) responseMap.get("files")) {
				GtdataFile gtdataFile = new GtdataFile();
				gtdataFile.setPath((String) fileMap.get("path"));
				gtdataFile.setSize((String) fileMap.get("size"));
				gtdataFile.setTime(new DateTime(Long.parseLong(fileMap
						.get("time") + "000")).toString("yyyy-MM-dd HH:mm:ss"));
				gtdataFile.setFilename(StringUtils.substringAfterLast(
						gtdataFile.getPath(), "/"));
				List<GtdataFile> child = null;
				if (fileMap.containsKey("files")) {
					child = mapToGtdataFiles(fileMap);// 递归
				}
				gtdataFile.setChild(child);
				gtdataFiles.add(gtdataFile);
			}
		} else {
			GtdataFile gtdataFile = new GtdataFile();
			gtdataFile.setPath((String) responseMap.get("path"));
			gtdataFile.setSize((String) responseMap.get("size"));
			gtdataFile.setTime(new DateTime(Long.parseLong(responseMap
					.get("time") + "000")).toString("yyyy-MM-dd HH:mm:ss"));
			gtdataFile.setFilename(StringUtils.substringAfterLast(
					gtdataFile.getPath(), "/"));
			gtdataFiles.add(gtdataFile);
		}

		return gtdataFiles;
	}

	/**
	 * 
	 * Description： 登陆并更新认证信息
	 *
	 */
	protected void login() throws GtDataRestException {
		Map<String, Object> tokenMap = getToken();
		defaultToken = (String) tokenMap.get("token");
		defaultTime = (String) tokenMap.get("time");
		if (200 != (Integer) tokenMap.get("HttpStatusCode")) {
			throw new GtDataRestException((String) tokenMap.get("errorCode"));
		}

		Map<String, Object> loginMap = login(defaultToken, defaultTime);
		defaultTime = (String) loginMap.get("time");
		defaultSign = (String) loginMap.get("sign");
		if (200 != (Integer) loginMap.get("HttpStatusCode")) {
			throw new GtDataRestException((String) loginMap.get("errorCode"));
		}

	}

	/**
	 *
	 * Description： 子用户登陆并更新认证信息
	 *
	 */
	public GdLoginVO rsignUserlogin(String user, String pass) throws GtDataRestException {
		Map<String, Object> tokenMap = getToken(user, user);
		String userToken = (String) tokenMap.get("token");
		String userTime = (String) tokenMap.get("time");
		if (200 != (Integer) tokenMap.get("HttpStatusCode")) {
			throw new GtDataRestException((String) tokenMap.get("errorCode"));
		}

		Map<String, Object> loginMap = login(user, pass, userToken, userTime, user);
		GdLoginVO gdLoginVO = new GdLoginVO(){{
			setTime((String) loginMap.get("time"));
			setSign((String) loginMap.get("sign"));
		}};
		if (200 != (Integer) loginMap.get("HttpStatusCode")) {
			throw new GtDataRestException((String) loginMap.get("errorCode"));
		}
		return gdLoginVO;
	}

	/**
	 * 
	 * Description： 更新认证信息
	 *
	 */
	protected void updateAuth() throws GtDataRestException {
		Map<String, Object> signMap = getSign(defaultSign, defaultTime);
		defaultTime = (String) signMap.get("time");
		defaultSign = (String) signMap.get("sign");
		if (200 != (Integer) signMap.get("HttpStatusCode")) {
			throw new GtDataRestException((String) signMap.get("errorCode"));
		}
	}

	/**
	 * Description：创建逻辑组
	 * 
	 * @param groupName
	 *            逻辑组名称
	 * @return
	 *
	 */
	public Map<String, Object> createLogicGroup(String groupName) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=CREATELOGICGROUP&sign={1}&time={2}&groupname={3}",
				gtDataUrl, defaultSign, defaultTime, groupName);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：增加逻辑组成员
	 * 
	 * @param groupId
	 *            逻辑组ID
	 * @param userName
	 *            成员名称
	 * @return
	 */
	public Map<String, Object> addToLogicGroup(String groupId, String userName) {
		String resourceUrl = MessageFormat
				.format("{0}?op=ADDTOLOGICGROUP&sign={1}&time={2}&groupid={3}&user={4}",
						gtDataUrl, defaultSign, defaultTime, groupId, userName);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：删除逻辑组成员
	 * 
	 * @param groupId
	 *            用户所属的组id
	 * @param userName
	 *            要删除的用户名
	 * @return
	 */
	public Map<String, Object> delFromLogicGroup(String groupId, String userName) {
		String resourceUrl = MessageFormat
				.format("{0}?op=DELFROMLOGICGROUP&sign={1}&time={2}&groupid={3}&user={4}",
						gtDataUrl, defaultSign, defaultTime, groupId, userName);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：添加好友
	 * 
	 * @param userName
	 *            好友用户名
	 * @return
	 */
	public Map<String, Object> addFriend(String userName) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=ADDFRIEND&sign={1}&time={2}&user={3}", gtDataUrl,
				defaultSign, defaultTime, userName);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：删除好友
	 *
	 * @param userName
	 *            好友用户名
	 * @return
	 */
	public Map<String, Object> delFriend(String userName) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=DELFRIEND&sign={1}&time={2}&user={3}", gtDataUrl,
				defaultSign, defaultTime, userName);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：修改逻辑组权限及管理员标志位
	 * 
	 * @param groupId
	 *            要修改权限的逻辑组id
	 * @param userName
	 *            要修改权限的用户
	 * @param newpermisson
	 *            新权限
	 * @return
	 */
	public Map<String, Object> modLogicGroupPermisson(String groupId,
			String userName, String newpermisson) {
		String resourceUrl = MessageFormat
				.format("{0}?op=MODLOGICGROUPPERMISSON&sign={1}&time={2}&groupid={3}&user={4}&newpermisson={5}",
						gtDataUrl, defaultSign, defaultTime, groupId, userName,
						newpermisson);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：修改是否接受分享标志位（逻辑组）
	 * 
	 * @param groupId
	 *            要修改的逻辑组id
	 * @param shareFlag
	 *            1------接受分享， 0------不接受分享
	 * @return
	 */
	public Map<String, Object> modLogicGroupShareFlag(String groupId,
			String shareFlag) {
		String resourceUrl = MessageFormat
				.format("{0}?op=MODLOGICGROUPSHAREFLAG&sign={1}&time={2}&groupid={3}&shareflag={4}",
						gtDataUrl, defaultSign, defaultTime, groupId, shareFlag);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：修改是否接受分享标志位（好友）
	 * 
	 * @param userName
	 *            要修改的好友用户
	 * @param shareFlag
	 *            1------接受分享， 0------不接受分享
	 * @return
	 */
	public Map<String, Object> modFriendShareFlag(String userName,
			String shareFlag) {
		String resourceUrl = MessageFormat
				.format("{0}?op==MODFRIENDSHAREFLAG&sign={1}&time={2}&user={3}&shareflag={4}",
						gtDataUrl, defaultSign, defaultTime, userName,
						shareFlag);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：分享至公共云（组分享）
	 * 
	 * @param path
	 * @param groupId
	 * @return
	 */
	public Map<String, Object> groupShare(String path, String groupId) {
		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=GROUPSHARE&sign={2}&time={3}&groupid={4}",
				gtDataUrl, path, defaultSign, defaultTime, groupId);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * 
	 * Description：好友分享
	 * 
	 * @param userName
	 *            分享给哪个好友的好友名称
	 * @return
	 *
	 */
	public Map<String, Object> friendShare(String userName) {
		String resourceUrl = MessageFormat.format(
				"{0}{1}?op=FRIENDSHARE&sign={2}&time={3}&user={4}", gtDataUrl,
				defaultSign, defaultTime, userName);
		Map<String, Object> responseMap = restGet(resourceUrl);
		return responseMap;
	}

	/**
	 * Description：取消分享
	 * 
	 * @param groupId
	 * @return
	 *
	 */
	public Map<String, Object> cancelShare(String path, String groupId,
			String sharetime) {
		String resourceUrl = MessageFormat
				.format("{0}{1}?op=CANCELSHARE&sign={2}&time={3}&groupid={4}&sharetime={5}",
						gtDataUrl, path, defaultSign, defaultTime, groupId,
						sharetime);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			myResponseMap.putAll(responseMap);
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：删除分享
	 * 
	 * @param groupId
	 *            分享属于哪个组
	 * @param username
	 *            谁分享的
	 * @param item
	 *            分享的项目名
	 * @param sharetime
	 *            分享时间
	 * @return
	 */
	public Map<String, Object> deleteShare(String groupId, String username,
			String item, String sharetime) {
		String resourceUrl = MessageFormat
				.format("{0}?op=DELETESHARE&sign={1}&time={2}&groupid={3}&user={4}&item={5}&sharetime={6}",
						gtDataUrl, defaultSign, defaultTime, groupId, username,
						item, sharetime);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：保存至我的网盘
	 * 
	 * @param destination
	 *            目的路径
	 * @param groupId
	 *            分享属于哪个组
	 * @param userName
	 *            谁分享的
	 * @param item
	 *            分享的项目名
	 * @param sharetime
	 *            分享时间
	 * @return
	 */
	public Map<String, Object> saveToMyDisk(String destination, String groupId,
			String userName, String item, String sharetime) {
		String resourceUrl = MessageFormat
				.format("{0}?op=SAVETOMYDISK&destination={1}&sign={2}&time={3}&groupid={4}&user={5}&item={6}&sharetime={7}",
						gtDataUrl, destination, defaultSign, defaultTime,
						groupId, userName, item, sharetime);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：列取用户所有好友
	 * 
	 * @return
	 */
	public Map<String, Object> listAllFriends() {
		String resourceUrl = MessageFormat.format(
				"{0}?op=LISTALLFRIENDS&sign={1}&time={2}", gtDataUrl,
				defaultSign, defaultTime);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			List<ShareFile> shareFiles = mapToShareFiles(responseMap, "friends");
			myResponseMap.put("files", shareFiles);
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;

	}

	/**
	 * Description：列取用户所属所有组
	 * 
	 * @return
	 */
	public Map<String, Object> listAllGroups() {
		String resourceUrl = MessageFormat.format(
				"{0}?op=LISTALLGROUPS&sign={1}&time={2}", gtDataUrl,
				defaultSign, defaultTime);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			List<ShareFile> shareFiles = mapToShareFiles(responseMap, "groups");
			myResponseMap.put("files", shareFiles);
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;

	}

	/**
	 * Description：查看组分享
	 * 
	 * @return
	 */
	public Map<String, Object> queryGroupShare(String groupId) {
		String resourceUrl = MessageFormat.format(
				"{0}?op=QUERYGROUPSHARE&sign={1}&time={2}&groupid={3}",
				gtDataUrl, defaultSign, defaultTime, groupId);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			List<ShareFile> shareFiles = mapToShareFiles(responseMap,
					"groupshare");
			myResponseMap.put("files", shareFiles);
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：查看好友分享
	 * 
	 * @return
	 */
	public Map<String, Object> queryFriendShare() {
		String resourceUrl = MessageFormat.format(
				"{0}?op=QUERYFRIENDSHARE &sign={1}&time={2}", gtDataUrl,
				defaultSign, defaultTime);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			List<ShareFile> shareFiles = mapToShareFiles(responseMap,
					"friendshare");
			myResponseMap.put("files", shareFiles);
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：查看我的分享
	 * 
	 * @return
	 */
	public Map<String, Object> queryMyShare() {
		String resourceUrl = MessageFormat.format(
				"{0}?op=QUERYMYSHARE&sign={1}&time={2}", gtDataUrl,
				defaultSign, defaultTime);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			List<ShareFile> shareFiles = mapToShareFiles(responseMap, "myshare");
			myResponseMap.put("files", shareFiles);
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;
	}

	/**
	 * Description：列取分享目录
	 * 
	 * @param path
	 * @param groupId
	 *            组id
	 * @param userName
	 *            用户名
	 * @param sharetime
	 *            分享shijian
	 * @param recursive
	 *            是否递归列取子目录的内容
	 * @return
	 */
	public Map<String, Object> listShareDir(String path, String groupId,
			String userName, String sharetime, String recursive) {
		String resourceUrl = MessageFormat
				.format("{0}{1}?op=LISTSHAREDIR&sign={2}&time={3}&groupid={4}&user={5}&sharetime={6}&recursive={7}",
						gtDataUrl, path, defaultSign, defaultTime, groupId,
						userName, sharetime, recursive);
		Map<String, Object> responseMap = restGet(resourceUrl);
		Map<String, Object> myResponseMap = new HashMap<String, Object>();
		if (responseMap != null
				&& 200 == (Integer) responseMap.get("HttpStatusCode")) {
			List<ShareFile> shareFiles = mapToShareFilesToQueryList(responseMap);
			myResponseMap.put("files", shareFiles);
			myResponseMap.put("HttpStatusCode", 200);// 调用成功
			return myResponseMap;
		}
		return responseMap;
	}

}
