/*
Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface)
This program is distributed under the terms of the GNU General Public License.
This file is part of xFace.
xFace is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
xFace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with xFace. If not, see <http://www.gnu.org/licenses/>.
*/
package com.polyvi.xface.extension.advancedfiletransfer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.polyvi.xface.extension.XCallbackContext;
import com.polyvi.xface.extension.XExtension;
import com.polyvi.xface.extension.XExtensionContext;
import com.polyvi.xface.extension.XExtensionResult;
import com.polyvi.xface.plugin.api.XIWebContext;
import com.polyvi.xface.util.XFileUtils;
import com.polyvi.xface.util.XLog;
import com.polyvi.xface.util.XPathResolver;
public class XAdvancedFileTransferExt extends XExtension {
private static final String CLASS_NAME = XAdvancedFileTransferExt.class
.getSimpleName();
private static final String ILLEGAL_ARGUMENT_EXCEPTION_NOT_IN_ROOT_DIR = "filePath is not in root directory";
private static final String ILLEGAL_ARGUMENT_EXCEPTION_NAME_CONTAINS_COLON = "This file has a : in its name";
private static final String COMMAND_DOWNLOAD = "download";
private static final String COMMAND_UPLOAD = "upload";
private static final String COMMAND_PAUSE = "pause";
private static final String COMMAND_CANCEL = "cancel";
private static final int FILE_NOT_FOUND_ERR = 1;
private static final int INVALID_URL_ERR = 2;
private static final int CONNECTION_ERR = 3;
private static XFileTransferManager mFileTransferManager;
public XAdvancedFileTransferExt() {
}
@Override
public void init(XExtensionContext extensionContext, XIWebContext webContext) {
super.init(extensionContext, webContext);
if (null == mFileTransferManager) {
mFileTransferManager = new XFileTransferManager(getContext());
}
}
@Override
public void sendAsyncResult(String result) {
}
@Override
public boolean isAsync(String action) {
return true;
}
@Override
public void destroy() {
// 退出引擎时停止所有的任务
mFileTransferManager.stopAll();
}
@Override
public void onPageStarted() {
// 页面切换时暂停该app中的所有任务
mFileTransferManager.stopAllByApp(mWebContext.getApplication().getAppId());
}
@Override
public void onAppClosed() {
// 退出app时暂停该app中的所有任务
mFileTransferManager.stopAllByApp(mWebContext.getApplication().getAppId());
}
@Override
public void onAppUninstalled() {
// 卸载app时移除FileTransferManager中该app对应的Map<String, XIFileTransfer>
Map<String, Map<String, XIFileTransfer>> hashFileTransfers = mFileTransferManager
.getHashMapFileTransfer();
Map<String, XIFileTransfer> fileTransfers = hashFileTransfers
.get(mWebContext.getApplication().getAppId());
if (null != fileTransfers) {
hashFileTransfers.remove(mWebContext.getApplication().getAppId());
}
// 卸载app时移除FileTransferManager中该app对应的XFileTransferRecorder
Map<String, XFileTransferRecorder> recorders = mFileTransferManager
.getFileTransferRecorders();
recorders.remove(mWebContext.getApplication().getAppId());
}
@Override
public XExtensionResult exec(String action,
JSONArray args, XCallbackContext callbackCtx) throws JSONException {
String source = null;
String target = null;
String appId = mWebContext.getApplication().getAppId();
try {
if (action.equals(COMMAND_DOWNLOAD)) {
source = args.getString(0);
target = args.getString(1);
download(mWebContext, source, target, callbackCtx);
XLog.d(CLASS_NAME, "*** About to return a result from download");
return new XExtensionResult(XExtensionResult.Status.NO_RESULT);
} else if (action.equals(COMMAND_UPLOAD)) {
source = args.getString(0);
target = args.getString(1);
upload(mWebContext, source, target, callbackCtx);
XLog.d(CLASS_NAME, "*** About to return a result from upload");
return new XExtensionResult(XExtensionResult.Status.NO_RESULT);
} else if (action.equals(COMMAND_PAUSE)) {
source = args.getString(0);
mFileTransferManager.pause(appId, source);
return new XExtensionResult(XExtensionResult.Status.OK);
} else if (action.equals(COMMAND_CANCEL)) {
source = args.getString(0);
target = args.getString(1);
boolean isUpload = args.getBoolean(2);
if (isUpload) {
mFileTransferManager.cancel(appId, source, null,
COMMAND_UPLOAD);
} else {
target = new File(mWebContext.getWorkSpace(), target)
.getAbsolutePath();
mFileTransferManager.cancel(mWebContext.getApplication()
.getAppId(), source, target, COMMAND_DOWNLOAD);
}
return new XExtensionResult(XExtensionResult.Status.OK);
}
} catch (FileNotFoundException e) {
XLog.e(CLASS_NAME, e.getMessage());
JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR,
source, target);
return new XExtensionResult(XExtensionResult.Status.ERROR, error);
} catch (IllegalArgumentException e) {
XLog.e(CLASS_NAME, e.getMessage());
JSONObject error = createFileTransferError(INVALID_URL_ERR, source,
target);
return new XExtensionResult(XExtensionResult.Status.ERROR, error);
} catch (IOException e) {
XLog.e(CLASS_NAME, e.getMessage());
JSONObject error = createFileTransferError(CONNECTION_ERR, source,
target);
return new XExtensionResult(XExtensionResult.Status.ERROR, error);
} catch (JSONException e) {
XLog.e(CLASS_NAME, e.getMessage(), e);
return new XExtensionResult(XExtensionResult.Status.JSON_EXCEPTION);
}
return new XExtensionResult(XExtensionResult.Status.INVALID_ACTION);
}
/**
* 发起一个下载请求
*
* @param app
* 当前应用
* @param url
* 服务器的URL
* @param filePath
* 设备上的路径
* @param callbackCtx
* 回调上下文环境
*/
public void download(XIWebContext webContext, String url, String filePath,
XCallbackContext callbackCtx) throws FileNotFoundException, IOException {
// 目前下载目的地址只支持http协议
if (!url.startsWith("http://")) {
throw new IllegalArgumentException();
}
if (filePath.contains(":")) {
throw new FileNotFoundException(
ILLEGAL_ARGUMENT_EXCEPTION_NAME_CONTAINS_COLON);
}
File file = new File(webContext.getWorkSpace(), filePath);
if (!XFileUtils.isFileAncestorOf(webContext.getWorkSpace(),
file.getCanonicalPath())) {
throw new FileNotFoundException(
ILLEGAL_ARGUMENT_EXCEPTION_NOT_IN_ROOT_DIR);
}
file.getParentFile().mkdirs();
mFileTransferManager.addFileTranferTask(url, file.getCanonicalPath(),
mExtensionContext, callbackCtx, webContext, COMMAND_DOWNLOAD);
}
public void upload(XIWebContext webContext, String filePath, String server,
XCallbackContext callbackCtx) throws FileNotFoundException,
IllegalArgumentException {
// 目前上传目的地址只支持http协议
if (!server.startsWith("http://")) {
throw new IllegalArgumentException();
}
// 在此处检测文件是否存在,防止由于文件不存在运行很多不该执行的代码
XPathResolver pathResolver = new XPathResolver(filePath,
webContext.getWorkSpace());
String absoluteFilePath = pathResolver.resolve();
if (null != absoluteFilePath) {
File uploadFile = new File(absoluteFilePath);
if (uploadFile.exists()) {
mFileTransferManager.addFileTranferTask(filePath, server,
mExtensionContext, callbackCtx, webContext,
COMMAND_UPLOAD);
} else {
throw new FileNotFoundException();
}
} else {
throw new FileNotFoundException();
}
}
/**
* 创建FileTransferError对象
*
* @param errorCode
* 错误码
* @return JSONObject 包含错误的JSON对象
*/
private JSONObject createFileTransferError(int errorCode, String source,
String target) {
JSONObject error = null;
try {
error = new JSONObject();
error.put("code", errorCode);
error.put("source", source);
error.put("target", target);
} catch (JSONException e) {
XLog.e(CLASS_NAME, e.getMessage(), e);
}
return error;
}
}