You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2241 lines
79 KiB
2241 lines
79 KiB
package com.fr.env; |
|
|
|
import com.fr.base.*; |
|
import com.fr.base.remote.RemoteDeziConstants; |
|
import com.fr.data.core.DataCoreUtils; |
|
import com.fr.data.core.db.TableProcedure; |
|
import com.fr.data.impl.Connection; |
|
import com.fr.data.impl.EmbeddedTableData; |
|
import com.fr.data.impl.storeproc.ProcedureDataModel; |
|
import com.fr.data.impl.storeproc.StoreProcedure; |
|
import com.fr.dav.DavXMLUtils; |
|
import com.fr.dav.UserBaseEnv; |
|
import com.fr.design.DesignerEnvManager; |
|
import com.fr.design.ExtraDesignClassManager; |
|
import com.fr.design.dialog.InformationWarnPane; |
|
import com.fr.design.file.HistoryTemplateListPane; |
|
import com.fr.design.fun.DesignerEnvProcessor; |
|
import com.fr.design.mainframe.DesignerContext; |
|
import com.fr.design.mainframe.DesignerFrameFileDealerPane; |
|
import com.fr.design.mainframe.loghandler.DesignerLogHandler; |
|
import com.fr.file.CacheManager; |
|
import com.fr.file.DatasourceManager; |
|
import com.fr.file.DatasourceManagerProvider; |
|
import com.fr.file.filetree.FileNode; |
|
import com.fr.general.*; |
|
import com.fr.general.http.HttpClient; |
|
import com.fr.json.JSONArray; |
|
import com.fr.json.JSONException; |
|
import com.fr.json.JSONObject; |
|
import com.fr.plugin.Plugin; |
|
import com.fr.plugin.PluginLicense; |
|
import com.fr.plugin.PluginLicenseManager; |
|
import com.fr.plugin.PluginLoader; |
|
import com.fr.share.ShareConstants; |
|
import com.fr.stable.*; |
|
import com.fr.stable.file.XMLFileManagerProvider; |
|
import com.fr.stable.project.ProjectConstants; |
|
import com.fr.stable.xml.XMLPrintWriter; |
|
import com.fr.stable.xml.XMLTools; |
|
import com.fr.stable.xml.XMLableReader; |
|
import com.fr.web.ResourceConstants; |
|
|
|
import javax.swing.*; |
|
import javax.xml.transform.*; |
|
import javax.xml.transform.dom.DOMSource; |
|
import javax.xml.transform.stream.StreamResult; |
|
import java.awt.*; |
|
import java.io.*; |
|
import java.net.HttpURLConnection; |
|
import java.net.NoRouteToHostException; |
|
import java.net.Socket; |
|
import java.util.*; |
|
import java.util.List; |
|
import java.util.Timer; |
|
import java.util.logging.Level; |
|
import java.util.regex.Pattern; |
|
|
|
public class RemoteEnv extends AbstractEnv { |
|
private static final int TIME_OUT = 30 * 1000; |
|
private static final int PLAIN_SOCKET_PORT = 80; |
|
private static final int SSL_PORT = 443; |
|
private static final int MAX_PER_ROUTE = 20; |
|
private static final int MAX_TOTAL = 100; |
|
private static final String REMOTE_PLUGIN = "remote_plugin.info"; |
|
private static final String CERT_KEY = "javax.net.ssl.trustStore"; |
|
private static final String PWD_KEY = "javax.net.ssl.trustStorePassword"; |
|
private static final String HTTPS_PREFIX = "https:"; |
|
private final static String[] FILE_TYPE = {"cpt", "frm", "form", "cht", "chart"}; |
|
private String path; |
|
private String user; |
|
private String password; |
|
private Clock clock = null; |
|
private String userID; |
|
private Timer timer; |
|
private int licNotSupport = 0; |
|
private boolean isRoot = false; |
|
private Timer logTimer = null; |
|
private static ThreadLocal<String> threadLocal = new ThreadLocal<String>(); |
|
private boolean isReadTimeOut = false; |
|
|
|
public RemoteEnv() { |
|
this.clock = new Clock(this); |
|
} |
|
|
|
public RemoteEnv(String path, String userName, String password) { |
|
this(); |
|
this.path = path; |
|
this.user = userName; |
|
this.password = password; |
|
} |
|
|
|
/** |
|
* 返回env配置路径 |
|
*/ |
|
@Override |
|
public String getPath() { |
|
return this.path; |
|
} |
|
|
|
public void setPath(String s) { |
|
this.path = s; |
|
} |
|
|
|
/** |
|
* 当前设计环境的用户名,用于远程设计 |
|
*/ |
|
public String getUser() { |
|
return user; |
|
} |
|
|
|
public void setUser(String user) { |
|
this.user = user; |
|
clearUserID(); |
|
} |
|
|
|
public String getPassword() { |
|
return password; |
|
} |
|
|
|
public void setPassword(String password) { |
|
this.password = password; |
|
clearUserID(); |
|
} |
|
|
|
public Clock getClock() { |
|
return this.clock; |
|
} |
|
|
|
public void setClock(Clock clock) { |
|
this.clock = clock; |
|
} |
|
|
|
private void clearUserID() { |
|
this.userID = null; |
|
} |
|
|
|
public void setThreadLocal(String value) { |
|
synchronized (this) { |
|
threadLocal.set(value); |
|
} |
|
|
|
} |
|
|
|
public String getThreadLocal() { |
|
return threadLocal.get(); |
|
} |
|
|
|
/** |
|
* 所有与服务器端交互前,都要调用这个方法生成UserID |
|
*/ |
|
private String createUserID() throws EnvException { |
|
// 如果登录之后userID还是null |
|
if (this.userID == null) { |
|
if (!VT4FR.REMOTE_DESIGN.support() && licNotSupport <= 0) { |
|
licNotSupport++; |
|
JOptionPane.showMessageDialog(null, Inter.getLocText("FR-Lic_does_not_Support_Remote")); |
|
} |
|
throw new EnvException(Inter.getLocText("Env-Invalid_User_and_Password")); |
|
} |
|
|
|
return this.userID; |
|
} |
|
|
|
private HttpClient createHttpMethod(HashMap<String, String> para) throws EnvException, UnsupportedEncodingException { |
|
return createHttpMethod(para, false); |
|
} |
|
|
|
/** |
|
* 根据nameValuePairs,也就是参数对,生成PostMethod |
|
*/ |
|
private HttpClient createHttpMethod(HashMap<String, String> para, boolean isSignIn) throws EnvException, UnsupportedEncodingException { |
|
String methodPath = this.path; |
|
if (!isSignIn) { |
|
methodPath = methodPath + "?id=" + createUserID(); |
|
} |
|
return new HttpClient(methodPath, para); |
|
} |
|
|
|
/** |
|
* 根据nameValuePairs,也就是参数对,生成PostMethod,不同之处在于,参数拼在path后面,不是method.addParameters |
|
*/ |
|
private HttpClient createHttpMethod2(HashMap<String, String> para) throws EnvException { |
|
StringBuilder sb = new StringBuilder(path); |
|
|
|
sb.append('?'); |
|
sb.append("id=").append(createUserID()); |
|
|
|
return new HttpClient(sb.toString(), para, true); |
|
} |
|
|
|
|
|
/* |
|
* Read the response body. |
|
* 拿出InputStream中所有的Byte,转换成ByteArrayInputStream的形式返回 |
|
* |
|
* 这样做的目的是确保method.releaseConnection |
|
* |
|
* TODO 但如果不做method.releaseConnection,有多大危害呢?不确定... |
|
*/ |
|
|
|
/** |
|
* execute method之后,取返回的inputstream |
|
*/ |
|
private ByteArrayInputStream execute4InputStream(HttpClient client) throws Exception { |
|
setHttpsParas(); |
|
try { |
|
int statusCode = client.getResponseCode(); |
|
if (statusCode != HttpURLConnection.HTTP_OK) { |
|
//数据加载太多,屏蔽掉 |
|
//doWithTimeOutException(); |
|
throw new EnvException("Method failed: " + statusCode); |
|
} |
|
} catch (Exception e) { |
|
FRContext.getLogger().info("Connection reset "); |
|
} |
|
InputStream in = client.getResponseStream(); |
|
if (in == null) { |
|
return null; |
|
} |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
try { |
|
Utils.copyBinaryTo(in, out); |
|
|
|
// 看一下传过来的byte[]是不是DesignProcessor.INVALID,如果是的话,就抛Exception |
|
byte[] bytes = out.toByteArray(); |
|
// carl:格式一致传中文 |
|
String message = new String(bytes, EncodeConstants.ENCODING_UTF_8); |
|
if (ComparatorUtils.equals(message, RemoteDeziConstants.NO_SUCH_RESOURCE)) { |
|
return null; |
|
} else if (ComparatorUtils.equals(message, RemoteDeziConstants.INVALID_USER)) { |
|
throw new EnvException(RemoteDeziConstants.INVALID_USER); |
|
} else if (ComparatorUtils.equals(message, RemoteDeziConstants.FILE_LOCKED)) { |
|
JOptionPane.showMessageDialog(null, Inter.getLocText("FR-Remote_File_is_Locked")); |
|
return null; |
|
} else if (message.startsWith(RemoteDeziConstants.RUNTIME_ERROR_PREFIX)) { |
|
} |
|
return new ByteArrayInputStream(bytes); |
|
} finally { |
|
synchronized (this) { |
|
in.close(); |
|
out.close(); |
|
client.release(); |
|
} |
|
} |
|
} |
|
|
|
private void doWithTimeOutException() { |
|
boolean isNotNeedTip = ComparatorUtils.equals(getThreadLocal(), "HEART_BEAT") || ComparatorUtils.equals(getThreadLocal(), "LOG_MESSAGE"); |
|
if (!isReadTimeOut && !isNotNeedTip) { |
|
isReadTimeOut = true; |
|
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText(new String[]{"Data", "read_time_out"})); |
|
isReadTimeOut = false; |
|
} |
|
FRContext.getLogger().info("Connection reset "); |
|
} |
|
|
|
|
|
/** |
|
* nameValuePairs,这个参数要接着this.path,拼成一个URL,否则服务器端req.getParameter是无法得到的 |
|
* |
|
* @param bytes 数据 |
|
* @return 是否成功提交 |
|
* @throws Exception 异常 |
|
*/ |
|
private boolean postBytes2Server(byte[] bytes, HashMap<String, String> para) throws Exception { |
|
HttpClient client = createHttpMethod2(para); |
|
client.setContent(bytes); |
|
execute4InputStream(client); |
|
|
|
return true; |
|
} |
|
|
|
/** |
|
* 把InputStream转成一段String |
|
* |
|
* @param in InputStream输入流 |
|
* @return 转换后的字符串 |
|
*/ |
|
public static String stream2String(InputStream in) { |
|
if (in == null) { |
|
return null; |
|
} |
|
BufferedReader br; |
|
try { |
|
br = new BufferedReader(new InputStreamReader(in, EncodeConstants.ENCODING_UTF_8)); |
|
} catch (UnsupportedEncodingException e) { |
|
br = new BufferedReader(new InputStreamReader(in)); |
|
} |
|
StringBuilder sb = new StringBuilder(); |
|
String line; |
|
|
|
try { |
|
while ((line = br.readLine()) != null) { |
|
if (sb.length() > 0) { |
|
sb.append('\n'); |
|
} |
|
sb.append(line); |
|
} |
|
} catch (IOException e) { |
|
FRContext.getLogger().error(e.getMessage(), e); |
|
} |
|
|
|
return sb.toString(); |
|
} |
|
|
|
/** |
|
* 测试连接服务器 |
|
* |
|
* @return 测试连接成功返回true |
|
* @throws Exception 异常 |
|
*/ |
|
public boolean testServerConnection() throws Exception { |
|
return testConnection(true, true, DesignerContext.getDesignerFrame()); |
|
} |
|
|
|
/** |
|
* 测试当前配置是否正确 |
|
* |
|
* @return 链接是否成功 |
|
* @throws Exception 异常 |
|
*/ |
|
public boolean testServerConnectionWithOutShowMessagePane() throws Exception { |
|
return testConnection(false, true, DesignerContext.getDesignerFrame()); |
|
} |
|
|
|
/** |
|
* 主要用于在环境配置面板中的测试连接按钮时,不要注册进远程环境 |
|
* |
|
* @param messageParentPane 弹框的依赖的面板 |
|
* @return 是否测试连接成功 |
|
* @throws Exception 异常 |
|
*/ |
|
public boolean testConnectionWithOutRegisteServer(Component messageParentPane) throws Exception { |
|
return testConnection(true, false, messageParentPane); |
|
} |
|
|
|
|
|
private boolean testConnection(boolean needMessage, boolean isRegisteServer, Component parentComponent) throws Exception { |
|
extraChangeEnvPara(); |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "test_server_connection"); |
|
para.put("user", user); |
|
para.put("password", password); |
|
|
|
if (path.startsWith("https") && (!DesignerEnvManager.getEnvManager().isHttps())) { |
|
return false; |
|
} |
|
|
|
HttpClient client = createHttpMethod(para, true); |
|
|
|
String res = stream2String(execute4InputStream(client)); |
|
if (res == null) { |
|
if (needMessage) { |
|
JOptionPane.showMessageDialog(parentComponent, Inter.getLocText("Datasource-Connection_failed")); |
|
} |
|
return false; |
|
} else if (ComparatorUtils.equals(res, "true")) { |
|
if (!clock.connected && isRegisteServer) { |
|
//服务器中断又重新启动之后,重新向远程服务器注册 |
|
register2Server(); |
|
} |
|
return true; |
|
} else if (ComparatorUtils.equals(res, "invalid username or password.")) { |
|
JOptionPane.showMessageDialog(parentComponent, |
|
Inter.getLocText(new String[]{"Datasource-Connection_failed", "Registration-User_Name", "Password", "Error"}, new String[]{",", "", "", "!"}) |
|
, Inter.getLocText("FR-Server-All_Error"), JOptionPane.ERROR_MESSAGE); |
|
return false; |
|
} else if (res.indexOf("RegistEditionException") != -1) { |
|
if (needMessage) { |
|
JOptionPane.showMessageDialog(parentComponent, Inter.getLocText(new String[]{"Datasource-Connection_failed", "Version-does-not-support"}, new String[]{",", "!"})); |
|
} else { |
|
FRLogger.getLogger().info(Inter.getLocText(new String[]{"Datasource-Connection_failed", "Version-does-not-support"}, new String[]{",", "!"})); |
|
} |
|
return false; |
|
} else if (ComparatorUtils.equals(res, "war not support remote design.")) { |
|
if (needMessage) { |
|
JOptionPane.showMessageDialog(parentComponent, Inter.getLocText(new String[]{"Datasource-Connection_failed", "NS-war-remote"}, new String[]{",", "!"})); |
|
} else { |
|
FRLogger.getLogger().info(Inter.getLocText(new String[]{"Datasource-Connection_failed", "NS-war-remote"}, new String[]{",", "!"})); |
|
} |
|
return false; |
|
} else { |
|
throw new EnvException(res); |
|
} |
|
} |
|
|
|
private void extraChangeEnvPara() { |
|
//在env连接之前, 加载一下不依赖env的插件. 看看需不需要改变参数. |
|
PluginLoader.init(); |
|
DesignerEnvProcessor envProcessor = ExtraDesignClassManager.getInstance().getSingle(DesignerEnvProcessor.XML_TAG); |
|
if (envProcessor != null) { |
|
this.path = envProcessor.changeEnvPathBeforeConnect(user, password, path); |
|
} |
|
} |
|
|
|
private void setHttpsParas() { |
|
if (path.startsWith(HTTPS_PREFIX) && System.getProperty(CERT_KEY) == null) { |
|
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager(); |
|
System.setProperty(CERT_KEY, envManager.getCertificatePath()); |
|
System.setProperty(PWD_KEY, envManager.getCertificatePass()); |
|
} |
|
} |
|
|
|
private void register2Server() { |
|
try { |
|
SignIn.signIn(this); |
|
} catch (Exception e) { |
|
FRLogger.getLogger().error(e.getMessage()); |
|
} |
|
} |
|
|
|
/** |
|
* 心跳访问,用来更新当前用户的访问时间 |
|
* |
|
* @throws Exception |
|
*/ |
|
public void heartBeatConnection() throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "heart_beat"); |
|
para.put("user", user); |
|
para.put("userid", userID); |
|
|
|
HttpClient client = createHttpMethod(para, true); |
|
execute4InputStream(client); |
|
|
|
//这做法不好, 30秒刷一次, 刷新的时候会重新构建树, 构建完会把子节点都收缩起来, 效果太差. |
|
//为什么不保存刷新前树的伸缩状态, 因为刷新后的树和刷新前的树的结构未必是一致的. |
|
|
|
//服务器通知客户端更新左上角文件树面板 |
|
// try { |
|
// if (ComparatorUtils.equals(stream2String(execute4InputStream(method)), "true")) { |
|
// DesignerFrameFileDealerPane.getInstance().refresh(); |
|
// } |
|
// } catch (Exception e) { |
|
// FRLogger.getLogger().error(e.getMessage()); |
|
// } |
|
} |
|
|
|
/** |
|
* 返回描述该运行环境的名字 |
|
* |
|
* @return 描述环境名字的字符串 |
|
*/ |
|
public String getEnvDescription() { |
|
return Inter.getLocText("Env-Remote_Server"); |
|
} |
|
|
|
/** |
|
* 登录,返回userID |
|
*/ |
|
public void signIn() throws Exception { |
|
if (clock != null && clock.connected) { |
|
return; |
|
} |
|
String remoteVersion = getDesignerVersion(); |
|
if (StringUtils.isBlank(remoteVersion) || ComparatorUtils.compare(remoteVersion, ProductConstants.DESIGNER_VERSION) < 0) { |
|
throw new Exception("version not match"); |
|
} |
|
clearUserID(); |
|
startLogTimer(); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "r_sign_in"); |
|
para.put("user", user); |
|
para.put("password", password); |
|
|
|
simulaRPC(para, true); |
|
|
|
//neil:调用Clock方法,10秒向服务器发送一个字节,确保没掉线 |
|
if (clock == null) { |
|
Clock clock = new Clock(this); |
|
setClock(clock); |
|
} |
|
clock.start(); |
|
|
|
// 远程登录的心跳访问, 防止设计器强制关闭而没有Logout |
|
if (timer != null) { |
|
timer.cancel(); |
|
} |
|
timer = new Timer(); |
|
timer.schedule(new TimerTask() { |
|
public void run() { |
|
try { |
|
RemoteEnv.this.setThreadLocal("HEART_BEAT"); |
|
RemoteEnv.this.heartBeatConnection(); |
|
} catch (Exception e) { |
|
FRContext.getLogger().error("Server may be disconnected.", e); |
|
} |
|
} |
|
}, RemoteDeziConstants.HEARTBEAT_DELAY, RemoteDeziConstants.HEARTBEAT_DELAY); |
|
} |
|
|
|
|
|
private void startLogTimer() { |
|
if (logTimer != null) { |
|
logTimer.cancel(); |
|
} |
|
|
|
logTimer = new Timer(); |
|
logTimer.schedule(new TimerTask() { |
|
public void run() { |
|
try { |
|
RemoteEnv.this.setThreadLocal("LOG_MESSAGE"); |
|
FRContext.getCurrentEnv().printLogMessage(); |
|
} catch (Exception e) { |
|
FRLogger.getLogger().info(e.getMessage()); |
|
} |
|
} |
|
}, 10000, 10000); |
|
} |
|
|
|
private void stopLogTimer() { |
|
if(logTimer != null) { |
|
logTimer.cancel(); |
|
logTimer = null; |
|
} |
|
} |
|
|
|
/** |
|
* 根据userID sign out |
|
* |
|
* @return 成功签出返回true |
|
* @throws Exception |
|
*/ |
|
public boolean signOut() throws Exception { |
|
if (userID == null) { |
|
return true; |
|
} |
|
stopLogTimer(); |
|
// richer:登出的时候就把定时发送的时钟停掉 |
|
clock.stop(); |
|
// richer:把轮训使用的定时器也去掉 |
|
timer.cancel(); |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "r_sign_out"); |
|
para.put("id", userID); |
|
|
|
return simulaRPC(para, false |
|
); |
|
} |
|
|
|
protected boolean simulaRPC(HashMap<String, String> para, boolean isSignIn) throws Exception { |
|
HttpClient client = createHttpMethod(para, isSignIn); |
|
|
|
// execute method取到input stream再转成String |
|
String resJSON = null; |
|
try { |
|
resJSON = stream2String(execute4InputStream(client)); |
|
} catch (Exception e) { |
|
FRLogger.getLogger().error(e.getMessage()); |
|
} |
|
|
|
if (resJSON == null) { |
|
return false; |
|
} |
|
if (resJSON.indexOf("RegistEditionException") != -1) { |
|
JOptionPane.showMessageDialog(null, Inter.getLocText("FR-Lic_does_not_Support_Remote")); |
|
return false; |
|
} |
|
try { |
|
JSONObject jo = new JSONObject(resJSON); |
|
|
|
if (isSignIn) { |
|
if (jo.has("id")) { |
|
userID = jo.getString("id"); |
|
} |
|
if (jo.has("isRoot")) { |
|
isRoot = jo.getBoolean("isRoot"); |
|
} |
|
|
|
if (userID != null) { |
|
return true; |
|
} |
|
} else { |
|
if (jo.has("res")) { |
|
return jo.getBoolean("res"); |
|
} |
|
} |
|
String exception = jo.getString("exp"); |
|
if (exception != null) { |
|
throw new EnvException(exception); |
|
} |
|
} catch (JSONException je) { |
|
// 返回的resJSON不是JSON格式的,那就直接返回resJSON作为userID |
|
return true; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
protected boolean doLockOperation(String[] filePathes, String cmd) throws Exception { |
|
if (filePathes == null || filePathes.length == 0) { |
|
return true; |
|
} |
|
|
|
JSONArray ja = new JSONArray(filePathes); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", cmd); |
|
para.put("pathes", ja.toString()); |
|
|
|
return simulaRPC(para, false); |
|
} |
|
|
|
/** |
|
* 取路径filePath下面文件的lock |
|
* <p/> |
|
* 处于同一个原子操作,要么拿到所有的锁,要么一个锁也没有拿到 |
|
*/ |
|
public boolean getLock(String[] filePathes) throws Exception { |
|
return doLockOperation(filePathes, "design_get_lock"); |
|
} |
|
|
|
/** |
|
* 解锁文件 |
|
* |
|
* @param filePathes 文件路径 |
|
* @return 成功解锁返回true |
|
* @throws Exception |
|
*/ |
|
public boolean releaseLock(String[] filePathes) throws Exception { |
|
return doLockOperation(filePathes, "design_release_lock"); |
|
} |
|
|
|
/** |
|
* 当前Env下,tplPath目录下是否存在模板 |
|
* |
|
* @param reportPath 路径 |
|
* @return 是否存在 |
|
*/ |
|
@Override |
|
public boolean isTemplateExist(String reportPath) throws Exception { |
|
if (reportPath == null) { |
|
return false; |
|
} |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_report_exist"); |
|
para.put("report_path", reportPath); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
return ComparatorUtils.equals(stream2String(input), "true"); |
|
} |
|
|
|
/** |
|
* 解锁当前模板,用于远程设计。当远程设计某张模板 时,在解锁之前改模板处于锁定状态 |
|
* |
|
* @param tplPath 路径 |
|
* @throws Exception |
|
*/ |
|
@Override |
|
public void unlockTemplate(String tplPath) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_close_report"); |
|
para.put(RemoteDeziConstants.TEMPLATE_PATH, tplPath); |
|
HttpClient client = createHttpMethod(para); |
|
|
|
InputStream input = execute4InputStream(client); |
|
String info = Utils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8); |
|
|
|
FRContext.getLogger().error(info); |
|
} |
|
|
|
public class Bytes2ServerOutputStream extends OutputStream { |
|
private ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
private HashMap<String, String> nameValuePairs; |
|
|
|
public Bytes2ServerOutputStream(HashMap<String, String> nameValuePairs) { |
|
this.nameValuePairs = nameValuePairs; |
|
} |
|
|
|
public HashMap<String, String> getNameValuePairs() { |
|
return nameValuePairs; |
|
} |
|
|
|
public ByteArrayOutputStream getOut() { |
|
return out; |
|
} |
|
|
|
public OutputStream getZipOutputStream() throws Exception { |
|
return IOUtils.toZipOut(out); |
|
} |
|
|
|
/** |
|
* post ro Server 提交到服务器 |
|
* |
|
* @return 是否提交成功 |
|
*/ |
|
public boolean post2Server() { |
|
try { |
|
return postBytes2Server(out.toByteArray(), nameValuePairs); |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage(), e); |
|
return false; |
|
} |
|
} |
|
|
|
/** |
|
* 刷新数出流,并提交 |
|
* |
|
* @throws IOException |
|
*/ |
|
public void flush() throws IOException { |
|
super.flush(); |
|
post2Server(); |
|
} |
|
|
|
/** |
|
* 将指定字节写入输入流数组 |
|
* |
|
* @param b 写入的字节 |
|
* @throws IOException |
|
*/ |
|
@Override |
|
public void write(int b) throws IOException { |
|
out.write(b); |
|
|
|
} |
|
} |
|
|
|
/** |
|
* 测试数据连接是否能够正确的连接上 |
|
* |
|
* @param database 数据连接 |
|
* @return 如果能正确的连接到数据库则返回true |
|
* @throws Exception 无法正确连接到数据库则抛出此异常 |
|
* TODO alex_ENV 个人以为,这里应该是测试所有Connection的连接,所以Connection与TableData接口的关联需要思考 |
|
*/ |
|
@Override |
|
public boolean testConnection(com.fr.data.impl.Connection database) throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
|
|
// 把database写成xml文件到out |
|
DavXMLUtils.writeXMLFileDatabaseConnection(database, out); |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_test_con"); |
|
|
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} |
|
|
|
/** |
|
* ben:取schema |
|
*/ |
|
@Override |
|
public String[] getTableSchema(com.fr.data.impl.Connection database) throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
|
|
DavXMLUtils.writeXMLFileDatabaseConnection(database, out); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_get_schema"); |
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
if (input == null) { |
|
return null; |
|
} |
|
return DavXMLUtils.readXMLFileSchema(input); |
|
} |
|
|
|
/** |
|
* b:分别取Table,View,Procedure,实际应用时更有意义 |
|
*/ |
|
@Override |
|
public TableProcedure[] getTableProcedure(com.fr.data.impl.Connection database, String type, String schema) throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
DavXMLUtils.writeXMLFileDatabaseConnection(database, out); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_get_tables"); |
|
para.put("__type__", type); |
|
para.put("__dbschema__", schema); |
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
if (input == null) { |
|
return new TableProcedure[0]; |
|
} |
|
return DavXMLUtils.readXMLSQLTables(input); |
|
} |
|
|
|
public List getProcedures(com.fr.data.impl.Connection datasource, String[] schemas, boolean isOracle, boolean isOracleSysSpace) throws Exception { |
|
HashMap schemaTableProcedureMap = new HashMap(); |
|
List sqlTableObjs = new ArrayList(); |
|
TableProcedure[] sqlTableObj = null; |
|
int len = schemas.length; |
|
if (len > 0) { |
|
for (int i = 0; i < len; i++) { |
|
String schema = schemas[i]; |
|
sqlTableObj = this.getTableProcedure(datasource, TableProcedure.PROCEDURE, schema); |
|
if (sqlTableObj == null) { |
|
sqlTableObj = new TableProcedure[0]; |
|
} |
|
sqlTableObjs.add(sqlTableObj); |
|
schemaTableProcedureMap.put(schema, sqlTableObj); |
|
} |
|
} else { |
|
sqlTableObj = this.getTableProcedure(datasource, TableProcedure.PROCEDURE, null); |
|
if (sqlTableObj == null) { |
|
sqlTableObj = new TableProcedure[0]; |
|
} |
|
sqlTableObjs.add(sqlTableObj); |
|
schemaTableProcedureMap.put(null, sqlTableObj); |
|
} |
|
DataCoreUtils.putProcedureMap(datasource, schemaTableProcedureMap); |
|
return sqlTableObjs; |
|
} |
|
|
|
/** |
|
* 在当前路径下新建文件夹 |
|
* |
|
* @param folderPath 文件名 |
|
* @return 成功创建返回true |
|
* @throws Exception |
|
*/ |
|
@Override |
|
public boolean createFolder(String folderPath) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_create_folder"); |
|
para.put("folder_path", folderPath); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} |
|
|
|
/** |
|
* 新建一个文件 |
|
* |
|
* @param filePath :目标文件相对路径 |
|
* @return 成功新建返回true |
|
* @throws Exception |
|
*/ |
|
public boolean createFile(String filePath) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_create_file"); |
|
para.put("file_path", filePath); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} |
|
|
|
public boolean renameFile(String newPath, String oldPath) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_rename_file"); |
|
para.put("newPath", newPath); |
|
para.put("oldPath", oldPath); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} |
|
|
|
/** |
|
* 判断文件是否存在 |
|
* |
|
* @param filePath :目标文件相对路径 |
|
* @return 文件是否存在 |
|
* @throws Exception |
|
*/ |
|
@Override |
|
public boolean fileExists(String filePath) throws Exception { |
|
if (filePath == null) { |
|
return false; |
|
} |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_file_exists"); |
|
para.put("file_path", filePath); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} |
|
|
|
/** |
|
* 判断文件是否锁住 |
|
* |
|
* @param filePath 文件路径 |
|
* @return 文件被锁住了,返回true |
|
* @throws Exception |
|
*/ |
|
public boolean fileLocked(String filePath) throws Exception { |
|
if (filePath == null) { |
|
return false; |
|
} |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_file_locked"); |
|
para.put("file_path", filePath); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} |
|
|
|
|
|
/** |
|
* 注册环境,用于检测是否启动定时器,主要用于本地环境来监测远程 |
|
* |
|
* @param env 用户环境 |
|
*/ |
|
public void registerUserEnv(UserBaseEnv env) { |
|
} |
|
|
|
/** |
|
* 用于检测用户环境 |
|
* ,启动定时器 |
|
*/ |
|
public void startUserCheckTimer() { |
|
} |
|
|
|
|
|
/** |
|
* 停止定时器 |
|
*/ |
|
public void stopUserCheckTimer() { |
|
} |
|
|
|
/** |
|
* 删除文件 |
|
* |
|
* @param filePath 文件地址 |
|
* @return 删除成功返回true |
|
*/ |
|
public boolean deleteFile(String filePath) { |
|
if (filePath == null) { |
|
return false; |
|
} |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "delete_file"); |
|
para.put("file_path", filePath); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} catch (Exception e) { |
|
FRLogger.getLogger().error(e.getMessage()); |
|
} |
|
return false; |
|
} |
|
|
|
/** |
|
* 远程设计器设计时,假如开了权限就不可预览了。这边放一个全局的map来开后门 |
|
* |
|
* @param key 键值 |
|
* @param value 值 |
|
* @return 如果写入成功,返回true |
|
* @throws Exception |
|
*/ |
|
public boolean writePrivilegeMap(String key, String value) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "write_privilege_map"); |
|
para.put("current_user", this.user); |
|
para.put("current_password", this.password); |
|
para.put("key", key); |
|
para.put("value", value); |
|
|
|
HttpClient client = createHttpMethod(para); //jim :加上user,远程设计点击预览时传递用户角色信息 |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} |
|
|
|
/** |
|
* DataSource中去除当前角色没有权限访问的数据源 |
|
*/ |
|
public void removeNoPrivilegeConnection() { |
|
DatasourceManagerProvider dm = DatasourceManager.getProviderInstance(); |
|
|
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fs_remote_design"); |
|
para.put("cmd", "env_get_role"); |
|
para.put("currentUsername", this.getUser()); |
|
para.put("currentPwd", this.getPassword()); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
JSONArray ja = new JSONArray(stream2String(input)); |
|
ArrayList<String> toBeRemoveTDName = new ArrayList<String>(); |
|
for (int i = 0; i < ja.length(); i++) { |
|
String toBeRemoveConnName = (String) ((JSONObject) ja.get(i)).get("name"); |
|
dm.removeConnection(toBeRemoveConnName); |
|
Iterator it = dm.getTableDataNameIterator(); |
|
while (it.hasNext()) { |
|
String tdName = (String) it.next(); |
|
TableData td = dm.getTableData(tdName); |
|
td.registerNoPrivilege(toBeRemoveTDName, toBeRemoveConnName, tdName); |
|
} |
|
} |
|
|
|
for (int i = 0; i < toBeRemoveTDName.size(); i++) { |
|
dm.removeTableData(toBeRemoveTDName.get(i)); |
|
} |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage()); |
|
} |
|
} |
|
|
|
/** |
|
* 列出WEB-INF目录下指定路径的文件夹与文件 |
|
* |
|
* @param rootFilePath 指定目录 |
|
* @return WEB-INF目录下指定路径的文件夹与文件 |
|
* @throws Exception |
|
*/ |
|
@Override |
|
public FileNode[] listFile(String rootFilePath) throws Exception { |
|
return listFile(rootFilePath, false); |
|
} |
|
|
|
/** |
|
* 列出WEB-INF上层目录下指定路径的文件夹与文件 |
|
* |
|
* @param rootFilePath 指定目录 |
|
* @return WEB-INF上层目录下指定路径的文件夹与文件 |
|
* @throws Exception |
|
*/ |
|
@Override |
|
public FileNode[] listReportPathFile(String rootFilePath) throws Exception { |
|
return listFile(rootFilePath, true); |
|
} |
|
|
|
private FileNode[] listFile(String rootFilePath, boolean isWebReport) throws Exception { |
|
FileNode[] fileNodes; |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fs_remote_design"); |
|
para.put("cmd", "design_list_file"); |
|
para.put("file_path", rootFilePath); |
|
para.put("currentUserName", this.getUser()); |
|
para.put("currentUserId", this.createUserID()); |
|
para.put("isWebReport", isWebReport ? "true" : "false"); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return new FileNode[0]; |
|
} |
|
|
|
// 远程环境下左侧目录树暂不需要打开xlsx,xls文件 |
|
fileNodes = DavXMLUtils.readXMLFileNodes(input); |
|
ArrayList<FileNode> al = new ArrayList<FileNode>(); |
|
for (int i = 0; i < fileNodes.length; i++) { |
|
al.add(fileNodes[i]); |
|
} |
|
|
|
FileNode[] fileNodes2 = new FileNode[al.size()]; |
|
for (int i = 0; i < al.size(); i++) { |
|
fileNodes2[i] = al.get(i); |
|
} |
|
|
|
return fileNodes2; |
|
} |
|
|
|
|
|
/** |
|
* 列出目标目录下所有cpt文件或文件夹 |
|
* |
|
* @param rootFilePath 指定目录 |
|
* @return 列出目标目录下所有cpt文件或文件夹 |
|
* @throws Exception |
|
*/ |
|
public FileNode[] listCpt(String rootFilePath) throws Exception { |
|
return listCpt(rootFilePath, false); |
|
} |
|
|
|
/** |
|
* 列出目标目录下所有cpt文件或文件夹 |
|
* |
|
* @param rootFilePath 指定目录 |
|
* @param recurse 是否递归查找其子目录 |
|
* @return 列出目标目录下所有cpt文件或文件夹 |
|
* @throws Exception |
|
*/ |
|
public FileNode[] listCpt(String rootFilePath, boolean recurse) { |
|
List<FileNode> fileNodeList = new ArrayList<FileNode>(); |
|
try { |
|
listAll(rootFilePath, fileNodeList, new String[]{"cpt"}, recurse); |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage(), e); |
|
} |
|
return fileNodeList.toArray(new FileNode[fileNodeList.size()]); |
|
} |
|
|
|
private void listAll(String rootFilePath, List<FileNode> nodeList, String[] fileTypes, boolean recurse) throws Exception { |
|
FileNode[] fns = listFile(rootFilePath); |
|
for (FileNode fileNode : fns) { |
|
if (isAcceptFileType(fileNode, fileTypes)) { |
|
nodeList.add(fileNode); |
|
} else if (fileNode.isDirectory()) { |
|
if (recurse) { |
|
listAll(rootFilePath + File.separator + fileNode.getName(), nodeList, fileTypes, true); |
|
} else { |
|
nodeList.add(fileNode); |
|
} |
|
} |
|
} |
|
} |
|
|
|
private boolean isAcceptFileType(FileNode fileNode, String[] fileTypes) { |
|
for (String fileType : fileTypes) { |
|
if (fileNode.isFileType(fileType)) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/** |
|
* 获取指定数据集的参数 |
|
* |
|
* @param tableData 数据集 |
|
* @return 数据集的参数 |
|
* @throws Exception 获取参数失败则抛出此异常 |
|
*/ |
|
public Parameter[] getTableDataParameters(TableData tableData) throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
|
|
// 把tableData写成xml文件到out |
|
DavXMLUtils.writeXMLFileTableData(tableData, out); |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_td_pars"); |
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
|
|
if (input == null) { |
|
return new Parameter[0]; |
|
} |
|
return DavXMLUtils.readXMLParameters(input); |
|
} |
|
|
|
|
|
/** |
|
* 获取存储过程中的参数 |
|
* |
|
* @param storeProcedure 存储过程 |
|
* @return 返回存储过程中的所有参数组成的数组 |
|
* @throws Exception 如果获取参数失败则抛出此异常 |
|
*/ |
|
public Parameter[] getStoreProcedureParameters(StoreProcedure storeProcedure) throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
|
|
// 把tableData写成xml文件到out |
|
DavXMLUtils.writeXMLFileStoreProcedureAndSource(storeProcedure, out); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_sp_pars"); |
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
|
|
if (input == null) { |
|
return new Parameter[0]; |
|
} |
|
return DavXMLUtils.readXMLParameters(input); |
|
} |
|
|
|
/** |
|
* 根据指定的参数生成一个实际可预览的数据集 |
|
* |
|
* @param tableData 带参数的数据集 |
|
* @param parameterMap 参数键值对 |
|
* @param rowCount 需要获取的行数 |
|
* @return 实际的二维数据集 |
|
* @throws Exception 如果生成数据失败则抛出此异常 |
|
*/ |
|
public EmbeddedTableData previewTableData(Object tableData, java.util.Map parameterMap, int rowCount) throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
|
|
// 把tableData写成xml文件到out |
|
DavXMLUtils.writeXMLFileTableDataAndSource((TableData) tableData, out); |
|
|
|
// 把parameterMap转成JSON格式的字符串 |
|
JSONObject jo = new JSONObject(parameterMap); |
|
String jsonParameter = jo.toString(); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_preview_td"); |
|
para.put("pars", jsonParameter); |
|
para.put("rowcount", String.valueOf(rowCount)); |
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
|
|
if (input == null) { |
|
return null; |
|
} |
|
|
|
return (EmbeddedTableData) DavXMLUtils.readXMLTableData(input); |
|
} |
|
|
|
/** |
|
* 根据指定的参数生成一个实际可预览的数据集 |
|
* |
|
* @param tableData 带参数的数据集 |
|
* @param parameterMap 参数键值对 |
|
* @param start 开始 |
|
* @param end 结尾 |
|
* @param cols 列名 |
|
* @param colIdx 列序号 |
|
* @return 实际的二位数据条 |
|
* @throws Exception 异常 |
|
*/ |
|
public Object previewTableData(Object tableData, java.util.Map parameterMap, int start, int end, String[] cols, int[] colIdx) throws Exception { |
|
return previewTableData(tableData, parameterMap, -1); |
|
} |
|
|
|
/** |
|
* nameValuePairs,这个参数要接着this.path,拼成一个URL,否则服务器端req.getParameter是无法得到的 |
|
* |
|
* @param bytes 数据 |
|
* @param para 参数 |
|
* @return 从服务器端得到InputStream |
|
* @throws Exception 异常 |
|
*/ |
|
public InputStream postBytes2ServerB(byte[] bytes, HashMap<String, String> para) throws Exception { |
|
HttpClient client = createHttpMethod2(para); |
|
client.setContent(bytes); |
|
return execute4InputStream(client); |
|
} |
|
|
|
/** |
|
* Read XML.<br> |
|
* The method will be invoked when read data from XML file.<br> |
|
* May override the method to read the data that you saved. |
|
*/ |
|
public void readXML(XMLableReader reader) { |
|
if (reader.isChildNode()) { |
|
String tmpVal; |
|
if ("DIR".equals(reader.getTagName())) { |
|
if ((tmpVal = reader.getAttrAsString("path", null)) != null) { |
|
this.path = tmpVal; |
|
} |
|
if ((tmpVal = reader.getAttrAsString("user", null)) != null) { |
|
this.user = tmpVal; |
|
} |
|
if ((tmpVal = reader.getAttrAsString("password", null)) != null) { |
|
this.password = tmpVal; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Write XML.<br> |
|
* The method will be invoked when save data to XML file.<br> |
|
* May override the method to save your own data. |
|
* |
|
* @param writer the PrintWriter. |
|
*/ |
|
public void writeXML(XMLPrintWriter writer) { |
|
writer.startTAG("DIR").attr("path", this.path).attr("user", this.user).attr("password", this.password).end(); |
|
} |
|
|
|
|
|
public static class Clock { |
|
|
|
private static final long CONNECT_INTERVAL = 3000L; |
|
private boolean connected = false; |
|
|
|
private RemoteEnv remoteEnv; |
|
|
|
public Clock(RemoteEnv remoteEnv) { |
|
this.remoteEnv = remoteEnv; |
|
} |
|
|
|
/** |
|
* 开始连接 |
|
*/ |
|
public void start() { |
|
if (connected) { |
|
return; |
|
} |
|
connected = true; |
|
|
|
new Thread(new Runnable() { |
|
@Override |
|
public void run() { |
|
// richie:连续三次尝试连接都没有响应才判定为丢失连接 |
|
while (connected) { |
|
try { |
|
attemptConnect(); |
|
} catch (Exception ex) { |
|
try { |
|
attemptConnect(); |
|
} catch (Exception ee) { |
|
try { |
|
attemptConnect(); |
|
} catch (Exception exc) { |
|
stop(); |
|
if (exc instanceof NoRouteToHostException) { |
|
//网络问题导致的连接中断 |
|
if (JOptionPane.showConfirmDialog(null, Inter.getLocText("FR-Remote_Connect2Server_Again"), UIManager.getString("OptionPane.titleText"), JOptionPane.YES_NO_OPTION) |
|
== JOptionPane.OK_OPTION) { |
|
//调用重新连接服务器的方法 |
|
connectedAgain(); |
|
} |
|
} else { |
|
//服务器关闭引起的连接中断 |
|
if (JOptionPane.showConfirmDialog(null, Inter.getLocText("FR-Remote_Re_Connect_to_Server"), UIManager.getString("OptionPane.titleText"), JOptionPane.YES_NO_OPTION) |
|
== JOptionPane.OK_OPTION) { |
|
//调用重新连接服务器的方法 |
|
connectedAgain(); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
}).start(); |
|
} |
|
|
|
/** |
|
* 服务器连接中断后重新连接 |
|
*/ |
|
private void connectedAgain() { |
|
try { |
|
if (!remoteEnv.testServerConnectionWithOutShowMessagePane()) { |
|
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText(new String[]{"Datasource-Connection_failed", "check_communication"}, |
|
new String[]{",", "!"})); |
|
DesignerFrameFileDealerPane.getInstance().refresh(); |
|
return; |
|
} |
|
String remoteVersion = remoteEnv.getDesignerVersion(); |
|
if (StringUtils.isBlank(remoteVersion) || ComparatorUtils.compare(remoteVersion, ProductConstants.DESIGNER_VERSION) < 0) { |
|
String infor = Inter.getLocText("FR-Server_Version_Tip"); |
|
String moreInfo = Inter.getLocText("FR-Server_Version_Tip_MoreInfo"); |
|
FRLogger.getLogger().log(Level.WARNING, infor); |
|
new InformationWarnPane(infor, moreInfo, Inter.getLocText("FR-Designer_Tooltips")).show(); |
|
return; |
|
} |
|
SignIn.signIn(remoteEnv); |
|
LicUtils.resetBytes(); |
|
HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().refreshToolArea(); |
|
} catch (Exception em) { |
|
FRContext.getLogger().error(em.getMessage(), em); |
|
} |
|
} |
|
|
|
/** |
|
* 停止连接 |
|
*/ |
|
public void stop() { |
|
connected = false; |
|
} |
|
|
|
private void attemptConnect() throws Exception { |
|
Thread.sleep(CONNECT_INTERVAL); |
|
Pattern pattern = Pattern.compile("[/:]+"); |
|
String[] strs = pattern.split(remoteEnv.path); |
|
|
|
String shost = strs[1];//host,如:192.168.100.195 |
|
int sport = Integer.parseInt(strs[2]);//端口,如:8080 |
|
|
|
Socket socket = new Socket(shost, sport); |
|
//OOBBINLINE:是否支持发送一个字节的TCP紧急数据,false表示服务器不用处理这个数据 |
|
socket.setOOBInline(false); |
|
socket.sendUrgentData(0xFF); |
|
socket.close(); |
|
} |
|
} |
|
|
|
/** |
|
* 读报表运行环境所需的配置文件,如datasource.xml, config.xml,这些文件都保存在WEB-INF/resources目录下面 |
|
* |
|
* @param resourceName 配置文件的名字,如datasource.xml |
|
* @return 输入流 |
|
* @throws Exception |
|
*/ |
|
@Override |
|
public InputStream readResource(String resourceName) throws Exception { |
|
return readBean(resourceName, ProjectConstants.RESOURCES_NAME); |
|
} |
|
|
|
|
|
/** |
|
* 读取路径下的svg文件 |
|
* |
|
* @param path 制定路径,是基于报表目录下resource文件夹路径 |
|
* @return 读到的文件 |
|
*/ |
|
public File[] readPathSvgFiles(String path) { |
|
String cataloguePath = StableUtils.pathJoin(new String[]{CacheManager.getProviderInstance().getCacheDirectory().getPath(), SvgProvider.SERVER, path}); |
|
|
|
//检查缓存文件保存的目录下serversvgs文件夹是否存在 ,先用来暂存服务器读过来的svg文件 |
|
File catalogue = new File(cataloguePath); |
|
if (!catalogue.exists()) { |
|
catalogue.mkdirs(); |
|
} |
|
|
|
ArrayList<File> fileArray = new ArrayList<>(); |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_read_svgfile"); |
|
para.put("resourcePath", path); |
|
para.put("current_uid", this.createUserID()); |
|
para.put("currentUsername", this.getUser()); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
JSONArray ja = new JSONArray(stream2String(input)); |
|
for (int i = 0; i < ja.length(); i++) { |
|
JSONObject jsonObject = (JSONObject) ja.get(i); |
|
String svgFileName = (String) jsonObject.get("svgfileName"); |
|
String svgfileContent = (String) jsonObject.get("svgfileContent"); |
|
File file = new File(StableUtils.pathJoin(new String[]{cataloguePath, svgFileName})); |
|
InputStream in = new ByteArrayInputStream(svgfileContent.getBytes(EncodeConstants.ENCODING_UTF_8)); |
|
FileOutputStream out = new FileOutputStream(file); |
|
IOUtils.copyBinaryTo(in, out); |
|
fileArray.add(file); |
|
} |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage()); |
|
} |
|
|
|
return fileArray.toArray(new File[fileArray.size()]); |
|
} |
|
|
|
|
|
/** |
|
* 写svg文件 |
|
* |
|
* @param svgFile svg文件 |
|
* @return 是否写入成功 |
|
* @throws Exception 异常 |
|
*/ |
|
public boolean writeSvgFile(SvgProvider svgFile) throws Exception { |
|
testServerConnection(); |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_save_svg"); |
|
para.put("filePath", svgFile.getFilePath()); |
|
para.put("current_uid", this.createUserID()); |
|
para.put("currentUsername", this.getUser()); |
|
|
|
// 通过ByteArrayOutputStream将svg写成字节流 |
|
Bytes2ServerOutputStream out = new Bytes2ServerOutputStream(para); |
|
OutputStreamWriter outWriter = new OutputStreamWriter(out, "UTF-8"); |
|
StreamResult result = new StreamResult(outWriter); |
|
|
|
Source source = new DOMSource(svgFile.getSvgDocument()); |
|
try { |
|
Transformer xformer = TransformerFactory.newInstance().newTransformer(); |
|
try { |
|
xformer.transform(source, result); |
|
} catch (TransformerException ex) { |
|
FRContext.getLogger().error(ex.getMessage()); |
|
} |
|
|
|
} catch (TransformerConfigurationException ex) { |
|
FRContext.getLogger().error(ex.getMessage()); |
|
return false; |
|
} |
|
|
|
try { |
|
HttpClient client = createHttpMethod2(out.getNameValuePairs()); |
|
client.setContent(out.getOut().toByteArray()); |
|
String res = stream2String(execute4InputStream(client)); |
|
if (StringUtils.isNotEmpty(res)) { |
|
JOptionPane.showMessageDialog(null, Inter.getLocText("FR-Already_exist") + res); |
|
return false; |
|
} |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage()); |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
/** |
|
* 写报表运行环境所需的配置文件 |
|
* |
|
* @param mgr 管理各个资源文件的管理器 |
|
* @return 写入xml成功返回true |
|
* @throws Exception 写入xml错误则抛出此异常 |
|
*/ |
|
@Override |
|
public boolean writeResource(XMLFileManagerProvider mgr) throws Exception { |
|
testServerConnection(); |
|
|
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_save_resource"); |
|
para.put("resource", mgr.fileName()); |
|
para.put("class_name", mgr.getClass().getName()); |
|
para.put("current_uid", this.createUserID()); |
|
para.put("currentUsername", this.getUser()); |
|
|
|
// alex:通过ByteArrayOutputStream将mgr写成字节流 |
|
Bytes2ServerOutputStream out = new Bytes2ServerOutputStream(para); |
|
XMLTools.writeOutputStreamXML(mgr, out); |
|
|
|
try { |
|
HttpClient client = createHttpMethod2(out.getNameValuePairs()); |
|
client.setContent(out.getOut().toByteArray()); |
|
String res = stream2String(execute4InputStream(client)); |
|
if (StringUtils.isNotEmpty(res)) { |
|
JOptionPane.showMessageDialog(null, Inter.getLocText("FR-Already_exist") + res); |
|
return false; |
|
} |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage()); |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
/** |
|
* 读取文件 |
|
* |
|
* @param beanPath 文件名 |
|
* @param prefix 当前Env下得工程分类,如reportlets,lib等 |
|
* @return InputStream 输入流 |
|
*/ |
|
public InputStream readBean(String beanPath, String prefix) |
|
throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fs_remote_design"); |
|
para.put("cmd", "design_open"); |
|
para.put(RemoteDeziConstants.PREFXI, prefix); |
|
para.put("resource", beanPath); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
// return Utils.toZipIn(execute4InputStream(method)); |
|
//Utils.toZipIn这边有bug,远程连接的时候datasource.xml不能读取,先还原了 |
|
return execute4InputStream(client); |
|
} |
|
|
|
/** |
|
* 写文件 |
|
* |
|
* @param beanPath 文件名 |
|
* @param prefix 当前Env下得工程分类,如reportlets,lib等 |
|
* @return OutputStream 输出流 |
|
*/ |
|
public OutputStream writeBean(String beanPath, String prefix) |
|
throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fs_remote_design"); |
|
para.put("cmd", "design_save_report"); |
|
para.put(RemoteDeziConstants.PREFXI, prefix); |
|
para.put(RemoteDeziConstants.TEMPLATE_PATH, beanPath); |
|
|
|
return new Bytes2ServerOutputStream(para); |
|
} |
|
|
|
/** |
|
* 返回数据库表的列名 |
|
* |
|
* @param selectedName 所选择数据库名 |
|
* @param schema 数据库模式,用于存储过程 |
|
* @param tableName 所选择数据库名 |
|
*/ |
|
@Override |
|
public String[] getColumns(String selectedName, String schema, String tableName) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_columns"); |
|
para.put("dsName", selectedName); |
|
para.put("schema", schema); |
|
para.put("tableName", tableName); |
|
|
|
HttpClient client = createHttpMethod2(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return null; |
|
} |
|
|
|
String colums = stream2String(input); |
|
if (StringUtils.isEmpty(colums)) { |
|
return null; |
|
} |
|
return colums.split("\\."); |
|
} |
|
|
|
/** |
|
* 返回模板文件路径 |
|
*/ |
|
@Override |
|
public String getWebReportPath() { |
|
return getPath().substring(0, getPath().lastIndexOf("/")); |
|
} |
|
|
|
@Override |
|
public String getProcedureText(String connectionName, String databaseName) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_get_procedure_text"); |
|
para.put("procedure_name", databaseName); |
|
para.put("connectionName", connectionName); |
|
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
if (input == null) { |
|
return StringUtils.EMPTY; |
|
} |
|
return DavXMLUtils.readXMLProcedureText(input); |
|
} |
|
|
|
@Override |
|
public StoreProcedureParameter[] getStoreProcedureDeclarationParameters(String connectionName, String databaseName, String parameterDefaultValue) throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_get_sp_parameters"); |
|
para.put("__name__", databaseName); |
|
para.put("__default_value__", parameterDefaultValue); |
|
para.put("connectionName", connectionName); |
|
|
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
if (input == null) { |
|
return new StoreProcedureParameter[0]; |
|
} |
|
return DavXMLUtils.readXMLStoreProcedureParameters(input); |
|
} |
|
|
|
/** |
|
* 获取datasource.xml文件的修改表 |
|
*/ |
|
public ModifiedTable getDataSourceModifiedTables(String type) { |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "get_datasource_modified_tables"); |
|
para.put("type", type); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
if (input == null) { |
|
return new ModifiedTable(); |
|
} |
|
return DavXMLUtils.readXMLModifiedTables(input); |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage()); |
|
} |
|
return new ModifiedTable(); |
|
} |
|
|
|
|
|
/** |
|
* 写修改表 |
|
* |
|
* @param modifiedTable 修改表 |
|
* @param type 操作类型,是数据连接还是服务器数据集 |
|
* @return 写入成功返回true |
|
*/ |
|
public boolean writeDataSourceModifiedTables(ModifiedTable modifiedTable, String type) { |
|
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
|
|
// 把tableData写成xml文件到out |
|
DavXMLUtils.writeXMLModifiedTables(modifiedTable, out); |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "update_modifytable_to_server"); |
|
para.put("type", type); |
|
|
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
|
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage()); |
|
} |
|
return false; |
|
} |
|
|
|
public String[] getProcedureColumns(StoreProcedure storeProcedure, java.util.Map parameterMap) throws Exception { |
|
String[] columns; |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "list_sp"); |
|
HttpClient client = createHttpMethod(para); |
|
try { |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return ArrayUtils.EMPTY_STRING_ARRAY; |
|
} |
|
|
|
columns = DavXMLUtils.readXMLSPColumns(input); |
|
return columns; |
|
} catch (Exception e) { |
|
FRLogger.getLogger().error(e.getMessage()); |
|
} |
|
|
|
return new String[0]; |
|
} |
|
|
|
; |
|
|
|
public String[] getProcedureColumns(String name) throws Exception { |
|
String[] columns; |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "list_sp_columns_name"); |
|
para.put("name", name); |
|
HttpClient client = createHttpMethod(para); |
|
try { |
|
InputStream input = execute4InputStream(client); |
|
if (input == null) { |
|
return ArrayUtils.EMPTY_STRING_ARRAY; |
|
} |
|
columns = DavXMLUtils.readXMLSPColumns(input); |
|
return columns; |
|
} catch (Exception e) { |
|
FRLogger.getLogger().error(e.getMessage()); |
|
} |
|
return new String[0]; |
|
|
|
} |
|
|
|
/** |
|
* 输出日志信息 |
|
* |
|
* @throws Exception |
|
*/ |
|
public void printLogMessage() throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "get_log_message"); |
|
|
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
if (input == null) { |
|
return; |
|
} |
|
LogRecordTime[] records = DavXMLUtils.readXMLLogRecords(input); |
|
for (LogRecordTime logRecordTime : records) { |
|
DesignerLogHandler.getInstance().printRemoteLog(logRecordTime); |
|
|
|
} |
|
} |
|
|
|
public String getUserID() { |
|
return userID; |
|
} |
|
|
|
|
|
//TODO: |
|
|
|
/** |
|
* 预览存储过程 |
|
* |
|
* @param storeProcedure 存储过程 |
|
* @param parameterMap 参数map |
|
* @param rowCount 行数 |
|
* @return 返回取到的存储过程 |
|
*/ |
|
@Override |
|
public ProcedureDataModel[] previewProcedureDataModel(StoreProcedure storeProcedure, Map parameterMap, int rowCount) { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
|
|
// 把tableData写成xml文件到out |
|
DavXMLUtils.writeXMLFileStoreProcedureAndSource(storeProcedure, out); |
|
|
|
// 把parameterMap转成JSON格式的字符串 |
|
JSONObject jo = new JSONObject(parameterMap); |
|
String jsonParameter = jo.toString(); |
|
|
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "list_sp"); |
|
para.put("pars", jsonParameter); |
|
|
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
if (input == null) { |
|
return null; |
|
} |
|
|
|
TableData[] tableDatas = DavXMLUtils.readXMLTableDataArray(input); |
|
if (tableDatas == null || tableDatas.length == 0) { |
|
return new ProcedureDataModel[0]; |
|
} |
|
ProcedureDataModel[] procedureDataModels = new ProcedureDataModel[tableDatas.length]; |
|
for (int i = 0; i < tableDatas.length; i++) { |
|
if (tableDatas[i] instanceof EmbeddedTableData) { |
|
procedureDataModels[i] = ((EmbeddedTableData) tableDatas[i]).trans2ProcedureDataModel(); |
|
} |
|
} |
|
return procedureDataModels; |
|
|
|
|
|
} catch (Exception e) { |
|
FRLogger.getLogger().error(e.getMessage()); |
|
} |
|
return new ProcedureDataModel[0]; |
|
} |
|
|
|
|
|
public String getAppName() { |
|
return "WebReport"; |
|
} |
|
|
|
/** |
|
* 是否为Oracle数据连接 |
|
* |
|
* @param database 数据连接 |
|
* @return 是返回true |
|
* @throws Exception |
|
*/ |
|
public boolean isOracle(Connection database) throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
DavXMLUtils.writeXMLFileDatabaseConnection(database, out); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_get_isOracle"); |
|
InputStream input = postBytes2ServerB(out.toByteArray(), para); |
|
if (input == null) { |
|
return true; |
|
} |
|
return DavXMLUtils.readXMLBoolean(input); |
|
} |
|
|
|
public String[] getSupportedTypes() { |
|
return FILE_TYPE; |
|
} |
|
|
|
/** |
|
* 在模板面板中是否支持增加打开所在文件夹、重命名、删除三个工具栏选项 |
|
* |
|
* @return 不支持返回false |
|
*/ |
|
public boolean isSupportLocalFileOperate() { |
|
return false; |
|
} |
|
|
|
/** |
|
* 判断是否有文件夹权限 |
|
* |
|
* @param path 路径 |
|
* @return 有权限则返回true |
|
*/ |
|
public boolean hasFileFolderAllow(String path) { |
|
HttpClient client = null; |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fs_remote_design"); |
|
para.put("cmd", "design_filefolder_allow"); |
|
para.put("current_uid", this.createUserID()); |
|
para.put(RemoteDeziConstants.TEMPLATE_PATH, path); |
|
|
|
client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
|
|
if (input == null) { |
|
return false; |
|
} |
|
return Boolean.valueOf(IOUtils.inputStream2String(input, EncodeConstants.ENCODING_UTF_8)); |
|
} catch (Exception e) { |
|
FRLogger.getLogger().error(e.getMessage()); |
|
return false; |
|
} |
|
|
|
} |
|
|
|
/** |
|
* 是否是管理员身份 |
|
* |
|
* @return 是则返回true |
|
*/ |
|
public boolean isRoot() { |
|
return isRoot; |
|
} |
|
|
|
/** |
|
* 是否为压缩包部署 |
|
* |
|
* @return 是则返回true |
|
*/ |
|
@Override |
|
public boolean isPackDeploy() { |
|
return false; |
|
} |
|
|
|
@Override |
|
public String getDesignerVersion() throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_get_designer_version"); |
|
para.put("user", user); |
|
para.put("password", password); |
|
|
|
HttpClient client = createHttpMethod(para, true); |
|
try { |
|
return stream2String(execute4InputStream(client)); |
|
} catch (Exception e) { |
|
FRLogger.getLogger().error(e.getMessage()); |
|
} |
|
return null; |
|
} |
|
|
|
public InputStream getDataSourceInputStream(String filePath) throws Exception { |
|
return readBean(filePath, "datasource"); |
|
} |
|
|
|
|
|
@Override |
|
public ArrayList getAllRole4Privilege(boolean isFS) { |
|
ArrayList allRoleList = new ArrayList(); |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "get_all_role"); |
|
para.put("isFS", String.valueOf(isFS)); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
JSONArray ja = new JSONArray(stream2String(input)); |
|
for (int i = 0; i < ja.length(); i++) { |
|
String roleName = (String) ((JSONObject) ja.get(i)).get("name"); |
|
allRoleList.add(roleName); |
|
} |
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage()); |
|
} |
|
return allRoleList; |
|
} |
|
|
|
@Override |
|
public String getLicName() { |
|
return LicUtils.FILE_NAME; |
|
} |
|
|
|
@Override |
|
public void setLicName(String licName) { |
|
//do nth |
|
} |
|
|
|
/** |
|
* 获取当前env的build文件路径 |
|
*/ |
|
public String getBuildFilePath() { |
|
return ResourceConstants.BUILD_PATH; |
|
} |
|
|
|
/** |
|
* 设置当前env的build文件路径 |
|
*/ |
|
public void setBuildFilePath(String buildFilePath) { |
|
} |
|
|
|
/** |
|
* 编译Java源代码,方便二次开发的进行 |
|
* |
|
* @param sourceText 源代码 |
|
* @return 编译信息,有可能是成功信息,也有可能是出错或者警告信息 |
|
*/ |
|
public JavaCompileInfo compilerSourceCode(String sourceText) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_compile_source_code"); |
|
InputStream in = postBytes2ServerB(sourceText.getBytes(EncodeConstants.ENCODING_UTF_8), para); |
|
BufferedReader br = new BufferedReader(new InputStreamReader(in, EncodeConstants.ENCODING_UTF_8)); |
|
StringBuilder sb = new StringBuilder(); |
|
String line; |
|
while ((line = br.readLine()) != null) { |
|
sb.append(line); |
|
} |
|
JSONObject jo = new JSONObject(sb.toString()); |
|
JavaCompileInfo info = new JavaCompileInfo(); |
|
info.parseJSON(jo); |
|
return info; |
|
} |
|
|
|
/** |
|
* 将文件拷贝到插件目录 |
|
* |
|
* @param dir 要拷贝的文件 |
|
* @param plugin 插件 |
|
*/ |
|
public void copyFilesToPluginAndLibFolder(File dir, Plugin plugin) throws Exception { |
|
|
|
} |
|
|
|
/** |
|
* 将文件添加到指定目录或者删除指定目录的文件 |
|
* |
|
* @param file 解压插件的临时目录 |
|
* @param plugin 当前处理的插件 |
|
*/ |
|
public void movePluginEmbFile(File file, Plugin plugin) throws Exception { |
|
|
|
} |
|
|
|
/** |
|
* 将文件从插件目录删除 |
|
* |
|
* @param plugin 要删除插件 |
|
* @return 同上 |
|
*/ |
|
public String[] deleteFileFromPluginAndLibFolder(Plugin plugin) { |
|
return new String[0]; |
|
} |
|
|
|
/** |
|
* 保存插件的配置文件 |
|
* |
|
* @param plugin 插件 |
|
*/ |
|
public void writePlugin(Plugin plugin) throws Exception { |
|
|
|
} |
|
|
|
|
|
/** |
|
* 获取插件的配置目录 |
|
* |
|
* @param plugin |
|
*/ |
|
public String getPluginFilePath(Plugin plugin) { |
|
|
|
return StringUtils.EMPTY; |
|
} |
|
|
|
public void readPluginLicenses() throws Exception { |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_plugin_licenses"); |
|
|
|
InputStream inputStream = postBytes2ServerB(out.toByteArray(), para); |
|
String pluginsLicensesStr = IOUtils.inputStream2String(inputStream, EncodeConstants.ENCODING_UTF_8); |
|
if (StringUtils.isNotBlank(pluginsLicensesStr) && pluginsLicensesStr.startsWith("[")) { |
|
JSONArray jsonArray = new JSONArray(pluginsLicensesStr); |
|
for (int i = 0; i < jsonArray.length(); i++) { |
|
PluginLicense pluginLicense = new PluginLicense(); |
|
pluginLicense.parseJSON(jsonArray.getJSONObject(i)); |
|
PluginLicenseManager.getInstance().addRemotePluginLicense(pluginLicense); |
|
} |
|
} |
|
} |
|
|
|
@Override |
|
public String pluginServiceAction(String serviceID, String req) throws Exception { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_get_plugin_service_data"); |
|
para.put("serviceID", serviceID); |
|
para.put("req", req); |
|
HttpClient client = createHttpMethod(para); //jim :加上user,远程设计点击预览时传递用户角色信息 |
|
InputStream inputStream = execute4InputStream(client); |
|
return IOUtils.inputStream2String(inputStream); |
|
} |
|
|
|
/** |
|
* 远程不启动,使用虚拟服务 |
|
* @param serviceID |
|
*/ |
|
@Override |
|
public void pluginServiceStart(String serviceID){ |
|
} |
|
|
|
@Override |
|
public void checkAndRegisterLic(FileNode node, Plugin plugin) throws Exception { |
|
|
|
} |
|
|
|
@Override |
|
public File[] loadREUFile() throws Exception { |
|
File target = new File(CacheManager.getProviderInstance().getCacheDirectory(), |
|
ShareConstants.DIR_SHARE_CACHE); |
|
StableUtils.deleteFile(target); |
|
StableUtils.mkdirs(target); |
|
File cacheDir = null; |
|
File zip = null; |
|
OutputStream out = null; |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_read_reufile"); |
|
para.put("current_uid", this.createUserID()); |
|
para.put("currentUsername", this.getUser()); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = client.getResponseStream();//拿到服务端传过来的整个共享文件夹的压缩文件的文件流 |
|
zip = new File(StableUtils.pathJoin(CacheManager.getProviderInstance().getCacheDirectory().getAbsolutePath()), "share.zip"); |
|
cacheDir = new File(StableUtils.pathJoin(CacheManager.getProviderInstance().getCacheDirectory().getAbsolutePath()), ShareConstants.DIR_SHARE_CACHE); |
|
StableUtils.deleteFile(cacheDir); |
|
StableUtils.mkdirs(cacheDir); |
|
StableUtils.makesureFileExist(zip); |
|
out = new FileOutputStream(zip); |
|
IOUtils.copyBinaryTo(input, out);//放到本地缓存目录下 |
|
|
|
IOUtils.unzip(zip, cacheDir.getAbsolutePath(), EncodeConstants.ENCODING_GBK);//先解压到临时目录 |
|
if (cacheDir.exists() && cacheDir.isDirectory()) { |
|
return cacheDir.listFiles(new FilenameFilter() { |
|
public boolean accept(File file, String s) { |
|
return s.endsWith("reu"); |
|
} |
|
}); |
|
} |
|
|
|
} catch (Exception e) { |
|
FRContext.getLogger().error(e.getMessage()); |
|
} finally { |
|
if (out != null) { |
|
out.flush(); |
|
out.close(); |
|
} |
|
StableUtils.deleteFile(zip); |
|
} |
|
return new File[0]; |
|
} |
|
|
|
@Override |
|
public boolean installREUFile(File reuFile) { |
|
if (reuFile == null) { |
|
return false; |
|
} |
|
File tempFile = new File(CacheManager.getProviderInstance().getCacheDirectory(), "temp_remote"); |
|
IOUtils.unzip(reuFile, tempFile.getAbsolutePath()); |
|
String shareXMLName = StableUtils.pathJoin(tempFile.getAbsolutePath(), ShareConstants.NAME_XML_MODULE); |
|
String helpXMLName = StableUtils.pathJoin(tempFile.getAbsolutePath(), ShareConstants.NAME_XML_HELP); |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_install_reufile"); |
|
para.put("current_uid", this.createUserID()); |
|
para.put("currentUsername", this.getUser()); |
|
para.put("reuFileName", reuFile.getName()); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
client.setContent(IOUtils.inputStream2Bytes(new FileInputStream(new File(shareXMLName)))); |
|
InputStream input = execute4InputStream(client); |
|
client.release(); |
|
para.put("isComplete", "true"); |
|
HttpClient client1 = createHttpMethod(para); |
|
client1.setContent(IOUtils.inputStream2Bytes(new FileInputStream(new File(helpXMLName)))); |
|
InputStream input1 = execute4InputStream(client1); |
|
return ComparatorUtils.equals(stream2String(input), "true") && ComparatorUtils.equals(stream2String(input1), "true"); |
|
} catch (Exception e) { |
|
return false; |
|
} |
|
} |
|
|
|
@Override |
|
public boolean removeREUFilesByName(String fileName) { |
|
if (StringUtils.isEmpty(fileName)) { |
|
return true; |
|
} |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_remove_reufile"); |
|
para.put("current_uid", this.createUserID()); |
|
para.put("currentUsername", this.getUser()); |
|
para.put("reuFileName", fileName); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
return ComparatorUtils.equals(stream2String(input), "true"); |
|
} catch (Exception e) { |
|
return false; |
|
} |
|
} |
|
|
|
@Override |
|
public String getSharePath() { |
|
try { |
|
HashMap<String, String> para = new HashMap<String, String>(); |
|
para.put("op", "fr_remote_design"); |
|
para.put("cmd", "design_get_share_path"); |
|
para.put("current_uid", this.createUserID()); |
|
para.put("currentUsername", this.getUser()); |
|
|
|
HttpClient client = createHttpMethod(para); |
|
InputStream input = execute4InputStream(client); |
|
return stream2String(input); |
|
} catch (Exception e) { |
|
return StringUtils.EMPTY; |
|
} |
|
} |
|
} |