forked from fanruan/design
Browse Source
* commit '1f70c2dd16ccc91d46bb150ec7c45deb203f9eb8': 继续移植插件监听 支持War部署 ba-9.0 => pf-9.0 暂时先把war部署下插件相关的部分删了,一会儿尝试写到新的插件加载逻辑里面master
superman
8 years ago
7 changed files with 122 additions and 468 deletions
@ -1,359 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.base.Env; |
||||
import com.fr.base.FRContext; |
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.extra.plugindependence.DownLoadDependenceUI; |
||||
import com.fr.general.*; |
||||
import com.fr.general.http.HttpClient; |
||||
import com.fr.plugin.Plugin; |
||||
import com.fr.plugin.PluginConfigManager; |
||||
import com.fr.stable.plugin.PluginConstants; |
||||
import com.fr.plugin.PluginLoader; |
||||
import com.fr.plugin.PluginManagerHelper; |
||||
import com.fr.plugin.dependence.PluginDependence; |
||||
import com.fr.plugin.dependence.PluginDependenceException; |
||||
import com.fr.plugin.dependence.PluginDependenceUnit; |
||||
import com.fr.stable.ArrayUtils; |
||||
import com.fr.stable.EncodeConstants; |
||||
import com.fr.stable.StableUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.project.ProjectConstants; |
||||
import com.fr.stable.xml.XMLTools; |
||||
|
||||
import javax.swing.*; |
||||
import java.io.*; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URLDecoder; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.concurrent.ExecutionException; |
||||
|
||||
/** |
||||
* @author richie |
||||
* @date 2015-03-10 |
||||
* @since 8.0 |
||||
*/ |
||||
public class PluginHelper { |
||||
private static final String TEMP_PATH = System.getProperty("user.dir") + "/tmp"; |
||||
public static final String DOWNLOAD_PATH = System.getProperty("user.dir") + "/download"; |
||||
//插件依赖的下载位置
|
||||
public static final String DEPENDENCE_DOWNLOAD_PATH = System.getProperty("user.dir") + "/download/dependence"; |
||||
public static final String TEMP_FILE = "temp.zip"; |
||||
public static final String CONNECTION_404 = "404"; |
||||
|
||||
/** |
||||
* 下载插件 |
||||
* |
||||
* @param id 插件id |
||||
* @param p 下载百分比处理 |
||||
*/ |
||||
public static void downloadPluginFile(String id, String username, String password, Process<Double> p) throws Exception { |
||||
HttpClient httpClient = new HttpClient(getDownloadPath(id, username, password)); |
||||
if (httpClient.getResponseCode() == HttpURLConnection.HTTP_OK) { |
||||
int totalSize = httpClient.getContentLength(); |
||||
InputStream reader = httpClient.getResponseStream(); |
||||
String temp = StableUtils.pathJoin(DOWNLOAD_PATH, TEMP_FILE); |
||||
StableUtils.makesureFileExist(new File(temp)); |
||||
FileOutputStream writer = new FileOutputStream(temp); |
||||
byte[] buffer = new byte[PluginConstants.BYTES_NUM]; |
||||
int bytesRead = 0; |
||||
int totalBytesRead = 0; |
||||
|
||||
while ((bytesRead = reader.read(buffer)) > 0) { |
||||
writer.write(buffer, 0, bytesRead); |
||||
buffer = new byte[PluginConstants.BYTES_NUM]; |
||||
totalBytesRead += bytesRead; |
||||
p.process(totalBytesRead / (double) totalSize); |
||||
} |
||||
reader.close(); |
||||
writer.flush(); |
||||
writer.close(); |
||||
} else { |
||||
throw new com.fr.plugin.PluginVerifyException(Inter.getLocText("FR-Designer-Plugin_Connect_Server_Error")); |
||||
} |
||||
} |
||||
|
||||
private static boolean invalidUser(String id, String username, String password) { |
||||
if (StringUtils.isEmpty(id)) { |
||||
return false; |
||||
} else if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){ |
||||
return false; |
||||
} else { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
private static String getDownloadPath(String id, String username, String password) throws Exception { |
||||
HashMap<String, String> map = new HashMap<String, String>(); |
||||
map.put("id", id); |
||||
map.put("username", username); |
||||
map.put("password", password); |
||||
HttpClient httpClient = new HttpClient(SiteCenter.getInstance().acquireUrlByKind("plugin.download"), map); |
||||
String resText = httpClient.getResponseText(); |
||||
String charSet = EncodeConstants.ENCODING_UTF_8; |
||||
resText = URLDecoder.decode(URLDecoder.decode(resText, charSet), charSet); |
||||
|
||||
return resText; |
||||
} |
||||
|
||||
public static File getDownloadTempFile() { |
||||
return new File(StableUtils.pathJoin(DOWNLOAD_PATH, TEMP_FILE)); |
||||
} |
||||
|
||||
/** |
||||
* 从压缩文件中读取插件信息 |
||||
* |
||||
* @param chosenFile 选择的压缩文件 |
||||
* @return 返回插件对象 |
||||
* @throws Exception 读取插件信息失败则抛出异常 |
||||
*/ |
||||
public static Plugin readPlugin(File chosenFile) throws Exception { |
||||
// 需要先删除临时目录保证加压出来的文件不会和安装失败的文件混合到一起
|
||||
StableUtils.deleteFile(new File(TEMP_PATH)); |
||||
|
||||
IOUtils.unzip(chosenFile, TEMP_PATH); |
||||
File pluginFileDir = getTempPluginFileDirectory(); |
||||
if (pluginFileDir == null) { |
||||
return null; |
||||
} |
||||
Plugin plugin = null; |
||||
if (pluginFileDir.isDirectory()) { |
||||
File[] pluginFiles = pluginFileDir.listFiles(); |
||||
if (ArrayUtils.isNotEmpty(pluginFiles)) { |
||||
for (File f : pluginFiles) { |
||||
if (f.getName().equals("plugin.xml")) { |
||||
plugin = new Plugin(); |
||||
InputStream inputStream = plugin.readEncryptXml(new FileInputStream(f)); |
||||
XMLTools.readInputStreamXML(plugin, inputStream); |
||||
//检查是否需要准备插件依赖环境
|
||||
checkDependenceEnv(plugin); |
||||
if (!plugin.isValidate()) { |
||||
return null; |
||||
} |
||||
inputStream.close(); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return plugin; |
||||
} |
||||
|
||||
//将所有未配置好的资源文件依赖准备好
|
||||
private static void checkDependenceEnv(Plugin plugin) throws PluginDependenceException { |
||||
PluginDependence dependence = plugin.getDependence(); |
||||
if (dependence == null) { |
||||
return; |
||||
} |
||||
|
||||
List<PluginDependenceUnit> needInstallDependence = new ArrayList<PluginDependenceUnit>(); |
||||
|
||||
String currentID = dependence.getCurrentPluginID(); |
||||
List<PluginDependenceUnit> list = dependence.getDependPlugins(); |
||||
for (int i = 0; list != null && i < list.size(); i++) { |
||||
PluginDependenceUnit dependenceUnit = list.get(i); |
||||
if (!dependenceUnit.checkFileEnv()) { |
||||
needInstallDependence.add(dependenceUnit); |
||||
} |
||||
} |
||||
|
||||
if (needInstallDependence.isEmpty()) { |
||||
return; |
||||
} |
||||
|
||||
//安装插件依赖
|
||||
installDependenceOnline(currentID, needInstallDependence); |
||||
} |
||||
|
||||
/** |
||||
* 构造一个下载UI |
||||
* |
||||
* @param currentID |
||||
* @param list |
||||
* @throws PluginDependenceException |
||||
*/ |
||||
private static void installDependenceOnline(String currentID, List<PluginDependenceUnit> list) throws PluginDependenceException { |
||||
DownLoadDependenceUI ui = new DownLoadDependenceUI(currentID, list); |
||||
ui.installOnline(); |
||||
} |
||||
|
||||
/** |
||||
* 从选中的压缩文件中安装插件 |
||||
* |
||||
* @param chosenFile 选择的压缩文件 |
||||
* @param after 操作完成事件 |
||||
* @throws Exception 安装失败则抛出异常 |
||||
*/ |
||||
public static void installPluginFromDisk(File chosenFile, After after) throws Exception { |
||||
Plugin plugin = readPlugin(chosenFile); |
||||
installPluginFromUnzippedTempDir(FRContext.getCurrentEnv(), plugin, after); |
||||
} |
||||
|
||||
/** |
||||
* 从压缩文件中复制Restart*.class和restart.exe到bin目录下 |
||||
* |
||||
* @param file 插件文件 |
||||
* @param plugin 插件 |
||||
* @throws Exception |
||||
*/ |
||||
public static void copyFilesToBinFolder(File file, Plugin plugin) throws Exception { |
||||
File[] pluginFiles = file.listFiles(); |
||||
for (File restartFile : pluginFiles) { |
||||
if (restartFile.getAbsolutePath().endsWith(".class")) { |
||||
String installHome = StableUtils.getInstallHome(); |
||||
IOUtils.copy(restartFile, new File(StableUtils.pathJoin(new String[]{installHome, "bin"}))); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 从插件压缩包解压到得临时文件中安装插件 |
||||
* |
||||
* @param env 报表运行环境 |
||||
* @param plugin 插件 |
||||
* @param after 操作完成事件 |
||||
* @throws Exception |
||||
*/ |
||||
public static void installPluginFromUnzippedTempDir(Env env, final Plugin plugin, final After after) throws Exception { |
||||
validPlugin(plugin); |
||||
if (plugin.isValidate()) { |
||||
File file = getTempPluginFileDirectory(); |
||||
env.copyFilesToPluginAndLibFolder(file, plugin); |
||||
copyFilesToBinFolder(file, plugin); |
||||
env.movePluginEmbFile(file, plugin); |
||||
} |
||||
// 删除放解压文件的临时文件夹
|
||||
StableUtils.deleteFile(new File(TEMP_PATH)); |
||||
PluginConfigManager.getProviderInstance().pushNewPlugin(plugin); |
||||
PluginConfigManager.getProviderInstance().syncPluginConfig(); |
||||
new SwingWorker<String, Void>() { |
||||
|
||||
@Override |
||||
protected String doInBackground() throws Exception { |
||||
return sendInstalledPluginInfo(plugin); |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
try { |
||||
String text = get(); |
||||
FRLogger.getLogger().info("plugin install:" + text); |
||||
} catch (InterruptedException e) { |
||||
FRLogger.getLogger().error(e.getMessage(), e); |
||||
} catch (ExecutionException e) { |
||||
FRLogger.getLogger().error(e.getMessage(), e); |
||||
} |
||||
if (after != null) { |
||||
after.done(); |
||||
} |
||||
} |
||||
}.execute(); |
||||
} |
||||
|
||||
private static void validPlugin(Plugin plugin) throws Exception { |
||||
if (plugin == null) { |
||||
throw new com.fr.plugin.PluginVerifyException(Inter.getLocText("FR-Designer-Plugin_Illegal_Plugin_Zip_Cannot_Be_Install")); |
||||
} |
||||
if (PluginLoader.getLoader().isInstalled(plugin)) { |
||||
throw new com.fr.plugin.PluginVerifyException(Inter.getLocText("FR-Designer-Plugin_Has_Been_Installed")); |
||||
} |
||||
if (plugin.checkIfJarExpired()) { |
||||
String jarExpiredInfo = Inter.getLocText(new String[]{"FR-Designer-Plugin_Jar_Expired", ",", "FR-Designer-Plugin_Install_Failed", ",", "FR-Designer-Plugin_Please_Update_Jar", plugin.getRequiredJarTime()}); |
||||
FRLogger.getLogger().error(jarExpiredInfo); |
||||
throw new com.fr.plugin.PluginVerifyException(jarExpiredInfo); |
||||
} |
||||
File fileToCheck = getTempPluginFileDirectory(); |
||||
File oldfile = new File(StableUtils.pathJoin(FRContext.getCurrentEnv().getPath(), ProjectConstants.PLUGINS_NAME, "plugin-" + plugin.getId())); |
||||
if (!PluginManagerHelper.checkLic(plugin, fileToCheck)) { |
||||
if (!PluginManagerHelper.checkLic(plugin, oldfile)) {//安装时,在安装目录下和压缩包里都没有才弹框
|
||||
String checkLicFail = Inter.getLocText("FR-Designer-PluginLicense_Check_Failed"); |
||||
FRLogger.getLogger().error(checkLicFail); |
||||
throw new com.fr.plugin.PluginVerifyException(checkLicFail); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取插件解压的临时文件夹 |
||||
* |
||||
* @return 临时文件 |
||||
*/ |
||||
public static File getTempPluginFileDirectory() { |
||||
File file = new File(TEMP_PATH); |
||||
if (file.isDirectory() && !file.getName().startsWith(".")) { |
||||
File[] files = file.listFiles(); |
||||
if (ArrayUtils.isNotEmpty(files)) { |
||||
for (File f : files) { |
||||
if (foundConfigFile(f)) { |
||||
return f; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private static boolean foundConfigFile(File dir) { |
||||
if (!dir.isDirectory()) { |
||||
return false; |
||||
} |
||||
File[] files = dir.listFiles(); |
||||
if (ArrayUtils.isNotEmpty(files)) { |
||||
for (File f : files) { |
||||
if ("plugin.xml".equals(f.getName())) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* 从运行环境中卸载插件 |
||||
* |
||||
* @param env 报表运行环境 |
||||
* @param plugin 插件 |
||||
* @return 返回没有删除掉的文件的集合 |
||||
* @throws Exception 卸载出错的时候抛出此异常 |
||||
*/ |
||||
public static String[] uninstallPlugin(Env env, Plugin plugin) throws Exception { |
||||
if (plugin == null || env == null) { |
||||
return ArrayUtils.EMPTY_STRING_ARRAY; |
||||
} |
||||
//卸载前监听
|
||||
plugin.preUninstall(); |
||||
PluginLoader.getLoader().deletePlugin(plugin); |
||||
return env.deleteFileFromPluginAndLibFolder(plugin); |
||||
} |
||||
|
||||
/** |
||||
* 比较插件的版本,这里简单的比价字符串,不需要用数字作为标号 |
||||
* 版本号相同也认为是更新 |
||||
* |
||||
* @param plugin 当前的插件 |
||||
* @param oldPlugin 老的插件 |
||||
* @return 当前插件比老的插件版本高则返回true,否则返回false |
||||
*/ |
||||
public static boolean isNewThan(Plugin plugin, Plugin oldPlugin) { |
||||
return ComparatorUtils.compare(plugin.getVersion(), oldPlugin.getVersion()) >= 0; |
||||
} |
||||
|
||||
private static String sendInstalledPluginInfo(final Plugin plugin) { |
||||
if (StableUtils.isDebug()) { |
||||
return "debug status"; |
||||
} |
||||
HashMap<String, String> map = new HashMap<String, String>(); |
||||
map.put("key", DesignerEnvManager.getEnvManager().getActivationKey()); |
||||
map.put("detail", plugin.toJSONObject().toString()); |
||||
map.put("build", GeneralUtils.readBuildNO()); |
||||
//第三个参数encode, nodejs服务器那边如果参数不encode, 带了空格会报错, 直接用urlconnection也是一样, jetty没能还原.
|
||||
HttpClient httpClient = new HttpClient(SiteCenter.getInstance().acquireUrlByKind("plugin.install"), map, true); |
||||
httpClient.setTimeout(TIME_OUT); |
||||
httpClient.asGet(); |
||||
return httpClient.getResponseText(); |
||||
} |
||||
|
||||
private static final int TIME_OUT = 5000; |
||||
} |
Loading…
Reference in new issue