/**
* Copyright (c)2010-2011 Enterprise Website Content Management System(EWCMS), All rights reserved.
* EWCMS PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
* http://www.ewcms.com
*/
package com.ewcms.publication.deploy.provider;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.NameScope;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.auth.StaticUserAuthenticator;
import org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ewcms.publication.PublishException;
import com.ewcms.publication.deploy.DeployOperatorable;
/**
* 发布指定的资源
*
* @author wangwei
*/
public abstract class DeployOperatorBase implements DeployOperatorable {
private static final Logger logger = LoggerFactory.getLogger(DeployOperatorBase.class);
private static final String PATH_SPARATOR = "/";
public static abstract class BuilderBase{
protected String hostname;
protected String port;
protected String username;
protected String password;
protected String path;
public String getHostname() {
return hostname;
}
public BuilderBase setHostname(String hostname) {
this.hostname = hostname;
return this;
}
public String getPort() {
return port;
}
public BuilderBase setPort(String port) {
this.port = port;
return this;
}
public String getUsername() {
return username;
}
public BuilderBase setUsername(String username) {
this.username = username;
return this;
}
public String getPassword() {
return password;
}
public BuilderBase setPassword(String password) {
this.password = password;
return this;
}
public String getPath() {
return path;
}
public BuilderBase setPath(String path) {
this.path = path;
return this;
}
public abstract DeployOperatorable build();
}
private BuilderBase builder;
public DeployOperatorBase(BuilderBase builder){
this.builder = builder;
}
/**
* 设置服务器认证
*
* @param opts 文件系统设置选项
* @param username 用户名
* @param password 密码
* @throws FileSystemException
*/
protected void setAuthenticator(FileSystemOptions opts,String username,String password)throws FileSystemException{
if(username != null){
StaticUserAuthenticator auth = new StaticUserAuthenticator(null,username,password);
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
}
}
/**
* 得到发布的根目录文件对象
*
* <br/>
* 根据不同的文件服务实现
*
* @param opts
* 文件系统设置选项
* @param builder
* 构建对象
* @param manager
* 文件管理对象
* @return 根目录文件对象
* @throws FileSystemException
*/
protected abstract FileObject getRootFileObject(FileSystemOptions opts,
BuilderBase builder,FileSystemManager manager) throws FileSystemException;
/**
* 得到发布的根目录文件对象
* @return 文件对象
* @throws FileSystemException
*/
protected FileObject getRootFileObject() throws FileSystemException {
FileSystemOptions opts = new FileSystemOptions();
setAuthenticator(opts, builder.getUsername(), builder.getPassword());
return getRootFileObject(opts, builder, VFS.getManager());
}
/**
* 得到输出文件的绝对路径
*
* @param root
* 根目录路径
* @param path
* 相对根目录路径
* @return 绝对路径
*/
protected String targetFullPath(String root, String path) {
String s = root + PATH_SPARATOR + path;
String[] segments = StringUtils.split(s, PATH_SPARATOR);
return PATH_SPARATOR + StringUtils.join(segments, PATH_SPARATOR);
}
/**
* 得到目标文件对象
*
* @param root
* 根目录路径
* @param path
* 相对根目录路径
* @return
* @throws FileSystemException
*/
protected FileObject getTargetFileObject(FileObject root, String path)throws FileSystemException {
FileObject out = root.resolveFile(path ,NameScope.DESCENDENT);
if (!out.exists()) {
out.createFile();
}
return out;
}
@Override
public void copy(String sourcePath,String targetPath)throws PublishException {
copy(new File(sourcePath),targetPath);
}
@Override
public void copy(File sourceFile,String targetPath)throws PublishException {
//TODO 资源路径与发布中径相同时,资源文件会变成空文件
if(!sourceFile.exists()){
logger.debug("Source file path's {} is not exists.",sourceFile.getPath());
return ;
}
String targetFullPath = targetFullPath(builder.getPath(),targetPath);
logger.debug("Server file's path is {}", targetFullPath);
logger.debug("Source file's path is {} ",sourceFile.getPath());
FileObject root = null;
FileObject target = null;
try {
root = getRootFileObject();
//target = getTargetFileObject(root, targetFullPath);
//-------------- Windows下设置本地发布通过 未没其他发布方式----------------------
targetPath = targetPath.replace("\\", "/").replace("//", "/");
if (targetPath.indexOf("/") == 0){
targetPath = targetPath.substring(1);
}
target = getTargetFileObject(root, targetPath);
//--------------------------------------------------------------
FileContent fileContent = target.getContent();
OutputStream out = fileContent.getOutputStream();
InputStream in = new FileInputStream(sourceFile);
byte[] buffer = new byte[1024 * 8];
int len = 0;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.flush();
in.close();
out.close();
fileContent.close();
} catch (FileSystemException e) {
logger.error("Copy {} is error:{}", targetFullPath,e);
throw new PublishException(e);
} catch (IOException e) {
logger.error("Copy {} is error:{}", targetFullPath,e);
throw new PublishException(e);
} finally{
try{
if(root != null){
root.close();
}
if(target != null){
target.close();
}
}catch(Exception e){
logger.error("vfs close is error:{}",e.toString());
}
}
}
@Override
public void copy(byte[] content,String targetPath)throws PublishException {
String targetFullPath = targetFullPath(builder.getPath(),targetPath);
logger.debug("Server file's path is {}", targetFullPath);
FileObject root =null;
FileObject target = null;
try {
root = getRootFileObject();
//target = getTargetFileObject(root, targetFullPath);
//-------------- Windows下设置本地发布通过 未没其他发布方式----------------------
targetPath = targetPath.replace("\\", "/").replace("//", "/");
if (targetPath.indexOf("/") == 0){
targetPath = targetPath.substring(1);
}
target = getTargetFileObject(root, targetPath);
//--------------------------------------------------------------
FileContent fileContent = target.getContent();
OutputStream stream = fileContent.getOutputStream();
stream.write(content);
stream.flush();
stream.close();
fileContent.close();
target.close();
root.close();
} catch (FileSystemException e) {
logger.error("Copy {} is error:{}", targetFullPath,e);
throw new PublishException(e);
} catch (IOException e) {
logger.error("Copy {} is error:{}", targetFullPath,e);
throw new PublishException(e);
} finally{
try{
if(root != null){
root.close();
}
if(target != null){
target.close();
}
}catch(Exception e){
logger.error("vfs close is error:{}",e.toString());
}
}
}
@Override
public void delete(String path)throws PublishException{
String fullPath = targetFullPath(builder.getPath(),path);
logger.debug("Delete file's path is {}", path);
try {
FileObject root = getRootFileObject();
path = path.replace("\\", "/").replace("//", "/");
if (path.indexOf("/") == 0){
path = path.substring(1);
}
FileObject target = getTargetFileObject(root, path);
if(target.exists()){
target.delete();
}
target.close();
root.close();
} catch (FileSystemException e) {
logger.error("Delete {} file delete is error:{}", fullPath, e);
throw new PublishException(e);
}
}
@Override
public boolean test()throws PublishException{
FileObject root = null;
try {
root = getRootFileObject();
} catch (FileSystemException e) {
logger.error("Test is fail:{}", e.toString());
throw new PublishException("error.output.notconnect");
}
try{
if(!root.exists()){
throw new PublishException("error.output.nodir");
}
if(!root.isWriteable()){
throw new PublishException("error.output.notwrite");
}
root.close();
return true;
}catch(FileSystemException e){
logger.error("Test is fail:{}", e.toString());
return false;
}
}
}