/*
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.util;
import java.io.File;
import java.io.IOException;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
/**
* 把传入的路径解析为对应的相对于app workspace的路径、sdcard路径或其他绝对路径
*/
public class XPathResolver {
private String mPath;
private String mAppWorkspace;
private Context mContext;
public enum Scheme
{
NONE,
FILE,
CONTENT,
HTTP,
HTTPS,
UNKNOWN
}
private static final String FILE_SCHEME = "file";
private static final String CONTENT_SCHEME = "content";
private static final String HTTP_SCHEME = "http";
private static final String HTTPS_SCHEME = "https";
private static final String SDCARD_HOST = "sdcard";
private static final String LOCAL_HOST = "localhost";
private static final String NULL_HOST = "";
/**
*
* @param path 需要解析的路径
* @param appWorkspace app的workspace
*/
public XPathResolver(String path, String appWorkspace) {
mPath = path;
mAppWorkspace = appWorkspace;
}
/**
*
* @param path 需要解析的路径
* @param appWorkspace app的workspace
* @param context 解析Content协议用到的context
*/
public XPathResolver(String path, String appWorkspace, Context context) {
mPath = path;
mAppWorkspace = appWorkspace;
mContext = context;
}
/**
* 根据host获取跟路径
*
* @param host
* 主机名
* @return 如果host存在,就返回其对应的跟路径
*/
private String getRootByHost( String host )
{
//目前只有两种host,sdcard host和默认的local host
if(null == host) {
return null;
} else if( host.equals(SDCARD_HOST))
{
return getSdcardPath();
}else if( host.equals(NULL_HOST) || host.equals(LOCAL_HOST))
{
return "";
}
return null;
}
/**解析路径
*
* @return 路径合法就返回在当前系统中对应的路径,否则就返回null。
* 路径不合法可能是因为以下原因之一:
* 1、file://... uri不符合格式或主机不存在,目前只有sdcard host和默认的local host
* 2、sdcard不可访问,
* 3、相对app workspace的路径不在app workspace之内。
*/
public String resolve()
{
//根据协议解析路径
if(null == mPath) {
return null;
}
Uri uri = Uri.parse(mPath);
String schemeString = uri.getScheme();
if(null == schemeString) {//相对app workspace的路径
return resolveAppRelativePath(mPath);
} else if (schemeString.equals(FILE_SCHEME)) {//解析文件协议
String host = uri.getHost();
String path = uri.getPath();
return resolveLocalFileUri(host, path);
} else if (schemeString.equals(CONTENT_SCHEME)) {//解析CONTENT协议
return resolveContentUri(mPath);
} else if (schemeString.equals(HTTP_SCHEME) || schemeString.equals(HTTPS_SCHEME)) {//解析http协议
return mPath;
}
return null;
}
/**解析路径
*
* @return 路径合法就返回在当前系统中对应的路径,否则就返回null。
* 路径不合法可能是因为以下原因之一:
* 1、file://... uri不符合格式或主机不存在,目前只有sdcard host和默认的local host
* 2、sdcard不可访问,
* 3、相对app workspace的路径不在app workspace之内。
*/
public Scheme getSchemeType()
{
//根据uri解析协议的类型
Uri uri = Uri.parse(mPath);
String schemeString = uri.getScheme();
if(null == schemeString) {//相对app workspace的路径
return Scheme.NONE;
} else if (schemeString.equals(FILE_SCHEME)) {//文件协议
return Scheme.FILE;
} else if (schemeString.equals(CONTENT_SCHEME)) {//CONTENT协议
return Scheme.CONTENT;
} else if (schemeString.equals(HTTP_SCHEME)) {//http协议
return Scheme.HTTP;
}else if ( schemeString.equals(HTTPS_SCHEME)) {//https协议
return Scheme.HTTPS;
}
return Scheme.UNKNOWN;
}
/**
* 获得当前系统的sdcard路径
*
* @return 如果sdcard可访问,则返回带当前系统的sdcard路径,否则返回null。
*/
private String getSdcardPath() {
String path = null;
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
path = Environment.getExternalStorageDirectory().getAbsolutePath();
}
return path;
}
/**
* 解析本地文件uri为绝对路径
*
*@param host
* uri的host部分
*@param path
* uri的path部分
* @return 如果主机存在,则返回uri在当前系统对应的文件路径,否则返回null。
*/
private String resolveLocalFileUri(String host, String path) {
//根据host获取跟路径
String root = getRootByHost(host);
if(null != root) {
return root + path;
}
return null;
}
/**
* 解析content uri为绝对路径
*
*@param uri
* content uri
* @return 成功返回文件绝对路径,失败返回null。
*/
private String resolveContentUri(String uri) {
if(null != mContext) {
Cursor cursor = mContext.getContentResolver().query(Uri.parse(mPath), new String[] { MediaStore.Images.Media.DATA }, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
String path = null;
if(cursor.moveToFirst()) {
path = cursor.getString(column_index);
}
cursor.close();
return path;
}
return null;
}
/**
* 解析相对 app workspace 的路径
*
* @param path
* 要解析的路径
*
* @return 路径在app workspace之内,则返回该路径的绝对路径,否则返回null。
*/
private String resolveAppRelativePath(String path) {
File file = new File(mAppWorkspace, path);
String absolutePath = null;
try {
absolutePath = file.getCanonicalPath();
//路径是否在app workspace 之内
if(!XFileUtils.isFileAncestorOf(mAppWorkspace, absolutePath)) {
absolutePath = null;
}
} catch (IOException e) {
absolutePath = null;
e.printStackTrace();
}
return absolutePath;
}
/**
* 返回Uri
* @return
*/
public Uri getUri()
{
switch (getSchemeType()) {
case NONE:
case FILE:
case CONTENT:
return Uri.parse(XConstant.FILE_SCHEME + resolve());
default:
return Uri.parse(mPath);
}
}
}