package org.quickbundle.mda.gp;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.dom4j.Element;
import org.dom4j.Node;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.quickbundle.config.RmBaseConfig;
import org.quickbundle.tools.helper.RmStringHelper;
import org.quickbundle.tools.helper.io.RmFileHelper;
import org.quickbundle.tools.helper.xml.RmXmlHelper;
public class CopyProjectEngine {
GenerateProjectRule gpRule = null;
Map<String, String> mReplaceInFile = null;
Map<String, String> mReplacePath = null;
public CopyProjectEngine(GenerateProjectRule gpRule) {
this.gpRule = gpRule;
mReplaceInFile = getKeywordReplaceInFile();
mReplacePath = getKeywordReplacePath();
}
/**
* The worker method. It will find the container, create the file if missing
* or just replace its contents, and open the editor on the newly created
* file.
*/
public void doFinish(IProgressMonitor monitor) throws CoreException {
monitor.beginTask("preparing...", 1);
String strSource = gpRule.getProjectTemplatePath().toString();
Set<String> sFileType = getFilterFileType();
QbGenerateProjectPlugin.log("strSource:" + RmXmlHelper.formatToFile(strSource));
globalTotalFileSum = getFileSum(RmXmlHelper.formatToFile(strSource));
QbGenerateProjectPlugin.log("start copy files: globalTotalFileSum=" + globalTotalFileSum);
monitor.beginTask("generation begin...", globalTotalFileSum);
long startTime = System.currentTimeMillis();
copyFolder(strSource, gpRule.getProjectPathValue(), sFileType, monitor);
QbGenerateProjectPlugin.log("cost " + (System.currentTimeMillis() - startTime) + " Millisecond!");
monitor.setTaskName("All files generated!");
monitor.done();
}
@SuppressWarnings("unchecked")
private Map<String, String> getKeywordReplaceInFile() {
Map<String, String> result = new HashMap<String, String>();
List<Element> items = gpRule.getProjectRule().selectNodes("/rules/keywordReplace/items/item");
for(Element item : items) {
result.put(item.valueOf("@keyword"), item.valueOf("text()"));
}
return result;
}
@SuppressWarnings("unchecked")
private Map<String, String> getKeywordReplacePath() {
Map<String, String> result = new HashMap<String, String>();
List<Element> items = gpRule.getProjectRule().selectNodes("/rules/keywordReplace/items/item[@replacePath='true']");
for(Element item : items) {
result.put(item.valueOf("@keyword"), item.valueOf("text()"));
}
return result;
}
/**
* 功能: 获得需要过滤关键字的文件类型后缀Set
*
* @return
*/
@SuppressWarnings("unchecked")
private Set<String> getFilterFileType() {
Set<String> sFileType = new HashSet<String>();
List<Element> lFileAffix = gpRule.getProjectRule().selectNodes("/rules/keywordReplace/fileFilter/fileAffix");
for (Element fileAffix : lFileAffix) {
String tempStr = fileAffix.valueOf("@name");
sFileType.add(tempStr);
if ("*".equals(tempStr)) { // 如果加上*,则暴慢无比
sFileType = new HashSet<String>();
break;
}
}
return sFileType;
}
private int globalTotalFileSum = 0;
/**
* 功能: 得到文件个数
*
* @param file
* @return
*/
public static int getFileSum(String file) {
int sum = 0;
File thisFile = new File(file);
if (!thisFile.exists()) {
return 0;
} else {
if (thisFile.isFile()) {
return 1;
} else {
File[] childFile = thisFile.listFiles();
for (int i = 0; i < childFile.length; i++) {
sum += getFileSum(childFile[i].toString());
}
return sum;
}
}
}
/**
* 复制整个文件夹内容
*
* @param monitor
* @param oldPath
* @param newPath
* @param mToBeReplace
* @param sFileType
*/
public void copyFolder(String oldPath, String newPath, Set<String> sFileType, IProgressMonitor monitor) {
oldPath = RmXmlHelper.formatToFile(oldPath);
newPath = RmXmlHelper.formatToFile(newPath);
File fOldPath = new File(oldPath);
try {
boolean needMkdirs = false;
String shortOldPath = getFileEndPart(new File(oldPath));
for (String p : gpRule.getSNeedMkdirsFolder()) {
if (shortOldPath.matches(p)) {
needMkdirs = true;
break;
}
}
{ // 把目标路径中的所有关键字都替换成用户指定的,项目路径和war名称
for (String strFrom : mReplacePath.keySet()) {
String strTo = mReplacePath.get(strFrom);
newPath = RmStringHelper.replaceAll(newPath, strFrom, strTo);
}
}
{ // 初始化本目录
if (needMkdirs) {
new File(newPath).mkdirs();
}
}
File sourceFile = null;
String[] fileList = fOldPath.list();
for (int i = 0; i < fileList.length; i++) {
String thisOldFile = fileList[i];
String thisReplacedFile = thisOldFile;
// 把要替换到的目标文件的文件名过滤一遍
for (String strFrom : mReplacePath.keySet()) {
String strTo = mReplacePath.get(strFrom);
thisReplacedFile = RmStringHelper.replaceAll(thisOldFile, strFrom, strTo);
}
if (oldPath.endsWith(File.separator)) {
sourceFile = new File(oldPath + thisOldFile);
} else {
sourceFile = new File(oldPath + File.separator + thisOldFile);
}
String targetFilePath = newPath + File.separator + thisReplacedFile;
if (sourceFile.isFile()) {
copySingleFile(sourceFile, targetFilePath, sFileType, monitor, thisReplacedFile);
} else if (sourceFile.isDirectory()) {// 如果是子文件夹
copyFolder(sourceFile.getCanonicalPath(), targetFilePath, sFileType, monitor);
} else {
QbGenerateProjectPlugin.log(sourceFile + "既不是文件也不是目录,忽略!");
}
}
} catch (Exception e) {
QbGenerateProjectPlugin.log("复制整个文件夹内容操作出错: " + e.getMessage());
e.printStackTrace();
}
}
/**
* 复制单个文件
*
* @param sourceFile
* @param displayFilePath
* @param mToBeReplace
* @param sFileType
* @param monitor
* @param thisReplacedFile
*/
@SuppressWarnings("unchecked")
private void copySingleFile(File sourceFile, String targetFile, Set<String> sFileType, IProgressMonitor monitor,
String thisReplacedFile) {
FileInputStream input = null;
FileOutputStream output = null;
{ // 显示生成过程
String displayFilePath = RmXmlHelper.formatToFile(targetFile);
if (displayFilePath.length() > 140) {
displayFilePath = displayFilePath.substring(0, 12) + "..." + displayFilePath.substring(displayFilePath.length() - 125);
}
monitor.worked(1);
monitor.setTaskName("copy:" + displayFilePath);
}
int fileNeedCopyType = fileNeedCopy(sourceFile);
if (fileNeedCopyType > 0) {
try {
new File(targetFile).getParentFile().mkdirs(); // 如果文件夹不存在
// 则建立新文件夹
// 得到文件后缀
int dotPos = thisReplacedFile.lastIndexOf(".");
if (dotPos < 0) {
dotPos = -1;
}
String fileType = thisReplacedFile.substring(dotPos + 1);
if (sFileType.contains(fileType) || fileNeedCopyType == 1) {
Map<String, String[]> mToBeReplaceKey = new HashMap<String, String[]>();
String thisFileEncode = RmBaseConfig.getSingleton().getDefaultEncode();
if (fileNeedCopyType == 1) {
List<Node> lNotNeedModuleFileKey = gpRule.getProjectRule().selectNodes("/rules/modules/module[@isBuild='false']/file[count(key)>0]");
for (Node nodeFile : lNotNeedModuleFileKey) {
if (getFileEndPart(sourceFile).matches(nodeFile.getText().trim())) {
{ // 读取特别指定的编码
String tempEncode = nodeFile.valueOf("@encode");
if (tempEncode != null && tempEncode.length() > 0) {
thisFileEncode = tempEncode;
}
}
// 读取key
List<Node> lKey = nodeFile.selectNodes("key");
for (Node nodeKey : lKey) {
String[] aStr = new String[2];
// 如果指定了替换字符串
if (nodeKey.selectNodes("replace").size() > 0) {
aStr[0] = nodeKey.valueOf("replace[1]/text()");
} else {
aStr[0] = "";
}
aStr[1] = nodeKey.valueOf("@p");
mToBeReplaceKey.put(nodeKey.getText().trim(), aStr);
}
}
}
// QbGenerateProjectPlugin.log("copy file: " +
// targetFile + ", filter key=" + mToBeReplaceKey);
}
// 读取源文件
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile), thisFileEncode));
String s = null;
StringBuilder sb2 = new StringBuilder();
boolean isFirstLine = true;
while ((s = in.readLine()) != null) {
if (isFirstLine) {
isFirstLine = false;
} else {
sb2.append("\n");
}
sb2.append(s);
}
in.close();
String sFinal = sb2.toString();
// 替换对话框中指定的字符串
if (sFileType.contains(fileType)) {
for (String strFrom : mReplaceInFile.keySet()) {
String strTo = mReplaceInFile.get(strFrom);
sFinal = RmStringHelper.replaceAll(sFinal, strFrom, strTo);
}
}
// 替换xml配置中定义的字符串
if (fileNeedCopyType == 1) {
for (String strFrom : mToBeReplaceKey.keySet()) {
String[] strTo = mToBeReplaceKey.get(strFrom);
if ("true".equals(strTo[1])) { // 如果是正则表达式
sFinal = Pattern.compile(strFrom, Pattern.DOTALL).matcher(sFinal).replaceAll(strTo[0]);
} else { // 直接替换
sFinal = RmStringHelper.replaceAll(sFinal, strFrom, strTo[0]);
}
}
}
// 写入目标文件
BufferedReader in4 = new BufferedReader(new StringReader(sFinal));
BufferedWriter out1 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), thisFileEncode));
isFirstLine = true;
while ((s = in4.readLine()) != null) {
if (isFirstLine) {
isFirstLine = false;
} else {
out1.write("\n");
}
out1.write(s);
}
out1.flush();
out1.close();
in4.close();
} else { // Stream方式直接复制文件
input = new FileInputStream(sourceFile);
output = new FileOutputStream(targetFile);
byte[] b = new byte[1024 * 10];
int len;
while ((len = input.read(b)) != -1) {
output.write(b, 0, len);
}
output.flush();
}
} catch (Exception e) {
QbGenerateProjectPlugin.log(e.toString());
e.printStackTrace();
} finally {
try {
if (input != null) {
input.close();
}
if (output != null) {
output.close();
}
} catch (Exception e1) {
QbGenerateProjectPlugin.log(e1.toString());
e1.printStackTrace();
}
}
} else {
// QbGenerateProjectPlugin.log("skip file: " + targetFile);
}
}
/**
* 得到文件名中去掉模板路径的结尾部分字符串
*
* @param sourceFile
* @return
*/
private String getFileEndPart(File sourceFile) {
String uriSourceFile = null;
try {
uriSourceFile = sourceFile.getCanonicalPath();
} catch (IOException e1) {
uriSourceFile = sourceFile.getAbsolutePath();
}
uriSourceFile = RmXmlHelper.formatToUrl(uriSourceFile);
uriSourceFile = uriSourceFile.substring(RmFileHelper.formatToUrl(gpRule.getProjectTemplatePath()).length());
return uriSourceFile;
}
/**
* 功能: 判断是否需要构建这个文件
*
* @param sourceFile
* @return 0 不需要, 1 需要但要过滤未选择模块的key值, 2 Stream方式直接拷贝(文件名可能经过webAppName过滤 )
*/
@SuppressWarnings("unchecked")
private int fileNeedCopy(File sourceFile) {
String uriSourceFile = getFileEndPart(sourceFile);
RmXmlHelper.formatToUrl(sourceFile.toString());
List<Node> lNotNeedModuleFile = gpRule.getProjectRule().selectNodes("/rules/modules/module[@isBuild='false']/file[count(key)=0]");
for (Node nodeFile : lNotNeedModuleFile) {
if (uriSourceFile.matches(nodeFile.getText().trim())) {
return 0;
}
}
List<Node> lNotNeedModuleFileKeyString = gpRule.getProjectRule().selectNodes("/rules/modules/module[@isBuild='false']/file[count(key)>0]");
for (Node nodeFile : lNotNeedModuleFileKeyString) {
if (uriSourceFile.matches(nodeFile.getText().trim())) {
return 1;
}
}
return 2;
}
public void openProject() {
File projectFolder = new File(gpRule.getProjectPathValue());
if (projectFolder.exists() && projectFolder.isDirectory()) {
if(new File(projectFolder.toString() + File.separator + ".project").exists()) {
boolean successOpen = doOpenProject(projectFolder.toString() + File.separator + ".project");
if(successOpen) {
return;
}
}
File[] folders = listProjectFolder(projectFolder);
for (File folder : folders) {
if(new File(folder.toString() + File.separator + ".project").exists()) {
doOpenProject(folder.toString() + File.separator + ".project");
}
}
}
}
@SuppressWarnings("unchecked")
private File[] listProjectFolder(File projectFolder) {
File projectTemplatePath = new File(gpRule.getProjectTemplatePath());
final Set<String> possibleFolders = new HashSet<String>();
projectTemplatePath.listFiles(new FileFilter() {
public boolean accept(File pathname) {
if(pathname.isDirectory()) {
possibleFolders.add(pathname.getName());
}
return false;
}
});
List<Element> items = gpRule.getProjectRule().selectNodes("/rules/keywordReplace/items/item");
for(Element item : items) {
possibleFolders.add(item.valueOf("text()"));
}
return projectFolder.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory() && possibleFolders.contains(pathname.getName());
}
});
}
private boolean doOpenProject(String dotProjectPath) {
try {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
IProjectDescription description = workspace.loadProjectDescription(new Path(dotProjectPath));
IProject project = root.getProject(description.getName());
if (!project.exists()) {
project.create(description, null);
} else {
project.refreshLocal(IResource.DEPTH_INFINITE, null);
}
if (!project.isOpen()) {
project.open(null);
}
return true;
} catch (Exception e) {
QbGenerateProjectPlugin.log(e.toString());
e.printStackTrace();
return false;
}
}
}