diff options
Diffstat (limited to 'src/com/nis/nmsclient')
59 files changed, 16615 insertions, 0 deletions
diff --git a/src/com/nis/nmsclient/NmsClient.java b/src/com/nis/nmsclient/NmsClient.java new file mode 100644 index 0000000..101a4c6 --- /dev/null +++ b/src/com/nis/nmsclient/NmsClient.java @@ -0,0 +1,549 @@ +package com.nis.nmsclient; + +import java.io.File; +import java.io.IOException; +import java.util.Calendar; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.common.SysConfig; +import com.nis.nmsclient.config.DetecConfReqHandle; +import com.nis.nmsclient.model.AlarmInfo; +import com.nis.nmsclient.model.SetInfo; +import com.nis.nmsclient.thread.WritePidThread; +import com.nis.nmsclient.thread.alarm.AlarmThread; +import com.nis.nmsclient.thread.alarm.AlarmUtil; +import com.nis.nmsclient.thread.alarm.ErrorCode; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.thread.socket.SSLClient; +import com.nis.nmsclient.thread.socket.SSLServer; +import com.nis.nmsclient.thread.task.TaskResultOper; +import com.nis.nmsclient.thread.timer.DelLocalFileThread; +import com.nis.nmsclient.thread.upload.DataSendThread; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.ProcessUtil; +import com.nis.nmsclient.util.Utils; + +/** + * NMSClient 程序启动主方法类 + */ +public class NmsClient{ + static Logger logger = Logger.getLogger(NmsClient.class); + // 监测设置信息,初始化完成后清空 + public List<SetInfo> setInfos = new LinkedList<SetInfo>(); + // 监测设置的报警字段设置信息,初始化完成后清空 + public Map<Long, List<AlarmInfo>> alarmInfos = new HashMap<Long, List<AlarmInfo>>(); + private int testGap = 60; //单位:秒 + + static{ +// Thread.currentThread().setName("NMSClient主程序"); + Thread.currentThread().setName("NMSClient Main Program"); + } + + /** + * NMSClient 程序启动入口 + */ + public static void main(String[] args) { + logger.info("------- NMSClient 启动开始------------"); + + //NMSClient进程停止保存缓存操作 + doShutDownWork(); + + /** + * 启动通信程序, 如果端口已存在即SSLServer创建失败,退出程序 + */ + //通讯端口放在第一步,为了确保初始化配置不成功或个数为0时 新建任务下发、DC收集数据、握手等操作 能正常执行 + //注意:要在通讯程序中判断SeqId是否为空,为空 则只接收握手通信、收集数据通信,其他的通信都抛弃 + SSLServer sslServer = null; + try { + sslServer = new SSLServer(); + } catch (IOException e) { + TaskResultOper.handerAgentUpgradeResult(false); + logger.error("NMSClient Program termination:" + e.getMessage()); + AlarmUtil.sendNMSErrorMsg(ErrorCode.ProtListenerError, Utils.getLocalIp(), "i18n_client.NmsClient.ncCommunicatePortErr_n81i"); + System.exit(0); + } +// Thread server = new Thread(sslServer, "通讯线程"); + Thread server = new Thread(sslServer, "Communication Thread"); + server.start(); + + /** + * 启动守护进程 + */ + try { + String os = System.getProperty("os.name"); + String cmd = ""; + String procSearchKey = null; + if (os.startsWith("Windows")) { + String homePath = new File(Contants.SYSTEM_PATH).getParent();//NC布署路径 + cmd = homePath + File.separator + "script" + File.separator + "nmsclient_shouhu.bat"; + procSearchKey = "nmsclient_shouhu.bat"; + } else if (os.startsWith("Linux")) { + cmd = Contants.SYSTEM_PATH + File.separator + "nmsclient_shouhu.sh"; + procSearchKey = "nmsclient_shouhu.sh"; + } + Object[] objArr = ProcessUtil.checkPidAndGetPid(null, procSearchKey); + int isExistFlag = Integer.parseInt(objArr[0].toString()); + if(isExistFlag == 0){// 守护进程不存在,启动 + logger.info("正在启动守护进程..."); + ProcessUtil.runExec(cmd, new String[]{Contants.localTaskResultPath}, null, null, true); + objArr = ProcessUtil.checkPidAndGetPid(null, procSearchKey); + isExistFlag = Integer.parseInt(objArr[0].toString()); + if(isExistFlag != 0){ + logger.info("守护进程 启动成功"); + }else{ + logger.info("守护进程 启动失败"); + AlarmUtil.sendNMSErrorMsg(ErrorCode.DeamonNotExist, Utils.getLocalIp(), "i18n_client.NmsClient.ncDeamonStartFail_n81i"); + } + }else { + logger.info("守护进程 已存在,无需再启动"); + } + + } catch (Exception e) { + logger.error("Start the daemon exception", e); + AlarmUtil.sendNMSErrorMsg(ErrorCode.DeamonNotExist, Utils.getLocalIp(), "i18n_client.NmsClient.ncDeamonStartException_n81i," + e.getMessage()); + } + + /** + * 相关业务操作入口 + */ + new NmsClient().run(); + + } + + public void run() { + //执行写PID线程 + Common.service.submit(new WritePidThread()); + + // 2013-3-8 由于初始化监测配置个数为0时不断重新获取,致使任务初始化无法执行,先将任务与监测配置分开执行 + // 为了将初始化监测配置放于任务之后,所以在开始执行之前,先与DC握手通讯,以保证通讯正常 + while (true) { + try { + //与Server通信 + Future<?> serFuture = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), + CommonSocket.REQ_HAND_SHAKE, null)); + if (Contants.isSucessByResult((String) serFuture.get())) { + break; + } + } catch (Exception e) { + logger.error("Handshake communication abnormality:" + Utils.printExceptionStack(e)); + } + + try { + Thread.sleep(1000 * testGap);// 如果握手失败,让当前线程暂停N秒,再重试 + } catch (InterruptedException e) { + logger.error(Utils.printExceptionStack(e)); + continue; + } + } + + // 获取本机唯一标识 + initUUID(); + // 检查本机操作系统和IP是否变更 + checkLocalOperSystemAndIp(); + + /**************************** 任务部分处理操作 ***************************/ + // 处理Agent自身升级时的执行结果文件 + TaskResultOper.handerAgentUpgradeResult(true); + // 发送所有之前上发失败的任务结果 + TaskResultOper.initSendAllTaskResult(); + + // 初始化执行中的任务 + if (Contants.DEBUG_INIT_TASK_FLAG == 0) { +// Common.scheduled.schedule(new SSLClient("初始化任务", + Common.scheduled.schedule(new SSLClient("Initialization Task", + CommonSocket.REQ_INIT_TASK, null), + Contants.COMMON_TASK_INIT_DELAY_MINUTES, TimeUnit.MINUTES); + } + // 定时上传发送失败的任务结果 + /*if (Contants.DEBUG_TASKRESULT_FLAG == 0) { + Common.scheduled.scheduleWithFixedDelay(new Runnable() { + public void run() { + Thread.currentThread().setName("上传任务结果"); + TaskResultOper.initSendAllTaskResult(); + } + }, 0, Contants.COMMON_TASK_RESULT_SEND_MINUTES, TimeUnit.MINUTES); + }*/ + // 定时上传发送失败的回传文件 + /*if (Contants.DEBUG_TASKRETURN_FLAG == 0) { + Common.scheduled.scheduleWithFixedDelay(new Runnable() { + public void run() { + Thread.currentThread().setName("回传文件"); + new TaskReturnHandle().sendAllTaskReturnFile(); + } + }, 0, Contants.COMMON_TASK_RESULT_SEND_MINUTES, TimeUnit.MINUTES); + }*/ + // 定时清理内存中已完成的任务 + Common.scheduled.scheduleWithFixedDelay(new Runnable() { + public void run() { +// Thread.currentThread().setName("清理已完成任务"); + Thread.currentThread().setName("Clean Up The Completed Task"); + // == 1、针对结果文件过多时打包上传未完成的文件 + File taskDir = new File(Contants.localTaskPath); + if (taskDir.exists()) { + // ----取所有未上传完成的Zip文件 + File[] zipArr = FileUtil.getFilesEndWith(taskDir, ".zip"); + // 若存在未上传完成的ZIP结果文件,则不清理内存中的任务 + if (zipArr.length > 0) { + return; + } + } + + // == 2、检查当前结果文件数量 + File resultDir = new File(TaskResultOper.getTaskResultPath()); + if(resultDir.exists()){ + File[] fileArr = FileUtil.getFilesEndWith(resultDir, Contants.TASK_RESULT_FILE_SUFFIX); + // 若存在未上传的结果文件,则不清理内存中的任务 + if(fileArr.length > 0){ + return; + } + } + + // -- 清理已完成的任务,待考虑 以后定时清理方案 + Common.removeCancelAndDoneTaskFuture(); + } + }, Contants.COMMON_TASK_CLEAR_HOURS, Contants.COMMON_TASK_CLEAR_HOURS, TimeUnit.HOURS); + + /**************************** 定时清理本地文件操作 ***************************/ + // 定时删除本地生成的文件 + if (Contants.DEBUG_DELFILE_FLAG == 0) { + //2012-4-28 将所有删除文件的线程合并为一个,取设置的所有清理文件间隔中的最小值作为检查间隔 + //2012-12-17 第一次执行删除文件时间,不是启动立即删除,设置延迟到启动之后的第一个凌晨0点 + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, 1); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + long delay = cal.getTimeInMillis()-System.currentTimeMillis(); +// Common.scheduled.scheduleAtFixedRate(new DelLocalFileThread("删除文件"), delay, + Common.scheduled.scheduleAtFixedRate(new DelLocalFileThread("Delete Files"), delay, + getMinCheckPeriod() * 60 * 60 * 1000, TimeUnit.MILLISECONDS); + } + + /**************************** 监测配置信息处理操作 ***************************/ + // 初始化监测配置信息 + initDetecConfig(); + // 启动三方监测程序 + if (Contants.DEBUG_PLUGIN_FLAG == 0) { + //-------------初始化三方监测 start + for (SetInfo setInfo : setInfos) { + // 缓存三方监测配置信息,用于合并临时结果文件 + Common.putPluginDetecSetInfo(setInfo.getId(), setInfo); + + if (!Common.COMMON_SYS_SETINFO.equals(setInfo.getIsSchedule())) { // 第三方且由Agent启动 + Common.startPluginDetec(setInfo); + } + } + //-------------初始化三方监测 end + } + //启动预设监测程序 + if (Contants.DEBUG_SYSDETECT_FLAG == 0) { + //-------------初始化预设监测 start + for (SetInfo setInfo : setInfos) { + if (Common.COMMON_SYS_SETINFO.equals(setInfo.getIsSchedule())) {// 判断如果是系统预设类型 + Common.addOrUpdateSysDetec(setInfo, alarmInfos + .get(setInfo.getId())); + } + } + //-------------初始化预设监测 end + } + + //启用监测主动上报 + if(Contants.DATA_SEND_THREAD_FLAG == 0){ + Common.scheduled.scheduleWithFixedDelay(new DataSendThread(Contants.DATA_SEND_THREAD_HOST, Contants.DATA_SEND_THREAD_PORT), (int)(Math.random()*Contants.DATA_SEND_THREAD_INTERVAL), Contants.DATA_SEND_THREAD_INTERVAL, TimeUnit.SECONDS); + logger.info("监测主动上报已成功添加到线程池"); + } + + // 启动上传数据程序 + /*if (Contants.DEBUG_UPLOADDATA_FLAG == 0) { + Common.scheduled.scheduleWithFixedDelay(new UploadDataThread("上传数据"), 1, + Contants.COMMON_UPLOAD_DATA_MINUTES, TimeUnit.MINUTES); + }*/ + // 启动主动报警程序 + if (Contants.DEBUG_ALARM_FLAG == 0) { +// Common.scheduled.scheduleAtFixedRate(new AlarmThread("主动预警"), 1, + Common.scheduled.scheduleAtFixedRate(new AlarmThread("Active Early Warning"), 1, + Contants.COMMON_UPLOAD_DATA_MINUTES, TimeUnit.MINUTES); + } + + //清空变量 + setInfos.clear(); + setInfos = null; + alarmInfos.clear(); + alarmInfos = null; + } + + /** + * 第一次布署NMSAgent时,初始化本机唯一标志 + */ + public void initUUID() { + if (Contants.AGENT_HOST_UUID == null) {// 第一次布署Agent + while (true) { + String uuid = null; + try { + Future<?> future = Common.service.submit(new SSLClient( +// "获取本机标识", CommonSocket.REQ_LOCAL_UUID, null)); + "Obtain The Local Identity", CommonSocket.REQ_LOCAL_UUID, null)); + String msg = (String) future.get(); + if (Contants.isSucessByResult(msg)) { + // dc发送的数据格式为 uuid:::localIp + String[] result = Contants.getDescByResult(msg).split( + ":::"); + uuid = result[0]; + String localIp = result[1]; + logger.info("本机标识ID:" + uuid); + if (!(uuid == null || "".equals(uuid) + || "null".equals(uuid) || localIp == null + || "".equals(localIp) || "null".equals(localIp))) { + + SysConfig.setUUIDValue(uuid); + //根据ip地址获取端口名称 + String name = Utils.getNetInterfaceNameByIp(localIp); + //将端口名称写入配置文件 + SysConfig.setInterfaceNameValue(name); + break; + } + } + } catch (Exception e) { + logger.error("Get the unique identity of the native or IP port name exception:" + Utils.printExceptionStack(e)); + } + try { + logger.debug((1000 * testGap ) +"s 后重试"); + Thread.sleep(1000 * testGap);// 如果获取失败,让当前线程暂停N秒,再重试 + } catch (InterruptedException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + } + /** + * 每次启动时检查本机操作系统类型和IP是否有变更,若有,则将最新信息写入文件并发送信息到Server, + * 由Server端根据SeqID更新所有相关节点信息 + */ + public void checkLocalOperSystemAndIp() { + // ---- 取本机相关信息 + String operateSysType = getOperateSysType(); + String localIp = Utils.getIpAddressByEthName(Contants.AGENT_INTERFACE_NAME_KEY); + + logger.info("本机通讯IP:" + localIp); + if (localIp != null && !"".equals(localIp) && !"null".equals(localIp)) { + // ----- 与原有信息比较 + if (Contants.AGENT_OPERATE_SYSTEM == null + || Contants.AGENT_LOCAL_IP == null + || !operateSysType.equals(Contants.AGENT_OPERATE_SYSTEM) + || !localIp.equals(Contants.AGENT_LOCAL_IP)) { + // 若有变更,则将本机系统和IP写入文件,再发送到Server + SysConfig.setUUIDValue(operateSysType, localIp); + // 发送UUID、SystemType、LocalIp到Server + String sendMsg = Contants.AGENT_HOST_UUID + + Contants.COMMON_MSG_SEPRATOR + + Contants.AGENT_OPERATE_SYSTEM; + try { + Future<?> future1 = Common.service.submit(new SSLClient( +// "信息变更", CommonSocket.REQ_LOCAL_CHANGE, sendMsg)); + "Information Change", CommonSocket.REQ_LOCAL_CHANGE, sendMsg)); + String resultMsg = (String) future1.get(); + String descMsg = Contants.getDescByResult(resultMsg); + if (!Contants.isSucessByResult(resultMsg)) { + if (descMsg == null || "".equals(descMsg) + || "null".equals(descMsg)) { +// descMsg = "信息变更出现问题,可能存在重复IP,请手动检查"; + descMsg = "Information changes may occur. Duplicate IP may exist. Please check manually."; + } + logger.error("Failure of information change:" + descMsg); + } else if (descMsg != null && !"".equals(descMsg)) { + logger.info("信息变更:" + descMsg); + } + } catch (Exception e) { + logger.error("Information change:" + Utils.printExceptionStack(e)); + } + } + } + } + + + /** + * 获取本机操作系统类型 + * + * @return 1代表linux ;2代表windows; “” 为其它 + */ + public static String getOperateSysType() { + String operateSysType = null; + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + operateSysType = "2"; + } else if (os.startsWith("Linux")) { + operateSysType = "1"; + } else { + operateSysType = ""; + } + return operateSysType; + } + + +// /** +// * 第一次布署NMSAgent时,初始化本机唯一标志 +// */ +// public void initUUID(){ +// if(Contants.AGENT_HOST_UUID == null){//第一次布署Agent +// while (true) { +// String uuid = null; +// try { +// Future<?> future = Common.service.submit(new SSLClient( +// "获取本机标识", CommonSocket.REQ_LOCAL_UUID, null)); +// String msg = (String) future.get(); +// if (Contants.isSucessByResult(msg)) { +// uuid = Contants.getDescByResult(msg); +// logger.info("本机标识ID:" + uuid); +// if(uuid != null && !"".equals(uuid) && !"null".equals(uuid)){ +// SysConfig.setUUIDValue(uuid); +// break; +// } +// } +// } catch (Exception e) { +// logger.error("获取本机唯一标识异常:" + Utils.printExceptionStack(e)); +// } +// +// try { +// Thread.sleep(1000 * testGap);// 如果获取失败,让当前线程暂停N秒,再重试 +// } catch (InterruptedException e) { +// logger.error(Utils.printExceptionStack(e)); +// } +// } +// } +// } +// +// /** +// * 每次启动时检查本机操作系统类型和IP是否有变更,若有,则将最新信息写入文件并发送信息到Server,由Server端根据SeqID更新所有相关节点信息 +// */ +// public void checkLocalOperSystemAndIp(){ +// //---- 取本机相关信息 +// String operateSysType = null; +// String os = System.getProperty("os.name"); +// if (os.startsWith("Windows")) { +// operateSysType = "2"; +// }else if (os.startsWith("Linux")){ +// operateSysType = "1"; +// }else{ +// operateSysType = ""; +// } +// String localIp = Utils.getLocalIp(); +// //----- 与原有信息比较 +// if (Contants.AGENT_OPERATE_SYSTEM == null +// || Contants.AGENT_LOCAL_IP == null +// || !operateSysType.equals(Contants.AGENT_OPERATE_SYSTEM) +// || !localIp.equals(Contants.AGENT_LOCAL_IP)) { +// //若有变更,则将本机系统和IP写入文件,再发送到Server +// SysConfig.setUUIDValue(operateSysType, localIp); +// //发送UUID、SystemType、LocalIp到Server +// String sendMsg = Contants.AGENT_HOST_UUID +// + Contants.COMMON_MSG_SEPRATOR +// + Contants.AGENT_OPERATE_SYSTEM; +// try { +// Future<?> future = Common.service.submit(new SSLClient("信息变更", +// CommonSocket.REQ_LOCAL_CHANGE, sendMsg)); +// String resultMsg = (String) future.get(); +// String descMsg = Contants.getDescByResult(resultMsg); +// if (!Contants.isSucessByResult(resultMsg)) { +// if(descMsg == null || "".equals(descMsg) || "null".equals(descMsg)){ +// descMsg = "信息变更出现问题,可能存在重复IP,请手动检查"; +// } +// logger.error("信息变更失败:" + descMsg); +// }else if(descMsg!=null && !"".equals(descMsg)){ +// logger.info("信息变更:" + descMsg); +// } +// } catch (Exception e) { +// logger.error("信息变更:" + Utils.printExceptionStack(e)); +// } +// } +// } + + /** + * 请求获得初始化监测配置信息: 获取失败或获取配置个数为0,则不断循环获取 + */ + public void initDetecConfig(){ + while (true) { + try { + Future<?> future = Common.service.submit(new SSLClient( +// "初始化监测配置", CommonSocket.REQ_INIT_CONFIG, null)); + "Initialization Of Monitoring Configuration", CommonSocket.REQ_INIT_CONFIG, null)); + String msg = (String) future.get(); + if (Contants.isSucessByResult(msg)) { + msg = Contants.getDescByResult(msg); + new DetecConfReqHandle().handlerConfigByInit(msg, setInfos, alarmInfos); + logger.info("初始化监测配置个数:" + setInfos.size()); + if(setInfos.size()>0){ + break; + } + + } + } catch (Exception e) { + logger.error("Initialization of monitoring configuration exceptions:" + Utils.printExceptionStack(e)); + } + + try { + Thread.sleep(1000 * testGap);//如果初始化失败,让当前线程暂停N秒,再重试 + } catch (InterruptedException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + + /** + * 取设置的所有清理文件间隔中的最小值, 单位:小时 + */ + public int getMinCheckPeriod(){ + int period = Contants.COMMON_DEL_DATA_HOURS; + period = period < Contants.COMMON_DEL_LOG_DAYS * 24 ? period + : Contants.COMMON_DEL_LOG_DAYS * 24; + period = period < Contants.COMMON_DEL_TEMP_DAYS * 24 ? period + : Contants.COMMON_DEL_TEMP_DAYS * 24; + period = period < Contants.COMMON_DEL_UPGRADEFILE_DAYS * 24 ? period + : Contants.COMMON_DEL_UPGRADEFILE_DAYS * 24; + logger.debug("=========del file period=" + period); + + return period; + } + + + /** + * 进程停用时,触发该事件,将缓存数据存入硬盘 + * 在NC侧 当前情况是当NMSClient服务停止时无需做操作,因为NC启动的时候NC会将执行失败的任务结果发送给DC(TaskResultOper.initSendAllTaskResult()), + * 再收集DC的任务,不会有数据丢失。 + * + * 暂时无需做操作,先提供退出触发的机制,供后续使用 + * + * @author jinshujuan Jul 15, 2013 + * @version 1.0 + */ + public static void doShutDownWork() { + logger.info("注册程序退出事件"); + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + try { +// Thread.currentThread().setName("退出NMSClient,缓存数据清理线程"); + Thread.currentThread().setName("Exit NMSClient, Caching Data Cleaning Thread"); + logger.info("停止NMSClient,处理缓存数据。。。"); + //清理缓存数据Common类控制 + //logger.info("清空缓存"); + logger.info("停止NMSClient,处理缓存数据 完成"); + } catch (Exception ex) { + logger.error("Stop NMSClient, cache data entry anomalies, cache data to disk.", ex);//1.全部入库,入库异常时存盘 或 2.全部存盘,下次启动时入库 + //缓存数据存入硬盘操作 + //logger.info("保存缓存"); + logger.error("Stop NMSClient, cache data entry anomalies, cache data stored in hard disk to complete", ex);//1.全部入库,入库异常时存盘 或 2.全部存盘,下次启动时入库 + } + } + }); + } + +} diff --git a/src/com/nis/nmsclient/common/Common.java b/src/com/nis/nmsclient/common/Common.java new file mode 100644 index 0000000..7b56c16 --- /dev/null +++ b/src/com/nis/nmsclient/common/Common.java @@ -0,0 +1,453 @@ +package com.nis.nmsclient.common; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.filefilter.FalseFileFilter; +import org.apache.commons.io.filefilter.FileFilterUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.config.DetecConfOper; +import com.nis.nmsclient.model.AlarmInfo; +import com.nis.nmsclient.model.SetInfo; +import com.nis.nmsclient.thread.alarm.AlarmPO; +import com.nis.nmsclient.thread.alarm.AlarmUtil; +import com.nis.nmsclient.thread.plugin.StartPluginRun; +import com.nis.nmsclient.thread.task.LoopTaskThread; +import com.nis.nmsclient.util.ProcessUtil; +import com.nis.systeminfo.thread.GetInfoRun; + +public class Common { + static Logger logger = Logger.getLogger(Common.class); + + public static final String COMMON_SYS_SETINFO = "0"; + public static boolean NC_UPGRADE_FLAG = false; + + public static final ExecutorService service = Executors + .newFixedThreadPool(Contants.COMMON_THREAD_SOCKET_SIZE); // 通讯线程池 + public static final ScheduledExecutorService scheduled = Executors + .newScheduledThreadPool(Contants.COMMON_THREAD_SCHEDULE_SIZE); // 定时执行线程池 + + // 任务变更或取消控制集 object[1]=ScheduledFuture<?>,object[2]=LoopTaskThread + private static Map<Long, Object[]> taskFutureMap = Collections.synchronizedMap(new HashMap<Long, Object[]>()); + // 主动告警信息: 主动报警线程使用 + private static Map<Long, AlarmPO> alarmPOs = Collections.synchronizedMap(new HashMap<Long, AlarmPO>()); + // 预置监测控制集 + private static Map<Long, ScheduledFuture<?>> sysDetecFutrue = Collections.synchronizedMap(new HashMap<Long, ScheduledFuture<?>>()); + // Agent定时启动的三方监测控制集 + private static Map<Long, ScheduledFuture<?>> pluginDetecFutrue = Collections.synchronizedMap(new HashMap<Long, ScheduledFuture<?>>()); + // 三方监测设置集 + private static Map<Long, SetInfo> pluginDetecSetInfoMap = new HashMap<Long, SetInfo>(); + // 监测信息报警相关信息(alarmInfo.setInfoId, alarmInfo) + public static Map<Long, List<AlarmInfo>> detecAlarmInfoMap = new HashMap<Long, List<AlarmInfo>>(); + + /** + * 缓存三方监测设置 + * + * @param key + * @param setInfo + * @param lastMergeFileDetecTime + */ + public static void putPluginDetecSetInfo(Long key, SetInfo setInfo) { + long planTime = (setInfo.getControlStartTime() != null) ? setInfo.getControlStartTime() : 0; + + // 初始化已合并的最后一个临时结果文件的监测时间,用于判断是否出现未生成监测数据的周期 + // 监测设置下发时,记录该监测的计划启动时间 + // NC重启时,记录当前时间(周期启动监测由NC控制,若NC重启后存在未合并的临时结果,忽略该时间段内未生成监测数据的周期) + if(setInfo.getLastMergeDetecTime() == null) { + setInfo.setLastMergeDetecTime(Math.max(System.currentTimeMillis(), planTime)); + } + if(setInfo.getPlanCheckTime() == null || setInfo.getPlanCheckTime().longValue() == 0) { + // GetRunInfo.startTime + setInfo.setPlanCheckTime(System.currentTimeMillis()); + } + + pluginDetecSetInfoMap.put(key, setInfo); + } + + /** + * 获取三方监测设置集 + * + * @param key + * @return + */ + public static Collection<SetInfo> getPluginDetecSetInfos() { + return pluginDetecSetInfoMap.values(); + } + + public static void putAllDetecAlarmInfo(Map<Long, List<AlarmInfo>> alarmMap) { + detecAlarmInfoMap.putAll(alarmMap); + } + + /** + * 监测信息报警相关信息 + * @param setInfoId + * @return + */ + public static List<AlarmInfo> getDetecAlarmInfo(Long setInfoId) { + return detecAlarmInfoMap.get(setInfoId); + } + + /** + * 获取任务 + */ + public static ScheduledFuture<?> getTaskFuture(Long key) { + synchronized (taskFutureMap) { + Object[] objects = taskFutureMap.get(key); + if (objects != null && objects.length > 0 && objects[0] != null) { + return (ScheduledFuture<?>) objects[0]; + } else { + return null; + } + } + } + + /** + * 添加任务 + */ + public static void putTaskFuture(Long key, ScheduledFuture<?> value, LoopTaskThread loopTask) { + synchronized (taskFutureMap) { + taskFutureMap.put(key, new Object[] { value, loopTask }); + logger.info("添加任务 id:" + key); + } + } + + /** + * 注销任务 + */ + public static void cancleTaskFuture(final Long key, long delayMs) { + scheduled.schedule(new Runnable() { + public void run() { + synchronized (taskFutureMap) { +// Thread.currentThread().setName("注销任务 id:" + key); + Thread.currentThread().setName("Write Off Task ID:" + key); + Object[] objects = taskFutureMap.get(key); + if (objects!=null && objects.length>0 && objects[0]!=null) { + ScheduledFuture<?> future = (ScheduledFuture<?>) objects[0]; + logger.info("任务状态: " + + ((future.isDone() || future + .isCancelled()) ? "已停止" : "运行中")); + if (objects.length > 1 && objects[1] != null) { + LoopTaskThread loopTask = (LoopTaskThread) objects[1]; + loopTask.cancle(); + } + future.cancel(true); + taskFutureMap.remove(key); + logger.info("注销成功"); + } else { + logger.info("任务不存在"); + } + + } + } + }, delayMs, TimeUnit.MILLISECONDS); + } + + /** + * 从全局变量移除执行完成或者取消的任务(每次在上传发送失败的结果时检查并移除) + */ + public static void removeCancelAndDoneTaskFuture() { + synchronized (taskFutureMap) { + Iterator<Long> iterator = taskFutureMap.keySet().iterator(); + while (iterator.hasNext()) { + Long key = iterator.next(); + Object[] objects = taskFutureMap.get(key); + if (objects != null && objects.length > 0) { + ScheduledFuture<?> future = (ScheduledFuture<?>) objects[0]; + if (future.isCancelled() || future.isDone()) { + iterator.remove(); + logger.info("任务控制集 移除 id:" + key + " 状态: " + + ((future.isDone() || future + .isCancelled()) ? "已停止" : "运行中")); + } + } else { + iterator.remove(); + logger.info("任务控制集 移除 id:" + key); + } + } + } + } + + /** + * 获取存放预警信息集 + */ + public static Map<Long, AlarmPO> getAlarmPOs() { + synchronized (alarmPOs) { + return alarmPOs; + } + } + + /** + * 取消某一监测类型的主动预警 + */ + public static void removeAlarmPO(Long key) { + synchronized (alarmPOs) { + if (alarmPOs.containsKey(key)) { + AlarmPO alarmPO = alarmPOs.get(key); + alarmPOs.remove(key); + logger.info("主动预警集 移除 setId:" + key + " >> " + + alarmPO.getType() + "_" + alarmPO.getProcIden()); + } + } + } + + /** + * 添加或更新对某一监测类型的主动预警 + */ + public static void addOrUpdateAlarmPO(AlarmPO alarmPO) { + synchronized (alarmPOs) { + Long key = alarmPO.getId(); + String infoMsg = "添加"; + + if (alarmPOs.containsKey(key)) { + infoMsg = "更新"; + } + + alarmPOs.put(key, alarmPO); + + logger.info("主动预警集 " + infoMsg + " setId:" + key + " >> " + alarmPO.getType() + "_" + alarmPO.getProcIden()); + } + } + + /** + * 取得预设监测总数 + */ + public static int getSysDetecCount() { + synchronized (sysDetecFutrue) { + return sysDetecFutrue.size(); + } + } + + /** + * 停用预设监测 + */ + public static void stopSysDetec(SetInfo setInfo) { + synchronized (sysDetecFutrue) { + Long key = setInfo.getId(); +// String threadName = "预设监测_" + String threadName = "Presupposition Monitoring_" + + DetecConfOper.getFileName(setInfo.getCheckTypeName(), + setInfo.getProcessIden(), null); + + ScheduledFuture<?> future = sysDetecFutrue.get(key); + if (future != null) { + future.cancel(true); + sysDetecFutrue.remove(key); + logger.info("预设监测线程 停用 setId:" + setInfo.getId() + " >> " + + threadName); + } + } + } + + /** + * 添加或更新系统预设监测 + * @param setInfo + * @param alarmInfos + */ + public static void addOrUpdateSysDetec(SetInfo setInfo, List<AlarmInfo> alarmInfos) { + synchronized (sysDetecFutrue) { + Long key = setInfo.getId(); + String infoMsg = "添加"; + + ScheduledFuture<?> future = sysDetecFutrue.get(key); + if (future != null) { + future.cancel(true); + sysDetecFutrue.remove(key); + + infoMsg = "更新"; + } + + long delay = 0; + Date startTime = new Date(); + if (setInfo.getPlanCheckTime() != null) { + try { + long gap = setInfo.getPlanCheckTime() - System.currentTimeMillis(); + if (gap > 0) { + delay = gap; + startTime = new Date(setInfo.getPlanCheckTime()); + } + } catch (Exception e) { + logger.error("Please check whether the next test time is set correctly!", e); + } + } + +// String threadName = "预设监测_" + String threadName = "Presupposition Monitoring_" + + DetecConfOper.getFileName(setInfo.getCheckTypeName(), + setInfo.getProcessIden(), null); + + future = Common.scheduled.scheduleAtFixedRate(new GetInfoRun( + threadName, setInfo, startTime, alarmInfos), delay, setInfo + .getCheckGap(), TimeUnit.MINUTES); + sysDetecFutrue.put(key, future); + + logger.info("预设监测线程 " + infoMsg + " setId:" + setInfo.getId() + " >> " + threadName); + } + } + + /** + * 启动三方监测 + */ + public static void startPluginDetec(SetInfo setInfo) { +// String threadName = "三方监测_" + String threadName = "Three Party Monitoring_" + + DetecConfOper.getFileName(setInfo.getCheckTypeName(), + setInfo.getProcessIden(), null); + + Common.scheduled.schedule(new StartPluginRun(setInfo, threadName), 0, + TimeUnit.MILLISECONDS); + + logger.info("三方监测 添加 setId:" + setInfo.getId() + " >> " + threadName); + } + + /** + * 添加定时启动的三方监测 + */ + public static void putPluginDetecFuture(Long key, ScheduledFuture<?> future) { + synchronized (pluginDetecFutrue) { + pluginDetecFutrue.put(key, future); + } + } + + /** + * 停止定时启动的三方监测任务 + */ + public static void stopPluginDetecFuture(Long key, String threadName) { + synchronized (pluginDetecFutrue) { + ScheduledFuture<?> future = pluginDetecFutrue.get(key); + if (future != null) { + future.cancel(true); + sysDetecFutrue.remove(key); + logger.info("三方监测 移除 setId:" + key + " >> " + threadName); + } + } + } + + /** + * 检查三方监测是否存在(NC周期启动、NC单次启动) + */ + public static boolean containPluginDetecFuture(Long key) { + ScheduledFuture<?> future = pluginDetecFutrue.get(key); + return (future != null); + } + + /** + * 停用三方监测 + */ + public static void stopPluginDetec(SetInfo setInfo) { + // NC周期启动监测需要获取三方监测的关键字 + if("2".equals(setInfo.getIsControlStart())) { + generateCommandAndKeyword(setInfo); + } + + Long key = setInfo.getId(); +// String threadName = "三方监测_" + String threadName = "Three Party Monitoring_" + + DetecConfOper.getFileName(setInfo.getCheckTypeName(), + setInfo.getProcessIden(), null); + synchronized (pluginDetecFutrue) { + ScheduledFuture<?> future = pluginDetecFutrue.get(key); + if (future != null) { + future.cancel(true); + sysDetecFutrue.remove(key); + logger.info("三方监测 移除 setId:" + setInfo.getId() + " >> " + threadName); + } + } + try { + // 检查PID + Object[] objArr = ProcessUtil.checkPidAndGetPid(setInfo.getProcessFile(), setInfo.getProcessSearchKeyCode()); + int isExistFlag = Integer.parseInt(objArr[0].toString()); + String pidInfo = objArr[1].toString(); + + if (isExistFlag == 0) {// 不存在 + logger.info("停用" + threadName + ":进程原本不存在,不用杀进程"); + } else if (isExistFlag == 1) {// 存在且只有一个进程,杀PID + ProcessUtil.killProcess(pidInfo); + logger.info("停用" + threadName + ":杀进程 PID:" + pidInfo); + } else if (isExistFlag == 2) {// 找到多个进程,告警 + logger.info("停用" + threadName + ":" + pidInfo); +// String alarmMsg = "停用三方监测进程:" + pidInfo; + String alarmMsg = "Discontinuation Of The Three Party Monitoring Process:" + pidInfo; + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo + .getCheckTypeName(), setInfo.getProcessIden(), + new Date(), new Date(), 1, + Contants.DETECTION_STATUS_FAILURE, alarmMsg); + } + } catch (Exception e) { + logger.error("Discontinuation of three party monitoring anomalies", e); + } + } + + /** + * 设置三方监测中由Web管理的监测脚本的启动参数(针对NC启动的周期监测)<br/> + * 生成三方监测的执行命令及查询关键字 + * + * @param setInfo + * @return 脚本启动命令 + */ + public static String generateCommandAndKeyword(SetInfo setInfo) { + String command = null; + try { + if ("2".equals(setInfo.getIsControlStart())) { // NC周期启动 + File scriptDir = new File(Contants.localPluginScriptPath); + final String keyword = "_" + setInfo.getProcessIden() + "."; + Collection<?> files = FileUtils.listFiles(scriptDir, + FileFilterUtils.asFileFilter(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + if(name.endsWith(".tp")) { + return false; // 排除临时文件 + } + return name.contains(keyword); + } + }), FalseFileFilter.FALSE); + if (!files.isEmpty()) { + File scriptFile = (File) files.iterator().next(); + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + command = scriptFile.getCanonicalPath(); + } else if (os.startsWith("Linux")) { + command = "./ " + scriptFile.getCanonicalFile(); + } + setInfo.setProcessPath(command); // 设置执行命令 + setInfo.setProcessSearchKeyCode(scriptFile.getName()); // 搜索关键字 + // 更新缓存中的监测设置 + Common.putPluginDetecSetInfo(setInfo.getId(), setInfo); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + return command; + } + + public static int byteArrayToInt(byte[] b) { + return b[3] & 0xFF | + (b[2] & 0xFF) << 8 | + (b[1] & 0xFF) << 16 | + (b[0] & 0xFF) << 24; + } + + public static byte[] intToByteArray(int a) { + return new byte[] { + (byte) ((a >> 24) & 0xFF), + (byte) ((a >> 16) & 0xFF), + (byte) ((a >> 8) & 0xFF), + (byte) (a & 0xFF) + }; + } +} diff --git a/src/com/nis/nmsclient/common/Contants.java b/src/com/nis/nmsclient/common/Contants.java new file mode 100644 index 0000000..3f43a06 --- /dev/null +++ b/src/com/nis/nmsclient/common/Contants.java @@ -0,0 +1,307 @@ +package com.nis.nmsclient.common; + +import java.io.File; + +import org.apache.commons.lang.StringUtils; + +import com.nis.nmsclient.util.FileUtil; + + +public class Contants { + + public static final String SYSTEM_PATH; //NMSClient应用启动主目录 + + /** ========= SSLSocket相关配置参数,客户与服务两端交互数据信息 ========**/ + public static final String SOCKET_SERVER_HOST_KEY= "server_host"; + public static String SOCKET_SERVER_HOST;//服务器IP + public static final Integer SOCKET_SERVER_PORT;//服务器端口 + public static final Integer SOCKET_AGENT_PORT;//客户端端口 + public static final Integer SOCKET_TIMEOUT_MINUTES;// Socket通信超时时间 + public static final String SSL_KEY_STORE;//key证书库文件 + public static final String SSL_TRUST_KEY_STORE;//认证证书库文件 + public static final String SSL_JSSE_TYPE = "TLS";//类型TLS、SSL + public static final String SSL_KEYSTORE_TYPE = "JCEKS";//KeyStore的类型有:jceks、jks + public static final String SSL_KEY_PRIVATE_PASS = "123456"; + public static final String SSL_KEY_STORE_PASS = "client"; + + public static final String keyPath; + + /**=======================本地文件相关参数========================*/ + public static final String localDetecConfSuffix;// 监测设置信息文件名后缀 + public static final String localDetecConfPath;// 监测设置信息存放路径 + public static final String localDataCollection;// 监测数据存放集 + public static final String localDataFilePath;//------------监测数据存放路径 + public static final String localDataDonePath;//------------成功处理数据存放路径 + public static final String localDataErrorPath;//------------不完整数据0大小文件存放路径 + public static final String localBackupPath;// 备份文件存放目录 + public static final String localUploadsPath;// 推送文件存入目录 + public static final String localTaskPath;// 任务相关信息存放目录 + public static final String localTaskDonePath;// ------------成功处理任务存放目录 + public static final String localTaskErrorPath;// -----------不完整0大小回传文件存放目录 + public static final String localTaskResultPath;// ------------任务结果存放目录 + public static final String localTaskReturnPath;// ------------任务回传文件存放目录 + public static final String localLogsPath;// 日志存放路径 + public static final String localTempPath;// 临时文件存放目录 + public static final String localTempDataIncomingPath; // 第三方监测临时文件存放目录 + public static final String localAgentPidFile;// Agent自身进程PID存放文件 + public static final String localPluginScriptPath;// 第三方监测脚本存放目录 + public static final String LOCAL_SCRIPT_PATH; + + /**=======================系统预计监测类型========================*/ + public static final String SYS_CHECK_TYPE_CPU; + public static final String SYS_CHECK_TYPE_MEMORY; + public static final String SYS_CHECK_TYPE_DISK; + public static final String SYS_CHECK_TYPE_NET; + public static final String SYS_CHECK_TYPE_SYSDATE; + public static final String SYS_CHECK_TYPE_PROCESS; + public static final String SYS_CHECK_TYPE_PROCESS_NMSAGENT; + public static final String SYS_CHECK_TYPE_SYSTEMINFO; + + /** =====================Common时间时隔==================== **/ + // ------------ 清除本地文件 + public static final Integer COMMON_DEL_LOG_DAYS;// 删除日志文件间隔时间 + public static final Integer COMMON_DEL_DATA_HOURS;// 删除数据文件间隔时间 + public static final Integer COMMON_DEL_TASK_HOURS;// 删除任务相关文件间隔时间 + public static final Integer COMMON_DEL_UPGRADEFILE_DAYS;// 删除升级文件间隔时间 + public static final Integer COMMON_DEL_TEMP_DAYS;// 删除临时文件间隔时间 + public static String[] COMMON_DEL_PATH_INCLUDE;// 指定Agent可删除文件的范围 + public static String[] COMMON_DEL_PATH_EXCLUDE;// 指定Agent可删除文件范围内不可删除部分 + // ------------ 监测、任务、预警 + public static final Integer COMMON_ALARM_MINUTES = 5;// 主动告警轮循间隔时间 + public static final Integer COMMON_TASK_RESULT_SEND_MINUTES = 5;// 重发之前发送失败的任务执行结果间隔时间 + public static final Integer COMMON_TASK_INIT_DELAY_MINUTES = 2;// 启动时初始化任务请求延迟时间 + public static final Integer COMMON_UPLOAD_DATA_MINUTES;// 上传数据轮循间隔时间 + public static final Integer COMMON_TASK_CLEAR_HOURS;// 定时清理内存中已完成任务的间隔时间 + // ------------线程池 + public static final Integer COMMON_THREAD_SOCKET_SIZE ;// socket通信线程最大个数 + public static final Integer COMMON_THREAD_SCHEDULE_SIZE;// 定时任务线程最大个数 + // ------------打包上传 + public static final Integer COMMON_ZIP_MIN_SIZE;// 文件数越过一定值时压缩用 + public static final Integer COMMON_ZIP_MAX_SIZE;// 文件数越过一定值时压缩文件最多包含文件个数 + public static final Integer COMMON_MAX_RETURN_CNT;// 回传文件数越过一定值时压缩用 + // -----------任务结果、主动告警等信息中各字段的分隔符 + public static final String COMMON_MSG_SEPRATOR = "$@$"; + public static final String COMMON_MSG_SEPRATOR_SPLIT = "\\$@\\$"; + public static final int COMMON_MSG_SUCCESS = 0; + public static final int COMMON_MSG_FAIL = 1; + // -----------设置文件编码方式 + public static final String charset; + + /** ========================告警状态常量========================== **/ + //用于报警: -1监测执行失败,0监测信息不正常,1监测信息正常,-2异常主动告警,2主动告警恢复正常) + public static final int DETECTION_STATUS_FAILURE = -1;//监测执行失败 + public static final int DETECTION_STATUS_ABNORMAL = 0;//监测信息不正常 + public static final int DETECTION_STATUS_NORMAL = 1;//监测信息正常 + //public static final int DETECTION_ALARM_ABNORMAL = -2;//告警检查:监测线程异常(未取到数据,相应的文件找不到,或者连续N次都超过设置的告警值) + //public static final int DETECTION_ALARM_NORMAL = 2;//告警检查:监测线程恢复正常 + + /** ========================任务部分文件后缀============================ **/ + public static final String TASK_RESULT_FILE_SUFFIX = ".result"; + public static final String TASK_RESULT_AGENTTMPFILE_SUFFIX = ".upgrade"; + public static final String TASK_RETURN_FILE_SUFFIX = ".return"; + + /** ========================Debug============================ **/ + public static final Integer DEBUG_INIT_TASK_FLAG; + public static final Integer DEBUG_PLUGIN_FLAG; + public static final Integer DEBUG_SYSDETECT_FLAG; + public static final Integer DEBUG_UPLOADDATA_FLAG; + public static final Integer DEBUG_ALARM_FLAG; + public static final Integer DEBUG_DELFILE_FLAG; + public static final Integer DEBUG_TASKRESULT_FLAG; + public static final Integer DEBUG_TASKRETURN_FLAG; + + //================= + public static final int max_times = 5;// 失败后重试次数 + public static final long max_delay_seconds = 30;// 重试间隔,秒 + public static final int noDataTimes = 4;// 未取到数据的次数,用于主动告警 + public static final int overAlarmValTimes = 4;// 连续超过预警值的次数,用于主动告警 + //--------------Agent唯一标志UUID + public static Long AGENT_HOST_UUID = null; + public static String AGENT_OPERATE_SYSTEM = null; + public static String AGENT_LOCAL_IP = null; + + public static final String DETEC_STATE_INFO_FORMATE_POINT = "$@$";//用于监测数据的状态信息web界面显示的格式化的连接符 + + public static Boolean ACTIIVE_ALARM_START = false;//默认不启动主动告警 + public static String AGENT_INTERFACE_NAME_KEY = null;//网络端口名称 + /** + * 监测数据主动上报 + */ + //监测数据主动上报 + public static final int DATA_SEND_THREAD_FLAG; + //主动数据上报 IP + public static final String DATA_SEND_THREAD_HOST; + //主动数据上报 PORT + public static final int DATA_SEND_THREAD_PORT; + //主动数据上报间隔 INTERVAL,单位 10 S + public static final int DATA_SEND_THREAD_INTERVAL; + + static{ + SYSTEM_PATH = SysConfig.getSystemDir(); + + // -------------------SSLSocket + SOCKET_SERVER_HOST = SysConfig.getStringVal(SOCKET_SERVER_HOST_KEY); + SOCKET_SERVER_PORT = SysConfig.getIntegerVal("server_port"); + SOCKET_AGENT_PORT = SysConfig.getIntegerVal("agent_port"); + SOCKET_TIMEOUT_MINUTES = SysConfig.getIntegerVal("socket.timeout.minutes", "30"); + SSL_KEY_STORE = formatPath(SysConfig.getStringVal("local.ssl.keys")); + SSL_TRUST_KEY_STORE = formatPath(SysConfig.getStringVal("local.ssl.trust")); + + keyPath = formatPath(SysConfig.getStringVal("local.ssl.path")); + + /*=======================文件相关参数========================*/ + // 可删范围 + String path = SysConfig.getStringVal("common.del.path.include"); + if(path!=null && !"".equals(path)){ + COMMON_DEL_PATH_INCLUDE = path.split(","); + for(int i=0; i<COMMON_DEL_PATH_INCLUDE.length; i++){ + COMMON_DEL_PATH_INCLUDE[i] = FileUtil.handlerPath(COMMON_DEL_PATH_INCLUDE[i]); + } + } + // 禁删范围 + path = SysConfig.getStringVal("common.del.path.exclude"); + if(path!=null && !"".equals(path)){ + COMMON_DEL_PATH_EXCLUDE = path.split(","); + for(int i=0; i<COMMON_DEL_PATH_EXCLUDE.length; i++){ + COMMON_DEL_PATH_EXCLUDE[i] = FileUtil.handlerPath(COMMON_DEL_PATH_EXCLUDE[i]); + } + } + // 文件总路径 + String localFilePath = SysConfig.getStringVal("local.data.path"); + // ---------------Local Path + LOCAL_SCRIPT_PATH = formatPath(SysConfig.getStringVal("local.script.path")); + localDetecConfSuffix = SysConfig.getStringVal("local.config.file.suffix"); + localAgentPidFile = formatPath(SysConfig.getStringVal("local.agent.pidfile")); + localDetecConfPath = localFilePath + File.separator + "nc_config"; + localPluginScriptPath = localFilePath + File.separator + "nc_detecScript"; + localDataCollection = localFilePath + File.separator + "nc_data"; + localDataFilePath = localDataCollection + File.separator + "incoming"; + localDataDonePath = localDataCollection + File.separator + "done"; + localDataErrorPath = localDataCollection + File.separator + "error"; + localBackupPath = localFilePath + File.separator + "nc_backup"; + localUploadsPath = localFilePath + File.separator + "nc_uploads"; + localTaskPath = localFilePath + File.separator + "nc_task"; + localTaskDonePath = localTaskPath + File.separator + "done";// 成功处理任务存放目录 + localTaskErrorPath = localTaskPath + File.separator + "error";// 成功处理任务存放目录 + localTaskResultPath = localTaskPath + File.separator + "incoming" + File.separator + "result";//任务结果存放目录 + localTaskReturnPath = localTaskPath + File.separator + "incoming" + File.separator + "return";//任务回传文件存放目录 + localLogsPath = formatPath(SysConfig.getLogPath()); + localTempPath = localFilePath + File.separator + "nc_temp"; + localTempDataIncomingPath = localDataCollection + File.separator + "temp"; + + // ---------------字符编码 + charset = SysConfig.getStringVal("charset"); + + // ---------------System Check Type + SYS_CHECK_TYPE_CPU = SysConfig.getStringVal("sys.check.type.cpu", "cpu"); + SYS_CHECK_TYPE_MEMORY = SysConfig.getStringVal("sys.check.type.memory", "memory"); + SYS_CHECK_TYPE_DISK = SysConfig.getStringVal("sys.check.type.disk", "disk"); + SYS_CHECK_TYPE_NET = SysConfig.getStringVal("sys.check.type.net", "net"); + SYS_CHECK_TYPE_SYSDATE = SysConfig.getStringVal("sys.check.type.systemdate", "systemdate"); + SYS_CHECK_TYPE_PROCESS = SysConfig.getStringVal("sys.check.type.process", "process"); + SYS_CHECK_TYPE_PROCESS_NMSAGENT = SysConfig.getStringVal("sys.check.type.process.nmsagent", "nmsclient"); + SYS_CHECK_TYPE_SYSTEMINFO = SysConfig.getStringVal("sys.check.type.systeminfo", "systeminfo"); + + // --------------Common Clear Gaps + COMMON_DEL_LOG_DAYS = SysConfig.getIntegerVal("common.del.log.days", "7"); + COMMON_DEL_DATA_HOURS = SysConfig.getIntegerVal("common.del.data.hours", "24"); + // 2013-5-20 添加功能 删除任务相关信息最小时间,不得少于一天 + if(COMMON_DEL_DATA_HOURS > 24){ + COMMON_DEL_TASK_HOURS = COMMON_DEL_DATA_HOURS; + }else{ + COMMON_DEL_TASK_HOURS = 24; + } + COMMON_DEL_UPGRADEFILE_DAYS = SysConfig.getIntegerVal("common.del.upgradefile.days", "30"); + COMMON_DEL_TEMP_DAYS = SysConfig.getIntegerVal("common.del.temp.days", "2"); + COMMON_UPLOAD_DATA_MINUTES = SysConfig.getIntegerVal("common.upload.data.minutes", "5"); + COMMON_TASK_CLEAR_HOURS = SysConfig.getIntegerVal("common.task.clear.hours", "2"); + + // -------------- ThreadPool + COMMON_THREAD_SOCKET_SIZE = SysConfig.getIntegerVal("common.thread.socket.size", "10"); + COMMON_THREAD_SCHEDULE_SIZE = SysConfig.getIntegerVal("common.thread.schedule.size", "15"); + // -------------- Compress + COMMON_ZIP_MIN_SIZE = SysConfig.getIntegerVal("common.zip.min.size", "1000"); + COMMON_ZIP_MAX_SIZE = SysConfig.getIntegerVal("common.zip.max.size", "2000"); + COMMON_MAX_RETURN_CNT = SysConfig.getIntegerVal("common.max.return.size", "10"); + // ----------------Debug + DEBUG_INIT_TASK_FLAG = SysConfig.getIntegerVal("debug.init.task.flag", "0"); + DEBUG_PLUGIN_FLAG = SysConfig.getIntegerVal("debug.plugin.flag", "0"); + DEBUG_SYSDETECT_FLAG = SysConfig.getIntegerVal("debug.sysdetect.flag", "0"); + DEBUG_UPLOADDATA_FLAG = SysConfig.getIntegerVal("debug.uploaddata.flag", "0"); + DEBUG_ALARM_FLAG = SysConfig.getIntegerVal("debug.alarm.flag", "0"); + DEBUG_DELFILE_FLAG = SysConfig.getIntegerVal("debug.delfile.flag", "0"); + DEBUG_TASKRESULT_FLAG = SysConfig.getIntegerVal("debug.taskresult.flag", "0"); + DEBUG_TASKRETURN_FLAG = SysConfig.getIntegerVal("debug.taskreturn.flag", "0"); + +// ACTIIVE_ALARM_START = SysConfig.getStringVal("active.alarm.start", "true");//是否启用主动告警,默认不启动主动告警---用于nc配置文件,现修改为从web控制 + + + //监测数据主动上报 + DATA_SEND_THREAD_FLAG = SysConfig.getIntegerVal("data.send.thread.flag", "0"); + //主动数据上报 IP + DATA_SEND_THREAD_HOST = SysConfig.getStringVal("data.send.thread.host", SOCKET_SERVER_HOST); + //主动数据上报 PORT + DATA_SEND_THREAD_PORT = SysConfig.getIntegerVal("data.send.thread.port", "9527"); + //主动数据上报间隔 INTERVAL,单位 10 S + DATA_SEND_THREAD_INTERVAL = SysConfig.getIntegerVal("data.send.thread.interval", "10"); + + + // 初始化创建文件夹 + if(!new File(localDetecConfPath).exists()){ + new File(localDetecConfPath).mkdirs(); + } + if(!new File(localPluginScriptPath).exists()) { + new File(localPluginScriptPath).mkdirs(); + } + if(!new File(localDataCollection).exists()){ + new File(localDataCollection).mkdirs(); + } + if(!new File(localBackupPath).exists()){ + new File(localBackupPath).mkdirs(); + } + if(!new File(localUploadsPath).exists()){ + new File(localUploadsPath).mkdirs(); + } + if(!new File(localTaskPath).exists()){ + new File(localTaskPath).mkdirs(); + } + if(!new File(localTempPath).exists()){ + new File(localTempPath).mkdirs(); + } + if(!new File(localTempDataIncomingPath).exists()){ + new File(localTempDataIncomingPath).mkdirs(); + } + } + + private static String formatPath(String path){ + String returnPath = path; + if(path!=null && !"".equals(path) && !new File(path).isAbsolute()){// 路径不为空且是相对路径 + returnPath = SYSTEM_PATH + File.separator + path; + } + return returnPath; + } + + public static boolean isSucessByResult(String msg){ + boolean flag = false; + if (!StringUtils.isEmpty(msg)) { + String[] result = msg.split(Contants.COMMON_MSG_SEPRATOR_SPLIT); + if (result != null && result.length > 0) { + if (Integer.parseInt(result[0])==Contants.COMMON_MSG_SUCCESS) { + flag = true; + } + } + } + return flag; + } + + public static String getDescByResult(String msg){ + String desc = null; + if (!StringUtils.isEmpty(msg)) { + String[] result = msg.split(Contants.COMMON_MSG_SEPRATOR_SPLIT); + if (result != null && result.length > 1) { + desc = result[1]; + } + } + return desc; + } +} diff --git a/src/com/nis/nmsclient/common/StopWatch.java b/src/com/nis/nmsclient/common/StopWatch.java new file mode 100644 index 0000000..f11655f --- /dev/null +++ b/src/com/nis/nmsclient/common/StopWatch.java @@ -0,0 +1,152 @@ +package com.nis.nmsclient.common; + +import java.util.LinkedHashMap; + +/** + * 秒表计时器 + * @author fang + * + */ +public class StopWatch { + private static final long SEC_MILL = 1000; + private static final long MIN_MILL = 60 * SEC_MILL; + private static final long HOUR_MILL = 60 * MIN_MILL; + private static final long DAY_MILL = 24 * HOUR_MILL; + private long start; + private long end; + private LinkedHashMap<String,Long> tagMap = new LinkedHashMap<String,Long>(); + + public StopWatch(){ + start(); + } + + public static StopWatch newStopWacth(){ + return new StopWatch(); + } + + /** + * 计时器开始 + * @return + */ + public long start(){ + this.start = System.currentTimeMillis(); + return start; + } + + /** + * 计时器结束 + * @return + */ + public long end(){ + this.end = System.currentTimeMillis(); + return end; + } + + + public long tag(String tag){ + long l = System.currentTimeMillis(); + this.tagMap.put(tag, l); + return l; + } + + /** + * 计算两个 tag 之间的时间差 + * @param b + * @param a + * @return + */ + public long between(String b,String a){ + Long l1 = this.tagMap.get(b); + Long l2 = this.tagMap.get(a); + if(l1 != null && l2 != null){ + return l1-l2; + } + return -1; + } + + public static String toString(long l){ + StringBuilder sb = new StringBuilder(); + if(l >= DAY_MILL){ + sb.append((l/DAY_MILL)); + sb.append( "天"); + l = l % DAY_MILL; + } + if(l >= HOUR_MILL){ + sb.append((l/HOUR_MILL)); + sb.append( "小时"); + l = l % HOUR_MILL; + } + if(l >= MIN_MILL){ + sb.append((l/MIN_MILL)); + sb.append( "分"); + l = l % MIN_MILL; + } + if(l >= SEC_MILL){ + sb.append((l/SEC_MILL)); + sb.append( "秒"); + l = l % SEC_MILL; + } + + sb.append((l)); + sb.append( "毫秒"); + + return sb.toString(); + } + + public String toString(){ + + return ""; + } + + /** + * 从开始到结束总耗时 + * @return + */ + public long total(){ + long temp = System.currentTimeMillis(); + if(this.end < this.start){ + this.end = temp; + } + return end - start; + } + + + public void reset(){ + this.tagMap.clear(); + this.start(); + } + + public long getStart() { + return start; + } + + public void setStart(long start) { + this.start = start; + } + + public long getEnd() { + return end; + } + + public void setEnd(long end) { + this.end = end; + } + + public LinkedHashMap<String, Long> getTag() { + return tagMap; + } + + public void LinkedHashMap(LinkedHashMap<String, Long> tag) { + this.tagMap = tag; + } + + public static void main(String[] args) { + long s = System.currentTimeMillis(); + long end = s +2*DAY_MILL+ 12 * MIN_MILL + 30*SEC_MILL + 388; + + String string = StopWatch.toString(end -s); + System.out.println(string); + + } + +} diff --git a/src/com/nis/nmsclient/common/SysConfig.java b/src/com/nis/nmsclient/common/SysConfig.java new file mode 100644 index 0000000..e22a35f --- /dev/null +++ b/src/com/nis/nmsclient/common/SysConfig.java @@ -0,0 +1,365 @@ +package com.nis.nmsclient.common; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import java.util.ResourceBundle; + +import javax.swing.JOptionPane; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + + +public class SysConfig { + static Logger logger = Logger.getLogger(SysConfig.class); + + /** ==============myconfig.properties文件获取参数=============== **/ + private static Properties myProperties; + private static String url = null; + static { + URL urlObj = SysConfig.class.getClassLoader().getResource("myconfig.properties"); + if(urlObj==null){ +// JOptionPane.showMessageDialog(null, "缺少配置文件,程序无法执行!\n请先执行参数配置程序进行配置", "错误", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, "i18n_client.Sysconfig.init_n81i", "i18n_client.Sysconfig.error_n81i", JOptionPane.ERROR_MESSAGE); + logger.error("NMSClient program termination: lack of configuration files, programs can not be executed! Please execute the configuration program for configuration first"); + System.exit(0); + }else{ + url = urlObj.getPath().replaceAll("%20", " "); + } + myProperties = new Properties(); + + FileInputStream fis = null; + try { + fis = new FileInputStream(url); + myProperties.load(fis); + } catch (IOException e) { + logger.error("Reading myconfig.properties file error", e); + }finally{ + try { + if(fis!= null)fis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // 升级时更新参数配置使用 + updateConfigFile(); + } + + /** + * 向资源配置文件host_uuid.properties中更新UUID键值 + */ + public static void setInterfaceNameValue(String value) { + try { + Properties properties = new Properties(); + if (uuidUrl != null && !"".equals(uuidUrl)) { + properties.load(new FileInputStream(uuidUrl)); + // 添加或更新键值对 + properties.setProperty(AGENT_INTERFACE_NAME_KEY, value); + // 保存到文件 + properties.store(new FileOutputStream(uuidUrl), ""); + } + properties.clear(); + + if(value != null && !"".equals(value)){ + Contants.AGENT_INTERFACE_NAME_KEY = value; + } + } catch (Exception e) { + logger.error("Setting the network port name eth* attribute error", e); + } + } + + + /** + * 根据相应的参数配置来更新配置并写入文件 + */ + private static void updateConfigFile(){ + FileInputStream fis = null; + BufferedReader reader = null; + BufferedWriter writer = null; + try { + ResourceBundle resource = ResourceBundle.getBundle(UpdateParams.class.getName()); + //判断是否更新properties + String updateFlag = myProperties.getProperty(UpdateParams.CONFIG_UPDATE_FLAG,"-1"); + if(updateFlag.equals(resource.getString(UpdateParams.CONFIG_UPDATE_FLAG))){ //配置文件已经更新,退出操作 + return; + } + + List<String> proList = new LinkedList<String>(); + + String encode = System.getProperty("file.encoding"); + logger.debug("----file.encoding----" + encode); + + //读取配置文件原有的参数到proList + fis = new FileInputStream(url); + reader = new BufferedReader(new InputStreamReader(fis,Charset.forName(encode))); + String str =null; + while((str = reader.readLine() )!=null){ + proList.add(str); + } + + //将UpdateParams中的值更新到proList和myProperties中 + Enumeration<String> en = resource.getKeys(); + while (en.hasMoreElements()) { + String elem = (String) en.nextElement(); + String value = resource.getString(elem); + boolean addFlag = true; + try { + for (int i = 0; i < proList.size(); i++) { + String strV = proList.get(i); + if (StringUtils.isEmpty(strV)) { + continue; + } + if(strV.split("=", 2)[0].trim().equals(elem)){ + if(elem.equalsIgnoreCase(UpdateParams.CONFIG_UPDATE_FLAG)){ + proList.set(i, elem + " = " + value);// 更新配置文件中某属性的值 + logger.info("参数更新:" + elem + " = " + (StringUtils.isBlank(value) ? "" : value)); + myProperties.put(elem, value); + } + addFlag = false; + break ; + } + } + + if(addFlag){ + proList.add(elem + " = " + value); + logger.info("参数新增:" + elem + " = " + (StringUtils.isBlank(value) ? "" : value)); + myProperties.put(elem, value); + } + } catch (Exception e) { + logger.error("Update the configuration file myconfig.properties parameter " + elem + "error", e); + } + } + + //将文件信息写入到文件中 + writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(url),Charset.forName(encode))); + Iterator<String> it = proList.iterator(); + while (it.hasNext()) { + String elem = (String) it.next(); + writer.write((elem==null?"":elem)+"\r\n"); + } + writer.flush(); + + } catch (Exception e) { + logger.error("Update configuration file myconfig.properties exception", e); + } finally{ + try { + if(reader!= null)reader.close(); + if(fis!= null)fis.close(); + if(writer!= null ){ + writer.close(); + writer = null; + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static void updateConfigFile(String key, String value){ + FileInputStream fis = null; + BufferedReader reader = null; + BufferedWriter writer = null; + try { + List<String> proList = new LinkedList<String>(); + + String encode = System.getProperty("file.encoding"); + logger.debug("----file.encoding----" + encode); + + //读取配置文件原有的参数到proList + fis = new FileInputStream(url); + reader = new BufferedReader(new InputStreamReader(fis,Charset.forName(encode))); + String str =null; + while((str = reader.readLine() )!=null){ + proList.add(str); + } + + //将值更新到proList中 + try { + for (int i = 0; i < proList.size(); i++) { + String strV = proList.get(i); + if (StringUtils.isEmpty(strV)) { + continue; + } + if(strV.split("=", 2)[0].trim().equals(key)){ + proList.set(i, key + " = " + value);// 更新配置文件中某属性的值 + logger.info("参数更新:" + key + " = " + (StringUtils.isBlank(value) ? "" : value)); + break ; + } + } + } catch (Exception e) { + logger.error("Update the configuration file myconfig.properties parameter " + key + "error", e); + } + + //将文件信息写入到文件中 + writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(url),Charset.forName(encode))); + Iterator<String> it = proList.iterator(); + while (it.hasNext()) { + String elem = (String) it.next(); + writer.write((elem==null?"":elem)+"\r\n"); + } + writer.flush(); + + } catch (Exception e) { + logger.error("Update configuration file myconfig.properties exception", e); + } finally{ + try { + if(reader!= null)reader.close(); + if(fis!= null)fis.close(); + if(writer!= null ){ + writer.close(); + writer = null; + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static String getStringVal(String key, String... defaultVal){ + String dStr = ""; + if(defaultVal!=null && defaultVal.length>=1 && defaultVal[0]!=null && defaultVal.length>0){ + dStr = defaultVal[0]; + } + return myProperties.getProperty(key,dStr).trim(); + } + + public static Integer getIntegerVal(String name, String... defaultVal){ + try { + String val = getStringVal(name, defaultVal); + return StringUtils.isEmpty(val)? null : Integer.parseInt(val); + } catch (Exception e) { + logger.error("Digital formatting error", e); + } + return null; + } + + public static String getSystemDir() { + return System.getProperty("user.dir"); + } + + public static String getLogPath(){ + FileInputStream fis = null; + try { + String log4jUrl = SysConfig.class.getClassLoader().getResource("log4j.properties").getPath().replaceAll("%20", " "); + fis = new FileInputStream(log4jUrl); + Properties log4jProperties = new Properties(); + log4jProperties.load(fis); + String logFile = log4jProperties.getProperty("log4j.appender.logfile.File"); + if(logFile!=null){ + return new File(logFile).getParent(); + } + } catch (IOException e) { + logger.error("Reading log4j.properties file error"+"",e); + }finally{ + try { + if(fis!= null)fis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return "../logs"; + } + + /** ==============host_uuid.properties文件获取参数=============== **/ + static final String AGENT_HOST_UUID_KEY = "agent_host_uuid"; + static final String AGENT_OPERATE_SYSTEM_KEY = "agent_operate_system"; + static final String AGENT_LOCAL_IP_KEY = "agent_local_ip"; + static String uuidUrl = null; + static final String AGENT_INTERFACE_NAME_KEY = "agent_interface_name"; + static { + String name = "host_uuid.properties"; + // 2014-11-13 jzz modify 由于将该配置文件放于系统安装目录中容易使节点混乱,故将其放于nmsdata指定目录 + /*URL urlObj = Contants.class.getClassLoader().getResource(name); + if(urlObj==null){ + uuidUrl = new File(url).getParent() + File.separator + name; + }else{ + uuidUrl = urlObj.getPath().replaceAll("%20", " "); + }*/ + String path = SysConfig.getStringVal("local.data.path") + File.separator + "nc_sysconf"; + File filePath = new File(path); + if(!filePath.exists()){ + filePath.mkdirs(); + } + + uuidUrl = path + File.separator + name; + + Properties properties = new Properties(); + try { + File file = new File(uuidUrl); + if(!file.exists()){ + file.createNewFile(); + } + properties.load(new FileInputStream(uuidUrl)); + String uuidStr = properties.getProperty(AGENT_HOST_UUID_KEY); + if(uuidStr != null && !"".equals(uuidStr.trim())){ + Contants.AGENT_HOST_UUID = Long.parseLong(uuidStr.trim()); + } + Contants.AGENT_OPERATE_SYSTEM = properties.getProperty(AGENT_OPERATE_SYSTEM_KEY); + Contants.AGENT_LOCAL_IP = properties.getProperty(AGENT_LOCAL_IP_KEY); + Contants.AGENT_INTERFACE_NAME_KEY = properties.getProperty(AGENT_INTERFACE_NAME_KEY); + } catch (IOException e) { + logger.error("Reading host_uuid.properties file error", e); + } + properties.clear(); + } + + /** + * 向资源配置文件host_uuid.properties中更新UUID键值 + */ + public static void setUUIDValue(String value) { + try { + Properties properties = new Properties(); + if (uuidUrl != null && !"".equals(uuidUrl)) { + properties.load(new FileInputStream(uuidUrl)); + // 添加或更新键值对 + properties.setProperty(AGENT_HOST_UUID_KEY, value); + // 保存到文件 + properties.store(new FileOutputStream(uuidUrl), ""); + } + properties.clear(); + + if(value != null && !"".equals(value)){ + Contants.AGENT_HOST_UUID = Long.parseLong(value); + } + } catch (Exception e) { + logger.error("Setting the UUID attribute error", e); + } + } + + /** + * 向资源配置文件host_uuid.properties中更新OperateSystem和LocalIP键值 + */ + public static void setUUIDValue(String sysTypeValue,String localIpValue) { + try { + Properties properties = new Properties(); + if (uuidUrl != null && !"".equals(uuidUrl)) { + properties.load(new FileInputStream(uuidUrl)); + // 添加或更新键值对 + properties.setProperty(AGENT_OPERATE_SYSTEM_KEY, sysTypeValue); + properties.setProperty(AGENT_LOCAL_IP_KEY, localIpValue); + // 保存到文件 + properties.store(new FileOutputStream(uuidUrl), ""); + } + properties.clear(); + Contants.AGENT_OPERATE_SYSTEM = sysTypeValue; + Contants.AGENT_LOCAL_IP = localIpValue; + } catch (Exception e) { + logger.error("Setting OperateSystemType and LocalIP attribute errors",e); + } + } +} diff --git a/src/com/nis/nmsclient/common/UpdateParams.java b/src/com/nis/nmsclient/common/UpdateParams.java new file mode 100644 index 0000000..b79b9fc --- /dev/null +++ b/src/com/nis/nmsclient/common/UpdateParams.java @@ -0,0 +1,18 @@ +package com.nis.nmsclient.common; + +public class UpdateParams extends java.util.ListResourceBundle { + public static String CONFIG_UPDATE_FLAG = "config.update.flag"; //更新标示 固定 判断配置文件指定值更新 建议自增1操作 + public static String CONFIG_UPDATE_FLAG_VALUE = "5"; //更新标示 该值 缺省值为0 每次修改都要 + static final String[][] contents = new String[][]{ + {CONFIG_UPDATE_FLAG,CONFIG_UPDATE_FLAG_VALUE}, //更新标示 固定 判断配置文件指定值更新 建议自增1操作 + {"socket.timeout.minutes", "30"}, // Socket通信超时时间设置 + {"common.zip.min.size", "1000"}, // 压缩文件最少包含文件个数 + {"common.zip.max.size", "2000"}, // 压缩文件最多包含文件个数 +// {"active.alarm.start","false"}, //是否启用NC的主动告警(只针对监测数据超过设置的值时的主动告警,避免异常信息重复):true:启用,false:停用-暂不使用,修改为web端控制nc是否报主动告警 + {"alarm.set.marker.separator","|"} //监测数据设置告警时,对于指定多个标识符(如多个盘符、多个CPU、多个网卡)的分隔符 + }; + + public Object[][] getContents() { + return contents; + } +} diff --git a/src/com/nis/nmsclient/common/VersionCfg.java b/src/com/nis/nmsclient/common/VersionCfg.java new file mode 100644 index 0000000..f48812c --- /dev/null +++ b/src/com/nis/nmsclient/common/VersionCfg.java @@ -0,0 +1,75 @@ +package com.nis.nmsclient.common; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +import org.apache.log4j.Logger; + +/** + * 获取和保存version信息的类 + * + */ +public class VersionCfg { + private static Logger logger = Logger.getLogger(VersionCfg.class); + public static final String NAGENT_VERSION = "NA_version"; + public static final String NSERVER_VERSION = "NS_version"; + + private static String url = null; + private static Properties properties; + + static { + url = VersionCfg.class.getClassLoader().getResource("version.properties").getPath().replaceAll("%20", " "); + + FileInputStream fis = null; + properties = new Properties(); + try { + fis = new FileInputStream(url); + properties.load(fis); + } catch (IOException e) { + logger.error("Reading version.properties file error", e); + }finally{ + try{ + if(fis!=null){ + fis.close(); + } + }catch (Exception e) {} + } + } + + /** + * 获取version值 + * + */ + public static String getValue(String key) { + return properties.getProperty(key); + } + + /** + * 向资源配置文件中添加或更新version键值对 + */ + public static void setValue(String key, String value) { + logger.debug("setVersion----->" + key + "=" + value); + // 添加或更新键值对 + properties.setProperty(key, value); + logger.debug("properties.getProperty(\"" + key + "\")----->" + value); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(url); + // 保存到文件 + if (url != null && !"".equals(url)) { + properties.store(fos, ""); + } + } catch (Exception e) { + logger.error(e); + } finally{ + try{ + if(fos!=null){ + fos.flush(); + fos.close(); + } + }catch (Exception e) {} + } + } +} diff --git a/src/com/nis/nmsclient/config/DetecConfOper.java b/src/com/nis/nmsclient/config/DetecConfOper.java new file mode 100644 index 0000000..a3fc65b --- /dev/null +++ b/src/com/nis/nmsclient/config/DetecConfOper.java @@ -0,0 +1,58 @@ +package com.nis.nmsclient.config; + +import java.io.File; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.model.SetInfo; + +public class DetecConfOper { + static Logger logger = Logger.getLogger(DetecConfOper.class); + + public static File getConfigFile(File dir, String fileName) { + File tmp = null; + if (dir.isDirectory()) { + for (File f : dir.listFiles()) { + if (!f.isDirectory()) { + if (f.getName().equals(fileName)) { + tmp = f; + break; + } + } + } + } + return tmp; + } + + public static String getFileName(String checkType, String processIden, + String suffix) { + String fileName = ""; + if (checkType != null && !"".equals(checkType)) { + fileName += checkType; + } + if (processIden != null && !"".equals(processIden)) { + fileName += "_" + processIden; + } + if (suffix != null && !"".equals(suffix)) { + fileName += suffix; + } + + return fileName; + } + + public static boolean isProcess(SetInfo setInfo){ + boolean flag = false; + if("1".equals(setInfo.getIsSchedule())){//非预设监测 + flag = true; + }else if(Contants.SYS_CHECK_TYPE_PROCESS.equalsIgnoreCase(setInfo.getCheckTypeName())){ + flag = true; + } + return flag; + } + + public static String getProcess(SetInfo setInfo){ + return setInfo.getProcessPath();// + File.separator + setInfo.getProcessFile(); + } + +} diff --git a/src/com/nis/nmsclient/config/DetecConfReqHandle.java b/src/com/nis/nmsclient/config/DetecConfReqHandle.java new file mode 100644 index 0000000..22ef967 --- /dev/null +++ b/src/com/nis/nmsclient/config/DetecConfReqHandle.java @@ -0,0 +1,297 @@ +package com.nis.nmsclient.config; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.model.AlarmInfo; +import com.nis.nmsclient.model.SetInfo; +import com.nis.nmsclient.thread.alarm.AlarmUtil; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.FileWrUtil; +import com.nis.nmsclient.util.ProcessUtil; +import com.nis.nmsclient.util.Utils; + +public class DetecConfReqHandle { + Logger logger = Logger.getLogger(DetecConfReqHandle.class); + + /** + * 初始化监测配置 + * 处理接收到监测配置信息:解析成自定义的对象 + * @param str JSONObject串 + */ + public void handlerConfigByInit(String str, List<SetInfo> setInfos, Map<Long, List<AlarmInfo>> alarmInfos) { + // -- 参数处理 + if (str == null || str.trim().length() <= 0) { + return; + } + if(setInfos==null || alarmInfos == null){ + return; + } + setInfos.clear(); + alarmInfos.clear(); + + // -- 初始化配置环境处理 + File file = new File(Contants.localDetecConfPath); + if (!file.exists()) {// 判断存放目录是否存在,不存创建 + file.mkdirs(); + } + File[] cfgFiles = file.listFiles(); + for (int i = 0; i < cfgFiles.length; i++) {//清空所有配置文件 + // 使用删除文件公共方法 + FileUtil.delDir(cfgFiles[i]); + logger.debug("handlerConfigByInit()--delete file=" + cfgFiles[i].getAbsolutePath()); + } + + // -- 监测配置解析 + JSONObject jsonObj = JSONObject.fromObject(str); + + List<SetInfo> setList = null; + if (str.toLowerCase().contains("setinfo")) { + JSONArray jsonArr = jsonObj.getJSONArray("setInfo"); + setList = handerSetInfo(jsonArr); + } + if (setList == null || setList.size() == 0) { + return; + } + Map<Long, List<AlarmInfo>> alarmMap = null; + if (str.toLowerCase().contains("alarminfo")) { + JSONArray jsonArr = jsonObj.getJSONArray("alarmInfo"); + alarmMap = handerAlarmInfo(jsonArr, setList); + } + // 20170413 zbc 缓存AlarmInfo信息(cfg文件中无报警单位字段) + if(alarmMap != null) { + Common.putAllDetecAlarmInfo(alarmMap); + } + + for (SetInfo setInfo : setList) { + if ("1".equals(setInfo.getCheckState()) + && "1".equals(setInfo.getCheckWay())) {// 有效,被动方式获取 + setInfos.add(setInfo); + Common.addOrUpdateAlarmPO(AlarmUtil.getAlarmPO(setInfo)); + } + } + if (alarmMap != null && alarmMap.size()>0) { + alarmInfos.putAll(alarmMap); + } + + if (str.toLowerCase().contains("showautoalarm")) { + Object obj = jsonObj.get("showAutoAlarm"); + if (obj != null) { + Contants.ACTIIVE_ALARM_START = (Boolean) obj; + } + } + } + + /** + * 更新监测配置:先解析成自定义的对象,再根据对象信息添加、更新、停用监测 + * 注:三方监测停用时Agent根据指定的PID杀掉进程 + * @param str JSONObject串 + */ + public void handlerConfigByUpdate(String str) { + if (str == null || str.trim().length() <= 0) { + return; + } + + File file = new File(Contants.localDetecConfPath); + if (!file.exists()) {// 判断存放目录是否存在,不存创建 + file.mkdirs(); + } + + JSONObject jsonObj = JSONObject.fromObject(str); + /*long flag = -1; + if (str.toLowerCase().contains("number")) { + flag = jsonObj.getLong("number"); + }*/ + List<SetInfo> setList = null; + if (str.toLowerCase().contains("setinfo")) { + JSONArray jsonArr = jsonObj.getJSONArray("setInfo"); + setList = handerSetInfo(jsonArr); + } + if (setList == null || setList.size() == 0) { + return; + } + Map<Long, List<AlarmInfo>> alarmMap = null; + if (str.toLowerCase().contains("alarminfo")) { + JSONArray jsonArr = jsonObj.getJSONArray("alarmInfo"); + alarmMap = handerAlarmInfo(jsonArr, setList); + } + + for (SetInfo setInfo : setList) { + if ("0".equals(setInfo.getCheckState()) + || "0".equals(setInfo.getCheckWay())) {// 将有效置为无效,或者将被动设为主动,停止线程 + Common.removeAlarmPO(setInfo.getId()); + if ("0".equals(setInfo.getIsSchedule())) { + Common.stopSysDetec(setInfo); + } else { + Common.stopPluginDetec(setInfo); + } + } else { + Common.addOrUpdateAlarmPO(AlarmUtil.getAlarmPO(setInfo)); + if ("0".equals(setInfo.getIsSchedule())) {// 如果是系统预设监测类型,则修改相应的监控线程 + List<AlarmInfo> alarmList = null; + if (alarmMap != null) { + alarmList = alarmMap.get(setInfo.getId()); + } + Common.addOrUpdateSysDetec(setInfo, alarmList); + } else { // 第三方监测 + // 缓存三方监测配置信息,用于合并临时结果文件 + Common.putPluginDetecSetInfo(setInfo.getId(), setInfo); + + if(!Common.COMMON_SYS_SETINFO.equals(setInfo.getIsSchedule())) { // 由Agent启动的第三方插件 + Common.startPluginDetec(setInfo); + } + } + } + }// for end + } + + /** + * 解析监测设置基本信息 + * 1、相应类型的监测数据目录不存在,创建,若是Linux并赋读写权限 + * 2、监测配置文件存在,先删除再重写,停用监测不再重写 + */ + private List<SetInfo> handerSetInfo(JSONArray jsonArr) { + // 文件路径 + List<SetInfo> setList = new ArrayList<SetInfo>(); + for (int i = 0; i < jsonArr.size(); i++) { + Object obj = JSONObject.toBean(JSONObject + .fromObject(jsonArr.get(i)), SetInfo.class); + if (obj == null) { + continue; + } + SetInfo setInfo = (SetInfo) obj; + // 创建建相应类型的数据文件夹 + File dataDir = new File(Contants.localDataFilePath + + File.separator + + DetecConfOper.getFileName(setInfo.getCheckTypeName(), + setInfo.getProcessIden(), null)); + if (!dataDir.exists()) { + dataDir.mkdirs(); + logger.debug("handerSetInfo()--create dataDir=" +dataDir.getAbsolutePath()); + } + // 文件名 + String fileName = DetecConfOper.getFileName( + setInfo.getCheckTypeName(), setInfo.getProcessIden(), + Contants.localDetecConfSuffix); + + // 判断文件是否存在,如果存在删除 + File cfgfile = new File(Contants.localDetecConfPath + File.separator + + fileName); + if (cfgfile.exists()){ + //cfgfile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(cfgfile); + logger.debug("handerSetInfo()--delete cfgfile=" + cfgfile.getAbsolutePath()); + //FileUtil.checkParentDirExist(cfgfile); + } + + if ("1".equals(setInfo.getCheckState()) + && "1".equals(setInfo.getCheckWay())) {//有效且被动方式获取的写入配置文件 + String dataDirStr = null; + try {// 为了去除路径中的"." 和 ".." + dataDirStr = dataDir.getCanonicalPath(); + } catch (IOException e) { + dataDirStr = dataDir.getAbsolutePath(); + } + try { + FileWrUtil.cfgFilePrinter(cfgfile, Contants.charset, + setInfo.getValArr(Contants.AGENT_HOST_UUID, dataDirStr)); + logger.debug("handerSetInfo()--write cfgfile=" + cfgfile.getAbsolutePath()); + } catch (Exception e) { + logger.error("Write the document“" + cfgfile.getAbsolutePath() + "”error: " + Utils.printExceptionStack(e)); + continue; + } + } + setList.add(setInfo); + + }// for end + //修改数据目录的权限 + ProcessUtil.permit(777, new File(Contants.localDataFilePath)); + + return setList; + } + + /** + * 解析监测设置的告警信息 + * 1、将同一监测的所有告警信息整理放到一个列表 + * 2、根据监测设置类型和设置名称找配置文件,找到了将告警信息追加到配置文件 + * 3、只要有监测设置,不管有没有设置告警信息,都要将相应字段追加到配置文件,只是无告警信息时,配置字段为空 + */ + private Map<Long, List<AlarmInfo>> handerAlarmInfo(JSONArray jsonArr, List<SetInfo> setList) { + if(setList==null || setList.size()==0){ + logger.info("无监测设置信息,无需处理报警设置"); + return null; + } + File dir = new File(Contants.localDetecConfPath); + if (!dir.exists()) {// 判断存放目录是否存在, 不存在返回 + logger.error("Please check whether the alarm settings information is consistent with the monitoring settings information!"); + return null; + } + Map<Long, List<AlarmInfo>> alarmMap = new HashMap<Long, List<AlarmInfo>>(); + if(jsonArr!=null){ + for (int i = 0; i < jsonArr.size(); i++) { + Object obj = JSONObject.toBean(JSONObject + .fromObject(jsonArr.get(i)), AlarmInfo.class); + if (obj != null) { + AlarmInfo alarmInfo = (AlarmInfo) obj; + if (alarmMap.containsKey(alarmInfo.getSetInfoId())) {// 如果报警信息中已经存在相应类型的报警则追加 + List<AlarmInfo> aList = alarmMap.get(alarmInfo.getSetInfoId()); + aList.add(alarmInfo); + alarmMap.put(alarmInfo.getSetInfoId(), aList); + } else { + List<AlarmInfo> aList = new ArrayList<AlarmInfo>(); + aList.add(alarmInfo); + alarmMap.put(alarmInfo.getSetInfoId(), aList); + } + } + } + } + Map<Long, List<AlarmInfo>> alarmMapNew = new HashMap<Long, List<AlarmInfo>>(); + // 依次查看监测设置信息,不管有没有设置告警信息,都要写配置police=,若无告警信息,配置字段值为空 + for(SetInfo setInfo : setList){ + Long key = setInfo.getId(); + List<AlarmInfo> alarmList = alarmMap.get(key); + // 配置信息保存对应的文件名 + String fileName = DetecConfOper.getFileName( + setInfo.getCheckTypeName(), setInfo.getProcessIden(), + Contants.localDetecConfSuffix); + File f = DetecConfOper.getConfigFile(dir, fileName); + {// 追加报警设置到相应的监测配置文件 + if (f != null && f.exists()) + try { + FileWrUtil.cfgFileAppender(f, + Contants.charset, new String[]{getAlarmArr(alarmList)}); + if(alarmList!=null){// 只有成功保存了文件并且设置为告警信息的,才返回给上一方法 + alarmMapNew.put(key, alarmList); + } + } catch (Exception e) { + logger.error("Write the document“" + f.getAbsolutePath() + "”error: " + Utils.printExceptionStack(e)); + } + } + } + return alarmMapNew; + } + + private static String getAlarmArr(List<AlarmInfo> alarmList) { + StringBuffer sb = new StringBuffer(); + sb.append("police="); + if (alarmList != null && alarmList.size() > 0) { + for (AlarmInfo alarmInfo : alarmList) { + sb.append(alarmInfo.toStringVal() + ","); + } + sb.delete(sb.toString().length() - 1, sb.toString().length()); + } + return sb.toString(); + } +} diff --git a/src/com/nis/nmsclient/model/AlarmInfo.java b/src/com/nis/nmsclient/model/AlarmInfo.java new file mode 100644 index 0000000..58d85e6 --- /dev/null +++ b/src/com/nis/nmsclient/model/AlarmInfo.java @@ -0,0 +1,184 @@ +package com.nis.nmsclient.model; + +/** + * 监测信息报警相关信息实体 + * + */ +public class AlarmInfo { + /** + * 告警设置id + */ + private Long id; + /** + * 监测设置id + */ + private Long setInfoId; + /** + * 监测类型 + */ + private String checkType; + /** + * 进程设置名称 + */ + private String processIden; + /** + * 字段Id + */ + private Long metadataId; + /** + * 字段描述 + */ + private String filedCommonts; + /** + * 字段序号 + */ + private Integer showNum; + /** + * 报警状态 + */ + private String policeState; + /** + * 报警值 + */ + private String policeValue; + /** + * 报警单位 + */ + private String policeUnit; + /** + * 报警比较符:针对number型数据>、<、>=、<=、= 针对字符串类型数据equal、 include、exclude + */ + private String policeSysmbols; + /** + * 报警等级 + */ + private Integer policeLevel; + /** + * 设置告警时,指定多个标识符(如多个盘符、多个CPU、多个网卡),如硬盘使用率,空:所有盘存在一个盘使用率超过告警值,则告警;all:所有盘总的使用率超过告警值,则告警;指定多个盘符:指定盘存在一个盘使用率超过告警值,则告警 + */ + private String marker; + /** + * 标识符对应字段在metadata表中的id + */ + private Integer markerFiledId;; + /** + * 标识符对应字段在metadata表中的showNum + */ + private Integer markerFiledShowNum; + + + public Long getSetInfoId() { + return setInfoId; + } + public void setSetInfoId(Long setInfoId) { + this.setInfoId = setInfoId; + } + public Long getMetadataId() { + return metadataId; + } + public void setMetadataId(Long metadataId) { + this.metadataId = metadataId; + } + public Integer getShowNum() { + return showNum; + } + public void setShowNum(Integer showNum) { + this.showNum = showNum; + } + public String getPoliceState() { + return policeState; + } + public void setPoliceState(String policeState) { + this.policeState = policeState; + } + public String getPoliceUnit() { + return policeUnit; + } + public void setPoliceUnit(String policeUnit) { + this.policeUnit = policeUnit; + } + public String getPoliceSysmbols() { + return policeSysmbols; + } + public void setPoliceSysmbols(String policeSysmbols) { + this.policeSysmbols = policeSysmbols; + } + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public Integer getPoliceLevel() { + return policeLevel; + } + public void setPoliceLevel(Integer policeLevel) { + this.policeLevel = policeLevel; + } + public String getCheckType() { + return checkType; + } + public void setCheckType(String checkType) { + this.checkType = checkType; + } + public String getProcessIden() { + return processIden; + } + public void setProcessIden(String processIden) { + this.processIden = processIden; + } + public String getFiledCommonts() { + return filedCommonts; + } + public void setFiledCommonts(String filedCommonts) { + this.filedCommonts = filedCommonts; + } + public String getPoliceValue() { + return policeValue; + } + public void setPoliceValue(String policeValue) { + this.policeValue = policeValue; + } + + public String toString() { + return "showNum=" + showNum + ",policeSysmbols=" + policeSysmbols + + ",policeValue=" + policeValue + ",policeLevel=" + policeLevel; + } + + public String toStringVal(){ + return showNum + "|" + policeSysmbols + "|" + policeValue + "|" + + policeLevel + "|" + filedCommonts; + } + + public String getMarker() + { + return marker; + } + + public void setMarker(String marker) + { + this.marker = marker; + } + + public Integer getMarkerFiledId() + { + return markerFiledId; + } + + public void setMarkerFiledId(Integer markerFiledId) + { + this.markerFiledId = markerFiledId; + } + + public Integer getMarkerFiledShowNum() + { + return markerFiledShowNum; + } + + public void setMarkerFiledShowNum(Integer markerFiledShowNum) + { + this.markerFiledShowNum = markerFiledShowNum; + } + +} diff --git a/src/com/nis/nmsclient/model/CommandPO.java b/src/com/nis/nmsclient/model/CommandPO.java new file mode 100644 index 0000000..0644924 --- /dev/null +++ b/src/com/nis/nmsclient/model/CommandPO.java @@ -0,0 +1,86 @@ +package com.nis.nmsclient.model; + +public class CommandPO { + /** + * ID + */ + private Long execId; + /** + * 类型:4 命令执行,6 升级 + */ + private long execType; + /** + * 升级文件存放目录 + */ + private String srcPath; + /** + * 命令名称 + */ + private String commandName; + /** + * 命令参数 + */ + private String commandParam; + /** + * 执行状态:4下发任务(40 下发成功,41下发失败),5杀进程(50成功,51失败)、6备份、7更新(覆盖) 、8启动进程 + */ + private long execState; + /** + * 恢复版本 + */ + private Long execVersion; + /** + * 是否周期任务 + */ + private long isLoop; + + public Long getExecId() { + return execId; + } + public void setExecId(Long execId) { + this.execId = execId; + } + public long getExecType() { + return execType; + } + public void setExecType(long execType) { + this.execType = execType; + } + public String getSrcPath() { + return srcPath; + } + public void setSrcPath(String srcPath) { + this.srcPath = srcPath; + } + public String getCommandName() { + return commandName; + } + public void setCommandName(String commandName) { + this.commandName = commandName; + } + public String getCommandParam() { + return commandParam; + } + public void setCommandParam(String commandParam) { + this.commandParam = commandParam; + } + public long getExecState() { + return execState; + } + public void setExecState(long execState) { + this.execState = execState; + } + public Long getExecVersion() { + return execVersion; + } + public void setExecVersion(Long execVersion) { + this.execVersion = execVersion; + } + public long getIsLoop() { + return isLoop; + } + public void setIsLoop(long isLoop) { + this.isLoop = isLoop; + } + +} diff --git a/src/com/nis/nmsclient/model/ParamBackup.java b/src/com/nis/nmsclient/model/ParamBackup.java new file mode 100644 index 0000000..5deac2a --- /dev/null +++ b/src/com/nis/nmsclient/model/ParamBackup.java @@ -0,0 +1,52 @@ +package com.nis.nmsclient.model; + +/** + * 备份命令的参数实体类 + * @date Mar 23, 2012 + * @author zhenzhen + * @version + */ +public class ParamBackup{ + /** + * 需要备份的文件或目录 + */ + private String backup = null; + /** + * 备份文件到的目的路径 + */ + private String backupTo = null; + /** + * 排除的文件或目录,即不需要备份的,如果是相对路径,则相对需要备份的文件或目录 + */ + private String[] except = null; + /** + * 备份压缩包时:Y 按绝对路径压缩,N 按进入备份目录压缩(这个属性只针对Linux有效,Windows下只按进入备份目录压缩) + */ + private String isAbs = null; + + public String getBackup() { + return backup; + } + public void setBackup(String backup) { + this.backup = backup; + } + public String getBackupTo() { + return backupTo; + } + public void setBackupTo(String backupTo) { + this.backupTo = backupTo; + } + public String[] getExcept() { + return except; + } + public void setExcept(String[] except) { + this.except = except; + } + public String getIsAbs() { + return isAbs; + } + public void setIsAbs(String isAbs) { + this.isAbs = isAbs; + } + +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/model/ParamCmdExec.java b/src/com/nis/nmsclient/model/ParamCmdExec.java new file mode 100644 index 0000000..c66b6a5 --- /dev/null +++ b/src/com/nis/nmsclient/model/ParamCmdExec.java @@ -0,0 +1,111 @@ +package com.nis.nmsclient.model; + +/** + * 命令执行(启动命令)的参数实体类 + * @date Mar 23, 2012 + * @author zhenzhen + * @version + */ +public class ParamCmdExec { + /** + * 执行文件或命令 + */ + private String execCmd; + /** + * 执行文件或命令的参数序列 + */ + private String[] execParams; + /** + * 该命令是否强制执行:Y是,N否 + */ + private String forceExec; + /** + * 常驻内存标识: Y是,N否 + */ + private String residentFlag; + /** + * 存放执行结果标识的文件:1、常驻内存的,写入PID,2、非常驻的,写执行结果:结果标识(0 成功 1 失败)|结果描述 + */ + private String execResult; + /** + * 回传标识: Y是,N否 + */ + private String returnFlag; + /** + * 回传文件或目录路径 + */ + private String returnPath; + /** + * 最终结果获取最大等待时间(单位:秒) + */ + private String maxWaitTime; + /** + * 执行文件或命令的用户名(只针对Linux有效) + */ + private String username; + /** + * 执行用户的密码(只针对Linux有效) + */ + private String param1; + + public String getExecCmd() { + return execCmd; + } + public void setExecCmd(String execCmd) { + this.execCmd = execCmd; + } + public String getForceExec() { + return forceExec; + } + public void setForceExec(String forceExec) { + this.forceExec = forceExec; + } + public String getResidentFlag() { + return residentFlag; + } + public void setResidentFlag(String residentFlag) { + this.residentFlag = residentFlag; + } + public String getExecResult() { + return execResult; + } + public void setExecResult(String execResult) { + this.execResult = execResult; + } + public String getReturnFlag() { + return returnFlag; + } + public void setReturnFlag(String returnFlag) { + this.returnFlag = returnFlag; + } + public String getReturnPath() { + return returnPath; + } + public void setReturnPath(String returnPath) { + this.returnPath = returnPath; + } + public String getMaxWaitTime() { + return maxWaitTime; + } + public void setMaxWaitTime(String maxWaitTime) { + this.maxWaitTime = maxWaitTime; + } + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String[] getExecParams() { + return execParams; + } + public void setExecParams(String[] execParams) { + this.execParams = execParams; + } + public String getParam1() { + return param1; + } + public void setParam1(String param1) { + this.param1 = param1; + } +} diff --git a/src/com/nis/nmsclient/model/ParamCoverUpdate.java b/src/com/nis/nmsclient/model/ParamCoverUpdate.java new file mode 100644 index 0000000..3d731d4 --- /dev/null +++ b/src/com/nis/nmsclient/model/ParamCoverUpdate.java @@ -0,0 +1,62 @@ +package com.nis.nmsclient.model; + +/** + * 覆盖更新的参数实体类 + * @date Mar 23, 2012 + * @author zhenzhen + * @version + */ +public class ParamCoverUpdate{ + /** + * 指定更新需要的文件 + */ + private String source = null; + /** + * 指定文件覆盖目录 + */ + private String cover = null; + /** + * 是否创建覆盖目录 + */ + private String isCreateCover = null; + /** + * 删除的文件或目录,如果是相对路径,则相对需要更新的目录 + */ + private String[] delete = null; + /** + * 如果更新源文件是个压缩包:Y 按绝对路径解压即在根目录下解压,N 按进入备份目录解压(这个属性只针对Linux有效,Windows下只按进入备份目录解压) + */ + private String isAbs = null; + + public String getSource() { + return source; + } + public void setSource(String source) { + this.source = source; + } + public String getCover() { + return cover; + } + public void setCover(String cover) { + this.cover = cover; + } + public String getIsCreateCover() { + return isCreateCover; + } + public void setIsCreateCover(String isCreateCover) { + this.isCreateCover = isCreateCover; + } + public String[] getDelete() { + return delete; + } + public void setDelete(String[] delete) { + this.delete = delete; + } + public String getIsAbs() { + return isAbs; + } + public void setIsAbs(String isAbs) { + this.isAbs = isAbs; + } + +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/model/ParamFilePush.java b/src/com/nis/nmsclient/model/ParamFilePush.java new file mode 100644 index 0000000..e775e22 --- /dev/null +++ b/src/com/nis/nmsclient/model/ParamFilePush.java @@ -0,0 +1,81 @@ +package com.nis.nmsclient.model; + +/** + * 文件推送的参数实体类 + * @date Mar 23, 2012 + * @author zhenzhen + * @version + */ +public class ParamFilePush { + /** + * 推送文件名 + */ + private String fileName; + /** + * 推送目的地 + */ + private String destPath; + /** + * 是否覆盖:Y是,N否 + */ + private String isCover; + /** + * 推送文件的属主(只针对Linux有效) + */ + private String username; + /** + * 属主密码(只针对Linux有效) + */ + private String param1; + /** + * 推送文件的属组(只针对Linux有效) + */ + private String groupName; + /** + * 推送文件拥有的权限(只针对Linux有效) + */ + private String permisson; + + public String getFileName() { + return fileName; + } + public void setFileName(String fileName) { + this.fileName = fileName; + } + public String getDestPath() { + return destPath; + } + public void setDestPath(String destPath) { + this.destPath = destPath; + } + public String getIsCover() { + return isCover; + } + public void setIsCover(String isCover) { + this.isCover = isCover; + } + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String getGroupName() { + return groupName; + } + public void setGroupName(String groupName) { + this.groupName = groupName; + } + public String getPermisson() { + return permisson; + } + public void setPermisson(String permisson) { + this.permisson = permisson; + } + public String getParam1() { + return param1; + } + public void setParam1(String param1) { + this.param1 = param1; + } +} diff --git a/src/com/nis/nmsclient/model/ParamUpgrade.java b/src/com/nis/nmsclient/model/ParamUpgrade.java new file mode 100644 index 0000000..891bbf1 --- /dev/null +++ b/src/com/nis/nmsclient/model/ParamUpgrade.java @@ -0,0 +1,174 @@ +package com.nis.nmsclient.model; + + +/** + * 升级命令的参数实体类 + * @date Mar 23, 2012 + * @author zhenzhen + * @version + */ +public class ParamUpgrade { + /** + * 指定更新需要的文件,如果是相对路径,则相对推送目的地 + */ + private String fileName = null; + /** + * 指定文件覆盖目录 + */ + private String cover = null; + /** + * 是否创建覆盖目录 + */ + private String isCreateCover = null; + /** + * 如果更新源文件是个压缩包:Y 按绝对路径解压即在根目录下解压,N 按进入备份目录解压(这个属性只针对Linux有效,Windows下只按进入备份目录解压) + */ + private String isAbs = null; + /** + * 需要删除的目录,如果是相对路径,则相对覆盖目录 + */ + private String [] delete = null; + /** + * 该命令是否强制执行:Y是,N否 + */ + private String forceExec; + /** + * 文件的属主或运行的用户(只针对Linux有效) + */ + private String username; + /** + * 用户密码(只针对Linux有效) + */ + private String param1; + /** + * 文件的属组(只针对Linux有效) + */ + private String groupName; + /** + * 权限设置 + */ + private String permisson = null; + //以上是升级用到的参数属性,以下是升级和恢复都有的参数属性 + /** + * 备份目录,如果是相对路径,则相对覆盖目录 + */ + private ParamBackup [] backups = null; + /** + * 恢复目录,逆向任务时使用 + */ + private ParamCoverUpdate[] recoverys; + /** + * 进程PID文件全路径 + */ + private String pidFile = null; + /** + * 进程启动文件全路径 + */ + private String startupFile = null; + /** + * 执行文件的参数序列 + */ + private String[] execParams; + /** + * 最终结果获取最大等待时间(单位:秒) + */ + private String maxWaitTime; + + public String getFileName() { + return fileName; + } + public void setFileName(String fileName) { + this.fileName = fileName; + } + public String getCover() { + return cover; + } + public void setCover(String cover) { + this.cover = cover; + } + public ParamBackup[] getBackups() { + return backups; + } + public void setBackups(ParamBackup[] backups) { + this.backups = backups; + } + public String getPidFile() { + return pidFile; + } + public void setPidFile(String pidFile) { + this.pidFile = pidFile; + } + public String getStartupFile() { + return startupFile; + } + public void setStartupFile(String startupFile) { + this.startupFile = startupFile; + } + public String[] getDelete() { + return delete; + } + public void setDelete(String[] delete) { + this.delete = delete; + } + public String getIsCreateCover() { + return isCreateCover; + } + public void setIsCreateCover(String isCreateCover) { + this.isCreateCover = isCreateCover; + } + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String getPermisson() { + return permisson; + } + public void setPermisson(String permisson) { + this.permisson = permisson; + } + public String getGroupName() { + return groupName; + } + public void setGroupName(String groupName) { + this.groupName = groupName; + } + public String getIsAbs() { + return isAbs; + } + public void setIsAbs(String isAbs) { + this.isAbs = isAbs; + } + public String getForceExec() { + return forceExec; + } + public void setForceExec(String forceExec) { + this.forceExec = forceExec; + } + public String getMaxWaitTime() { + return maxWaitTime; + } + public void setMaxWaitTime(String maxWaitTime) { + this.maxWaitTime = maxWaitTime; + } + public void setExecParams(String[] execParams) { + this.execParams = execParams; + } + public String[] getExecParams() { + return execParams; + } + public ParamCoverUpdate[] getRecoverys() { + return recoverys; + } + public void setRecoverys(ParamCoverUpdate[] recoverys) { + this.recoverys = recoverys; + } + public String getParam1() { + return param1; + } + public void setParam1(String param1) { + this.param1 = param1; + } + +} diff --git a/src/com/nis/nmsclient/model/ReturnFilePO.java b/src/com/nis/nmsclient/model/ReturnFilePO.java new file mode 100644 index 0000000..e781f42 --- /dev/null +++ b/src/com/nis/nmsclient/model/ReturnFilePO.java @@ -0,0 +1,106 @@ +package com.nis.nmsclient.model; + +import java.util.Date; + +public class ReturnFilePO { + /** + * ID + */ + private Long taskId; + /** + * 类型:4 命令执行,6 升级 + */ + private long taskType; + /** + * 唯一标志一台物理机(类似于IP) + */ + private long uuid; + /** + * 回传路径集: key 文件实际路径 value 文件别名 + */ +// private Map<String, String> filePathMap; + /** + * 当前要回传的文件 + */ +// private File curRetrunFile; + /** + * 回传文件名(统一处理后一个任务只有一个回传文件) + */ + private String returnFileName; + /** + * 回传状态:0 成功,1 失败 + */ + private long state; + /** + * 开始时间 + */ + private Date startTime; + /** + * 结束时间 + */ + private Date endTime; + /** + * 是否循环任务 + */ + private long isLoop; + /** + * 回传文件的结果描述 + */ + private String resDesc; + + public Long getTaskId() { + return taskId; + } + public void setTaskId(Long taskId) { + this.taskId = taskId; + } + public long getTaskType() { + return taskType; + } + public void setTaskType(long taskType) { + this.taskType = taskType; + } + public long getState() { + return state; + } + public void setState(long state) { + this.state = state; + } + public Date getStartTime() { + return startTime; + } + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + public Date getEndTime() { + return endTime; + } + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + public long getIsLoop() { + return isLoop; + } + public void setIsLoop(long isLoop) { + this.isLoop = isLoop; + } + public String getResDesc() { + return resDesc; + } + public void setResDesc(String resDesc) { + this.resDesc = resDesc; + } + public String getReturnFileName() { + return returnFileName; + } + public void setReturnFileName(String returnFileName) { + this.returnFileName = returnFileName; + } + public long getUuid() { + return uuid; + } + public void setUuid(long uuid) { + this.uuid = uuid; + } + +} diff --git a/src/com/nis/nmsclient/model/SetInfo.java b/src/com/nis/nmsclient/model/SetInfo.java new file mode 100644 index 0000000..c0e1338 --- /dev/null +++ b/src/com/nis/nmsclient/model/SetInfo.java @@ -0,0 +1,272 @@ +package com.nis.nmsclient.model; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.builder.ReflectionToStringBuilder; + +import com.nis.nmsclient.common.Contants; + +/** + * 客户端用到的监测设置信息实体 + * + */ +public class SetInfo { + /** + * 监测设置信息ID + */ + private Long id; + /** + * 检测类型 + */ + private String checkTypeName;//如:CPU、DISK等 + /** + * 检测类型的ID,预留 + */ + private Long checkTypeId; + /** + * 最大测试次数 + */ + private Long checkMaxTimes; + /** + * 时间间隔(单位:分钟) + */ + private Long checkGap; + /** + * 超时时间(单位:秒) + */ + private Long checkOutTime; + /** + * 监测状态:0无效;1有效 + */ + private String checkState; + /** + * 监测方式:0主动(DC执行),1被动(NC执行) + */ + private String checkWay; + /** + * 设置标志 + */ + private String processIden; + /** + * 进程PID存放文件 + */ + private String processFile; + /** + * 进程执行文件 + */ + private String processPath; + /** + * 是否系统启动(NMSAgent启动/第三方自己启动);默认0自启动;1NMSAgent启动 + */ + private String IsControlStart; + /** + * 控制启动时间 + */ + private Long controlStartTime; + /** + *上传数据时间间隔单位分钟:不能为空,默认15分钟。监测数据上传到NMSServer周期。 + */ + private Long uploadGap; + + /** + * 计划检测时间:针对当前配置信息首次执行时间 + */ + private Long planCheckTime; + /** + * 是否预置监测,0是,1否 + */ + private String isSchedule; + /** + * 进程搜索关键字 + */ + private String processSearchKeyCode; + + // ====== 以下信息仅供DC端使用,这里添加是为了不出现WARN信息 + private String nodeGroupsId; + private String nodeIpsId; + private Long viewLevel; + private String nodeIp2; + private Long isSNMP; + + // ======= 保存最后合并的临时结果文件的检测时间(仅用于NC) + private Long lastMergeDetecTime; + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public String getCheckTypeName() { + return checkTypeName; + } + public void setCheckTypeName(String checkTypeName) { + this.checkTypeName = checkTypeName; + } + public Long getCheckTypeId() { + return checkTypeId; + } + public Long getCheckMaxTimes() { + return checkMaxTimes; + } + public void setCheckMaxTimes(Long checkMaxTimes) { + this.checkMaxTimes = checkMaxTimes; + } + public Long getCheckGap() { + return checkGap; + } + public void setCheckGap(Long checkGap) { + this.checkGap = checkGap; + } + public Long getCheckOutTime() { + return checkOutTime; + } + public void setCheckOutTime(Long checkOutTime) { + this.checkOutTime = checkOutTime; + } + public String getCheckState() { + return checkState; + } + public void setCheckState(String checkState) { + this.checkState = checkState; + } + public String getProcessIden() { + return processIden; + } + public void setProcessIden(String processIden) { + this.processIden = processIden; + } + public String getProcessFile() { + return processFile; + } + public void setProcessFile(String processFile) { + this.processFile = processFile; + } + public String getProcessPath() { + return processPath; + } + public void setProcessPath(String processPath) { + this.processPath = processPath; + } + public void setCheckTypeId(Long checkTypeId) { + this.checkTypeId = checkTypeId; + } + public String getCheckWay() { + return checkWay; + } + public void setCheckWay(String checkWay) { + this.checkWay = checkWay; + } + + public String[] getValArr(Long uuid, String dataFileDir) { + List<String> list = new ArrayList<String>(); + list.add("pubInfo=" + uuid + "," + id + "," + checkTypeName + "," + processIden); + list.add("checkState=" + checkState); + //list.add("checkWay=" + checkWay); + //list.add("isControlStart=" + IsControlStart); + //list.add("controlStartTime=" + controlStartTime); + list.add("checkGap=" + checkGap); + list.add("checkOutTime=" + checkOutTime); + list.add("checkMaxTimes=" + checkMaxTimes); + //list.add("processFile=" + processFile); + //list.add("processPath=" + processPath); + list.add("planCheckTime=" + planCheckTime); + list.add("uploadGap=" + uploadGap); + list.add("dataFileDir=" + dataFileDir); + + try { + if("1".equals(isSchedule)) { // 第三方监测 + File dataDir = new File(dataFileDir); + File tempDataDir = new File(Contants.localTempDataIncomingPath, dataDir.getName()); + list.add("tempDataFileDir=" + tempDataDir.getCanonicalPath()); + } + } catch (IOException e) { + e.printStackTrace(); + } + + String[] val = new String[list.size()]; + return list.toArray(val); + } + public String getIsControlStart() { + return IsControlStart; + } + public void setIsControlStart(String isControlStart) { + IsControlStart = isControlStart; + } + public Long getUploadGap() { + return uploadGap; + } + public void setUploadGap(Long uploadGap) { + this.uploadGap = uploadGap; + } + public String getIsSchedule() { + return isSchedule; + } + public void setIsSchedule(String isSchedule) { + this.isSchedule = isSchedule; + } + public Long getControlStartTime() { + return controlStartTime; + } + public void setControlStartTime(Long controlStartTime) { + this.controlStartTime = controlStartTime; + } + public Long getPlanCheckTime() { + return planCheckTime; + } + public void setPlanCheckTime(Long planCheckTime) { + this.planCheckTime = planCheckTime; + } + public String getProcessSearchKeyCode() { + return processSearchKeyCode; + } + public void setProcessSearchKeyCode(String processSearchKeyCode) { + this.processSearchKeyCode = processSearchKeyCode; + } + public String getNodeGroupsId() { + return nodeGroupsId; + } + public void setNodeGroupsId(String nodeGroupsId) { + this.nodeGroupsId = nodeGroupsId; + } + public String getNodeIpsId() { + return nodeIpsId; + } + public void setNodeIpsId(String nodeIpsId) { + this.nodeIpsId = nodeIpsId; + } + public Long getViewLevel() { + return viewLevel; + } + public void setViewLevel(Long viewLevel) { + this.viewLevel = viewLevel; + } + public String getNodeIp2() { + return nodeIp2; + } + public void setNodeIp2(String nodeIp2) { + this.nodeIp2 = nodeIp2; + } + public Long getIsSNMP() { + return isSNMP; + } + public void setIsSNMP(Long isSNMP) { + this.isSNMP = isSNMP; + } + public void setLastMergeDetecTime(Long lastMergeDetecTime) { + this.lastMergeDetecTime = lastMergeDetecTime; + } + public Long getLastMergeDetecTime() { + return lastMergeDetecTime; + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } + + +} diff --git a/src/com/nis/nmsclient/model/Task1.java b/src/com/nis/nmsclient/model/Task1.java new file mode 100644 index 0000000..32950fb --- /dev/null +++ b/src/com/nis/nmsclient/model/Task1.java @@ -0,0 +1,49 @@ +package com.nis.nmsclient.model; + +/** + * 任务实体类:1 文件推送 + * + */ +public class Task1 { + /** + * 任务ID + */ + private Long taskId; + /** + * 任务类型:1 文件推送,2 非流文本数据获取,3 流文本数据获取,4 命令执行,5 shell注册 + */ + private long taskType; + /** + * 推送文件参数设置 + */ + private String taskParam; + /** + * 重新执行,原任务ID + */ + private Long oldTaskId; + + public Long getTaskId() { + return taskId; + } + public void setTaskId(Long taskId) { + this.taskId = taskId; + } + public long getTaskType() { + return taskType; + } + public void setTaskType(long taskType) { + this.taskType = taskType; + } + public String getTaskParam() { + return taskParam; + } + public void setTaskParam(String taskParam) { + this.taskParam = taskParam; + } + public Long getOldTaskId() { + return oldTaskId; + } + public void setOldTaskId(Long oldTaskId) { + this.oldTaskId = oldTaskId; + } +} diff --git a/src/com/nis/nmsclient/model/Task4.java b/src/com/nis/nmsclient/model/Task4.java new file mode 100644 index 0000000..302252c --- /dev/null +++ b/src/com/nis/nmsclient/model/Task4.java @@ -0,0 +1,166 @@ +package com.nis.nmsclient.model; + + +/** + * 任务实体类:4 命令执行 + * + */ +public class Task4 { + /** + * 任务ID + */ + private Long taskId; + /** + * 任务类型:1 文件推送,2 非流文本数据获取,3 流文本数据获取,4 命令执行,5 shell注册 + */ + private long taskType; + /** + * 命令类型:1 Agent原生支持命令,2 脚本,3 shell命令 + */ + private long commandType; + /** + * 命令名称 + */ + private String commandName; + /** + * 命令参数 + */ + private String commandParam; + /** + * 脚本路径(已无用) + */ + private String scriptPath; + /** + * 执行状态:4下发任务(40 下发成功,41下发失败),5杀进程(50成功,51失败)、6备份、7更新(覆盖) 、8启动进程 + */ + private long state; + /** + * 执行时间 + */ + private Long startTime; + /** + * 结束时间 + */ + private Long endTime; + /** + * 是否循环任务: 0 非周期, 1 周期,默认是0 + */ + private long isLoop; + /** + * 如果是循环任务,循环周期 + */ + private long loopDelay; + /** + * 任务状态:6撤销执行 + */ + private Long missionState; + /** + * 重新执行,原任务ID + */ + private Long oldTaskId; + + public Long getTaskId() { + return taskId; + } + + public void setTaskId(Long taskId) { + this.taskId = taskId; + } + + public long getTaskType() { + return taskType; + } + + public void setTaskType(long taskType) { + this.taskType = taskType; + } + + public long getCommandType() { + return commandType; + } + + public void setCommandType(long commandType) { + this.commandType = commandType; + } + + public long getState() { + return state; + } + + public void setState(long state) { + this.state = state; + } + + public String getCommandName() { + return commandName; + } + + public void setCommandName(String commandName) { + this.commandName = commandName; + } + + public String getCommandParam() { + return commandParam; + } + + public void setCommandParam(String commandParam) { + this.commandParam = commandParam; + } + + public String getScriptPath() { + return scriptPath; + } + + public void setScriptPath(String scriptPath) { + this.scriptPath = scriptPath; + } + + public Long getStartTime() { + return startTime; + } + + public void setStartTime(Long startTime) { + this.startTime = startTime; + } + + public Long getEndTime() { + return endTime; + } + + public void setEndTime(Long endTime) { + this.endTime = endTime; + } + + public long getIsLoop() { + return isLoop; + } + + public void setIsLoop(long isLoop) { + this.isLoop = isLoop; + } + + public long getLoopDelay() { + return loopDelay; + } + + public void setLoopDelay(long loopDelay) { + this.loopDelay = loopDelay; + } + + public Long getMissionState() { + return missionState; + } + + public void setMissionState(Long missionState) { + this.missionState = missionState; + } + + public Long getOldTaskId() { + return oldTaskId; + } + + public void setOldTaskId(Long oldTaskId) { + this.oldTaskId = oldTaskId; + } + +} diff --git a/src/com/nis/nmsclient/model/Task6.java b/src/com/nis/nmsclient/model/Task6.java new file mode 100644 index 0000000..06ddec7 --- /dev/null +++ b/src/com/nis/nmsclient/model/Task6.java @@ -0,0 +1,121 @@ +package com.nis.nmsclient.model; + + +/** + * 任务实体类:6 升级 + * + */ +public class Task6 { + /** + * 任务ID + */ + private Long taskId; + /** + * 任务类型:1 文件推送,4 命令执行,5 shell注册,6 升级 + */ + private long taskType; + /** + * 命令类型:4 Agent原生支持命令 + */ + private long commandType; + /** + * 命令名称 + */ + private String commandName; + /** + * 命令参数 + */ + private String commandParam; + /** + * 执行状态:4下发任务(40 下发成功,41下发失败),5杀进程(50成功,51失败)、6备份、7更新(覆盖) 、8启动进程 + */ + private Long state; + /** + * 如果是恢复(逆向任务),则为恢复到的版本(恢复到的任务ID)。判断它是否为空,来确定是否逆向任务 + */ + private Long version; + /** + * 升级时间 + */ + private Long upgradeTime; + /** + * 全局权限用户名(未来) + */ + private String username; + /** + * 全局权限密码(未来 约定加密方式) + */ + private String userpwd; + /** + * 重新执行,原任务ID + */ + private Long oldTaskId; + + public Long getTaskId() { + return taskId; + } + public void setTaskId(Long taskId) { + this.taskId = taskId; + } + public long getTaskType() { + return taskType; + } + public void setTaskType(long taskType) { + this.taskType = taskType; + } + public long getCommandType() { + return commandType; + } + public void setCommandType(long commandType) { + this.commandType = commandType; + } + public String getCommandName() { + return commandName; + } + public void setCommandName(String commandName) { + this.commandName = commandName; + } + public String getCommandParam() { + return commandParam; + } + public void setCommandParam(String commandParam) { + this.commandParam = commandParam; + } + public Long getState() { + return state; + } + public void setState(Long state) { + this.state = state; + } + public Long getVersion() { + return version; + } + public void setVersion(Long version) { + this.version = version; + } + public Long getUpgradeTime() { + return upgradeTime; + } + public void setUpgradeTime(Long upgradeTime) { + this.upgradeTime = upgradeTime; + } + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String getUserpwd() { + return userpwd; + } + public void setUserpwd(String userpwd) { + this.userpwd = userpwd; + } + public Long getOldTaskId() { + return oldTaskId; + } + public void setOldTaskId(Long oldTaskId) { + this.oldTaskId = oldTaskId; + } + +} diff --git a/src/com/nis/nmsclient/thread/WritePidThread.java b/src/com/nis/nmsclient/thread/WritePidThread.java new file mode 100644 index 0000000..8126978 --- /dev/null +++ b/src/com/nis/nmsclient/thread/WritePidThread.java @@ -0,0 +1,66 @@ +package com.nis.nmsclient.thread; + + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.management.ManagementFactory; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import com.nis.nmsclient.common.Contants; + +public class WritePidThread implements Runnable{ + + @Override + public void run() { + String SYSTEM_PATH = System.getProperty("user.dir"); +// Thread.currentThread().setName("写PID线程"); + Thread.currentThread().setName("Write The PID Thread"); + Logger logger = Logger.getLogger(WritePidThread.class); + + /* 获取程序运行PID */ + String path = Contants.localAgentPidFile;//2015-11-25:之前一直写的是"NMSClientPid.temp",不对配置的是agentPid.temp + String name = ManagementFactory.getRuntimeMXBean().getName(); + logger.info("当前程序PID:>"+(name.split("@")[0])); + + /* 判断系统类型是否写文件 */ + String os = System.getProperty("os.name"); + if(os!=null && !os.toLowerCase().startsWith("windows")){ + logger.info("非Windows系统 结束执行"); + return ; + } + /* 获取输出文件并检查文件路径是否存在 */ + File file = new File(path); + if(!file.getParentFile().exists()){ + file.getParentFile().mkdirs(); + } + + /* 将PID写入文件 */ + FileWriter writer = null; + try { + writer = new FileWriter(file); + writer.write(name.split("@")[0]); + writer.flush(); + logger.info("写PID完成"); + } catch (IOException e) { + logger.error("Write PID failure", e); + }finally{ + try { + if(writer!=null) + writer.close(); + writer = null; + } catch (IOException e) { + logger.error("", e); + } + logger.info("线程关闭"); + } + } + public static void main(String [] args) { + new Thread(new WritePidThread()).start(); + } + public static void pl (Object obj) { + System.out.println(obj==null?null:obj.toString()); + } + +} diff --git a/src/com/nis/nmsclient/thread/alarm/AlarmPO.java b/src/com/nis/nmsclient/thread/alarm/AlarmPO.java new file mode 100644 index 0000000..e1495ed --- /dev/null +++ b/src/com/nis/nmsclient/thread/alarm/AlarmPO.java @@ -0,0 +1,146 @@ +package com.nis.nmsclient.thread.alarm; + + +public class AlarmPO { + /** + * 监测ID + */ + private long id; + /** + * 监测类型 + */ + private String type; + /** + * 监测设置名称 + */ + private String procIden; + /** + * 时间间隔(单位:分钟) + */ + private long checkGap; + /** + * 是否是进程 + */ + private boolean isproc; + /** + * 进程路径与名称 + */ + private String proc; + /** + * PID文件 + */ + private String pidFileStr; + /** + * 进程搜索关键字 + */ + private String processSearchKeyCode; + /** + * 控制启动时间 + */ + private Long controlStartTime; + /** + * 是否系统启动(NMSAgent启动/第三方自己启动);默认0自启动;1NMSAgent启动 + */ + private String IsControlStart; + + public AlarmPO() { + super(); + } + + public AlarmPO(long id, String type, String procIden, long checkGap, + boolean isproc, String proc, String pidFileStr, + Long controlStartTime, String processSearchKeyCode, String IsControlStart) { + super(); + this.id = id; + this.type = type; + this.procIden = procIden; + this.checkGap = checkGap; + this.isproc = isproc; + this.proc = proc; + this.pidFileStr = pidFileStr; + this.controlStartTime = controlStartTime; + this.processSearchKeyCode = processSearchKeyCode; + this.IsControlStart = IsControlStart; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getProcIden() { + return procIden; + } + + public void setProcIden(String procIden) { + this.procIden = procIden; + } + + public long getCheckGap() { + return checkGap; + } + + public void setCheckGap(long checkGap) { + this.checkGap = checkGap; + } + + public boolean isIsproc() { + return isproc; + } + + public void setIsproc(boolean isproc) { + this.isproc = isproc; + } + + public String getProc() { + return proc; + } + + public void setProc(String proc) { + this.proc = proc; + } + + public String getPidFileStr() { + return pidFileStr; + } + + public void setPidFileStr(String pidFileStr) { + this.pidFileStr = pidFileStr; + } + + public Long getControlStartTime() { + return controlStartTime; + } + + public void setControlStartTime(Long controlStartTime) { + this.controlStartTime = controlStartTime; + } + + public String getProcessSearchKeyCode() { + return processSearchKeyCode; + } + + public void setProcessSearchKeyCode(String processSearchKeyCode) { + this.processSearchKeyCode = processSearchKeyCode; + } + + public String getIsControlStart() { + return IsControlStart; + } + + public void setIsControlStart(String isControlStart) { + IsControlStart = isControlStart; + } + +} diff --git a/src/com/nis/nmsclient/thread/alarm/AlarmThread.java b/src/com/nis/nmsclient/thread/alarm/AlarmThread.java new file mode 100644 index 0000000..41d989a --- /dev/null +++ b/src/com/nis/nmsclient/thread/alarm/AlarmThread.java @@ -0,0 +1,315 @@ +package com.nis.nmsclient.thread.alarm; + +import java.io.File; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.config.DetecConfOper; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.ProcessUtil; +import com.nis.nmsclient.util.Utils; + +/** + * 主动报警线程:针对当前所有有效监测设置进行主动报警 + * 定时监测某设置是否正常生成数据,N次未取到数据后向Server报警,恢复正常后向Server发送提示信息 + * @date Mar 22, 2012 + * @author zhenzhen + * @version + */ +public class AlarmThread implements Runnable{ + Logger logger = Logger.getLogger(AlarmThread.class); + private String name; + + private Map<Long, AlarmStateMsg> alarmSmMap = new HashMap<Long, AlarmStateMsg>(); + + public AlarmThread(String name) { + super(); + this.name = name; + } + + public void run() { + Thread.currentThread().setName(name); + + logger.debug("主动预警检查开始 ~~~~~~~"); + try{ + Map<Long, AlarmPO> alarmPOs = new HashMap<Long, AlarmPO>(Common + .getAlarmPOs()); + // 清除垃圾数据 + if (alarmSmMap.size() > alarmPOs.size()) { + Iterator<Long> it = alarmSmMap.keySet().iterator(); + while (it.hasNext()) { + Long key = it.next(); + if(!alarmPOs.containsKey(key)){ + //alarmSmMap.remove(key); + it.remove();//update by jinsj for 2013-07-08 java.util.ConcurrentModificationException + } + } + + } + Set<Map.Entry<Long, AlarmPO>> entrys = alarmPOs.entrySet(); + int alarmCnt = 0; + StringBuffer alarmDescInfo = new StringBuffer(); + for (Map.Entry<Long, AlarmPO> entry : entrys) { + // 如果监测进程未启动,则不进行告警检查 + if (entry.getValue().getControlStartTime() != null + && entry.getValue().getControlStartTime() > System + .currentTimeMillis()) { + continue; + } + // 对各监测设置告警状态信息进行赋初值 + Long key = entry.getValue().getId(); + if (alarmSmMap.get(key) == null) { + alarmSmMap.put(key, new AlarmStateMsg(new Date(), 0, + new StringBuffer(), false)); + }else if(alarmSmMap.get(key).getAlarmMsg().length() == 0){ + alarmSmMap.get(key).setStart(new Date()); + } + + boolean flag = alarm(entry.getValue()); + if(flag){ + alarmCnt += 1; + alarmDescInfo.append("\tsetId: " + key + " >> " + entry.getValue().getType() + "_" + entry.getValue().getProcIden()); + alarmDescInfo.append("\n"); + } + } + logger.info("本次预警轮循检查监测设置总数:" + alarmPOs.size() + ",正常:" + + (alarmPOs.size() - alarmCnt) + ",不正常:" + alarmCnt); + if(alarmCnt>0){ + logger.info("本次预警检查不正常的监测如下:\n" + alarmDescInfo.toString()); + } + }catch (Exception e) { + logger.error("Active early warning thread exception:" + Utils.printExceptionStack(e)); + } + logger.debug("主动预警检查结束 ~~~~~~~"); + } + + /** + * 针对一个监测设置的主动预警具体逻辑实现 + * @param alarm + * @return true 告警监测不正常 false 监测正常 + * @throws Exception + */ + public boolean alarm(AlarmPO alarm) throws Exception{ + Long key = alarm.getId(); + String sonDirName = DetecConfOper.getFileName(alarm.getType(), alarm.getProcIden(), null); + StringBuffer sbMsg = new StringBuffer(); + /** + * 1、检查是否存在数据: alarmLevel 0 -- 数据存在,非0 -- 数据不存在 + */ + int alarmLevel = checkDataIsExist(sonDirName, alarm.getCheckGap(), sbMsg); + + /** + * 2、判断进程是否存在:是进程且数据不存在才判断,不是进程如系统类型CPU,则不进行这些操作 + */ + if(alarmLevel!=0 && alarm.isIsproc()){ + if("2".equals(alarm.getIsControlStart())) { // NC周期启动(脚本间断性执行且执行时间较短,通过判断Java定时任务确认进程) + if(Common.containPluginDetecFuture(key)){ // 进程存在 + String temp = sbMsg.toString(); + sbMsg.delete(0, sbMsg.length()); +// sbMsg.append("进程存在,但" + temp); + sbMsg.append("i18n_client.AlarmThread.processExists_n81i" + temp); + alarmLevel = 2; + } else { // 进程不存在 + sbMsg.delete(0, sbMsg.length()); +// sbMsg.append("定时任务“" + alarm.getType() + "”不存在"); + sbMsg.append("i18n_client.AlarmThread.loopMission1_n81i“" + alarm.getType() + "”i18n_client.AlarmThread.loopMission2_n81i"); + alarmLevel = 1; + } + } else { + Object[] objArr = ProcessUtil.checkPidAndGetPid(alarm.getPidFileStr(), alarm.getProcessSearchKeyCode()); + int isExistFlag = Integer.parseInt(objArr[0].toString()); + String pidInfo = objArr[1].toString(); + + if(isExistFlag==0){// 进程不存在(包括PID文件不存在,PID值不存在,搜索关键字也找不到进程) + sbMsg.delete(0, sbMsg.length()); + sbMsg.append(pidInfo); + alarmLevel = 1; + } else {// 进程存在(一个进程或多个进程) + String temp = sbMsg.toString(); + sbMsg.delete(0, sbMsg.length()); +// sbMsg.append("进程存在,但" + temp); + sbMsg.append("i18n_client.AlarmThread.processExists_n81i" + temp); + alarmLevel = 2; + } + } + } + + /** + * 3、统计并发送报警信息 + */ + AlarmStateMsg asMsg= alarmSmMap.get(key); + int times = asMsg.getTimes(); + boolean flag = true; + if (sbMsg.length()>0 && sbMsg.toString().equals(asMsg.getAlarmMsg().toString())) { + times ++ ; + + if (times == Contants.noDataTimes) {// Contants.noDataTime次未取到数据,报警 + AlarmUtil.sendAlarmMsg(alarm, asMsg.getStart(), new Date(), + alarmLevel, Contants.DETECTION_STATUS_ABNORMAL, asMsg + .getAlarmMsg().toString() +// + ",此状态持续了" + times + "次"); + + ",i18n_client.AlarmThread.state_n81i" + times + "i18n_client.AlarmThread.times_n81i"); + asMsg.setAlarmState(true); + } + } else if (sbMsg.length() > 0 + && !sbMsg.toString().equals(asMsg.getAlarmMsg().toString())) { + asMsg.getAlarmMsg().delete(0, asMsg.getAlarmMsg().length()); + asMsg.getAlarmMsg().append(sbMsg.toString()); + times = 1; + } else { + asMsg.getAlarmMsg().delete(0, asMsg.getAlarmMsg().length()); + times = 0; + if(asMsg.isAlarmState()){ + /*AlarmUtil.sendAlarmMsg(alarm, asMsg.getStart(), new Date(), + 99, Contants.DETECTION_STATUS_NORMAL, "恢复正常");*/ + asMsg.setAlarmState(false); + } + flag = false; + } + asMsg.setTimes(times); + alarmSmMap.put(key, asMsg); + + return flag; + } + + /** + * 检查是否存在数据 + * @param sonDirName + * @param checkGap + * @return + */ + private int checkDataIsExist(String sonDirName, long checkGap, StringBuffer sbMsg){ + int alarmLevel = 0; + // ------- 1、先查看当前正在写入的数据文件夹 + File curDir = new File(Contants.localDataFilePath + File.separator + sonDirName); + if(!curDir.exists()){ +// sbMsg.append("数据文件目录“" + curDir.getAbsolutePath() + "”不存在"); + sbMsg.append("i18n_client.AlarmThread.dataFileNotExists1_n81i“" + curDir.getAbsolutePath() + "”i18n_client.AlarmThread.dataFileNotExists2_n81i"); + alarmLevel = 1; + return alarmLevel; + } + long timeMillis = System.currentTimeMillis() - Contants.noDataTimes * checkGap * 60 * 1000; + File[] rightFiles = FileUtil.getFilesAfterMillis(curDir, timeMillis); + if(rightFiles!=null && rightFiles.length>0){// 找到数据,正常 + alarmLevel = 0; + return alarmLevel; + } + + // -------- 2、如果当前正在写入的数据文件夹没有找到符合条件的数据,则查找上传成功后备份到的相应目录 + // 2013-3-28 修改内容:原本只检查当天日期目录是否存在数据,针对监测时间间隔超过一天的存在问题,所以当间隔时间大于等于一天时,改为检查当天日期之前的目录 + String dateDirName = DateUtil.getCurrentDate(DateUtil.YYYYMMDD); + File doneDir = new File(Contants.localDataDonePath + File.separator + sonDirName); + if(doneDir.exists()){ + if(checkGap >= 1440){// --- 检查当天日期及之前的目录 + // 找到指定的日期目录及之前的日期目录,将其降序排列,是为了最先查找当天日期 + File[] dateDirs = FileUtil.sortDescByFileName(FileUtil.getDirsBeforeDateName(doneDir, dateDirName)); + // 在找到的日期目录下检查文件是否存在 + for(File dateDir : dateDirs){ + rightFiles = FileUtil.getFilesAfterMillis(dateDir, timeMillis); + if(rightFiles!=null && rightFiles.length>0){// 在任一目录找到则不再继续查找其他目录 + break; + } + } + }else {// --- 只检查当天日期 + File dateDir = new File(doneDir.getAbsolutePath() + File.separator + dateDirName); + if(dateDir.exists()){ + rightFiles = FileUtil.getFilesAfterMillis(dateDir, timeMillis); + } + } + } + if(rightFiles!=null && rightFiles.length>0){// 找到数据,正常 + alarmLevel = 0; + return alarmLevel; + } + + // -------- 3、查找不完整数据即0大小文件备份到的相应目录 + File[] errorFiles = null; + File errorDir = new File(Contants.localDataErrorPath + File.separator + sonDirName); + if(errorDir.exists()){ + if(checkGap >= 1440){// --- 检查当天日期及之前的目录 + // 找到指定的日期目录及之前的日期目录,将其降序排列,是为了最先查找当天日期 + File[] dateDirs = FileUtil.sortDescByFileName(FileUtil.getDirsBeforeDateName(errorDir, dateDirName)); + // 在找到的日期目录下检查文件是否存在 + for(File dateDir : dateDirs){ + errorFiles = FileUtil.getFilesAfterMillis(dateDir, timeMillis); + if(errorFiles!=null && errorFiles.length>0){// 在任一目录找到则不再继续查找其他目录 + break; + } + } + }else {// --- 只检查当天日期 + File dateDir = new File(doneDir.getAbsolutePath() + File.separator + dateDirName); + if(dateDir.exists()){ + errorFiles = FileUtil.getFilesAfterMillis(errorDir, timeMillis); + } + } + + } + if(errorFiles!=null && errorFiles.length>0){ +// sbMsg.append("监测数据文件大小为0"); + sbMsg.append("i18n_client.AlarmThread.dataSize_n81i"); + alarmLevel = 1; + }else{ +// sbMsg.append("未取到监测数据"); + sbMsg.append("i18n_client.AlarmThread.noDetecateData_n81i"); + alarmLevel = 1; + } + + return alarmLevel; + } + + /** + * 告警检查过程中针对每个监测设置的过程变量状态的封装类 + * @date Mar 22, 2012 + * @author zhenzhen + * @version + */ + class AlarmStateMsg { + private Date start;//告警检查不正常情况的开始时间 + private Integer times;//连续告警次数 + private StringBuffer alarmMsg;//告警信息 + private boolean alarmState;//是否向Server发送了主动告警请求 + + public AlarmStateMsg(Date start, Integer times, StringBuffer alarmMsg, + boolean alarmState) { + super(); + this.start = start; + this.times = times; + this.alarmMsg = alarmMsg; + this.alarmState = alarmState; + } + + public Date getStart() { + return start; + } + public void setStart(Date start) { + this.start = start; + } + public Integer getTimes() { + return times; + } + public void setTimes(Integer times) { + this.times = times; + } + public StringBuffer getAlarmMsg() { + return alarmMsg; + } + public void setAlarmMsg(StringBuffer alarmMsg) { + this.alarmMsg = alarmMsg; + } + public boolean isAlarmState() { + return alarmState; + } + public void setAlarmState(boolean alarmState) { + this.alarmState = alarmState; + } + } + +} diff --git a/src/com/nis/nmsclient/thread/alarm/AlarmUtil.java b/src/com/nis/nmsclient/thread/alarm/AlarmUtil.java new file mode 100644 index 0000000..1c0a76f --- /dev/null +++ b/src/com/nis/nmsclient/thread/alarm/AlarmUtil.java @@ -0,0 +1,79 @@ +package com.nis.nmsclient.thread.alarm; + +import java.util.Date; +import java.util.concurrent.Future; +import org.apache.log4j.Logger; +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.config.DetecConfOper; +import com.nis.nmsclient.model.SetInfo; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.thread.socket.SSLClient; +import com.nis.nmsclient.util.Utils; + +public class AlarmUtil { + static Logger logger = Logger.getLogger(AlarmUtil.class); + + public static void sendAlarmMsg(AlarmPO alarm, Date start, + Date end, int alarmLevel, int state, String alarmMsg,String... showNum) { + sendAlarmMsg(alarm.getId(), alarm.getType(), alarm + .getProcIden(), start, end, alarmLevel, state, alarmMsg,showNum); + } + + public static void sendAlarmMsg(Long alarmId, String checkType, + String procIden, Date start, Date end, int alarmLevel, int state, + String alarmMsg,String... showNum) { + String seprator = Contants.COMMON_MSG_SEPRATOR; + String showAlarmNum=""; + if (showNum!=null && showNum.length>0) + { + showAlarmNum = showNum[0]; + } + String msg = alarmId + seprator + Contants.AGENT_HOST_UUID + seprator + + checkType + seprator + procIden + seprator + start.getTime() + + seprator + end.getTime() + seprator + alarmLevel + seprator + + state + seprator + alarmMsg+ seprator + showAlarmNum; + + Common.service.submit(new SSLClient(Thread.currentThread() + .getName(), CommonSocket.REQ_ALARM, msg)); + + logger.warn("Active alarm level" + alarmLevel + " >> setId: " + alarmId + + "," + checkType + "_" + procIden + ",state: " + state + " > " + + alarmMsg+ ",showNum: " +showAlarmNum); + } + + public static AlarmPO getAlarmPO(SetInfo setInfo){ + AlarmPO alarmPO = new AlarmPO(setInfo.getId(), setInfo + .getCheckTypeName(), setInfo.getProcessIden(), setInfo + .getCheckGap(), DetecConfOper.isProcess(setInfo), DetecConfOper + .getProcess(setInfo), setInfo.getProcessFile(), setInfo + .getControlStartTime(), setInfo.getProcessSearchKeyCode(), + setInfo.getIsControlStart()); + + return alarmPO; + } + + // 向DC发送NC端的异常信息 + public static void sendNMSErrorMsg(ErrorCode errorCode, String errorIp, String errorDesc) { + String seprator = Contants.COMMON_MSG_SEPRATOR; + try { + //异常信息顺序:CODE、发送IP、发生错误IP、发生错误时间、处理状态(1)、错误描述 + String msg = errorCode.toString() + seprator + Utils.getLocalIp() + seprator + errorIp + + seprator + System.currentTimeMillis() + seprator + "1" + + seprator + errorDesc; + + Future<?> future = Common.service.submit(new SSLClient(Thread.currentThread() + .getName(), CommonSocket.REQ_ERROR_INFO, msg)); + + if(errorCode.equals(ErrorCode.ProtListenerError)){ + future.get(); + } + + logger.error("Abnormal information " + errorCode + " >> errorIp: " + errorIp + " > " + + errorDesc); + } catch (Exception e) { + logger.error(e); + } + + } +} diff --git a/src/com/nis/nmsclient/thread/alarm/ErrorCode.java b/src/com/nis/nmsclient/thread/alarm/ErrorCode.java new file mode 100644 index 0000000..0f62cb9 --- /dev/null +++ b/src/com/nis/nmsclient/thread/alarm/ErrorCode.java @@ -0,0 +1,11 @@ +package com.nis.nmsclient.thread.alarm; + +public enum ErrorCode { + ProcessNotExist, //进程不存在 + MultipleProcessExist,//多个进程存在 + ThreadRuntimeError, //执行异常 + HandShakeError, //通讯握手失败 + ProtListenerError, //端口监听失败 + DeamonNotExist, //守护进程不存在 + SocketError//通讯失败 +} diff --git a/src/com/nis/nmsclient/thread/plugin/StartPluginRun.java b/src/com/nis/nmsclient/thread/plugin/StartPluginRun.java new file mode 100644 index 0000000..43ed9bc --- /dev/null +++ b/src/com/nis/nmsclient/thread/plugin/StartPluginRun.java @@ -0,0 +1,191 @@ +package com.nis.nmsclient.thread.plugin; + +import java.util.Date; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.config.DetecConfOper; +import com.nis.nmsclient.model.SetInfo; +import com.nis.nmsclient.thread.alarm.AlarmUtil; +import com.nis.nmsclient.util.ProcessUtil; +import com.nis.systeminfo.thread.NewPluginResultMerge; + +public class StartPluginRun implements Runnable { + static Logger logger = Logger.getLogger(StartPluginRun.class); + private String name; + private SetInfo setInfo; + + public StartPluginRun(SetInfo setInfo, String name) { + this.name = name; + this.setInfo = setInfo; + } + + public void run() { + Thread.currentThread().setName(name); + + logger.info("启动第三方插件程序开始!"); + if ("1".equals(setInfo.getCheckState()) + && "1".equals(setInfo.getCheckWay()) + && "1,2".contains(setInfo.getIsControlStart())) {// 有效,被动方式获取,Agent端启动 + Date startTime = null; + if (setInfo.getControlStartTime() != null && setInfo.getControlStartTime().longValue() != 0) { + startTime = new Date(setInfo.getControlStartTime()); + } else { + startTime = new Date(); + } + + /* + * 停止未启动的定时任务/周期任务 + */ + Common.stopPluginDetecFuture(setInfo.getId(), Thread.currentThread().getName()); + + /* + * 首先看进程设置的启动时间是否过时:如果过时,则查看进程是否存在,不存在启动;如果未过时,则定时启动 + */ + String cmd = DetecConfOper.getProcess(setInfo); + try { + /** + * 进程存在与否的判断标准: + * 1、先检查PID文件,取出PID,验证PID指定进程是否存在 + * PID文件不存在,或者PID文件中内容为空,或者取出的PID进程不存在,都认为不存在,进行下一步检查 + * 2、不存在再使用搜索关键字查找进程 + * 若未找出进程,不存在,若找出一个进程,正常存在,若找出多个进程,报警 + */ + + Object[] objArr = ProcessUtil.checkPidAndGetPid(setInfo.getProcessFile(), setInfo.getProcessSearchKeyCode()); + int isExistFlag = Integer.parseInt(objArr[0].toString()); + String pidInfo = objArr[1].toString(); + + if (isExistFlag == 0 || isExistFlag == 1) { // 进程不存在/存在一个进程 + if (isExistFlag == 1) {// 存在一个进程 + logger.info("三方监测进程”" + cmd + "“已存在,重启启动"); + ProcessUtil.killProcess(pidInfo); + } + + long delay = startTime.getTime() - System.currentTimeMillis(); + delay = Math.max(delay, 0); + + ScheduledFuture<?> future = null; + if ("1".equals(setInfo.getIsControlStart())) { + future = Common.scheduled.schedule(new ExecProcess(), delay, TimeUnit.MILLISECONDS); + } else if ("2".equals(setInfo.getIsControlStart())) { + long period = setInfo.getCheckGap() * 60 * 1000; + future = Common.scheduled.scheduleAtFixedRate(new ExecProcess2(), delay, period, TimeUnit.MILLISECONDS); + } + + Common.putPluginDetecFuture(setInfo.getId(), future); + logger.info("三方监测程序已加入定时器定时启动"); + + } else { // 找到多个进程,告警 +// String alarmMsg = "启动三方监测:" + pidInfo; + String alarmMsg = "i18n_client.StartPluginRun.startupDetecate_n81i:" + pidInfo; + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo + .getCheckTypeName(), setInfo.getProcessIden(), + new Date(), new Date(), 1, + Contants.DETECTION_STATUS_FAILURE, alarmMsg); + } + + } catch (Exception e) { + logger.error("Start the three party monitoring exception. Please check whether the process execution file and the PID file are set correctly:" + cmd, e); + } + } + logger.info("启动第三方插件程序结束!"); + }// run end + + class ExecProcess implements Runnable { + public void run() { + Thread.currentThread().setName(name); + String cmd = DetecConfOper.getProcess(setInfo); + try { + // 启动 + ProcessUtil.runExec(cmd, null, null, null); + + // 检查PID + Object[] objArr = ProcessUtil.checkPidAndGetPid(setInfo.getProcessFile(), setInfo.getProcessSearchKeyCode()); + int isExistFlag = Integer.parseInt(objArr[0].toString()); + String pidInfo = objArr[1].toString(); + + if (isExistFlag == 1) {// 存在, 一个进程 + logger.info("三方监测程序“" + cmd + "“启动成功"); + } else { // 进程不存在 或 找到多个进程,告警 + String alarmMsg = null; + if (isExistFlag == 0) {// 进程不存在 +// alarmMsg = "三方监测程序启动失败,请检查进程启动文件“" + cmd + "”是否设置正确"; + alarmMsg = "i18n_client.StartPluginRun.startupDetecateErr1_n81i “" + cmd + "” i18n_client.StartPluginRun.startupDetecateErr1.isTrue_n81i"; + } else {// 找到多个进程 +// alarmMsg = "启动三方监测:" + pidInfo; + alarmMsg = "i18n_client.StartPluginRun.startupDetecate_n81i:" + pidInfo; + } + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo + .getCheckTypeName(), setInfo.getProcessIden(), + new Date(), new Date(), 1, + Contants.DETECTION_STATUS_FAILURE, alarmMsg); + } + + } catch (Exception e) { + logger.error("Start the three party monitoring exception. Please check whether the process execution file and the PID file are set correctly:" + cmd, e); + } + } + } + + class ExecProcess2 implements Runnable { + public void run() { + + Thread.currentThread().setName(name); + // 三方监测脚本执行命令不存在,获取脚本命令及关键词 + // 因脚本下发与配置下发不同步,需要在执行任务中多次获取执行命令 + String cmd = Common.generateCommandAndKeyword(setInfo); + try { + boolean executeStatus = true; + + // 脚本执行前,清理临时数据目录 + new NewPluginResultMerge().clearTmpFile(setInfo); + + if (StringUtils.isBlank(cmd)) { + // 三方监测脚本执行命令不存在,当前时间NC上无监测脚本 + logger.info("三方监测程序启动失败,监测脚本下发未完成!"); +// String alarmMsg = "启动三方监测异常,监测脚本下发未完成!"; + String alarmMsg = "i18n_client.StartPluginRun.startupDetecateErr2_n81i"; + AlarmUtil.sendAlarmMsg(setInfo.getId(), + setInfo.getCheckTypeName(), + setInfo.getProcessIden(), new Date(), new Date(), + 1, Contants.DETECTION_STATUS_FAILURE, alarmMsg); + executeStatus = false; + + } else { + // 启动脚本 + String msg = ProcessUtil.runExec(cmd, null, null, null); + + if (StringUtils.isBlank(msg)) { // 执行成功 + logger.info("三方监测程序“" + cmd + "”执行成功"); + + } else { // 执行失败,返回错误信息 + logger.error("Three party monitoring procedure“" + cmd + "”erroneous execution:" + msg); +// String alarmMsg = "启动三方监测异常,监测脚本执行错误!"; + String alarmMsg = "i18n_client.StartPluginRun.startupDetecateErr3_n81i"; + AlarmUtil.sendAlarmMsg(setInfo.getId(), + setInfo.getCheckTypeName(), + setInfo.getProcessIden(), new Date(), + new Date(), 1, + Contants.DETECTION_STATUS_FAILURE, alarmMsg); + executeStatus = false; + } + } + + // 针对执行合并临时文件(ProcessUtil.runExec为同步执行,合并临时文件前已完成脚本执行过程) + if(executeStatus) { + new NewPluginResultMerge().merge(setInfo); + } + + } catch (Exception e) { + logger.error("Start the three party monitoring exception. Please check whether the process execution file and the PID file are set correctly:" + cmd, e); + } + } + } + +} diff --git a/src/com/nis/nmsclient/thread/socket/CommonSocket.java b/src/com/nis/nmsclient/thread/socket/CommonSocket.java new file mode 100644 index 0000000..8248f32 --- /dev/null +++ b/src/com/nis/nmsclient/thread/socket/CommonSocket.java @@ -0,0 +1,1199 @@ +package com.nis.nmsclient.thread.socket; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.MD5Util; +import com.nis.nmsclient.util.Utils; +import com.nis.nmsclient.util.file.BufferedRandomAccessFile; +import com.socket.utils.FileComment; + +public class CommonSocket{ + static Logger logger = Logger.getLogger(CommonSocket.class); + protected static final String TEMP_SUFFIX = ".tp"; + //缓存字节长度 + protected static final int BUFF_SIZE = 1024; + public static final String SUCCESS = "success"; + public static final String FAIL = "fail"; + public static final String END = "end"; + /** + * 与Server握手请求 + */ + public static final String REQ_HAND_SHAKE = "char:handshake"; + /** + * 获取本机标志UUID请求 + */ + public static final String REQ_LOCAL_UUID = "char:uuid"; + /** + * 发送本机变更信息请求 + */ + public static final String REQ_LOCAL_CHANGE = "char:agentChange"; + /** + * 初始化配置请求 + */ + public static final String REQ_INIT_CONFIG = "char:init"; + /** + * 初始化任务请求 + */ + public static final String REQ_INIT_TASK = "char:initTask"; + /** + * 主动告警请求 + */ + public static final String REQ_ALARM = "char:alarm"; + /** + * 获取Server端系统时间请求 + */ + public static final String REQ_SERVER_SYSTEMDATE = "char:systemdate"; + /** + * Server升级请求 + */ + public static final String REQ_SERVER_UPGRADE = "char:upgradeServer"; + /** + * NC向DC发送错误信息 + */ + public static final String REQ_ERROR_INFO = "char:ncErrorInfo"; + // ========== 现由DC主动获取数据,以下命令暂留 + /** + * 批量上传数据文件请求 + */ + public static final String REQ_UPLOAD_DATAS ="byte:datas"; + /** + * 回传文件请求 + */ + public static final String REQ_TASK_RETURNFILE = "byte:taskReturn"; + // ========== 现由DC主动获取数据,以上命令暂留 + /** + * 发送任务结果请求【数据收集方式改为DC主动后,此请求只在NC启动时发送所有任务结果使用】 + */ + public static final String REQ_TASK_RESULT = "char:taskResult"; + /** + * 上传回传文件、任务结果文件、数据文件的打包文件请求【数据收集方式改为DC主动后,此请求只在NC启动时发送所有任务结果使用】 + */ + public static final String REQ_BP_UPLOAD_FIFE = "byte:bpUploadFile"; + //bpUploadFile的子命令类型 + public static final String BP_TYPE_TASK_RESULT = "taskresult"; + public static final String BP_TYPE_TASK_RETURN = "taskreturn"; + public static final String BP_TYPE_DETECT_DATA = "detectdata"; + /** + * 交换证书通信命令 + */ + public static final String REQ_CERT = "byte:cert"; + /** + * 更新监测设置信息通信命令 + */ + public static final String SERVER_UPDATE_CONFIG = "char:updateConfig"; + /** + * 下发第三方监测脚本命令 + */ + public static final String SEND_PLUGIN_SCRIPT_FILE = "char:sendPluginScriptFile"; + /** + * NC端是否报主动告警 变更 + */ + public static final String ACTIVE_ALARM_START_ALERT = "char:isActiveAlarmStart"; + /** + * 文件推送通信命令 + */ + public static final String SERVER_FILE_PUSH = "byte:filePush"; + /** + * 升级通信命令 + */ + public static final String SERVER_UPGRADE = "byte:upgrade"; + /** + * 下发任务通信命令 + */ + public static final String SERVER_TASK = "char:task"; + /** + * 任务撤消命令 + */ + public static final String SERVER_TASK_CANCEL = "char:taskCancel"; + /** + * DC主动向NC再次获取任务结果 + */ + public static final String SERVER_GET_TASKRESULT = "char:collectNonRltTaskResult"; + /** + * DC主动向NC收集监测数据 + */ + public static final String SERVER_COLLECT_DATA = "byte:collectData"; + //收集数据,Agent发送的类型 + public static final String DATA_TYPE_ZIP_DETECT = "zipDetectData";//监测数据zip + public static final String DATA_TYPE_CSV_DETECT = "csvDetectData";//批量上传csv监测数据 + public static final String DATA_TYPE_ZIP_TASKRESULT = "zipTaskResult";//任务结果zip + public static final String DATA_TYPE_OBJ_TASKRESULT = "objTaskResult";//批量上传任务结果obj + public static final String DATA_TYPE_ZIP_TASKRETURN = "zipTaskReturn";//任务回传文件zip + public static final String DATA_TYPE_FILE_TASKETURN = "fileTaskReturn";//单个任务回传文件 + + protected Socket socket = null; + protected OutputStream out = null; + protected InputStream in = null; + + public CommonSocket() { + super(); + } + + public CommonSocket(Socket client) throws Exception { + socket = client; + out = socket.getOutputStream(); + in = socket.getInputStream(); + } + + /** + * 发送消息,以字符形式,发送一行信息 + **/ + public boolean sendMessageByChar(String msg) throws Exception { + logger.debug("sendMessageByChar---" + msg); + PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, + Contants.charset)); + pw.println(msg); + pw.flush(); + + return true; + } + + + /** + * 接收信息,以字符形式,接收一行信息 + * + */ + public String receiveMessageByChar() throws Exception { + BufferedReader br = new BufferedReader(new InputStreamReader(in, + Contants.charset)); + String str = br.readLine(); + logger.debug("receiveMessageByChar---" + str); + return str; + } + + /** + * 发送单个文件 + **/ + public boolean sendFileByByte(File file) throws Exception { + ObjectOutputStream oos = null; + FileInputStream fis = null; + try { + //发送文件大小和文件名 + oos = new ObjectOutputStream(out); + String[] strArr = new String[]{ + file.length() + "", file.getName() + }; + oos.writeObject(strArr); + //发送文件内容 + byte[] buff = new byte[BUFF_SIZE]; + int len = 0; + fis = new FileInputStream(file); + while ((len = fis.read(buff)) != -1) { + //将读取的内容写入文件 + out.write(buff, 0, len); + } + out.flush(); + } catch (Exception e) { + logger.error("Single file sending failure"); + throw e; + } finally{ + if(fis!=null){ + try { + fis.close(); + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + + return true; + } + + /** + * 接收单个文件 + * + */ + public boolean receiveFileByByte(String filePath) throws Exception { + ObjectInputStream ois = null; + FileOutputStream fos = null; + try { + + ois = new ObjectInputStream(in); + String[] strArr = (String[])ois.readObject(); + //接收文件大小 + long fileSize = Long.parseLong(strArr[0]); + //接收文件名 + String fileName = strArr[1]; + + //接收文件内容 + byte[] buff = new byte[BUFF_SIZE]; + fos = new FileOutputStream(filePath + File.separator + fileName); + int nRead = 0; + + //单个文件循环读取 + while ((nRead = in.read(buff, 0, (int)(BUFF_SIZE<fileSize?BUFF_SIZE:fileSize))) > 0) { + fos.write(buff,0,nRead); + fos.flush(); + fileSize -= nRead; + if(fileSize<=0){ + break; + } + } + fos.close(); + } catch (Exception e) { + logger.error("Single file receiving failure"); + throw e; + } finally { + try { + if (fos != null) { + fos.close(); + } + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + + } + + return true; + + } + + /** + * 批量上传文件 + * @param dir 本地文件集合根目录绝对路径 + * @param fileList 上传的文件列表 + */ + public void sendFileByBath(String dir, List<File> fileList) throws Exception { + ObjectOutputStream oos = null; + FileInputStream fis = null; + + try { + // 第一步发送本地根目录地址(用于地址截取)保证fileList的目录结构完整性 + this.sendMessageByChar(dir); + String result = this.receiveMessageByChar(); + logger.debug("根目录地址发送状态: " + result); + // 第二步 用ObjectOutputStream工具类 发送file对象信息 用于文件名,文件目录,文件大小的获取 + oos = new ObjectOutputStream(out); + List<String[]> fileStrList = new ArrayList<String[]>(); + if(fileList!=null && fileList.size()>0){ + for (File f : fileList) { + if (f.exists()) { + String[] tmpArr = new String[] { f.getAbsolutePath(), + f.length() + "" }; + fileStrList.add(tmpArr); + } else { + logger.warn("File:>" + f.getAbsolutePath() + + " do not exist, can not send"); + } + } + oos.writeObject(fileStrList); + // 第三部,发送文件 + byte[] buff = new byte[BUFF_SIZE]; + int len = 0; + // 循环上传文件 + for (File file : fileList) { + logger.debug("--sendFileByBath---" + file.getName() + "---length=" + file.length()); + fis = new FileInputStream(file); + while ((len = fis.read(buff)) != -1) {// 将读取的内容输出流 + out.write(buff, 0, len); + } + out.flush(); + fis.close(); + fis = null; + } + } + logger.debug("批量发送文件个数:" + (fileList==null ? 0 : fileList.size())); + } catch (Exception e) { + throw e; + } finally { + try { + if (fis != null) { + fis.close(); + fis = null; + } + } catch (IOException e) { + } + } + } + + /** + * 批量接收文件 + * @param newDir + */ + public boolean receiveFileByBath(String newDir) throws Exception { + ObjectInputStream ois = null; + FileOutputStream fos = null; + try { + //获取集合文件路径 + String oldDir = this.receiveMessageByChar(); + //logger.info("旧上传文件集合根目录: " + oldDir); + this.sendMessageByChar("success"); + ois = new ObjectInputStream(in); + List<String[]> fileList = (List<String[]>)ois.readObject(); + if(fileList != null && fileList.size()>0){ + for(String[] arr : fileList){ + String newUrl = arr[0].replace(oldDir, newDir);//新路径 + newUrl = newUrl.replaceAll("\\\\", "/"); + int fileLength = Integer.parseInt(arr[1]); //大小 + File newFile = new File(newUrl); + if(newFile.exists()){ + FileUtil.delDir(newFile); + logger.debug("receiveFileByBath delete file---" + newFile.getAbsolutePath()); + } + if(!newFile.getParentFile().exists()){ + newFile.getParentFile().mkdirs(); + } + fos = new FileOutputStream(newUrl+TEMP_SUFFIX); + + int nRead = 0; + byte[] buff = new byte[BUFF_SIZE]; + //单个文件循环读取 + while ((nRead = in.read(buff, 0, (int)(BUFF_SIZE<fileLength?BUFF_SIZE:fileLength))) > 0) { + fos.write(buff,0,nRead); + fos.flush(); + fileLength -= nRead; + if(fileLength<=0){ + break; + } + } + fos.close(); + fos = null; + File newFile2 = new File(newUrl+TEMP_SUFFIX); + //newFile2.renameTo(newFile); + FileUtils.copyFile(newFile2, newFile);//将临时文件名改为正式文件名,即去掉.tp后缀 + newFile2.delete();// 将临时文件删除 + } + } + logger.debug("批量接收文件个数:" + (fileList==null ? 0 : fileList.size())); + } catch (Exception e) { + throw e; + }finally{ + if(fos!=null){ + try { + fos.close(); + fos = null; + } catch (IOException e) { + } + } + } + + return true; + + } + + /** + * 批量上传文件, 并传入文件的Md5值 + * @param fileList 上传的文件列表 + */ + protected void sendFileWithMd5ByBath(List<String[]> fileCommentsList) throws IOException { + ObjectOutputStream oos = null; + FileInputStream fis = null; + + try { + // 第一步 用ObjectOutputStream工具类 发送file对象信息 用于文件名,文件目录,文件大小的获取 + oos = new ObjectOutputStream(out); + List<File> fileList = new LinkedList<File>(); + List<String[]> fileStrList = new ArrayList<String[]>(); + for(String[] fileComments : fileCommentsList){ + File file = new File(fileComments[0]); + if(file.exists()){ + String[] tmpArr = new String[]{ + file.getName(), file.length() + "",fileComments[1] + }; + fileList.add(file); + fileStrList.add(tmpArr); + }else { + logger.warn("File:>"+file.getAbsolutePath()+" do not exist, can not send"); + } + } + oos.writeObject(fileStrList); + // 第三部,发送文件 + byte[] buff = new byte[BUFF_SIZE]; + int len = 0; + // 循环上传文件 + for (File file : fileList) { + fis = new FileInputStream(file); + while ((len = fis.read(buff)) != -1) {// 将读取的内容输出流 + out.write(buff, 0, len); + } + out.flush(); + fis.close(); + fis = null; + } + logger.debug("批量发送文件结束,共 "+(fileList==null ? 0 : fileList.size())+ "个文件"); + } catch (IOException e) { + logger.error("Batch file failed!"); + throw new IOException(e); + } finally { + try { + if (fis != null) { + fis.close(); + fis = null; + } + } catch (IOException e) { + } + } + } + + /** + * 批量接收文件, 使用Md5校验文件是否完整 + * @param newDir + */ + public boolean receiveFileWithMd5ByBath(String newDir) throws IOException { + boolean flag = true; + ObjectInputStream ois = null; + FileOutputStream fos = null; + try { + ois = new ObjectInputStream(in); + List<String[]> fileList = (List<String[]>)ois.readObject(); + if(fileList != null && fileList.size()>0){ + int sucessCnt = 0; + int failCnt = 0; + for(int i=0; i<fileList.size(); i++){ + String[] arr = fileList.get(i);//arr[0] 存放文件名,arr[1] 存放文件长度,arr[2] 存放Md5值 + String newUrl = newDir + File.separator + arr[0]; + int fileLength = Integer.parseInt(arr[1]);//大小 + String md5Val = arr[2]; + File newFile = new File(newUrl); + if(newFile.exists()){ + FileUtil.delDir(newFile); + logger.debug("receiveFileWithMd5ByBath delete file--" + newFile.getAbsolutePath()); + } + if(!newFile.getParentFile().exists()){ + newFile.getParentFile().mkdirs(); + } + fos = new FileOutputStream(newUrl+TEMP_SUFFIX); + + //接收文件内容 + int nRead = 0; + byte[] buff = new byte[BUFF_SIZE]; + + //单个文件循环读取 + while ((nRead = in.read(buff, 0, (int)(BUFF_SIZE<fileLength?BUFF_SIZE:fileLength))) > 0) { + fos.write(buff,0,nRead); + fos.flush(); + fileLength -= nRead; + if(fileLength<=0){ + break; + } + } + fos.close(); + fos = null; + File newFile2 = new File(newUrl+TEMP_SUFFIX); + if (md5Val != null + && md5Val + .equals(MD5Util.getFileMD5String(newFile2))) { + logger.debug("接收文件" + (i+1) + "“" + newFile.getAbsolutePath() + "”完整"); + //newFile2.renameTo(newFile); + FileUtils.copyFile(newFile2, newFile);//将临时文件名改为正式文件名,即去掉.tp后缀 + newFile2.delete();// 将临时文件删除 + sucessCnt ++ ; + } else { + logger.debug("接收文件" + (i+1) + "“" + newFile.getAbsolutePath() + "”不完整,失败"); + failCnt ++ ; + } + } + logger.info("批理接收文件个数:" + fileList.size() + ", 成功:" + sucessCnt + ", 失败:" + failCnt); + if(failCnt > 0) { + flag = false; + } + }else{ + logger.info("批量接收文件列表为空"); + } + } catch (Exception e) { + logger.error("Batch file failure"); + throw new IOException(e); + }finally{ + if(fos!=null){ + try { + fos.close(); + fos = null; + } catch (IOException e) { + } + } + } + + return flag; + } + + /** + * 断点续传 发送方法 + * @time Mar 2, 2012-2:30:16 PM + * @param filePath + */ + protected boolean bpSendFile (String filePath) throws Exception { + File file = new File(filePath); + + //发送长度 end + this.sendMessageByChar(file.length()+""); + + String msg = this.receiveMessageByChar(); + long start = Long.parseLong(msg); + long end = file.length(); + logger.debug("start "+start); + logger.debug("end "+end); + bpSendFile(filePath, start, end); + + return true; + } + + /** + * 断点续传 接收方法 + * @time Mar 2, 2012-2:30:16 PM + * @param filePath + * @param start + * @param end + */ + protected int bpReceiveFile (String filePath) throws Exception { + File file = new File(filePath); + if(!file.exists()){ + file = new File(filePath+TEMP_SUFFIX); + } + String msg = this.receiveMessageByChar(); + long start = file.length(); + long end = Long.parseLong(msg); + this.sendMessageByChar(start+""); + + logger.debug("start "+start); + logger.debug("end "+end); + bpReceiveFile(file.getAbsolutePath(), start, end); + + //file.renameTo(new File(filePath)); + FileUtils.copyFile(file, new File(filePath));//将临时文件名改为正式文件名,即去掉.tp后缀 + file.delete();// 将临时文件删除 + + logger.debug("bpReceiveFile sucess"); + return 0; + } + + /** + * 断点续传 发送方法 + * @time Mar 2, 2012-2:30:16 PM + * @param filePath + * @param start + * @param end + */ + protected void bpSendFile (String filePath,long start,long end) throws Exception { + if (start == end) { + return; + } + BufferedRandomAccessFile braf = null; + try { + File file = new File(filePath); + + //- 不存在,终止; 存在则继续 + if(!file.exists()){ + this.sendMessageByChar(FAIL); + return ; + }else { + this.sendMessageByChar(SUCCESS); + } + + String msg = this.receiveMessageByChar(); + logger.debug("Recive: " + msg); + + //- BufferedRandomAccessFile 读取指定位置的文件字节数组,写入输出通讯 + byte[] b = new byte[BUFF_SIZE]; + braf = new BufferedRandomAccessFile(file,"r"); + braf.seek(start); + int nRead; + while ((nRead = braf.read(b, 0, BUFF_SIZE)) > 0) { + + out.write(b, 0, nRead); + start += nRead; + + //-- 读取完成 跳出 + if(start==end){break;} + + } + + }catch (Exception e) { + throw e; + }finally{ + try { + //- 关闭 随机访问文件对象(关闭流) + if(braf!= null){braf.close();} + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + + } + } + /** + * 断点续传 接收方法 + * @time Mar 2, 2012-2:30:16 PM + * @param filePath + * @param start + * @param end + */ + protected void bpReceiveFile (String filePath,long start,long end) throws Exception { + if(StringUtils.isEmpty(filePath)){ + return; + } + if (start == end) { + return; + } + BufferedRandomAccessFile raf = null; + try { + File file = new File(filePath); + + //- 文件路径不存在 则创建 + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + + //- 文件不存在 则创建 + if (!file.exists()) { + file.createNewFile(); + } + + //- 接收发送端 发送数据准备 确认信息 + String msg = this.receiveMessageByChar(); + + if (FAIL.equals(msg)) { //结束操作 + return; + } else { + this.sendMessageByChar(SUCCESS); // 通知发送端 接收数据准备完成 确认信息 + } + + // 将通信中读出的数据 写入文件指定位置 + byte[] b = new byte[BUFF_SIZE]; + raf = new BufferedRandomAccessFile(file, "rw"); + raf.seek(start); + int nRead; + + while ((nRead = in.read(b, 0, BUFF_SIZE)) > 0) { + raf.write(b, 0, nRead); + start += nRead; + + if (start == end) { //写完跳出 + break; + } + } + } catch (Exception e) { + throw e; + }finally{ + try { + //- 关闭 随机访问文件对象(关闭流) + if(raf!= null){raf.close();} + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + + /** + * 断点续传 批量上传文件 + * @param fileList 上传的文件列表 + * @param dir 本地文件集合根目录绝对路径 + */ + protected void bpSendFileByBath(List<File> fileList,String dir) throws Exception { + BufferedRandomAccessFile oReadFile = null; + + try { + // 第一步发送本地根目录地址(用于地址截取)保证fileList的目录结构完整性 + this.sendMessageByChar("abs:"+(dir==null?"":dir)); + String result = this.receiveMessageByChar(); + logger.debug("根目录路径通信状态: " + result); + // 第二步 用ObjectOutputStream工具类 发送file对象信息 用于文件名,文件目录,文件大小的获取 + + //原文件文件名 和 大小(即end长度) + List<String[]> sourceFileList = new ArrayList<String[]>(); + for(File f : fileList){ + String[] tmpArr = new String[]{ + f.getAbsolutePath(),0+"",f.length() + "" + }; + sourceFileList.add(tmpArr); + } + + logger.debug("发送信息: " + Arrays.toString(sourceFileList.toArray())); + this.sendObject(sourceFileList); + + //得到需要下载的文件信息 + List<String[]> sendFileList = (List<String[]>)receiveObject(); + + // 第三部,发送文件 + byte[] buff = new byte[BUFF_SIZE]; + + // 循环上传文件 + for (String[] sendFile: sendFileList) { + long start = Long.parseLong(sendFile[1]); + long end = Long.parseLong(sendFile[2]); + if(start >= end){ + continue; + } + File file = new File(sendFile[0]); + oReadFile = new BufferedRandomAccessFile(file,"r"); + + // 定位文件指针到nPos位置 + oReadFile.seek(start); //从0开始 + int nRead; + + // 从输入流中读入字节流,然后写到文件中 + while ((nRead = oReadFile.read(buff, 0, BUFF_SIZE)) > 0) { + + out.write(buff, 0, nRead); + start += nRead; //调整为从1开始 + if(start >= end){ + break; + } + + } + oReadFile.close(); + oReadFile = null; + } + logger.debug("多文件上传结束,共 "+(fileList==null ? 0 : fileList.size())+ "个文件"); + } catch (Exception e) { + throw e; + } finally { + try { + if (oReadFile != null) { + oReadFile.close(); + oReadFile = null; + } + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + + /** + * 断点续传 批量接收文件 + * @param newDir + */ + protected void bpReceiveFileByBath(String newDir) throws Exception { + + BufferedRandomAccessFile oSavedFile = null; + try { + //获取集合文件路径 + String oldDir = this.receiveMessageByChar(); + int headLength = "abs:".length(); + oldDir = ((StringUtils.isNotEmpty(oldDir) + && oldDir.length()>=headLength) + ?oldDir.substring(headLength,oldDir.length()) + :oldDir); + if(StringUtils.isEmpty(oldDir)){ + logger.debug("远程 目录根路径为空 接收文件不保留目录格式 统一存放到本地目录:》"+newDir); + }else{ + logger.debug("根目录 记录: " + oldDir+" VS "+newDir); + } + this.sendMessageByChar(SUCCESS); + + List<String[]> remoteFileList = (List<String[]>)receiveObject(); + List<String[]> receiveFileList = new LinkedList<String[]>(); + byte[] buff = new byte[BUFF_SIZE]; + if(remoteFileList != null && remoteFileList.size()>0){ + for(String[] arr : remoteFileList){ + String newUrl = null; + if(StringUtils.isEmpty(oldDir)){ + newUrl = newDir+(new File(arr[0].replaceAll("\\\\", "/")).getName()); + }else{ + newUrl = arr[0].replace(oldDir, newDir);//新路径 + newUrl = newUrl.replaceAll("\\\\", "/"); + } + + File newFile = new File(newUrl); + + //该文件已存在 + if(newFile.exists()){ + continue; + } + + newFile = new File(newUrl+TEMP_SUFFIX); + arr[1] = newFile.length()+""; + receiveFileList.add(arr); + } + } + this.sendObject(receiveFileList); + + if(receiveFileList != null && receiveFileList.size()>0){ + for(String[] arr : receiveFileList){ + String newUrl = null; + if(StringUtils.isEmpty(oldDir)){ + newUrl = newDir+(new File(arr[0].replaceAll("\\\\", "/")).getName()); + }else{ + newUrl = arr[0].replace(oldDir, newDir);//新路径 + newUrl = newUrl.replaceAll("\\\\", "/"); + } + + File newFile = new File(newUrl+TEMP_SUFFIX); + + if(!newFile.getParentFile().exists()){ + newFile.getParentFile().mkdirs(); + } + + if(!newFile.exists()){ + newFile.createNewFile(); + } + + int start = Integer.parseInt(arr[1]); // 起始 + int end = Integer.parseInt(arr[2]); // 结束 + if(start<end){ + oSavedFile = new BufferedRandomAccessFile(newFile,"rw"); + oSavedFile.seek(start); + int nRead; + rfile:while ((nRead = in.read(buff, 0, BUFF_SIZE<end?BUFF_SIZE:end)) > 0) { + oSavedFile.write(buff,0,nRead); + end -= nRead; + if(end<=0){ + break rfile; + } + } + oSavedFile.close(); + oSavedFile = null; + } +// newFile.renameTo(new File(newUrl)); //将临时文件名改为正式文件名,即去掉.tp后缀 + FileUtils.copyFile(newFile, new File(newUrl)); //将临时文件名改为正式文件名,即去掉.tp后缀 + newFile.delete(); + } + } + logger.debug("多文件接收结束,共 "+(remoteFileList==null ? 0 : remoteFileList.size())+ "个文件"); +// } catch (IOException e) { +// logger.error("",e); +// } catch (ClassNotFoundException e) { +// logger.error("",e); + }finally{ + if(oSavedFile!=null){ +// try { + oSavedFile.close(); + oSavedFile = null; +// } catch (IOException e) { +// logger.error("",e); +// } + } + } + } + + /** + * 断点续传 批量上传文件, 并传入文件的Md5值 + * @param fileList 上传的文件列表 + * @param dir 本地文件集合根目录绝对路径 + */ + protected void bpSendFileByBathMD5(List<FileComment> fileCommentsList) throws Exception { + BufferedRandomAccessFile oReadFile = null; + + try { + //原文件文件名 和 大小(即end长度) + List<FileComment> sourceFileList = new ArrayList<FileComment>(); + if(fileCommentsList !=null && fileCommentsList.size()!=0){ + for(FileComment fileComment : fileCommentsList){ + File f = new File(fileComment.getFileName()); + if(!f.exists()){ + sourceFileList.add(new FileComment(f.getAbsolutePath(),0,-1,fileComment.getMd5Val())); + }else { + String md5Val = StringUtils.isEmpty(fileComment.getMd5Val())?MD5Util.getFileMD5String(f):fileComment.getMd5Val(); + sourceFileList.add(new FileComment(f.getAbsolutePath(),0,f.length(),md5Val)); + } + } + } + + logger.debug("发送信息: " + Arrays.toString(sourceFileList.toArray())); + this.sendObject(sourceFileList); + + //得到需要下载的文件信息 + List<FileComment> sendFileList = (List<FileComment>)receiveObject(); + + // 第三部,发送文件 + byte[] buff = new byte[BUFF_SIZE]; + + // 循环上传文件 + for (FileComment sendFile: sendFileList) { + long start = sendFile.getStart(); + long end = sendFile.getEnd(); + if(start >= end){ + continue; + } + File file = new File(sendFile.getFileName()); + oReadFile = new BufferedRandomAccessFile(file,"r"); + + // 定位文件指针到nPos位置 + oReadFile.seek(start); //从0开始 + int nRead; + + // 从输入流中读入字节流,然后写到文件中 + while ((nRead = oReadFile.read(buff, 0, BUFF_SIZE)) > 0) { + + out.write(buff, 0, nRead); + start += nRead; //调整为从1开始 + if(start >= end){ + break; + } + + } + oReadFile.close(); + oReadFile = null; + } + logger.debug("多文件上传结束,共 "+(sendFileList==null ? 0 : sendFileList.size())+ "个文件"); + } catch (Exception e) { + throw e; + } finally { + try { + if (oReadFile != null) { + oReadFile.close(); + oReadFile = null; + } + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + + + /** + * 断点续传 批量接收文件, 使用Md5校验文件是否完整 + * @param newDir + */ + public int bpReceiveFileByBathMd5(String newDir) throws Exception{ + if(newDir!=null){ + newDir += File.separator; + } + int rFlag = 0; //0 OK -1 MD5 ERROR -2 Function ERROR -3 文件不存在 + BufferedRandomAccessFile oSavedFile = null; //有缓存的 随机文件IO对象 + try { + + List<FileComment> remoteFileList = (List<FileComment>)receiveObject(); //接收可接收的文件信息 string[]{fileName,start,end,MD5} + List<FileComment> receiveFileList = new LinkedList<FileComment>(); //需要续传的文件及其索引信息 string[]{fileName,start,end,MD5} + byte[] buff = new byte[BUFF_SIZE]; //缓存 大小 + + //- 检查实际接收文件大小 + if(remoteFileList != null && remoteFileList.size()>0){ + for(FileComment arr : remoteFileList){ + //String newUrl = newDir+removeTimeTagFileName(new File(arr.getFileName()).getName(),null); + String filePath = arr.getFileName().replaceAll("\\\\", "/"); + String fileName = filePath.substring(filePath.lastIndexOf("/")+1, filePath.length()); + String newUrl = newDir+removeTimeTagFileName(fileName,null); + + File newFile = new File(newUrl); + + //-- 已接收完成 + if(newFile.exists()){ + // continue; + // 2013-1-6 jzz 如果接收完成也比较MD5值,主要是针对再次执行任务,直接拷来的文件 + //-- MD5为空 无需校验 + if(StringUtils.isEmpty(arr.getMd5Val())){ + continue; + } + //-- MD5相等, 接收完成 + if(arr.getMd5Val().equals(MD5Util.getFileMD5String(newFile))){ + logger.debug("1--" + newFile.getAbsolutePath()+" MD5值校验一致"); + continue; + } else {//-- MD5不相等,则删除该文件,下面重新接收 + FileUtil.delDir(newFile); + logger.debug("1--bpReceiveFileByBathMd5 delete file ---" + newFile.getAbsolutePath()); + logger.debug("1--" + newFile.getAbsolutePath()+" MD5值校验不一致"); + } + // 2013-1-6 jzz 修改结束 + } + + //-- 续传文件及起始长度 + newFile = new File(newUrl+TEMP_SUFFIX); + arr.setStart(newFile.length()); + receiveFileList.add(arr); + } + } + this.sendObject(receiveFileList); + + //- 接收文件 + if(receiveFileList != null && receiveFileList.size()>0){ + for(FileComment arr : receiveFileList){ + //String newUrl = newDir+removeTimeTagFileName(new File(arr.getFileName()).getName(),null); + String filePath = arr.getFileName().replaceAll("\\\\", "/"); + String fileName = filePath.substring(filePath.lastIndexOf("/")+1, filePath.length()); + String newUrl = newDir+removeTimeTagFileName(fileName,null); + + File newFile = new File(newUrl+TEMP_SUFFIX); + + if(!newFile.getParentFile().exists()){ + newFile.getParentFile().mkdirs(); + } + + //创建空文件 + if (!newFile.exists()) { + newFile.createNewFile(); + } + + long start = arr.getStart(); // 起始 + long end = arr.getEnd(); // 结束 + if(end == -1){ + return -3; + } + + if(start<end){ + oSavedFile = new BufferedRandomAccessFile(newFile,"rw"); + oSavedFile.seek(start); + int nRead; + rfile:while ((nRead = in.read(buff, 0, (int)(BUFF_SIZE<end?BUFF_SIZE:end))) > 0) { + oSavedFile.write(buff,0,nRead); + end -= nRead; + if(end<=0){ + break rfile; + } + } + oSavedFile.close(); + oSavedFile = null; + } + //newFile.renameTo(new File(newUrl)); + FileUtils.copyFile(newFile, new File(newUrl));//将临时文件名改为正式文件名,即去掉.tp后缀 + newFile.delete();// 将临时文件删除 + logger.debug(newFile.getAbsolutePath()+" 下载完成!"); + + //-- MD5为空 无需校验 + if(StringUtils.isEmpty(arr.getMd5Val())){ + continue; + } + + File newFile2 = new File(newUrl); + //-- MD5不相等,则删除该文件 返回-1 + if(!arr.getMd5Val().equals(MD5Util.getFileMD5String(newFile2))){ + //newFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(newFile); + logger.debug("bpReceiveFileByBathMd5 delete file ---" + newFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(newFile); + logger.debug(newFile.getAbsolutePath()+" MD5值校验不一致"); + return -1; + } else {//-- MD5相等 + logger.debug(newFile.getAbsolutePath()+" MD5值校验一致"); + } + } + } + logger.debug("多文件接收结束,共 "+(remoteFileList==null ? 0 : remoteFileList.size())+ "个文件"); + return rFlag; + } catch (Exception e) { + //return -2; + throw e; + }finally{ + if(oSavedFile!=null){ + try { + oSavedFile.close(); + oSavedFile = null; + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + } + + /** + * Object 形式 发送信息 + */ + protected void sendObject(Object object) throws Exception { + ObjectOutputStream oos = new ObjectOutputStream(out); + oos.writeObject(object); + oos.flush(); + } + + /** + * Object 形式 接收信息 + */ + protected Object receiveObject() throws Exception { + ObjectInputStream ois = new ObjectInputStream(in); + return ois.readObject(); + } + + /** + * 关闭通讯 + */ + public void close() { + try { + if(out!=null){ + out.close(); + out = null; + } + if(in!=null){ + in.close(); + in = null; + } + if(socket!=null && socket.isConnected()){ + socket.close(); + socket = null; + } + } catch (Exception e) { + logger.error(Utils.printExceptionStack(e)); + } + } + + /** + * 删除addTimeTagForFileName()方法 所添加的时间戳 + * @time Mar 12, 2012-3:36:16 PM + * @param fileName + * @return + */ + public static String removeTimeTagFileName(String fileName, String taskId) { + + if (StringUtils.isNotBlank(fileName) && fileName.contains("_")) { + + String timeTag = fileName.substring(fileName.lastIndexOf("_"), + fileName.lastIndexOf(".")==-1?fileName.length():fileName.lastIndexOf(".")); //针对无后缀名文件,时间戳截取校验 + fileName = fileName.replace(timeTag, ""); + + if(taskId!=null){ + fileName = fileName.replace("_" + taskId, ""); + } + + } + + return fileName; + + } + + /** + * 上传文件时,判断该文件是否已存在,如存在,则在后面加入时间戳 + * + * @param fileName + * 单纯的文件名 + * @param taskId 标识ID + * @return + * @throws UnknownHostException + */ + public static String addTimeTagForFileName(String fileName, String taskId, boolean isFile){ + + try + { + Calendar calendar = new GregorianCalendar(); + long timestamp = calendar.getTimeInMillis(); + + // 文件后缀 + String fielType = ""; + + if (isFile) {// 只是文件做名称处理,目录的话不用处理,直接使用原名称 + if (fileName.lastIndexOf(".") != -1) { + fielType = fileName.substring(fileName.lastIndexOf(".")); + fileName = fileName.substring(0, fileName.lastIndexOf(".")); + } + } + + if(taskId!=null){ + fileName += "_" + taskId; + } + fileName += "_" + timestamp+""+((int)(Math.random()*1000)); + + if(StringUtils.isNotBlank(Contants.AGENT_LOCAL_IP)) { + fileName = fileName+"_"+Contants.AGENT_LOCAL_IP; + } + fileName += fielType; + logger.debug("回传文件名称为: "+fileName); + } catch (Exception e) + { + logger.error("Generating the name exception of the return file", e); + } + + return fileName; + } +} diff --git a/src/com/nis/nmsclient/thread/socket/SSLCertOper.java b/src/com/nis/nmsclient/thread/socket/SSLCertOper.java new file mode 100644 index 0000000..32cf8d0 --- /dev/null +++ b/src/com/nis/nmsclient/thread/socket/SSLCertOper.java @@ -0,0 +1,238 @@ +package com.nis.nmsclient.thread.socket; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.security.KeyStore; +import java.security.SecureRandom; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.Utils; + +public class SSLCertOper { + static Logger logger = Logger.getLogger(SSLCertOper.class); + + public static SSLContext getSSLContext() throws Exception { + // 初始化上下文 + SSLContext ctx = SSLContext.getInstance(Contants.SSL_JSSE_TYPE); + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + KeyStore ks = KeyStore.getInstance(Contants.SSL_KEYSTORE_TYPE); + ks.load(new FileInputStream(Contants.SSL_KEY_STORE), + Contants.SSL_KEY_STORE_PASS.toCharArray());// 载入keystore + kmf.init(ks, Contants.SSL_KEY_PRIVATE_PASS.toCharArray()); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + KeyStore tks = KeyStore.getInstance(Contants.SSL_KEYSTORE_TYPE); + tks.load(new FileInputStream(Contants.SSL_TRUST_KEY_STORE), + Contants.SSL_KEY_STORE_PASS.toCharArray());// 载入keystore + tmf.init(tks); + + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), + new SecureRandom()); + logger.debug("load keystore success."); + + return ctx; + } + + /** + * 创建 密匙对(私钥和公钥) + * + */ + public static String createKeyAndCert(String aliasName, String storePath, + String localIp, String keyPass, String storePass, String certName) { + BufferedReader bReader = null; + Process process = null; + try { + process = Runtime.getRuntime().exec( + "keytool -genkey -v -alias " + aliasName + + " -keyalg RSA -storetype " + + Contants.SSL_KEYSTORE_TYPE + " -keystore " + + storePath + " -validity 90 -dname \"CN=" + + localIp + + ",OU=cn,O=cn,L=cn,ST=cn,C=cn\" -storepass " + + storePass + " -keypass " + keyPass); + process.getOutputStream().close(); + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + process.getErrorStream().close(); + String line = null; + while ((line = bReader.readLine()) != null) { + System.out.println(line); + } + + process = Runtime.getRuntime().exec( + "keytool -export -alias " + aliasName + " -storetype " + + Contants.SSL_KEYSTORE_TYPE + " -keystore " + + storePath + " -file " + certName + " -storepass " + + storePass + ""); + + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + while ((line = bReader.readLine()) != null) { + System.out.println(line); + } + + return certName; + } catch (IOException e) { + logger.error("Create a key pair error!"); + logger.error(Utils.printExceptionStack(e)); + return null; + } finally { + if (bReader != null) { + try { + bReader.close(); + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + + } + + /** + * 将公钥引入KeyStore + * + */ + public static boolean importCertToStore(String aliasName, String storePath, + String certName, String storePass) { + BufferedReader bReader = null; + PrintWriter pw = null; + try { + Process process = Runtime.getRuntime().exec( + "keytool -import -v -trustcacerts -alias " + aliasName + + " -keystore " + storePath + " -file " + certName + + " -storetype " + Contants.SSL_KEYSTORE_TYPE + + " -storepass " + storePass + ""); + + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + pw = new PrintWriter(process.getOutputStream()); + + pw.write("y"); + pw.flush(); + pw.close(); + + String line = null; + while ((line = bReader.readLine()) != null) { + System.out.println(line); + } + + return true; + } catch (IOException e) { + logger.error("Error of importing authentication certificate!"); + logger.error(Utils.printExceptionStack(e)); + return false; + } finally { + if (pw != null) { + pw.close(); + } + if (bReader != null) { + try { + bReader.close(); + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + + } + + /** + * 删除KeyStore库中的密钥 + * + */ + public static boolean deleteKeyOrCertFromStore(String aliasName, + String storePath, String storePass) { + BufferedReader bReader = null; + PrintWriter pw = null; + try { + Process process = Runtime.getRuntime().exec( + "keytool -delete -v -alias " + aliasName + " -keystore " + + storePath + " -storetype " + + Contants.SSL_KEYSTORE_TYPE + " -storepass " + + storePass + ""); + + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + pw = new PrintWriter(process.getOutputStream()); + + // pw.write("y"); + pw.flush(); + pw.close(); + + String line = null; + while ((line = bReader.readLine()) != null) { + System.out.println(line); + } + + return true; + } catch (IOException e) { + logger.error("Delete" + storePath+ "library Key" + aliasName + "make a mistake!"); + logger.error(Utils.printExceptionStack(e)); + return false; + } finally { + if (pw != null) { + pw.close(); + } + if (bReader != null) { + try { + bReader.close(); + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + } + + } + + /** + * test main + * + * @time Aug 28, 2011-12:17:28 PM + * @param args + */ + public static void main(String args[]) { + String newServerKeyName = "serverks" + + DateUtil.getCurrentDate(DateUtil.YYYYMMDD); + String newServerKeyPsw = "123456"; + String newClientkeyName = "clientks" + + DateUtil.getCurrentDate(DateUtil.YYYYMMDD); + String newClientkeyPsw = "123456"; + String filepath0 = SSLCertOper.createKeyAndCert(newServerKeyName, + "D:\\workspace\\nms_client\\src\\key\\server_ks", "10.0.6.120", + newServerKeyPsw, "server", + "D:\\workspace\\nms_client\\src\\key\\server.cer"); + + SSLCertOper.importCertToStore(newServerKeyName, + "D:\\workspace\\nms_client\\src\\key\\client_ts", + "D:\\workspace\\nms_client\\src\\key\\server.cer", "client"); + + String filepath1 = SSLCertOper.createKeyAndCert(newClientkeyName, + "D:\\workspace\\nms_client\\src\\key\\client_ks", "localhost", + newClientkeyPsw, "client", + "D:\\workspace\\nms_client\\src\\key\\client.cer"); + + SSLCertOper.importCertToStore(newClientkeyName, + "D:\\workspace\\nms_client\\src\\key\\server_ts", + "D:\\workspace\\nms_client\\src\\key\\client.cer", "server"); + System.out.println(filepath0); + System.out.println(filepath1); + // Config.setValueByName("ssl.server.key.old", + // Constants.SSL_SERVER_KEY_NEW); + // Config.setValueByName("ssl.server.key.old.psw", + // Constants.SSL_SERVER_KEY_NEW_PSW); + // Config.setValueByName("ssl.server.key.new",newServerKeyName); + // Config.setValueByName("ssl.server.key.new.psw", newServerKeyPsw); + // Config.setValueByName("ssl.client.key",newClientkeyName); + // Config.setValueByName("ssl.client.key.psw", newClientkeyPsw); + } +} diff --git a/src/com/nis/nmsclient/thread/socket/SSLClient.java b/src/com/nis/nmsclient/thread/socket/SSLClient.java new file mode 100644 index 0000000..db8dd6d --- /dev/null +++ b/src/com/nis/nmsclient/thread/socket/SSLClient.java @@ -0,0 +1,288 @@ +package com.nis.nmsclient.thread.socket; + +import java.io.File; +import java.util.List; +import java.util.concurrent.Callable; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +import net.sf.json.JSONArray; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.model.ReturnFilePO; +import com.nis.nmsclient.thread.task.TaskReqHandle; +import com.nis.nmsclient.thread.task.TaskResultOper; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.Utils; + + +/** + * 安全通讯的客户端 + **/ + +public class SSLClient extends CommonSocket implements Callable<Object>{ + Logger logger = Logger.getLogger(SSLClient.class); + private String name; + private String reqCmd; + private Object obj; + private String serverHost; + + public SSLClient(String name, String reqCmd, Object obj) { + this.name = name; + this.reqCmd = reqCmd; + this.obj = obj; + this.serverHost = Contants.SOCKET_SERVER_HOST; + } + + public SSLClient(String name, String reqCmd, Object obj, String serverHost) { + this.name = name; + this.reqCmd = reqCmd; + this.obj = obj; + this.serverHost = serverHost; + } + + /** + * 初始化客户端Socket + **/ + public void init() throws Exception { + SSLContext ctx = SSLCertOper.getSSLContext(); + SSLSocketFactory ssf = ctx.getSocketFactory(); + + socket = (SSLSocket) ssf.createSocket(serverHost, + Contants.SOCKET_SERVER_PORT); + logger.debug("create socket success."); + + //2014-1-23 hyx 如果建立socket成功,但是startHandshake握手失败,且未设置超时时间时,则会一直阻塞 + socket.setSoTimeout(1000 * 60 * Contants.SOCKET_TIMEOUT_MINUTES); + + ((SSLSocket) socket).startHandshake(); + logger.debug("handshake success."); + } + + @Override + public Object call() throws Exception { +// Thread.currentThread().setName(name + ">>通信 " + serverHost); + Thread.currentThread().setName(name + ">>Communication " + serverHost); + Object object = null; + try { + init(); + if(socket!=null){ + out = socket.getOutputStream(); + in = socket.getInputStream(); + //设置超时时间 + socket.setSoTimeout(1000 * 60 * Contants.SOCKET_TIMEOUT_MINUTES); + object = toDo(); + } + }catch (Exception e) { +// object = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + "异常"; + object = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + "anomaly"; + logger.error("Communication anomaly:" + Utils.printExceptionStack(e)); + } finally { + logger.debug("关闭通信"); + close(); + } + + return object; + } + + protected Object toDo() throws Exception { + logger.debug("发送通信请求:" + reqCmd); + //-- 无效操作处理 + if(StringUtils.isEmpty(reqCmd)){ + return null; + } + boolean flag = false; + String msg = null; + String result = null; + //-- 命令判断 + // 与Server通信 + if(reqCmd.equals(REQ_HAND_SHAKE)){ + flag = this.sendMessageByChar(reqCmd); + logger.debug("握手状态:" + (result = this.receiveMessageByChar())); + } + // 通知Server准备升级 + if(reqCmd.equals(REQ_SERVER_UPGRADE)){ + flag = this.sendMessageByChar(reqCmd); + result = this.receiveMessageByChar(); + } + // 获取本机标志UUID + if(reqCmd.equals(REQ_LOCAL_UUID)){ + flag = this.sendMessageByChar(reqCmd); + msg = this.receiveMessageByChar(); + flag = this.sendMessageByChar(CommonSocket.SUCCESS); + logger.info("本机标志UUID:" + msg); + } + //注释 by jinsj 2012-0531 修改为DC主动获取NC时间 + // 获取服务器系统时间 + if(reqCmd.equals(REQ_SERVER_SYSTEMDATE)){ + flag = this.sendMessageByChar(reqCmd); + msg = this.receiveMessageByChar(); + logger.debug("服务器系统时间:" + msg); + flag = this.sendMessageByChar(CommonSocket.SUCCESS); + } + // 发送本机的变更信息(操作系统类型和IP) + if(reqCmd.equals(REQ_LOCAL_CHANGE)){ + // 发送请求 + flag = this.sendMessageByChar(reqCmd); + result = this.receiveMessageByChar(); + // 发送信息: UUID$@$操作系统类型$@$LocalIP + flag = this.sendMessageByChar((String)obj); + // 接收变更结果: 0/1 $@$ 信息 + msg = this.receiveMessageByChar(); + flag = this.sendMessageByChar(CommonSocket.SUCCESS); + return msg; + } + // 初始化配置 + if(reqCmd.equals(REQ_INIT_CONFIG)){ + flag = this.sendMessageByChar(reqCmd); + msg = this.receiveMessageByChar();//接收配置信息 + flag = this.sendMessageByChar(CommonSocket.SUCCESS); + } + // 初始化任务 + if(reqCmd.equals(REQ_INIT_TASK)){ + // 发送请求 + flag = this.sendMessageByChar(reqCmd); + result = this.receiveMessageByChar(); + // 发送本机唯一标识 + flag = this.sendMessageByChar(Contants.AGENT_HOST_UUID + ""); + msg = this.receiveMessageByChar(); + flag = this.sendMessageByChar(CommonSocket.SUCCESS); + if (msg != null && !"".equals(msg)) { + JSONArray jsonArr = JSONArray.fromObject(msg); + //这里处理的任务,原则上不应含有”1 文件推送“类型的任务 + for (int i = 0; i < jsonArr.size(); i++) { + new TaskReqHandle().taskHandle(jsonArr.get(i).toString()); + } + } + logger.debug("初始化任务完成--" + msg); + return null; + } + // 发送主动告警信息 + if(reqCmd.equals(REQ_ALARM)){ + if(obj!=null){ + // 主动告警请求 + flag = this.sendMessageByChar(reqCmd); + result = this.receiveMessageByChar(); + // 发送主动告警信息内容 + flag = this.sendMessageByChar((String)obj); + logger.debug("主动告警信息:" + (String)obj); + result = this.receiveMessageByChar(); + }else{ + logger.debug("主动告警信息为空"); + } + } + // 发送任务结果 + if(reqCmd.equals(REQ_TASK_RESULT)){ + if(obj!=null){ + //发送任务结果请求 + flag = this.sendMessageByChar(reqCmd); + result = this.receiveMessageByChar(); + //发送任务结果内容 + flag = this.sendMessageByChar((String)obj); + result = this.receiveMessageByChar(); + }else{ + logger.warn("Task result information is empty"); + } + } + // 批量上传监测数据【数据收集方式改为DC主动后,此通信废弃】 + if(reqCmd.equals(REQ_UPLOAD_DATAS)){ + if(obj!=null && obj instanceof Object[]) { + Object[] objArr = (Object[])obj; + if (objArr != null && objArr.length > 1 && objArr[0] != null + && objArr[1] != null && objArr[1] instanceof List) { + //发送上传数据请求 + flag = this.sendMessageByChar(reqCmd); + result = this.receiveMessageByChar(); + //上传数据 + this.sendFileByBath((String) objArr[0], (List<File>) objArr[1]); + result = this.receiveMessageByChar(); + }else{ + logger.warn("Uploading the contents of the monitored data object is incorrect"); + } + }else{ + logger.warn("Uploading monitoring data objects is empty"); + } + } + // 任务执行的回传文件:单个文件发送,断点续传【数据收集方式改为DC主动后,此类废弃】 + if(reqCmd.equals(REQ_TASK_RETURNFILE)){ + if(obj!=null && obj instanceof ReturnFilePO){ + ReturnFilePO rfPo = (ReturnFilePO)obj; + //发送回传文件请求 + flag = this.sendMessageByChar(reqCmd); + result = this.receiveMessageByChar(); + //发送回传文件任务信息 + this.sendMessageByChar(TaskResultOper.getTaskResultMsg(rfPo + .getTaskId(), rfPo.getTaskType(), null, null, null, rfPo + .getStartTime(), rfPo.getEndTime(), rfPo.getIsLoop())); + result = this.receiveMessageByChar(); + //发送回传文件文件名称 + this.sendMessageByChar(rfPo.getReturnFileName()); + result = this.receiveMessageByChar(); + //发送回传文件 + flag = this.bpSendFile(Contants.localTaskReturnPath + File.separator + rfPo.getReturnFileName()); + result = this.receiveMessageByChar(); + }else{ + logger.warn("The return file object is empty"); + } + } + + // 发送压缩文件,断点续传 + if(reqCmd.equals(REQ_BP_UPLOAD_FIFE)){ + if(obj!=null && obj instanceof String[]) { + String[] strArr = (String[])obj; + if (strArr != null && strArr.length > 1){ + //打包上传文件请求 + flag = this.sendMessageByChar(reqCmd + ":" + strArr[0]); + result = this.receiveMessageByChar(); + //发送打包文件名 + File file = new File(strArr[1]); + flag = this.sendMessageByChar(file.getName()); + result = this.receiveMessageByChar(); + //上传打包文件 + flag = this.bpSendFile(strArr[1]); + result = this.receiveMessageByChar(); + //上传成功后删除或移动文件 + if(flag && SUCCESS.equalsIgnoreCase(result) && file.exists()){ + String dataType = strArr[0]; + if(BP_TYPE_DETECT_DATA.equalsIgnoreCase(dataType)){ + FileUtil.moveFile(file, Contants.localDataDonePath, true); + }else if(BP_TYPE_TASK_RESULT.equalsIgnoreCase(dataType)){ + FileUtil.moveFile(file, Contants.localTaskDonePath, true); + }else if(BP_TYPE_TASK_RETURN.equalsIgnoreCase(dataType)){ + FileUtil.moveFile(file, Contants.localTaskDonePath, true); + } + } + } + } + } + // 向DC发送NC端异常信息 + if(reqCmd.equals(REQ_ERROR_INFO)){ + if(obj!=null){ + flag = this.sendMessageByChar(reqCmd); + result = this.receiveMessageByChar(); + //发送异常内容 + flag = this.sendMessageByChar((String)obj); + result = this.receiveMessageByChar(); + }else{ + logger.warn("Abnormal information is empty"); + } + } + + if (flag && (SUCCESS.equalsIgnoreCase(result) || msg!=null)) { + msg = Contants.COMMON_MSG_SUCCESS + Contants.COMMON_MSG_SEPRATOR + (msg!=null ? msg : "成功"); + } else { +// msg = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + "失败"; + msg = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + "failed"; + } + logger.debug("SSLClient toDo()---" + msg); + + logger.debug("发送通信请求结束:" + reqCmd); + // -- 命令判断 + return msg; + } +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/thread/socket/SSLServer.java b/src/com/nis/nmsclient/thread/socket/SSLServer.java new file mode 100644 index 0000000..27852f8 --- /dev/null +++ b/src/com/nis/nmsclient/thread/socket/SSLServer.java @@ -0,0 +1,534 @@ +package com.nis.nmsclient.thread.socket; + +import java.io.File; +import java.io.IOException; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import net.sf.json.JSONObject; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.filefilter.FalseFileFilter; +import org.apache.commons.io.filefilter.PrefixFileFilter; +import org.apache.commons.lang.ArrayUtils; +import org.apache.log4j.Logger; +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.common.SysConfig; +import com.nis.nmsclient.config.DetecConfReqHandle; +import com.nis.nmsclient.model.ReturnFilePO; +import com.nis.nmsclient.model.Task1; +import com.nis.nmsclient.model.Task4; +import com.nis.nmsclient.model.Task6; +import com.nis.nmsclient.thread.alarm.AlarmUtil; +import com.nis.nmsclient.thread.alarm.ErrorCode; +import com.nis.nmsclient.thread.task.AgentCommand; +import com.nis.nmsclient.thread.task.TaskReqHandle; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.FileWrUtil; +import com.nis.nmsclient.util.Utils; + +/** + * 用于安全通讯的服务Socket,采用java中的SSLServerSocket + * 接收服务端发送过来的对该客户端的各配置参数信息,并对相应程序进行设置 + **/ +public class SSLServer implements Runnable { + static Logger logger = Logger.getLogger(SSLServer.class); + SSLServerSocket ss = null; + + private String startTime;// 服务启动时间 + + public SSLServer() throws IOException{ + init(); + } + + /** + * 初始化服务Socket + **/ + public void init() throws IOException { + try { + startTime = System.currentTimeMillis() + ""; + + //初始化上下文 + SSLContext ctx = SSLCertOper.getSSLContext(); + ss = (SSLServerSocket) ctx.getServerSocketFactory() + .createServerSocket(Contants.SOCKET_AGENT_PORT); + ss.setNeedClientAuth(true);// 客户端要认证 + } catch (Exception e) { + logger.error(Utils.printExceptionStack(e)); +// throw new IOException("NmsClient监听端口[" + Contants.SOCKET_AGENT_PORT + "]创建失败"); + throw new IOException("NmsClient monitor port[" + Contants.SOCKET_AGENT_PORT + "]Create failure"); + } + } + + /** + * 重载方法:run 处理客户端的请求 + **/ + public void run() { + logger.info("通讯线程启动 成功"); + Socket socket = null; + while(true){ + try { + socket = ss.accept(); + if(!Common.NC_UPGRADE_FLAG){//当NC_UPGRADE_FLAG为false时,允许建立通讯,否则放弃通讯,用于NC升级功能 + logger.debug("来自:"+socket.getInetAddress().getHostAddress()); + Common.service.submit(new ServerThread(socket)); + }else{ //关闭 放弃的通讯 + logger.info("NC升级 抛弃通讯:"+socket.getInetAddress().getHostAddress()); + socket.close(); + } + } catch (Exception e) { + logger.error("Failure to establish communication " + ss.getInetAddress().getHostAddress() + + ": " + Utils.printExceptionStack(e)); + } + } + + } + + class ServerThread extends CommonSocket implements Runnable { + + public ServerThread(Socket s) throws Exception { + super(s); + } + + public void run(){ + String ip = null; + try { + ip = socket.getInetAddress().getHostAddress(); + + //设置超时时间 + socket.setSoTimeout(1000 * 60 * Contants.SOCKET_TIMEOUT_MINUTES); + +// Thread.currentThread().setName("通讯线程 》" + socket.getInetAddress().getHostAddress()); + Thread.currentThread().setName("Communication Thread 》" + socket.getInetAddress().getHostAddress()); + + String msg = this.receiveMessageByChar(); + logger.info("接收请求 " + msg); + + if(REQ_HAND_SHAKE.equalsIgnoreCase(msg)){// 握手操作 + //返回接收到的信息和NMSClient启动时间 + this.sendMessageByChar(SUCCESS+":"+msg+"|"+startTime); + }else if(SERVER_COLLECT_DATA.equalsIgnoreCase(msg)){// DC主动向NC收集数据 + /** ----当前通信DC_IP与配置DC_IP不同,更新IP---- **/ + if(!Contants.SOCKET_SERVER_HOST.equals(ip)){ + logger.info("变更通信DC_IP: " + Contants.SOCKET_SERVER_HOST + " --> " + ip); + Contants.SOCKET_SERVER_HOST = ip; + /** ----SeqId未取到,更新配置文件---- **/ + if(Contants.AGENT_HOST_UUID == null){ + SysConfig.updateConfigFile(Contants.SOCKET_SERVER_HOST_KEY, Contants.SOCKET_SERVER_HOST); + } + } + new ServerCollectData(this).sendData(); + }else if(SERVER_GET_TASKRESULT.equalsIgnoreCase(msg)){// DC再次向NC获取未入库的任务结果 + this.sendMessageByChar(SUCCESS); + String taskInfo = null; + List<File> fileList = new LinkedList<File>(); + while(!END.equalsIgnoreCase(taskInfo = this.receiveMessageByChar())){ + // taskInfo组织顺序:TaskId、TaskType、isLoop、startTime、endTime + String[] infos = taskInfo.split(Contants.COMMON_MSG_SEPRATOR_SPLIT); + if (infos.length < 4 || (!"0".equals(infos[2]) && infos.length < 5)) {// 参数个数不够4,或者周期任务参数个数不够5,则跳过本次处理 + logger.warn("DC gets the task result again, the task attribute is incomplete, skip this processing."); + this.sendMessageByChar(AgentCommand.RESULT_FAIL +// + Contants.COMMON_MSG_SEPRATOR + "任务参数不全,找不到任务结果"); + + Contants.COMMON_MSG_SEPRATOR + "i18n_client.SSLServer.sendMsg_n81i"); + continue; + } + String eTime = null; + if(infos.length > 4){// 非周期任务,参数个数为4 + eTime = infos[4]; + } + // 检查指定任务的的结果或回传文件是否存在:若存在,移动到incoming目录;若不存在,回复失败 + boolean isExistResult = checkTaskResultExist(infos[0], infos[1], infos[2], infos[3], eTime, fileList); + if(isExistResult){ + this.sendMessageByChar(AgentCommand.RESULT_OK + + Contants.COMMON_MSG_SEPRATOR + ""); + } else { + this.sendMessageByChar(AgentCommand.RESULT_FAIL +// + Contants.COMMON_MSG_SEPRATOR + "任务结果不存在"); + + Contants.COMMON_MSG_SEPRATOR + "i18n_client.SSLServer.noResult_n81i"); + } + } + this.sendMessageByChar(SUCCESS); + // 移动存在的任务结果和回传文件 + moveTaskResultOrReturn(fileList); + }else if(REQ_SERVER_SYSTEMDATE.equalsIgnoreCase(msg)){//add by jinsj 2012-05-31 DC主动获取NC时间 + this.sendMessageByChar(new Date().getTime()+""); + this.receiveMessageByChar(); + }else if(Contants.AGENT_HOST_UUID == null ){ + // 除了以上三个通信,其他通信都得判断SeqID是否获取到,若未取到,则要放弃通讯 + logger.info("NC尚未取到SeqID 抛弃通讯:"+socket.getInetAddress().getHostAddress()); + close(); + return; + } + + if(REQ_CERT.equalsIgnoreCase(msg)){ + this.sendMessageByChar(SUCCESS); + //接收证书 + this.receiveFileByByte(Contants.keyPath + File.separator + "server.cer"); + this.sendMessageByChar(SUCCESS); + //导入认证证书到库 + SSLCertOper.importCertToStore("serverks" + + DateUtil.getCurrentDate(DateUtil.YYYYMMDD), + Contants.SSL_TRUST_KEY_STORE, + Contants.keyPath + File.separator + "server.cer", Contants.SSL_KEY_STORE_PASS); + File file = new File(Contants.keyPath + File.separator + "server.cer"); + if(file.exists()){ + FileUtil.delDir(file); + } + + /*SSLClient sc = new SSLClient(); + SSLCertOper.CreateAndSendCert(sc); + sc.close();*/ + }else if(SERVER_UPDATE_CONFIG.equalsIgnoreCase(msg)){// 更新监测配置 + this.sendMessageByChar(SUCCESS); + String str = this.receiveMessageByChar(); + this.sendMessageByChar(SUCCESS); + logger.debug("updateConfig-->" + str); + new DetecConfReqHandle().handlerConfigByUpdate(str); + } else if(SEND_PLUGIN_SCRIPT_FILE.equalsIgnoreCase(msg)) { // 下发脚本 + File pluginDir = new File(Contants.localPluginScriptPath); + this.sendMessageByChar(SUCCESS); + String fileNames = this.receiveMessageByChar(); + Collection<?> files = FileUtils.listFiles(pluginDir, + new PrefixFileFilter(fileNames.split(",")), FalseFileFilter.FALSE); + for (Object file : files) { + ((File)file).delete(); + } + this.sendMessageByChar(SUCCESS); + this.bpReceiveFileByBath(pluginDir.getCanonicalPath()); + this.sendMessageByChar(SUCCESS); + + } else if(SERVER_FILE_PUSH.equalsIgnoreCase(msg)){//任务操作:文件推送 + this.sendMessageByChar(SUCCESS); + String str = this.receiveMessageByChar(); + logger.debug("task-->" + str); + this.sendMessageByChar(SUCCESS); + JSONObject jsonObj = JSONObject.fromObject(str); + String resultMsg = null; + if(str.contains("taskInfo")){ + JSONObject jsonObj2 = jsonObj.getJSONObject("taskInfo"); + Object obj = JSONObject.toBean(jsonObj2,Task1.class); + Task1 fileInfo = (Task1) obj; + // 接收文件 + resultMsg = new TaskReqHandle().filePush(this, fileInfo.getTaskParam(), fileInfo.getTaskId(), false); + } + if (resultMsg !=null && Contants.isSucessByResult(resultMsg)) { + this.sendMessageByChar(AgentCommand.RESULT_OK + + Contants.COMMON_MSG_SEPRATOR +// + "成功,详细信息如下:" + Contants.getDescByResult(resultMsg)); + + "i18n_client.SSLServer.success_n81i:" + Contants.getDescByResult(resultMsg)); + } else { + this.sendMessageByChar(AgentCommand.RESULT_FAIL + + Contants.COMMON_MSG_SEPRATOR +// + "失败,详细信息如下:" + Contants.getDescByResult(resultMsg)); + + "i18n_client.SSLServer.fail_n81i:" + Contants.getDescByResult(resultMsg)); + } + this.receiveMessageByChar(); + }else if(SERVER_UPGRADE.equalsIgnoreCase(msg)){//任务操作:升级 + this.sendMessageByChar(SUCCESS); + String str = this.receiveMessageByChar(); + logger.debug("task-->" + str); + this.sendMessageByChar(SUCCESS); + JSONObject jsonObj = JSONObject.fromObject(str); + String resultMsg = null; + TaskReqHandle handle = new TaskReqHandle(); + if(str.contains("taskInfo")){ + JSONObject jsonObj2 = jsonObj.getJSONObject("taskInfo"); + Object obj = JSONObject.toBean(jsonObj2,Task6.class); + Task6 task = (Task6) obj; + // 判断是否重新执行任务,并作提前处理 + reExecTask(task.getTaskId(), task.getOldTaskId()); + // 接收升级文件 + resultMsg = handle.filePush(this, task.getCommandParam(), + task.getTaskId(), true); + } + if (resultMsg !=null && Contants.isSucessByResult(resultMsg)) { + this.sendMessageByChar(AgentCommand.RESULT_SEND_OK + + Contants.COMMON_MSG_SEPRATOR +// + "下发成功,详细信息如下:" + Contants.getDescByResult(resultMsg)); + + "i18n_client.SSLServer.lssueSuccess_n81i:" + Contants.getDescByResult(resultMsg)); + } else { + this.sendMessageByChar(AgentCommand.RESULT_FAIL + + Contants.COMMON_MSG_SEPRATOR +// + "失败,详细信息如下: " + Contants.getDescByResult(resultMsg)); + + "i18n_client.SSLServer.fail_n81i: " + Contants.getDescByResult(resultMsg)); + } + String receiveMsg = this.receiveMessageByChar(); + if(resultMsg !=null && Contants.isSucessByResult(resultMsg) &&receiveMsg.equals(SUCCESS)){//处理升级 + handle.taskHandle(str); + } + }else if(SERVER_TASK.equalsIgnoreCase(msg)){//任务操作:命令执行和升级逆向任务 + this.sendMessageByChar(SUCCESS); + String str = this.receiveMessageByChar(); + logger.debug("task-->" + str); + this.sendMessageByChar(AgentCommand.RESULT_SEND_OK +// + Contants.COMMON_MSG_SEPRATOR + "下发成功"); + + Contants.COMMON_MSG_SEPRATOR + "i18n_client.SSLServer.lssueSuccess1_n81i"); + this.receiveMessageByChar(); + + //2015-6-23 针对reboot命令(之前存在会多次重启的问题,现修改为,接收到命令执行任务时,如果该任务的结果已经存在(incoming或者done里有),则不再执行) + try { + int taskType = 0; + JSONObject jsonObj = JSONObject.fromObject(str); + if(str.contains("typeInfo")){ + taskType = jsonObj.getInt("typeInfo"); + } + if(str.contains("taskInfo") && taskType==4){//taskType:命令执行任务(4) + JSONObject jsonObj2 = jsonObj.getJSONObject("taskInfo"); + Task4 task4 = (Task4)JSONObject.toBean(jsonObj2,Task4.class); + String taskId = task4.getTaskId()==null?"0":(task4.getTaskId()+""); + String isLoop = task4.getIsLoop()+""; + String startTime = task4.getStartTime()==null?"":task4.getStartTime()+""; + String endTime = task4.getEndTime()==null?"":task4.getEndTime()+""; + if(task4.getCommandType() == 2){//命令执行(4)->可执行命令(2) + logger.info("可执行命令 taskId:" + task4.getTaskId()); + List<File> fileList = new ArrayList<File>(); + boolean isExist = checkTaskResultExistFromDoneAndIncoming(taskId+"", taskType+"", isLoop, startTime, endTime, fileList);//非周期任务:0 + if(isExist) { + logger.info("任务已执行,不再重复执行:taskId:"+taskId+" taskType:"+taskType); + return; + } + } + } + } catch (Exception e) { + logger.error("For the next task, determine whether there is a result, if the result is no longer performing the exception", e); + } + + new TaskReqHandle().taskHandle(str); + }else if(SERVER_TASK_CANCEL.equalsIgnoreCase(msg)){//任务撤消操作 + this.sendMessageByChar(SUCCESS); + String str = this.receiveMessageByChar(); + logger.debug("taskcancle-->" + str); + if(str!=null && !"".equals(str)){ + Common.cancleTaskFuture(Long.parseLong(str), 0); + } + this.sendMessageByChar(AgentCommand.MISSION_CANCEL_FINISH +// + Contants.COMMON_MSG_SEPRATOR + "任务已撤消完成"); + + Contants.COMMON_MSG_SEPRATOR + "i18n_client.SSLServer.missionRevokeSuccess_n81i"); + this.receiveMessageByChar(); + }else if(ACTIVE_ALARM_START_ALERT.equalsIgnoreCase(msg)){// NC端是否报主动告警 变更 + this.sendMessageByChar(SUCCESS); + String str = this.receiveMessageByChar(); + this.sendMessageByChar(SUCCESS); + logger.debug("isStartActiveAlarm-->" + str); + JSONObject jsonObj = JSONObject.fromObject(str); + Boolean isStartActiveAlarm = (Boolean)jsonObj.get("showAutoAlarm"); + String webHandleTime = (String)jsonObj.get("webHandleTime"); + //更新Contants.ACTIIVE_ALARM_START + if(isStartActiveAlarm!=null) { + + Contants.ACTIIVE_ALARM_START = isStartActiveAlarm; + logger.info("NC是否主动告警:"+Contants.ACTIIVE_ALARM_START+" web端操作时间:"+webHandleTime); + } + } + + logger.debug("接收请求 " + msg + " 完成"); + } catch (Exception e) { + logger.error("Receiving information anomaly:" + Utils.printExceptionStack(e)); + if(ip==null){ + ip = Utils.getLocalIp(); + } +// AlarmUtil.sendNMSErrorMsg(ErrorCode.SocketError, ip , "NC通讯线程异常:" + e.getMessage()); + AlarmUtil.sendNMSErrorMsg(ErrorCode.SocketError, ip , "NC communication thread exception:" + e.getMessage()); + + return; + } finally { + logger.debug("关闭通信"); + close(); + } + } + + /** + * 重新执行任务,针对升级任务的推送文件的提前处理,将原任务的文件拷贝到新任务的临时目录 + * @param taskId + * @param oldTaskId + * @throws Exception + */ + private void reExecTask(Long taskId, Long oldTaskId) throws Exception { + // 如果原任务ID为空,说明不是重新执行任务,不执行任何操作 + if (oldTaskId == null || "".equals(oldTaskId.toString()) + || "0".equals(oldTaskId.toString())) { + return; + } + File tempDir = new File(Contants.localTempDataIncomingPath + File.separator + + "filepush_" + taskId); + if (!tempDir.exists()) { + tempDir.mkdirs(); + } + // 如果是升级任务,推送文件的保存路径getUpgradeTaskPushPath(taskId) + File oldFileDir = new File(TaskReqHandle.getUpgradeTaskPushPath(oldTaskId)); + try { + if(oldFileDir.exists()){ + FileUtils.copyDirectory(oldFileDir, tempDir); + } + } catch (IOException e) { + logger.error(e); + } + } + + /** + * DC再次获取任务结果 -- 检查指定任务的的结果或回传文件是否存在 + * @param isLoop 是否循环任务: 0 非周期, 1 周期 + * @param startTime 若非周期任务,升级时间或创建时间;若周期任务,某一周期的起始时间 + * @param endTime 若非周期任务,为空;若周期任务,某一周期的结束时间 + * @param fileList 用于存在找到的结果文件和回传文件 + * @return + */ + private boolean checkTaskResultExist(String taskId, String taskType, String isLoop, String sTime, String eTime, List<File> fileList) throws Exception{ + long startTime=(sTime==null || "".equals(sTime) || "null".equals(sTime)) ? 0l : Long.parseLong(sTime); + long endTime=(eTime==null || "".equals(eTime) || "null".equals(eTime)) ? 0l : Long.parseLong(eTime); + logger.debug("checkTaskResultExist startTime=" + DateUtil.getStingDate(DateUtil.YYYY_MM_DD_HH24_MM_SS, new Date(startTime))+" -- endTime=" + DateUtil.getStingDate(DateUtil.YYYY_MM_DD_HH24_MM_SS, new Date(endTime))); + + String dateName = DateUtil.getStingDate(DateUtil.YYYYMMDD, new Date(startTime)); + String prefix = "tasktype" + taskType + "_" + taskId; + + boolean isExistResult = false; + // 依次取nc_task/done下的result和return目录 + File[] fileDirs = FileUtil.getDirectoryArray(new File(Contants.localTaskDonePath)); + if(fileDirs==null){ + logger.info("fileDirs为空"); + }else{ + try{ + for(File dir : fileDirs){ + // -- 找到指定的日期目录dateName及之后的日期目录 + File[] dateFiles = FileUtil.sortASCByFileName(FileUtil.getDirsAfterDateName(dir, dateName)); + // -- 在找到的日期目录下检查文件是否存在 + for(File dateFile : dateFiles){ + File[] files = null; + if("0".equals(isLoop)){// 0 非周期 + files = FileUtil.getFilesStartWith(dateFile, prefix); + }else{//--- 周期任务取某一时间段内的结果与回传文件 + files = FileUtil.getFilesStartWithByMillis(dateFile, prefix, startTime, endTime); + } + + if(files.length>0){// 若在任一目录下找到,则不用再找其他日期目录,跳出第二个For循环 + fileList.addAll(Arrays.asList(files)); + isExistResult = true; + break; + } + } + } + }catch(Exception e){ + logger.error(e); + } + } + if(!isExistResult){ + logger.info("再次获取任务结果 > TaskId: " + taskId + ", TaskType: " + + taskType + ", IsLoop: " + isLoop + " > 任务结果不存在"); + } + + return isExistResult; + } + + /** + * + * 检查done和incoming里是否有任务结果信息(如果有,则不进行再次执行,避免重复执行任务,如重复reboot) + * @author dell Jun 23, 2015 + * @version 1.0 + * @param taskId + * @param taskType + * @param isLoop + * @param sTime + * @param eTime + * @param fileList + * @return + * @throws Exception + */ + private boolean checkTaskResultExistFromDoneAndIncoming(String taskId, String taskType, String isLoop, String sTime, String eTime, List<File> fileList) throws Exception{ + long startTime=(sTime==null || "".equals(sTime) || "null".equals(sTime)) ? 0l : Long.parseLong(sTime); + long endTime=(eTime==null || "".equals(eTime) || "null".equals(eTime)) ? 0l : Long.parseLong(eTime); + logger.debug("checkTaskResultExist startTime=" + DateUtil.getStingDate(DateUtil.YYYY_MM_DD_HH24_MM_SS, new Date(startTime))+" -- endTime=" + DateUtil.getStingDate(DateUtil.YYYY_MM_DD_HH24_MM_SS, new Date(endTime))); + + String dateName = DateUtil.getStingDate(DateUtil.YYYYMMDD, new Date(startTime)); + String prefix = "tasktype" + taskType + "_" + taskId; + + boolean isExistResult = false; + // 依次取nc_task/done和incoming下的result和return目录 + File[] fileDoneDirs = FileUtil.getDirectoryArray(new File(Contants.localTaskDonePath)); + File[] fileIncomingDirs = FileUtil.getDirectoryArray(new File(Contants.localTaskResultPath)); + File[] fileDirs = null; + if(fileIncomingDirs!=null && fileDoneDirs!=null) { + fileDirs = (File[])ArrayUtils.addAll(fileDoneDirs, fileIncomingDirs); + } + if(fileDirs==null){ + logger.info("fileDirs为空"); + }else{ + try{ + for(File dir : fileDirs){ + // -- 找到指定的日期目录dateName及之后的日期目录 + File[] dateFiles = FileUtil.sortASCByFileName(FileUtil.getDirsAfterDateName(dir, dateName)); + // -- 在找到的日期目录下检查文件是否存在 + for(File dateFile : dateFiles){ + File[] files = null; + if("0".equals(isLoop)){// 0 非周期 + files = FileUtil.getFilesStartWith(dateFile, prefix); + }else{//--- 周期任务取某一时间段内的结果与回传文件 + files = FileUtil.getFilesStartWithByMillis(dateFile, prefix, startTime, endTime); + } + + if(files.length>0){// 若在任一目录下找到,则不用再找其他日期目录,跳出第二个For循环 + fileList.addAll(Arrays.asList(files)); + isExistResult = true; + break; + } + } + } + }catch(Exception e){ + logger.error(e); + } + } + if(!isExistResult){ + logger.info("判断新下发的任务结果是否已经存在 > TaskId: " + taskId + ", TaskType: " + + taskType + ", IsLoop: " + isLoop + " > 任务结果不存在"); + }else { + logger.info("判断新下发的任务结果是否已经存在 > TaskId: " + taskId + ", TaskType: " + + taskType + ", IsLoop: " + isLoop + " > 任务结果已存在"); + } + + return isExistResult; + } + + /** + * DC再次获取任务结果 -- 移动找到的结果文件和回传文件到incoming目录 + */ + private void moveTaskResultOrReturn(List<File> fileList){ + if(fileList==null || fileList.size()==0){ + return; + } + try { + for(File file : fileList){ + // ---------- 任务回传文件处理 + if(file.getName().endsWith(Contants.TASK_RETURN_FILE_SUFFIX)){ + if(!file.exists() || !file.isFile()){ + continue; + } + // 移动实际回传的文件 + String[] resultArr = FileWrUtil.cfgFileReader(file); + if (resultArr != null && resultArr.length > 0) { + JSONObject jsonObject = JSONObject.fromObject(resultArr[0]); + ReturnFilePO rfPo = (ReturnFilePO) JSONObject.toBean(jsonObject, ReturnFilePO.class); + if(rfPo.getReturnFileName()!=null && !"".equals(rfPo.getReturnFileName())){ + File returnFile = new File(file.getParent() + File.separator + rfPo.getReturnFileName()); + FileUtil.moveFile(returnFile, Contants.localTaskReturnPath, true); + } + } + // 移动记录任务回传的临时文件 + FileUtil.moveFile(file, Contants.localTaskReturnPath, true); + }else { + // ---------- 任务结果处理 + FileUtil.moveFile(file, Contants.localTaskResultPath, true); + } + } + } catch (Exception e) { + logger.error("Get the task result again > mobile file exception again", e); + } + } + } + +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/thread/socket/ServerCollectData.java b/src/com/nis/nmsclient/thread/socket/ServerCollectData.java new file mode 100644 index 0000000..fa55551 --- /dev/null +++ b/src/com/nis/nmsclient/thread/socket/ServerCollectData.java @@ -0,0 +1,581 @@ +package com.nis.nmsclient.thread.socket; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import net.sf.json.JSONObject; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.model.ReturnFilePO; +import com.nis.nmsclient.thread.task.TaskResultOper; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.FileWrUtil; +import com.nis.nmsclient.util.StringUtil; +import com.nis.nmsclient.util.Utils; +import com.nis.nmsclient.util.ZipUtil; + +/** + * 用于定时扫描并上传监测数据文件 + * + **/ +public class ServerCollectData { + Logger logger = Logger.getLogger(ServerCollectData.class); + private CommonSocket socket; + + public ServerCollectData(CommonSocket socket) { + this.socket = socket; + } + + public void sendData() { + logger.debug("传送数据开始 ~~~~~~~"); + try { + // 发送监测数据 + handleDetectData(); + // 发送任务结果 + handleTaskResult(); + // 发送任务回传文件 + handleTaskReturnFile(); + // 发送任务结果--针对有回传文件时写的任务结果 + handleTaskResult(); + // 结束通讯 + socket.sendMessageByChar(CommonSocket.END); + + } catch (Exception e) { + logger.error("Transmits data anomalies:" + Utils.printExceptionStack(e)); + } + logger.debug("传送数据结束 ~~~~~~~"); + } + + private void handleDetectData() throws Exception { + logger.debug("传送监测数据开始 ~~~~~~~"); + long startTime = System.currentTimeMillis(); + File parDir = new File(Contants.localDataCollection); + if(!parDir.exists()){ + return; + } + // == 1、针对数据文件过多时打包上传未完成的文件继续上传 + // ------------取所有未上传完成的Zip文件 + List<File> fileList = new LinkedList<File>(); + File[] fileArr = FileUtil.getFilesEndWith(parDir, ".zip"); + if (fileArr != null && fileArr.length > 0) { + for (File file : fileArr) { + if (!file.getName().startsWith(CommonSocket.BP_TYPE_DETECT_DATA)) { + continue; + } + fileList.add(file); + } + } + // ------------传送Zip文件 + if (fileList.size() > 0) { + sendZipFile(fileList, CommonSocket.DATA_TYPE_ZIP_DETECT); + } + + // == 2、检查当前数据文件数量,批量发送文件或打包上传 + File dataDir = new File(Contants.localDataFilePath); + if (!dataDir.exists()) { + logger.warn("Data directory“" + dataDir.getAbsolutePath() + "”Non-existent!!!"); + } else { + long total = 0; + List<File> allFiles = new ArrayList<File>(); + File[] dataDirs = FileUtil.getDirectoryArray(dataDir); + // ---- 数据处理 + total = handleNullDataFile(allFiles, dataDirs); + logger.info("本次收集监测数据文件总数:" + total + ", 正常数据:" + allFiles.size() + ", 空数据:" + (total - allFiles.size())); + total = allFiles.size();// 正常的要上传的数据个数 + + // --- 将所有数据文件一起打包,发送 + if (total > Contants.COMMON_ZIP_MIN_SIZE) { + long zipCnt = total/Contants.COMMON_ZIP_MAX_SIZE; + if (zipCnt > 0) {//2013-5-6 未上传的数据太多时,将监测数据压缩为多个文件 + for(int i=0; i<total/Contants.COMMON_ZIP_MAX_SIZE; i++){ + // 组织每次压缩的文件数组 + File[] dataFiles = new File[Contants.COMMON_ZIP_MAX_SIZE]; + int start = i * Contants.COMMON_ZIP_MAX_SIZE; + int end = (i + 1) * Contants.COMMON_ZIP_MAX_SIZE; + for (int j = start, k = 0; j < end; j++, k++) { + dataFiles[k] = allFiles.get(j); + } + // 压缩并发送监测数据 + compressAndSendDetecData(dataFiles); + } + }else{ + // 压缩并发送监测数据 + compressAndSendDetecData(dataDirs); + } + logger.info("本次收集将所有监测数据打包传送,监测数据总数:" + total + ",用时:" + + (System.currentTimeMillis() - startTime) + "ms"); + } else if (total > 0) { + // -- 按正常所有监测数据批量上传 + sendCSVData(dataDir, allFiles); + logger.info("本次收集传送监测数据总数:" + total + ",用时:" + + (System.currentTimeMillis() - startTime) + "ms"); + } else { + logger.info("本次收集未传送监测数据"); + } + } + logger.debug("传送监测数据结束 ~~~~~~~"); + } + + private void handleTaskResult() throws Exception { + logger.debug("传送任务结果开始 ~~~~~~~"); + long startTime = System.currentTimeMillis(); + // == 1、针对结果文件过多时打包上传未完成的文件继续上传 + File taskDir = new File(Contants.localTaskPath); + if (!taskDir.exists()) { + return; + } + // ------------取所有未上传完成的Zip文件 + List<File> fileList = new LinkedList<File>(); + File[] zipArr = FileUtil.getFilesEndWith(taskDir, ".zip"); + if (zipArr != null && zipArr.length > 0) { + for (File file : zipArr) { + if (!file.getName().startsWith(CommonSocket.BP_TYPE_TASK_RESULT)) { + continue; + } + fileList.add(file); + } + } + // ------------传送Zip文件 + if(fileList.size()>0){ + sendZipFile(fileList, CommonSocket.DATA_TYPE_ZIP_TASKRESULT); + } + + // == 2、检查当前结果文件数量,批量发送文件或打包上传 + File resultDir = new File(TaskResultOper.getTaskResultPath()); + if(!resultDir.exists()){ + return; + } + File[] fileArr = FileUtil.getFilesEndWith(resultDir, Contants.TASK_RESULT_FILE_SUFFIX); + // -- 将所有任务结果文件一起打包,发送 + if(fileArr.length > Contants.COMMON_ZIP_MIN_SIZE){ + int zipCnt = fileArr.length/Contants.COMMON_ZIP_MAX_SIZE; + if(zipCnt>0){//2013-5-6 未上传的结果文件太多时,将结果文件压缩为多个文件 + for(int i=0; i<fileArr.length/Contants.COMMON_ZIP_MAX_SIZE; i++){ + // 组织每次压缩的文件数组 + File[] resultFiles = new File[Contants.COMMON_ZIP_MAX_SIZE]; + int start = i * Contants.COMMON_ZIP_MAX_SIZE; + int end = (i + 1) * Contants.COMMON_ZIP_MAX_SIZE; + for(int j=start,k=0; j<end; j++,k++){ + resultFiles[k] = fileArr[j]; + } + // 压缩并发送任务结果 + compressAndSendTaskResult(resultFiles); + } + }else{ + // 压缩并发送任务结果 + compressAndSendTaskResult(fileArr); + } + + logger.info("本次收集将所有任务结果打包传送,任务结果总数:" + fileArr.length + ",用时:" + (System.currentTimeMillis() - startTime) + "ms"); + }else if(fileArr.length > 0){ + // -- 按正常的多个结果批量发送 + sendTaskResult(fileArr); + logger.info("本次收集传送任务结果总数:" + fileArr.length + ",用时:" + + (System.currentTimeMillis() - startTime) + "ms"); + } else { + logger.info("本次收集未传送任务结果"); + } + logger.debug("传送任务结果结束 ~~~~~~~"); + } + + private void handleTaskReturnFile() throws Exception { + logger.debug("传送回传文件开始 ~~~~~~~"); + long startTime = System.currentTimeMillis(); + // == 1、针对回传文件过多时打包上传未完成的文件继续上传 + File taskDir = new File(Contants.localTaskPath); + if (!taskDir.exists()) { + return; + } + // ------------取所有未上传完成的Zip文件 + List<File> fileList = new LinkedList<File>(); + File[] zipArr = FileUtil.getFilesEndWith(taskDir, ".zip"); + if (zipArr != null && zipArr.length > 0) { + for (File file : zipArr) { + if (!file.getName().startsWith(CommonSocket.BP_TYPE_TASK_RETURN)) { + continue; + } + fileList.add(file); + } + } + // ------------传送Zip文件 + if(fileList.size()>0){ + sendZipFile(fileList, CommonSocket.DATA_TYPE_ZIP_TASKRETURN); + } + + // == 2、检查当前回传文件数量,单个发送文件或打包上传 + File returnDir = new File(Contants.localTaskReturnPath); + if(!returnDir.exists()){ + return; + } + File[] fileArr = FileUtil.getFilesEndWith(returnDir, Contants.TASK_RETURN_FILE_SUFFIX); + if(fileArr == null || fileArr.length == 0){ + return; + } + //--- 将所有任务的回传文件及回传信息保存文件一起打包,发送 + if(fileArr.length > Contants.COMMON_MAX_RETURN_CNT){ + //压缩并删除原文件 + String compressFileStr = Contants.localTaskPath + + File.separator + + CommonSocket.addTimeTagForFileName(CommonSocket.BP_TYPE_TASK_RETURN, + null, true) + + ".zip"; + // 2013-03-22 由于DC再次获取未保存任务结果这个功能的实现,现修改将任务结果和回传文件压缩时不删除文件,而是将其移动到相应的日期目录 + ZipUtil.zipWithMoveFile(returnDir.listFiles(), compressFileStr, false); + //发送 + sendZipFile(new File(compressFileStr), CommonSocket.DATA_TYPE_ZIP_TASKRETURN); + logger.info("本次收集将所有任务回传文件打包传送,回传文件总数:" + fileArr.length + ",用时:" + (System.currentTimeMillis() - startTime) + "ms"); + }else if(fileArr.length > 0){ + //-- 按正常的一个任务一个任务的回传 + sendTaskReturn(fileArr); + logger.info("本次收集传送任务回传总数:" + fileArr.length + ",用时:" + + (System.currentTimeMillis() - startTime) + "ms"); + } else { + logger.info("本次收集未传送任务回传文件"); + } + logger.debug("传送回传文件结束 ~~~~~~~"); + } + + /** + * 遍历所有准备上传的数据文件,将空数据文件移动到指定目录,并记录所有文件总数 + * @param allFiles 所有非空文件集合 + * @param dataDirs 所有数据目录 + * @return 所有文件个数(包括空文件) + * @throws Exception + */ + private long handleNullDataFile(List<File> allFiles, File[] dataDirs) throws Exception { + long total = 0l; + for(File dir : dataDirs){ + File[] files = FileUtil.getFilesEndWith(dir, ".csv"); + if(files==null || files.length==0){ + continue; + } + files = FileUtil.sortASCByModify(files); // 修改日期升序排序 + total += files.length; + for (File file : files) { + if (file.length() > 0) { + allFiles.add(file); + continue; + } + //--- 处理空文件数据:移动空文件数据到指定日期目录 + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = Contants.localDataErrorPath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + FileUtil.moveFile(file, newDir, true); + } + } + return total; + } + + private void compressAndSendDetecData(File[] dataFiles) throws Exception{ + // 压缩并移动原文件 + String compressFileStr = Contants.localDataCollection + + File.separator + + CommonSocket.addTimeTagForFileName( + CommonSocket.BP_TYPE_DETECT_DATA, null, true) + + ".zip"; + // 2013-3-29 由于压缩上传数据后,主动告警线程部分对数据检查存在问题,现将压缩后删除数据改为移动数据到日期目录 + ZipUtil.zipWithMoveFile(dataFiles, compressFileStr, true); + // 发送 + sendZipFile(new File(compressFileStr), CommonSocket.DATA_TYPE_ZIP_DETECT); + } + + private void compressAndSendTaskResult(File[] resultFiles) throws Exception { + //压缩并删除原文件 + String compressFileStr = Contants.localTaskPath + + File.separator + + CommonSocket.addTimeTagForFileName(CommonSocket.BP_TYPE_TASK_RESULT, null, true) + + ".zip"; + // 2013-03-22 由于DC再次获取未保存任务结果这个功能的实现,现修改将任务结果和回传文件压缩时不删除文件,而是将其移动到相应的日期目录 + ZipUtil.zipWithMoveFile(resultFiles, compressFileStr, true); + //发送 + sendZipFile(new File(compressFileStr), CommonSocket.DATA_TYPE_ZIP_TASKRESULT); + } + + private void compressAndSendTaskReturn(File[] returnFiles) throws Exception { + //压缩并删除原文件 + String compressFileStr = Contants.localTaskPath + + File.separator + + CommonSocket.addTimeTagForFileName(CommonSocket.BP_TYPE_TASK_RETURN, + null, true) + + ".zip"; + // 2013-03-22 由于DC再次获取未保存任务结果这个功能的实现,现修改将任务结果和回传文件压缩时不删除文件,而是将其移动到相应的日期目录 + ZipUtil.zipWithMoveFile(returnFiles, compressFileStr, false); + //发送 + sendZipFile(new File(compressFileStr), CommonSocket.DATA_TYPE_ZIP_TASKRETURN); + } + + /** + * 发送打包文件:整个命令通信包装方法 + * @param file + * @throws Exception + */ + private void sendZipFile(File file, String dataType) throws Exception { + //打包上传文件请求 + socket.sendMessageByChar(dataType); + socket.receiveMessageByChar(); + socket.sendMessageByChar(file.getName());//发送打包文件名 + socket.receiveMessageByChar(); + //上传打包文件 + socket.bpSendFile(file.getAbsolutePath()); + String result = socket.receiveMessageByChar(); + //上传成功后移动文件 + if(CommonSocket.SUCCESS.equalsIgnoreCase(result)){ + if(CommonSocket.DATA_TYPE_ZIP_DETECT.equalsIgnoreCase(dataType)){ + FileUtil.moveFile(file, Contants.localDataDonePath, true); + }else if(CommonSocket.DATA_TYPE_ZIP_TASKRESULT.equalsIgnoreCase(dataType)){ + FileUtil.moveFile(file, Contants.localTaskDonePath, true); + }else if(CommonSocket.DATA_TYPE_ZIP_TASKRETURN.equalsIgnoreCase(dataType)){ + FileUtil.moveFile(file, Contants.localTaskDonePath, true); + } + } + } + + private void sendZipFile(List<File> fileList, String dataType) throws Exception { + for(File file : fileList){ + sendZipFile(file, dataType); + } + } + + // 批量发送ZIP的 + /*private void sendZipFile(List<File> fileList, String parDir) throws Exception { + //打包上传文件请求 + socket.sendMessageByChar(CommonSocket.DETECT_DATA_TYPE_ZIP); + socket.receiveMessageByChar(); + //上传打包文件 + socket.bpSendFileByBath(fileList, parDir); + String result = socket.receiveMessageByChar(); + //上传成功后移动文件 + if(CommonSocket.SUCCESS.equalsIgnoreCase(result)){ + for(File file : fileList){ + FileUtil.moveFile(file, Contants.localDataDonePath, true); + } + } + }*/ + + /** + * 批量发送CSV数据文件 + * @param dataDir + * @param allFiles + * @throws Exception + */ + private void sendCSVData(File dataDir, List<File> allFiles) throws Exception { + //发送上传数据请求 + socket.sendMessageByChar(CommonSocket.DATA_TYPE_CSV_DETECT); + socket.receiveMessageByChar(); + //上传数据 + socket.sendFileByBath(dataDir.getParent(), allFiles); + String result = socket.receiveMessageByChar(); + if (CommonSocket.SUCCESS.equalsIgnoreCase(result)) { + /** + * 移动上传成功的数据文件到指定日期目录 + */ + File[] files = new File[allFiles.size()]; + moveDetecDataToDateDir(allFiles.toArray(files)); + } + } + + /** + * 批量发送任务结果 + * @param fileArr + * @throws Exception + */ + private void sendTaskResult(File[] fileArr) throws Exception { + //2013-4-16 修改升序排列方式:按修改时间 改为 按文件名,任务结果文件名都有时间后缀(ms),文件修改时间只到s取不到ms + fileArr = FileUtil.sortASCByFileName(fileArr); + List<String> results = new LinkedList<String>(); + StringBuffer sb = new StringBuffer(); + for(File file : fileArr){ + sb.delete(0, sb.length()); + if(!file.exists() || !file.isFile()){ + continue; + } + String[] resultArr = FileWrUtil.cfgFileReader(file); + if(resultArr!=null && resultArr.length>0){ + for(String res : resultArr){ + sb.append(res + ";"); + } + sb.deleteCharAt(sb.length()-1); + results.add(sb.toString()); + } + } + logger.debug("sendTaskResult-->" + Arrays.toString(results.toArray())); + //发送任务结果请求 + socket.sendMessageByChar(CommonSocket.DATA_TYPE_OBJ_TASKRESULT); + socket.receiveMessageByChar(); + //发送任务结果内容 + socket.sendObject(results); + String result = socket.receiveMessageByChar(); + if (CommonSocket.SUCCESS.equalsIgnoreCase(result)) { + // 移动上传成功的任务结果到指定日期目录 + moveTaskResultToDateDir(fileArr); + } + } + /** + * 单个发送任务回传文件 + * @param fileArr + * @throws Exception + */ + private void sendTaskReturn(File[] fileArr) throws Exception { + fileArr = FileUtil.sortASCByModify(fileArr); //修改日期升序排序 + for(File file : fileArr){ + if(!file.exists() || !file.isFile()){ + continue; + } + String[] resultArr = FileWrUtil.cfgFileReader(file); + if (resultArr == null || resultArr.length <= 0) { + continue; + } + JSONObject jsonObject = JSONObject.fromObject(resultArr[0]); + ReturnFilePO rfPo = (ReturnFilePO) JSONObject.toBean(jsonObject, ReturnFilePO.class); + + //--回传文件名和回传描述信息均为空时,则无回传文件 + if(StringUtil.isEmpty(rfPo.getReturnFileName()) && StringUtil.isEmpty(rfPo.getResDesc())){ + logger.warn("No return file, no return"); + FileUtil.delDir(file); + continue; + } + //--回传文件名为空,但回传描述信息不为空,则进行步骤2发送任务结果、删除文件 + /** + * 步骤1、回传文件 + */ + StringBuffer sb = new StringBuffer(); + if(rfPo.getResDesc()!=null){//取已有的结果描述信息 + sb.append(rfPo.getResDesc()); + } + //准备回传文件,回传文件名不为空即有回传的文件时,再回传 + boolean success = false; + if(rfPo.getReturnFileName()!=null && rfPo.getReturnFileName().trim().length()>0){ + //发送回传文件请求 + socket.sendMessageByChar(CommonSocket.DATA_TYPE_FILE_TASKETURN); + socket.receiveMessageByChar(); + //发送回传文件任务信息 + socket.sendMessageByChar(TaskResultOper.getTaskResultMsg(rfPo + .getTaskId(), rfPo.getTaskType(), null, null, null, rfPo + .getStartTime(), rfPo.getEndTime(), rfPo.getIsLoop())); + socket.receiveMessageByChar(); + //发送回传文件文件名称 + socket.sendMessageByChar(rfPo.getReturnFileName()); + socket.receiveMessageByChar(); + //发送回传文件 + socket.bpSendFile(Contants.localTaskReturnPath + File.separator + rfPo.getReturnFileName()); + String result = socket.receiveMessageByChar(); + success = true; +// sb.append("回传成功"); + sb.append("i18n_client.ServerCollectData.transFile_n81i"); + }else{ + success = true; + } + + /** + * 步骤2、判断文件是否回传完成 + */ + if(success){ + /** + * 步骤2-1、发送任务结果 + */ + TaskResultOper.sendTaskResult(rfPo.getTaskId(), rfPo.getTaskType(), + rfPo.getState(), sb.toString(), "", rfPo.getStartTime(), + rfPo.getEndTime(), false, rfPo.getIsLoop()); + /** + * 步骤2-2、移动上传成功的 保存回传文件信息的文件 和 回传文件 到指定日期目录 + */ + moveTaskReturnToDateDir(file, rfPo.getReturnFileName()); + } + } + } + + + /** + * 移动上传成功的任务结果到指定日期目录 + * 完整文件到目录:.../done/result/yyyyMMdd + * 0大小文件到目录: .../error/result/yyyyMMdd + */ + public static void moveTaskResultToDateDir(File... fileArr){ + if(fileArr==null || fileArr.length==0){ + return; + } + for (File file : fileArr) { + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = ""; + if (file.length() > 0) { + newDir = Contants.localTaskDonePath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } else { + newDir = Contants.localTaskErrorPath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } + // -- 文件移动 + FileUtil.moveFile(file, newDir, true); + } + } + + /** + * 移动上传成功的 保存回传文件信息的文件 和 回传文件 到指定日期目录 + * 完整文件到目录:.../done/return/yyyyMMdd + * 0大小文件到目录: .../error/return/yyyyMMdd + */ + public static void moveTaskReturnToDateDir(File file, String returnFileName){ + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = Contants.localTaskDonePath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + // -- 文件移动 + FileUtil.moveFile(file, newDir, true);// 保留任务信息的临时文件.return + if(returnFileName!=null && !"".equals(returnFileName)){// 实际回传的文件 + File curReturnFile = new File(Contants.localTaskReturnPath + File.separator + returnFileName); + FileUtil.moveFile(curReturnFile, newDir, true); + } + + } + + /** + * 移动上传成功的数据文件到指定日期目录 + * 完整文件到目录:.../done/type_procIden/yyyyMMdd + * 0大小文件到目录: .../error/type_procIden/yyyyMMdd + */ + public static void moveDetecDataToDateDir(File... allFiles){ + if(allFiles==null || allFiles.length==0){ + return; + } + for (File file : allFiles) { + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = ""; + if (file.length() > 0) { + newDir = Contants.localDataDonePath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } else { + newDir = Contants.localDataErrorPath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } + // -- 文件移动 + FileUtil.moveFile(file, newDir, true); + } + } + +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/thread/task/AgentCommand.java b/src/com/nis/nmsclient/thread/task/AgentCommand.java new file mode 100644 index 0000000..c165fef --- /dev/null +++ b/src/com/nis/nmsclient/thread/task/AgentCommand.java @@ -0,0 +1,1928 @@ + package com.nis.nmsclient.thread.task; + +import java.io.File; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import net.sf.json.JSONObject; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.common.VersionCfg; +import com.nis.nmsclient.model.CommandPO; +import com.nis.nmsclient.model.ParamBackup; +import com.nis.nmsclient.model.ParamCmdExec; +import com.nis.nmsclient.model.ParamCoverUpdate; +import com.nis.nmsclient.model.ParamUpgrade; +import com.nis.nmsclient.model.ReturnFilePO; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.thread.socket.SSLClient; +import com.nis.nmsclient.util.CompressFileMgr; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.FileWrUtil; +import com.nis.nmsclient.util.ProcessUtil; +import com.nis.nmsclient.util.Utils; + +public class AgentCommand { + static Logger logger = Logger.getLogger(AgentCommand.class); + public static final int RESULT_OK = 0; + public static final int RESULT_FAIL = 1; + public static final int RESULT_SEND_OK = 40; + public static final int RESULT_SEND_FAIL = 41; + public static final int RESULT_KILL_OK = 50; + public static final int RESULT_KILL_FAIL = 51; + public static final int RESULT_BACKUP_OK = 60; + public static final int RESULT_BACKUP_FAIL = 61; + public static final int RESULT_UPDATE_OK = 70; + public static final int RESULT_UPDATE_FAIL = 71; + public static final int RESULT_START_OK = 80; + public static final int RESULT_START_FAIL = 81; + public static final int RESULT_RECOVER_OK = 90; + public static final int RESULT_RECOVER_FAIL = 91; + public static final int MISSION_CANCEL_CREATE = 5;//任务准备撤消 + public static final int MISSION_CANCEL_START = 6;//任务撤消中 + public static final int MISSION_CANCEL_FINISH = 7;//任务撤消完成 + + private static final String RESULT_SEPRATOR = Contants.COMMON_MSG_SEPRATOR; + private static final String RESULT_SEPRATOR_SPLIT = Contants.COMMON_MSG_SEPRATOR_SPLIT; + + public static enum UpgradeSteps { + upgrade_agent, upgrade_other, + upgrade_server, upgrade_kill_process, + upgrade_backup, upgrade_update, + upgrade_start, upgrade_recover, + upgrade_exec, single_exec; + } + public static final String PARAM_SEPRATOR = "@&##&@"; + + // NC/DC升级锁,确保NC与DC不同时升级 + private static final Byte[] upgradeLock = new Byte[0]; + + private CommandPO command; + private Thread thread; + + public AgentCommand(CommandPO command) { + super(); + this.command = command; + } + + public boolean exec(){ + Date execTime = new Date(); +// String resultDesc = "执行失败"; +// String resultDesc = "Failure to execute"; + String resultDesc = "i18n_client.AgentCommand.execFail_n81i"; + long resultState = RESULT_FAIL; + boolean isServer = false; + try { + String commandParam = command.getCommandParam(); + if(commandParam==null || "".equals(commandParam)){ +// resultDesc = "执行失败:命令参数为空"; +// resultDesc = "Execution failure: command parameters are empty"; + resultDesc = "i18n_client.AgentCommand.execFailDesc1_n81i"; + resultState = RESULT_FAIL; +// logger.warn(resultDesc);//i18nlog + } else { + logger.debug("commandParam 1--" + commandParam); + //2012-4-28 任务参数中对路径的格式化将在界面上进行,原因此处会对转义字符的\也转换为/,故replace("\\", "/")去掉 + commandParam = commandParam.trim().replaceAll("[\n\t\r]","");//.replace("\\", "/");//[\\s*\n\t\r] + logger.debug("commandParam 2--" + commandParam); + String[] params = commandParam.trim().split(PARAM_SEPRATOR); + if (params != null && params.length >= 1) { + for(int i=0; i<params.length; i++){ + params[i] = params[i].trim(); + } + UpgradeSteps step = Enum.valueOf(UpgradeSteps.class,command.getCommandName()); + String resultStr = ""; + switch (step) { + case upgrade_server:// 命令参数,以;分隔的一个CommandForUpgrade对象的Json字符串 + isServer = true; + synchronized (upgradeLock) {//DC升级时锁,确保不与NC同时升级 + resultStr = upgradeOther(params, command + .getSrcPath(), command.getExecState(), command + .getExecId(), command.getExecVersion(), + isServer); + } + break; + case upgrade_other:// 命令参数,以;分隔的多个CommandForUpgrade对象的Json字符串 + resultStr = upgradeOther(params, command + .getSrcPath(), command.getExecState(), command + .getExecId(), command.getExecVersion(), + isServer); + break; + case upgrade_agent:// 命令参数,以;分隔的一个CommandForUpgrade对象的Json字符串 + //-- NC升级开始 关闭通讯 + Common.NC_UPGRADE_FLAG = true; + synchronized (upgradeLock) {//NC升级时锁,确保不与DC同时升级 + resultStr = upgradeAgent(params[0], command + .getSrcPath(), command.getExecState(), command + .getExecId(), command.getExecVersion()); + } + //-- NC升级完成 打开通讯 + Common.NC_UPGRADE_FLAG = false; + break; + case upgrade_kill_process:// 命令参数, 以;分隔的多个存放进程ID的文件 + resultStr = killProcessCmd(params); + break; + case upgrade_backup:// 命令参数,以;分隔的多个Backup对象的Json字符串 + ParamBackup[] backups = new ParamBackup[params.length]; + for (int i = 0; i < params.length; i++) { + logger.debug("backupCmd-->param: " + params[i]); + ParamBackup backup = (ParamBackup) JSONObject + .toBean(JSONObject.fromObject(params[i]), + ParamBackup.class); + backups[i] = backup; + } + resultStr = backupCmd(backups, null, command + .getExecId()); + break; + case upgrade_update:// 命令参数,以;分隔多个CoverUpdate对象的Json字符串 + case upgrade_recover:// 命令参数,以;分隔多个CoverUpdate对象的Json字符串 + ParamCoverUpdate[] updates = new ParamCoverUpdate[params.length]; + for (int i = 0; i < params.length; i++) { + logger.debug("updateCmd-->param: " + params[i]); + ParamCoverUpdate update = (ParamCoverUpdate) JSONObject + .toBean(JSONObject.fromObject(params[i]), + ParamCoverUpdate.class); + updates[i] = update; + } + resultStr = updateCmd(updates); + break; + case upgrade_start:// 命令参数,以;分隔多个CmdExec对象的Json字符串 + case upgrade_exec:// 可执行命令 + List<ParamCmdExec> execList = new ArrayList<ParamCmdExec>(); + for (String param : params) { + logger.debug("startCmd-->param: " + param); + ParamCmdExec exec = (ParamCmdExec) JSONObject + .toBean(JSONObject.fromObject(param), + ParamCmdExec.class); + execList.add(exec); + } + resultStr = startCmd(execList, execTime, false, command.getExecState()); + break; + case single_exec:// 单次执行命令,命令参数,以;分隔多个CmdExec对象的Json字符串 + List<ParamCmdExec> cmdExecList = new ArrayList<ParamCmdExec>(); + for (String param : params) { + logger.debug("singleExecCmd-->param: " + param); + ParamCmdExec exec = (ParamCmdExec) JSONObject + .toBean(JSONObject.fromObject(param), + ParamCmdExec.class); + cmdExecList.add(exec); + } + resultStr = singleExecCmd(cmdExecList, execTime, command.getExecState()); + break; + + default: +// resultDesc = "执行失败,不存在该命令"; +// resultDesc = "The execution failed and the command did not exist"; + resultDesc = "i18n_client.AgentCommand.execFailDesc2_n81i"; + resultState = RESULT_FAIL; +// logger.warn(resultDesc);//i18nlog + break; + } + + String[] res = resultStr.split(RESULT_SEPRATOR_SPLIT); + if (res != null && res.length >= 2) { + resultState = Long.parseLong(res[0]); + resultDesc = res[1]; + } + } else { +// resultDesc = "执行失败:命令参数不正确<" + commandParam + ">"; +// resultDesc = "Execution failure: incorrect command parameters<" + commandParam + ">"; + resultDesc = "i18n_client.AgentCommand.execFailDesc3_n81i<" + commandParam + ">"; + resultState = RESULT_FAIL; +// logger.warn(resultDesc);//i18nlog + } + + } + } catch (Exception e) { +// resultDesc = "执行失败:出现异常,详细信息请查看日志"; +// resultDesc = "Execution failure: abnormal. Please check log for details"; + resultDesc = "i18n_client.AgentCommand.execFailDesc4_n81i"; + resultState = RESULT_FAIL; +// logger.error(resultDesc + "\n" + Utils.printExceptionStack(e));//i18nlog + } + + // 发送信息 + TaskResultOper.sendTaskResult(command.getExecId(), command.getExecType(), + resultState, resultDesc, "", execTime, new Date(), isServer, command.getIsLoop()); + + return (resultState % 2 == 1) ? false : true; + } + + /** + * Agent原生支持命令,Agent自身升级 + * @param params 升级任务的参数 + * @param upgradePath 升级文件存放路径 + * @param stepState 任务执行步骤标志 + * @param curVersion 当前升级版本 + * @param reVersion 恢复到的版本 + * @return + */ + public String upgradeAgent(String param, String upgradePath, long stepState, Long curVersion, Long reVersion) { + logger.info("NC升级开始……"); +// String resultDesc = "执行失败"; +// String resultDesc = "Failure to execute"; + String resultDesc = "i18n_client.AgentCommand.execFail_n81i"; + int resultState = RESULT_FAIL; + File tempUpdateDir = null; + try { + Long curVer = Long.parseLong(VersionCfg + .getValue(VersionCfg.NAGENT_VERSION)); + if (curVer >= curVersion) { +// resultDesc = "执行失败:当前Agent版本为最新"; +// resultDesc = "Execution failure: the current Agent version is the latest"; + resultDesc = "i18n_client.AgentCommand.execFailDesc5_n81i"; + + logger.info("NC升级结果描述信息 >> " + resultDesc); + logger.info("NC升级结束……"); + return resultState + RESULT_SEPRATOR + resultDesc; + } + + /** + * 1、解析命令参数,包装到对象 + */ + logger.debug("upgradeAgent-->param: " + param); + ParamUpgrade cfu = (ParamUpgrade) JSONObject.toBean( + JSONObject.fromObject(param), ParamUpgrade.class); + //Agent的布署路径 + String homePath = new File(Contants.SYSTEM_PATH).getParent(); + /* + * 设置启动文件和PID文件 + */ + String pidFile = Contants.localAgentPidFile; + String startFile = null; + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + startFile = homePath + File.separator + "script" + File.separator + "restart.bat"; + if(!new File(startFile).exists()){ + startFile = Contants.SYSTEM_PATH + File.separator + "restart.bat"; + } + } else if (os.startsWith("Linux")) { + startFile = Contants.SYSTEM_PATH + File.separator + "restart.sh"; + } + cfu.setStartupFile(new File(startFile).getCanonicalPath()); + cfu.setPidFile(new File(pidFile).getCanonicalPath()); + /* + * 处理覆盖目录 + */ + if(cfu.getCover()!=null && !"".equals(cfu.getCover().trim())){ + cfu.setCover(getFilePath(cfu.getCover(), homePath)); + }else{//如果没有参数覆盖目录,则按默认Agent的布署路径 + cfu.setCover(homePath); + } + String backupOppDir = new File(cfu.getCover()).getCanonicalPath(); + + logger.debug("AgentUpgrade homePath----" + homePath); + logger.debug("AgentUpgrade restart file----" + cfu.getStartupFile()); + logger.debug("AgentUpgrade pid file----" + cfu.getPidFile()); + logger.debug("AgentUpgrade cover----" + cfu.getCover()); + + /** + * 步骤2:判断是逆向任务还是正常升级,恢复版本不为空则为逆向任务,反之正常升级 + */ + boolean next = true; + String srcDesc = null; + String destDesc = null; + File upgradeFile = null; + File coverDirFile = null; + if (command.getExecVersion() != null + && command.getExecVersion().longValue() > 0) {//恢复 + if(cfu.getRecoverys()==null || cfu.getRecoverys().length<=0){ +// resultDesc = "执行失败:恢复参数为空"; +// resultDesc = "Execution failure: recovery parameters are empty"; + resultDesc = "i18n_client.AgentCommand.execFailDesc6_n81i"; +// logger.info("NC升级结果描述信息 >> " + resultDesc);//i18nlog + logger.info("NC升级结束……"); + return resultState + RESULT_SEPRATOR + resultDesc; + } + ParamCoverUpdate recover = cfu.getRecoverys()[0]; + cfu.setIsAbs(recover.getIsAbs()); + //文件名称在此没有实际意义,只是为了下面验证时不为空 + cfu.setFileName(getRecoverSource(recover, reVersion)); + //-------必须先处理恢复目录,再处理恢复源文件,恢复源文件会用到恢复目录的名称,否则恢复目录如果是(.)这样的相对路径就会出问题 + //恢复目录若是相对,则相对升级的覆盖目录,若是绝对,则不变 + recover.setCover(getFilePath(recover.getCover(), cfu.getCover())); +// destDesc = "恢复目录"; +// destDesc = "Recovery Directory"; + destDesc = "i18n_client.AgentCommand.destDesc_n81i"; + coverDirFile = new File(recover.getCover()); +// srcDesc = "恢复源文件"; +// srcDesc = "Recovery Source File"; + srcDesc = "i18n_client.AgentCommand.srcDesc_n81i"; + upgradeFile = new File(getRecoverSource(recover, reVersion)); + + logger.debug("AgentUpgrade recover cover----" + recover.getCover()); + } else { + // 处理是否创建覆盖目录 + cfu.setIsCreateCover(handleYesOrNoField(cfu.getIsCreateCover())); +// srcDesc = "升级文件"; +// srcDesc = "Upgrade File"; + srcDesc = "i18n_client.AgentCommand.srcDesc_n81i"; + upgradeFile = new File(getFilePath(cfu.getFileName(), upgradePath)); +// destDesc = "更新目录"; +// destDesc = "Update Table Of Contents"; + destDesc = "i18n_client.AgentCommand.destDesc_n81i"; + coverDirFile = new File(cfu.getCover()); + } + if(coverDirFile.isFile()){ + coverDirFile = coverDirFile.getParentFile(); + } + // 处理解压时按绝对路径,还是相对路径, 只对LInux起作用, 默认按相对 + boolean isAbs = false; + if ("Y".equals(handleYesOrNoField(cfu.getIsAbs()))) { + isAbs = true; + } + /** + * 判断参数指定的升级文件与覆盖目录是否存在 + */ + if (cfu.getFileName() == null + || cfu.getFileName().trim().length() <= 0) { +// resultDesc = "执行失败:" + srcDesc + "为空"; +// resultDesc = "Failure to execute:" + srcDesc + "is empty"; + resultDesc = "i18n_client.AgentCommand.execFail_n81i:" + srcDesc + "i18n_client.AgentCommand.execFailDesc7_n81i"; + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + next = false; + } else if (!upgradeFile.exists()) { +// resultDesc = "执行失败:" + srcDesc + "不存在--" + upgradeFile.getAbsolutePath(); +// resultDesc = "Failure to execute:" + srcDesc + "non-existent--" + upgradeFile.getAbsolutePath(); + resultDesc = "i18n_client.AgentCommand.execFail_n81i:" + srcDesc + "i18n_client.AgentCommand.execFailDesc8_n81i--" + upgradeFile.getAbsolutePath(); + resultState = RESULT_FAIL; +// logger.debug(resultDesc + "--" + upgradeFile.getAbsolutePath());//i18nlog + next = false; + } + // 判断用户和密码是否正确 + /*if (!ProcessUtil.checkUserPass(cfu.getUsername(), cfu.getParam1())) { + resultDesc = "执行失败:用户名或密码不正确;"; + resultState = RESULT_FAIL; + logger.debug(resultDesc); + next = false; + }*/ + // 判断用户名是否正确 + if(!ProcessUtil.checkUserOrGroupExist(cfu.getUsername(), null)){ +// resultDesc = "执行失败:属主不正确;"; +// resultDesc = "Failure of execution: the owner is not correct;"; + resultDesc = "i18n_client.AgentCommand.execFailDesc9_n81i;"; + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + next = false; + } + boolean isCompressFile = false; + if (next) { + /** + * 判断覆盖目录是否存在: + * 1、必须判断:Window系统、或者Linux系统且不是压缩文件、或者Linux系统且是压缩文件且是相对路径 + * 2、不用判断:Linux系统下源文件是压缩文件且绝对解压,该属性无效 + */ + isCompressFile = CompressFileMgr.isCompressFile(upgradeFile); + if (os.startsWith("Windows") + || (!os.startsWith("Windows") && !isCompressFile) + || (!os.startsWith("Windows") && isCompressFile && !isAbs)) { + if (!coverDirFile.exists() + && "N".equalsIgnoreCase(cfu.getIsCreateCover())) { +// resultDesc = "执行失败:" + destDesc + "不存在"; +// resultDesc = "Failure to execute:" + destDesc + "non-existent"; + resultDesc = "i18n_client.AgentCommand.execFail_n81i:" + destDesc + "i18n_client.AgentCommand.execFailDesc8_n81i"; + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + next = false; + } else if (!coverDirFile.exists() + && "Y".equalsIgnoreCase(cfu.getIsCreateCover())) {// Y + // 创建目录 + coverDirFile.mkdirs(); + } + } else { + coverDirFile = new File("/"); + } + } + /** + * 步骤3、对参数指定的备份目录进行备份 + */ + boolean flag = false; + String resultStr = ""; + if (next && (stepState > RESULT_OK && stepState < RESULT_BACKUP_OK)) {// 备份 + Date execTime = new Date(); + resultStr = this.backupCmd(cfu.getBackups(), backupOppDir, curVersion); + String[] res = resultStr.split(RESULT_SEPRATOR_SPLIT); + if (res != null && res.length >= 2) { + resultState = Integer.parseInt(res[0]); + resultDesc = res[1]; + } + if (resultState == RESULT_OK) {// 备份成功,发送信息 + flag = true; + resultState = RESULT_BACKUP_OK; + TaskResultOper.sendTaskResult(command.getExecId(), command + .getExecType(), resultState, resultDesc, "", + execTime, new Date(), false, command.getIsLoop()); + } else { + flag = false; + } + + } + + /** + * 步骤4、覆盖并重启Agent + */ + if (next && flag) {// 解压成功,覆盖并重启Agent + Date execTime = new Date(); + + /** + * 4-1 发送重启请求 + */ + TaskResultOper.sendTaskResult(command.getExecId(), command +// .getExecType(), resultState, "正在覆盖并重启Agent", "", +// .getExecType(), resultState, "Overlaying and restarting Agent", "", + .getExecType(), resultState, "i18n_client.AgentCommand.coverRestart_n81i", "", + execTime, new Date(), false, command.getIsLoop()); + + // 判断是否解压升级文件,并放入临时目录 + tempUpdateDir = new File(Contants.localTempPath + File.separator + + "agent_updatedir_" + command.getExecId()); + if (upgradeFile.isDirectory()) { + FileUtils.copyDirectoryToDirectory(upgradeFile, tempUpdateDir); + } else { + if (isCompressFile) { + flag = new CompressFileMgr().decompressFile( + upgradeFile.getAbsolutePath(), tempUpdateDir + .getAbsolutePath(), false); + } else { + FileUtils.copyFileToDirectory(upgradeFile,tempUpdateDir); + } + } + + /** + * 4-2 删除文件,并写临时结果文件 + */ + //准备临时结果文件内容,初始状态为升级失败 + String[] msgs = new String[1]; + msgs[0] = TaskResultOper.getTaskResultMsg(command + .getExecId(), command.getExecType(), +// (long) RESULT_FAIL, "升级失败", "", execTime, new Date(), command.getIsLoop()); +// (long) RESULT_FAIL, "Failure to upgrade", "", execTime, new Date(), command.getIsLoop()); + (long) RESULT_FAIL, "i18n_client.AgentCommand.upgradeFail_n81i", "", execTime, new Date(), command.getIsLoop()); + File resultFile = new File(TaskResultOper + .getAgentUpgradeResultTempFile(command.getExecType(), + command.getExecId())); + if(!resultFile.getParentFile().exists()){ + resultFile.getParentFile().mkdirs(); + } + // 删除指定的文件 + String delMsg = this.delete(cfu.getDelete(), coverDirFile.getAbsolutePath()); + // 将删除日志换行加入结果文件 + if(!StringUtils.isEmpty(delMsg)){ + msgs = new String[]{msgs[0], delMsg}; + } + // 正式写入临时结果文件 + FileWrUtil.cfgFilePrinter(resultFile, Charset.defaultCharset().name(), msgs); + + /** + * 4-3 执行脚本(脚本中将覆盖操作的详细信息追加到结果文件;覆盖成功后将任务标识ID写入version.txt) + */ + List<ParamCmdExec> startList = new ArrayList<ParamCmdExec>(); + ParamCmdExec exec = new ParamCmdExec(); + exec.setExecCmd(cfu.getStartupFile()); + exec.setExecParams(new String[] { tempUpdateDir.getCanonicalPath(), + coverDirFile.getCanonicalPath(), + resultFile.getCanonicalPath() }); + exec.setExecResult(cfu.getPidFile()); + exec.setUsername(cfu.getUsername()); + exec.setParam1(cfu.getParam1()); + exec.setForceExec("Y"); + exec.setResidentFlag("Y"); + exec.setReturnFlag("N"); + startList.add(exec); + resultStr = this.startCmd(startList, execTime, true, resultState); + String[] res = resultStr.split(RESULT_SEPRATOR_SPLIT); + if (res != null && res.length >= 2) { + resultState = Integer.parseInt(res[0]); + resultDesc = res[1]; + } + if (resultState == RESULT_FAIL && resultFile.exists()) {// 如果失败直接返回结果,删除临时结果文件 + //resultFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(resultFile); + logger.debug("upgradeAgent delete file -- " + resultFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(resultFile); + } + } else { + if (stepState == RESULT_BACKUP_OK) { +// resultDesc = "重启失败,手工启动成功"; +// resultDesc = "Restart failure and start success by hand"; + resultDesc = "i18n_client.AgentCommand.restartFail_n81i"; + resultState = RESULT_FAIL; + String upgradeResultFile = TaskResultOper + .getAgentUpgradeResultTempFile(command + .getExecType(), command.getExecId()); + File resultFile = new File(upgradeResultFile); + if (resultFile.exists()) {// 如果失败直接返回结果,删除临时结果文件 + //resultFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(resultFile); + logger.debug("upgradeAgent delete file 2 -- " + resultFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(resultFile); + } + } + + } + } catch (Exception e) { +// resultDesc = "执行失败:出现异常," + e.getMessage() + ",详细信息请查看日志"; + resultDesc = "i18n_client.AgentCommand.execFailDesc10_n81i," + e.getMessage() + ",i18n_client.AgentCommand.execFailDesc10.showDetail_n81i"; + resultState = RESULT_FAIL; + logger.error("NC upgrade exception:" + Utils.printExceptionStack(e)); + } finally { + // 不能删除临时目录原因:覆盖操作在脚本中进行,可能出现脚本未运行完,临时目录被删除,这样覆盖操作就不能完成 + /*if(tempUpdateDir!=null && tempUpdateDir.exists()){ + try { + FileUtils.deleteDirectory(tempUpdateDir); + logger.debug("upgradeAgentNew-----finally delele tempUpdateDir = " + tempUpdateDir.getCanonicalPath()); + FileUtil.checkParentDirExist(tempUpdateDir); + } catch (IOException e) { + } + }*/ + } +// logger.info("NC升级结果描述信息 >> " + resultDesc);//i18nlog + logger.info("NC升级结束……"); + + return resultState + RESULT_SEPRATOR + resultDesc; + } + + /** + * Agent原生支持命令,第三方升级 + * @param params 升级任务的参数 + * @param upgradePath 升级文件存放目录 + * @param stepState 任务执行步骤标志 + * @param curVersion 当前升级版本 + * @param reVersion 恢复到的版本,如果是逆向任务即恢复时用到 + * @param isServer 是否NmsServer升级 + * @return + */ + public String upgradeOther(String[] params, String upgradePath, long stepState, long curVersion, Long reVersion, boolean isServer) { +// String pre = "三方升级"; + String pre = "Three Party Upgrade"; + if (isServer) {// 如果是NmsServer升级,判断版本 +// pre = "DC升级"; + pre = "DC Upgrade"; + } + logger.info(pre + "开始……"); +// String resultDesc = "执行失败"; + String resultDesc = "Failure to execute"; + int resultState = RESULT_FAIL; + try { + if(params==null || params.length==0){ +// resultDesc = "执行失败:参数为空"; +// resultDesc = "Execution failure: parameters are empty"; + resultDesc = "i18n_client.AgentCommand.execFailDesc11_n81i"; +// logger.info(pre + "结果描述信息 >> " + resultDesc);//i18nlog + logger.info(pre + "结束……"); + return resultState + RESULT_SEPRATOR + resultDesc; + } + if (isServer) {// 如果是NmsServer升级,判断版本 + Long curVer = Long.parseLong(VersionCfg + .getValue(VersionCfg.NSERVER_VERSION)); + if (curVer >= curVersion) { +// resultDesc = "执行失败:当前Server版本为最新"; +// resultDesc = "Execution failure: the current Server version is the latest"; + resultDesc = "i18n_client.AgentCommand.execFailDesc12_n81i"; +// logger.info(pre + "结果描述信息 >> " + resultDesc);//i18nlog + logger.info(pre + "结束……"); + return resultState + RESULT_SEPRATOR + resultDesc; + } + + } + /** + * 1、解析命令参数,包装到对象, 判断是否为逆向任务: + * 不是,判断所有参数指定的升级文件与覆盖目录是否存在; + * 是,设置默认强制执行并跳过判断 + */ + boolean next = true; + List<ParamUpgrade> cfuList = new ArrayList<ParamUpgrade>(); + for (String param : params) { + if (param.trim().length() <= 0) { + continue; + } + logger.debug("upgradeOther-->param: " + param); + ParamUpgrade cfu = (ParamUpgrade) JSONObject.toBean(JSONObject + .fromObject(param), ParamUpgrade.class); + logger.debug("upgradeOther-->pidFile: " + cfu.getPidFile()); + + // 判断用户和密码是否正确 + /*if (!ProcessUtil.checkUserPass(cfu.getUsername(), cfu.getParam1())) { + resultDesc = "执行失败:用户名或密码不正确;"; + resultState = RESULT_FAIL; + logger.debug(resultDesc); + next = false; + break; + }*/ + // 判断用户名是否正确 + if(!ProcessUtil.checkUserOrGroupExist(cfu.getUsername(), null)){ +// resultDesc = "执行失败:属主不正确;"; +// resultDesc = "Failure of execution: the owner is not correct;"; + resultDesc = "i18n_client.AgentCommand.execFailDesc13_n81i;"; + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + next = false; + } + + // 恢复版本不为空则为逆向任务 + if (reVersion != null && reVersion.longValue() > 0) {// 恢复 + cfuList.add(cfu); + continue; + } + + cfu.setIsCreateCover(handleYesOrNoField(cfu.getIsCreateCover())); + // 处理解压时按绝对路径,还是相对路径, 只对LInux起作用, 默认按相对 + boolean isAbs = false; + if ("Y".equals(handleYesOrNoField(cfu.getIsAbs()))) { + isAbs = true; + } + /** + * 判断升级文件是否存在 + */ + if (cfu.getFileName() == null + || cfu.getFileName().trim().length() <= 0) { +// resultDesc = "执行失败:升级文件名为空"; +// resultDesc = "Execution failure: the upgrade file name is empty"; + resultDesc = "i18n_client.AgentCommand.execFailDesc14_n81i"; + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + next = false; + break; + } + File upgradeFile = new File(getFilePath(cfu.getFileName(), + upgradePath)); + if (!upgradeFile.exists()) { +// resultDesc = "执行失败:升级文件“" + cfu.getFileName() + "”不存在--" +// resultDesc = "Execution failure: upgrade file“" + cfu.getFileName() + "”non-existent--" + resultDesc = "i18n_client.AgentCommand.execFailDesc15_n81i“" + cfu.getFileName() + "”i18n_client.AgentCommand.execFailDesc8_n81i--" + + upgradeFile.getAbsolutePath(); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + next = false; + break; + } + /** + * 判断覆盖目录是否存在: + * 1、必须判断:Window系统、或者Linux系统且不是压缩文件、或者Linux系统且是压缩文件且是相对路径 + * 2、不用判断:Linux系统下源文件是压缩文件且绝对解压,该属性无效 + */ + File coverDirFile = null; + boolean isCompressFile = CompressFileMgr.isCompressFile(upgradeFile); + String os = System.getProperty("os.name"); + if (os.startsWith("Windows") + || (!os.startsWith("Windows") && !isCompressFile) + || (!os.startsWith("Windows") && isCompressFile && !isAbs)) { + if (cfu.getCover() == null + || cfu.getCover().trim().length() <= 0) { +// resultDesc = "执行失败:覆盖目录为空"; +// resultDesc = "Execution failure: overlay the directory to be empty"; + resultDesc = "i18n_client.AgentCommand.execFailDesc16_n81i"; + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + next = false; + break; + } + coverDirFile = new File(cfu.getCover()); + if (!coverDirFile.exists() + && "N".equalsIgnoreCase(cfu.getIsCreateCover())) { +// resultDesc = "执行失败:覆盖目录不存在--" +// resultDesc = "Execution failure: the overlay directory does not exist--" + resultDesc = "i18n_client.AgentCommand.execFailDesc17_n81i--" + + coverDirFile.getAbsolutePath(); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + next = false; + break; + } + // Y 创建目录 + if (!coverDirFile.exists()) { + coverDirFile.mkdirs(); + } + } else { + coverDirFile = new File("/"); + } + + cfuList.add(cfu); + } + /** + * 步骤2、停用所有进程,所有对象同步进行,有一个失败则失败 + */ + String resultStr = ""; + boolean flag = false; + if (next && (stepState > RESULT_OK && stepState < RESULT_KILL_OK)) { + String temp = ""; + if (isServer) {// 如果是NmsServer升级,发送升级请求 + for (int i = 0; i < Contants.max_times; i++) {// 失败,尝试几次 + Future<?> future = Common.service + .submit(new SSLClient(Thread.currentThread().getName() + " >> DC升级请求", + CommonSocket.REQ_SERVER_UPGRADE, + null, Utils.getLocalIp())); + String msg = (String) future.get(); + temp = Contants.getDescByResult(msg); + if(Contants.isSucessByResult(msg)){ + break; + } + try {// 如果更新失败,让当前线程暂停几秒,再重试 + Thread.sleep(1000 * Contants.max_delay_seconds); + } catch (InterruptedException e) { + logger.error(Utils.printExceptionStack(e)); + continue; + } + } +// temp = "DC升级请求" + ((temp!=null && temp.trim().length()>0) ? temp : "失败") + ";"; +// temp = "DC upgrade request" + ((temp!=null && temp.trim().length()>0) ? temp : "失败") + ";"; + temp = "i18n_client.AgentCommand.DCupdate_n81i" + ((temp!=null && temp.trim().length()>0) ? temp : "i18n_client.AgentCommand.fail_n81i") + ";"; + } + + Date execTime = new Date(); + String[] pidArr = new String[cfuList.size()]; + int i = 0; + for(ParamUpgrade cfu:cfuList){ + pidArr[i++] = cfu.getPidFile(); + } + resultStr = this.killProcessCmd(pidArr); + String[] res = resultStr.split(RESULT_SEPRATOR_SPLIT); + if (res != null && res.length >= 2) { + resultState = Integer.parseInt(res[0]); + resultDesc = temp + res[1]; + } + if(resultState == RESULT_OK){ + flag = true; + resultState = RESULT_KILL_OK; + // 发送信息 + TaskResultOper.sendTaskResult(command.getExecId(), command.getExecType(), + resultState, resultDesc, "", execTime, new Date(), isServer, command.getIsLoop()); + }else{ + flag = false; + } + } + /** + * 步骤3、对所有参数指定的备份目录进行备份,有一个失败则失败 + */ + if (next && (flag || stepState == RESULT_KILL_OK)) {// 停用进程成功,再进行备份 + Date execTime = new Date(); + StringBuffer sb = new StringBuffer(); + for(ParamUpgrade cfu:cfuList){ + resultStr = this.backupCmd(cfu.getBackups(), cfu.getCover(), curVersion); + String[] res = resultStr.split(RESULT_SEPRATOR_SPLIT); + if (res != null && res.length >= 2) { + resultState = Integer.parseInt(res[0]); + sb.append(res[1] + ";"); + } + if(resultState == RESULT_FAIL){ + break; + } + } + resultDesc = sb.toString(); + if(resultState == RESULT_OK){ + flag = true; + resultState = RESULT_BACKUP_OK; + // 发送信息 + TaskResultOper.sendTaskResult(command.getExecId(), command.getExecType(), + resultState, resultDesc, "", execTime, new Date(), isServer, command.getIsLoop()); + }else{ + flag = false; + } + } + /** + * 步骤4、对所有参数指定的覆盖目录进行更新并删除指定的文件,有一个失败则失败 + */ + if (next && (flag || stepState == RESULT_BACKUP_OK)) {// 备份成功,再进行覆盖即更新 + Date execTime = new Date(); + ParamCoverUpdate[] updates = handleCoverUpdates(cfuList, reVersion, upgradePath); + for (int i = 0; i < Contants.max_times; i++) { + resultStr = this.updateCmd(updates); + String[] res = resultStr.split(RESULT_SEPRATOR_SPLIT); + if (res != null && res.length >= 2) { + resultState = Integer.parseInt(res[0]); + resultDesc = res[1]; + } + if (resultState == RESULT_OK) { + break; + } + try {// 如果更新失败,让当前线程暂停几秒,再重试 + Thread.sleep(1000 * Contants.max_delay_seconds); + } catch (InterruptedException e) { + logger.error(Utils.printExceptionStack(e)); + continue; + } + } + if (resultState == RESULT_OK) { + flag = true; + resultState = RESULT_UPDATE_OK; + // 发送信息 + TaskResultOper.sendTaskResult(command.getExecId(), command.getExecType(), + resultState, resultDesc, "", execTime, new Date(), isServer, command.getIsLoop()); + }else{ + flag = false; + } + if(flag && isServer){ + Long curVer = Long.parseLong(VersionCfg + .getValue(VersionCfg.NSERVER_VERSION)); + if (curVer < curVersion) { + VersionCfg.setValue(VersionCfg.NSERVER_VERSION, curVersion + ""); + logger.info("DC升级到版本" + curVersion); + } + } + } + /** + * 步骤5、顺序启动所有进程,有一个失败则失败 + */ + if (next && (flag || stepState == RESULT_UPDATE_OK)) {// 更新成功,再启动进程 + Date execTime = new Date(); + List<ParamCmdExec> startList = new ArrayList<ParamCmdExec>(); + for(ParamUpgrade cfu:cfuList){ + ParamCmdExec exec = new ParamCmdExec(); + exec.setExecCmd(cfu.getStartupFile()); + exec.setExecParams(cfu.getExecParams()); + exec.setExecResult(cfu.getPidFile()); + exec.setMaxWaitTime(cfu.getMaxWaitTime()); + exec.setUsername(cfu.getUsername()); + exec.setParam1(cfu.getParam1()); + exec.setForceExec("Y"); + exec.setResidentFlag("Y"); + exec.setReturnFlag("N"); + startList.add(exec); + } + resultStr = this.startCmd(startList, execTime, false, resultState); + String[] res = resultStr.split(RESULT_SEPRATOR_SPLIT); + if (res != null && res.length >= 2) { + resultState = Integer.parseInt(res[0]); + resultDesc = res[1]; + } + } + } catch (Exception e) { +// resultDesc = "执行失败:出现异常," + e.getMessage() + ",详细信息请查看日志"; +// resultDesc = "Execution failure: abnormality," + e.getMessage() + ",please check the log for details"; + resultDesc = "i18n_client.AgentCommand.execFailDesc18_n81i," + e.getMessage() + ",i18n_client.AgentCommand.execFailDesc10.showDetail_n81i"; + resultState = RESULT_FAIL; + logger.error(pre + "anormly:" + Utils.printExceptionStack(e)); + }finally{ + } +// logger.info(pre + "结果描述信息 >> " + resultDesc);//i18nlog + logger.info(pre + "结束……"); + + return resultState + RESULT_SEPRATOR + resultDesc; + } + + /** + * Agent原生支持命令,备份 + * @param backups 备份文件包装对象数组(需要备份的目录、备份到的目录、排除的目录) + * @param version + * @return + */ + public String backupCmd(ParamBackup[] backups, String oppositeBackupDir, Long version){ + logger.info("备份开始……"); + String resultDesc = ""; + long resultState = RESULT_FAIL; + try { + if(backups==null || backups.length<=0){ +// resultDesc = "备份成功:未指定备份参数,不需要备份"; +// resultDesc = "Backup success: no backup parameters specified, no backup required"; + resultDesc = "i18n_client.AgentCommand.backupSuccess1_n81i"; + resultState = RESULT_OK; +// logger.debug(resultDesc);//i18nlog + }else{ + StringBuffer sb = new StringBuffer(); + CompressFileMgr cfmImpl = new CompressFileMgr(); + for(int i=0; i<backups.length; i++){ + ParamBackup backup = backups[i]; + // 处理需要备份的目录 + logger.debug("backupCmd---->oppositeBackupDir=" + oppositeBackupDir); + if(oppositeBackupDir!=null && oppositeBackupDir.trim().length()>0){ + backup.setBackup(getFilePath(backup.getBackup(), oppositeBackupDir)); + } + // 判断需要备份的文件是否存在 + String backupPath = backup.getBackup(); + if(backup.getBackup()==null || backup.getBackup().trim().length()<=0){ +// resultDesc = "备份失败,需要备份的文件属性为空"; +// resultDesc = "Backup failed, the file property that needs to be backed up is empty"; + resultDesc = "i18n_client.AgentCommand.backupFail1_n81i"; + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + break; + } + File srcFile = new File(backup.getBackup().trim()); + if(!srcFile.exists()){ +// resultDesc = "备份“" + backupPath + "”失败,需要备份的文件不存在--" + srcFile.getAbsolutePath(); +// resultDesc = "Backup“" + backupPath + "” failed, the file that needs to be backed up does not exist--" + srcFile.getAbsolutePath(); + resultDesc = "i18n_client.AgentCommand.backup_n81i“" + backupPath + "” i18n_client.AgentCommand.backupFail2_n81i--" + srcFile.getAbsolutePath(); + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + break; + }else if(srcFile.isDirectory() && srcFile.list().length<=0){ +// resultDesc = "备份“" + backupPath + "”成功,需要备份的文件目录为空,不用进行备份"; +// resultDesc = "Backup“" + backupPath + "”successful, the backup file directory is empty without backup"; + resultDesc = "i18n_client.AgentCommand.backup_n81i“" + backupPath + "”i18n_client.AgentCommand.backupSuccess2_n81i"; + sb.append(resultDesc + ";"); + resultState = RESULT_OK; +// logger.debug(resultDesc);//i18nlog + continue; + } + // 处理压缩时按绝对路径,还是相对路径, 只对LInux起作用, 默认按相对 + boolean isAbs = false; + if("Y".equals(handleYesOrNoField(backup.getIsAbs()))){ + isAbs = true; + } + // 处理备份到的目录 + if(backup.getBackupTo()==null || backup.getBackupTo().trim().length()<=0){ + backup.setBackupTo(Contants.localBackupPath); + }else{ + backup.setBackupTo(Contants.localBackupPath + + File.separator + backup.getBackupTo().trim()); + } + // 处理备份操作 + String compressName = backup.getBackupTo() + File.separator + + getBakFileName(srcFile.getName(), version, isAbs); + File destDirFile = new File(compressName); + if (!destDirFile.exists()) { + if (!destDirFile.getParentFile().exists()) { + destDirFile.getParentFile().mkdirs(); + } + if (destDirFile.getParentFile().canWrite()) { + String[] excepts = backup.getExcept(); + if(excepts!=null && excepts.length>0){ + for(int j=0; j<excepts.length; j++){ + if(excepts[j]!=null && excepts[j].trim().length()>0){ + excepts[j] = getFilePath(excepts[j], backup.getBackup()); + } + } + } + boolean flag = cfmImpl.compressFile(srcFile.getAbsolutePath(), destDirFile.getAbsolutePath(), excepts, isAbs); + +// resultDesc = flag ? "备份“" + backupPath +// + "”成功,备份文件" + destDirFile.getAbsolutePath() +// : "备份“" + backupPath + "”失败"; + resultDesc = flag ? "i18n_client.AgentCommand.backup_n81i“" + backupPath + + "”i18n_client.AgentCommand.backupSuccess3_n81i" + destDirFile.getAbsolutePath() + : "i18n_client.AgentCommand.backup_n81i“" + backupPath + "”i18n_client.AgentCommand.backupFail3_n81i"; + sb.append(resultDesc + ";"); + resultState = flag ? RESULT_OK : RESULT_FAIL; + logger.debug(resultDesc + ": " +// + srcFile.getAbsolutePath() + " 到 " + + srcFile.getAbsolutePath() + " to " + + destDirFile.getAbsolutePath()); + if (resultState == RESULT_FAIL) { + break; + } + }else{ +// resultDesc = "备份“" + backupPath + "”失败,备份到的目录”" + backup.getBackupTo() + "“只读"; +// resultDesc = "Backup“" + backupPath + "”failed, backup to the directory”" + backup.getBackupTo() + "“read-only"; + resultDesc = "i18n_client.AgentCommand.backup_n81i“" + backupPath + "”i18n_client.AgentCommand.backupFail4_n81i”" + backup.getBackupTo() + "“i18n_client.AgentCommand.readonly_n81i"; + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc + "--" + destDirFile.getParent());//i18nlog + break; + } + }else{ +// resultDesc = "备份“" + backupPath + "”成功,已存在该版本备份,不用备份--备份文件" + destDirFile.getAbsolutePath(); +// resultDesc = "Backup“" + backupPath + "”Successful version already exists, without backup - backup files" + destDirFile.getAbsolutePath(); + resultDesc = "i18n_client.AgentCommand.backup_n81i“" + backupPath + "”i18n_client.AgentCommand.backupSuccess4_n81i" + destDirFile.getAbsolutePath(); + sb.append(resultDesc + ";"); + resultState = RESULT_OK; +// logger.debug(resultDesc + "--" + destDirFile.getAbsolutePath());//i18nlog + } + }//for end +// resultDesc = resultState==RESULT_OK ? "备份成功,详情信息如下:" + sb.toString() : "备份失败,详情信息如下:" + sb.toString(); +// resultDesc = resultState==RESULT_OK ? "The backup is successful, and the details are as follows:" + sb.toString() : "Backup failed, the details are as follows:" + sb.toString(); + resultDesc = resultState==RESULT_OK ? "i18n_client.AgentCommand.backupSuccess5_n81i:" + sb.toString() : "i18n_client.AgentCommand.backupFail5_n81i:" + sb.toString(); + } + } catch (Exception e) { +// resultDesc = "备份失败:出现异常," + e.getMessage() + ",详细信息请查看日志"; +// resultDesc = "Backup failure: Exception," + e.getMessage() + ",please check the log for details"; + resultDesc = "i18n_client.AgentCommand.backupFail6_n81i," + e.getMessage() + ",i18n_client.AgentCommand.execFailDesc10.showDetail_n81i"; + resultState = RESULT_FAIL; + logger.error("备份异常:" + Utils.printExceptionStack(e)); + } +// logger.info("备份结果描述信息 >> " + resultDesc);//i18nlog + logger.info("备份结束……"); + + return resultState + RESULT_SEPRATOR + resultDesc; + } + + /** + * Agent原生支持命令,覆盖更新或恢复 + * @param updates 覆盖更新包装对象数组(备份的文件、恢复的目录、删除的文件或目录) + * @return + */ + public String updateCmd(ParamCoverUpdate[] updates){ + logger.info("更新或恢复开始……"); + String resultDesc = ""; + long resultState = RESULT_FAIL; + try { + if(updates==null || updates.length<=0){ +// resultDesc = "覆盖成功:未指定参数,不需要覆盖"; +// resultDesc = "Overwrite success: unspecified parameters, no need to cover"; + resultDesc = "i18n_client.AgentCommand.coverSuccess1_n81i"; + resultState = RESULT_OK; +// logger.debug(resultDesc);//i18nlog + } else { + StringBuffer sb = new StringBuffer(); + CompressFileMgr cfmImpl = new CompressFileMgr(); + for(int i=0; i<updates.length; i++){ + ParamCoverUpdate update = updates[i]; + + + + // 处理是否创建覆盖目录 + update.setIsCreateCover(handleYesOrNoField(update.getIsCreateCover())); + // 处理解压时按绝对路径,还是相对路径, 只对LInux起作用, 默认按相对 + boolean isAbs = false; + if("Y".equals(handleYesOrNoField(update.getIsAbs()))){ + isAbs = true; + } + /** + * 判断源文件是否存在 + */ + if(update.getSource()==null || update.getSource().trim().length()<=0){ +// resultDesc = "覆盖“" + update.getCover() + "”失败,源文件为空"; +// resultDesc = "Overwrite“" + update.getCover() + "”failure, source file is empty"; + resultDesc = "i18n_client.AgentCommand.coverFail1_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverFail1_n81i"; + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + break; + } + File sourceFile = new File(update.getSource().trim()); + if (!sourceFile.exists()) { +// resultDesc = "覆盖“" + update.getCover() + "”失败,源文件不存在--" + sourceFile.getAbsolutePath(); +// resultDesc = "Overwrite“" + update.getCover() + "”failure, source files do not exist--" + sourceFile.getAbsolutePath(); + resultDesc = "i18n_client.AgentCommand.coverFail1_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverFail2_n81i--" + sourceFile.getAbsolutePath(); + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + break; + } + /** + * 判断覆盖目录是否存在: + * 1、必须判断:Window系统、或者Linux系统且不是压缩文件、或者Linux系统且是压缩文件且是相对路径 + * 2、不用判断:Linux系统下源文件是压缩文件且绝对解压,该属性无效 + */ + File coverDir = null; + boolean isCompressFile = CompressFileMgr.isCompressFile(sourceFile); + String os = System.getProperty("os.name"); + if (os.startsWith("Windows") + || (!os.startsWith("Windows") && !isCompressFile) + || (!os.startsWith("Windows") && isCompressFile && !isAbs)) { + if(update.getCover()==null || update.getCover().trim().length()<=0){ +// resultDesc = "覆盖“" + update.getCover() + "”失败,覆盖目录为空"; +// resultDesc = "Overwrite“" + update.getCover() + "”overwrite directory is empty"; + resultDesc = "i18n_client.AgentCommand.coverFail1_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverFail3_n81i"; + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + break; + } + coverDir = new File(update.getCover().trim()); + if (!coverDir.exists() && "N".equals(update.getIsCreateCover())) { +// resultDesc = "覆盖“" + update.getCover() + "”失败:覆盖目录不存在--" + coverDir.getAbsolutePath(); +// resultDesc = "Overwrite“" + update.getCover() + "”failed: Overwrite directory does not exist--" + coverDir.getAbsolutePath(); + resultDesc = "i18n_client.AgentCommand.coverFail1_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverFail4_n81i--" + coverDir.getAbsolutePath(); + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + break; + } + // Y 创建目录 + if (!coverDir.exists()) { + coverDir.mkdirs(); + } + }else{ + coverDir = new File("/"); + if(update.getCover()==null || update.getCover().trim().length()<=0){ + update.setCover("/"); + } + } + + //判断源文件或目录是否和覆盖目录相同 + if(sourceFile.getPath().equals(coverDir.getPath())){ +// resultDesc = "覆盖“" + update.getCover() + "”失败:覆盖目录“" + update.getCover() + "”和源目录相同!"; + resultDesc = "i18n_client.AgentCommand.coverFail1_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverFail5_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverFail5.sameDir_n81i"; + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + break; + } + + if (coverDir.canWrite()) { + String delMsg = this.delete(update.getDelete(), coverDir.getAbsolutePath()); + if(!StringUtils.isEmpty(delMsg)){ + sb.append(delMsg + ";"); + } + boolean flag = true; + if (sourceFile.isDirectory()) { + FileUtils.copyDirectoryToDirectory(sourceFile, coverDir); + } else { + if (isCompressFile) { + flag = cfmImpl.decompressFile(sourceFile.getAbsolutePath(), coverDir.getAbsolutePath(), isAbs); + } else { + if (coverDir.isFile()) { + coverDir = coverDir.getParentFile(); + } + FileUtils.copyFileToDirectory(sourceFile,coverDir); + } + } + if (flag) { +// resultDesc = "覆盖“" + update.getCover() + "”成功, " +// + sourceFile.getAbsolutePath() + " 到 " +// + coverDir.getAbsolutePath(); +// resultDesc = "Overwrite“" + update.getCover() + "”success, " +// + sourceFile.getAbsolutePath() + " to " +// + coverDir.getAbsolutePath(); + resultDesc = "i18n_client.AgentCommand.coverFail1_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverSuccess2_n81i, " + + sourceFile.getAbsolutePath() + "i18n_client.AgentCommand.coverSuccess2.to_n81i " + + coverDir.getAbsolutePath(); + } else { +// resultDesc = "覆盖“" + update.getCover() + "”失败"; +// resultDesc = "Overwrite“" + update.getCover() + "”failed"; + resultDesc = "i18n_client.AgentCommand.coverFail1_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverFail6_n81i"; + } + sb.append(resultDesc + ";"); + resultState = flag ? RESULT_OK : RESULT_FAIL; + logger.debug(resultDesc); + if (resultState == RESULT_FAIL) { + break; + } + } else { +// resultDesc = "覆盖“" + update.getCover() + "”失败:要覆盖的目录只读--" + coverDir.getAbsolutePath(); +// resultDesc = "Overwrite“" + update.getCover() + "”failed: The directory to be overwritten is read-only--" + coverDir.getAbsolutePath(); + resultDesc = "i18n_client.AgentCommand.coverFail1_n81i“" + update.getCover() + "”i18n_client.AgentCommand.coverFail7_n81i--" + coverDir.getAbsolutePath(); + sb.append(resultDesc + ";"); + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + break; + } + }// for end +// resultDesc = resultState==RESULT_OK ? "覆盖成功,详情信息如下:" + sb.toString() : "覆盖失败,详情信息如下:" + sb.toString(); +// resultDesc = resultState==RESULT_OK ? "Overwrite success, details are as follows:" + sb.toString() : "Overwrite failed, details are as follows:" + sb.toString(); + resultDesc = resultState==RESULT_OK ? "i18n_client.AgentCommand.coverSuccess3_n81i:" + sb.toString() : "i18n_client.AgentCommand.coverFail8_n81i:" + sb.toString(); + } + } catch (Exception e) { +// resultDesc = "覆盖失败:出现异常," + e.getMessage() + ",详细信息请查看日志"; +// resultDesc = "Overwrite failed: An exception occurred," + e.getMessage() + ",see the logs for details"; + resultDesc = "i18n_client.AgentCommand.coverFail9_n81i," + e.getMessage() + ",i18n_client.AgentCommand.execFailDesc10.showDetail_n81i"; + resultState = RESULT_FAIL; + logger.error("覆盖命令异常:" + Utils.printExceptionStack(e)); + } + +// logger.info("更新或恢复结果描述信息 >> " + resultDesc);//i18nlog + logger.info("更新或恢复结束……"); + + return resultState + RESULT_SEPRATOR + resultDesc; + } + + /** + * Agent原生支持命令,停用进程 + * @param pidFileArr 存放进程ID的文件的数组集 + * @return + */ + public String killProcessCmd(String[] pidFileArr) { + logger.info("停用进程集开始……"); + String resultDesc = ""; + long resultState = RESULT_FAIL; + + try { + if(pidFileArr==null || pidFileArr.length<=0){ +// resultDesc = "停用进程失败:未指定PID文件参数"; +// resultDesc = "Deactivation process failed: PID file parameter not specified"; + resultDesc = "i18n_client.AgentCommand.killProcFail1_n81i"; + resultState = RESULT_FAIL; +// logger.debug(resultDesc);//i18nlog + }else { + StringBuffer sb = new StringBuffer(); + for(String pidFileStr : pidFileArr){ + logger.debug("upgradeKillProcess pidFile------->" + pidFileStr); + File pidFile = new File(pidFileStr); + if(pidFileStr==null || pidFileStr.trim().length()<=0){ + resultState = RESULT_OK; +// resultDesc = "停用成功,进程PID文件为空"; +// resultDesc = "Disabled, process PID file is empty"; + resultDesc = "i18n_client.AgentCommand.killProcSuccess1_n81i"; + sb.append(resultDesc + ";"); +// logger.debug(resultDesc + "--" + pidFile.getAbsolutePath() );//i18nlog + }else if(!pidFile.exists()){ + resultState = RESULT_OK; +// resultDesc = "停用“" + pidFileStr + "”成功,进程PID文件找不到"; + resultDesc = "i18n_client.AgentCommand.deactivate_n81i“" + pidFileStr + "”i18n_client.AgentCommand.killProcSuccess2_n81i"; + sb.append(resultDesc + ";"); +// logger.debug(resultDesc + "--" + pidFile.getAbsolutePath() );//i18nlog + } else { + String[] pidArr = ProcessUtil.getProcessIdByFile(pidFile); + boolean isExist = false; + if (pidArr != null && pidArr.length > 0) { + for (int i = 0; i < pidArr.length; i++) {// 目前考虑只有一个PID的情况 + isExist = ProcessUtil + .isProcessExistByPid(pidArr[i]); + if (isExist) {// 只要有一个PID存在,就认为是进程存在 + break; + } + } + } + if (!isExist) { +// resultDesc = "停用“" + pidFileStr + "”成功:进程原本不存在"; +// resultDesc = "Deactivate“" + pidFileStr + "”Success: Process does not exist originally"; + resultDesc = "i18n_client.AgentCommand.deactivate_n81i“" + pidFileStr + "”i18n_client.AgentCommand.killProcSuccess3_n81i"; + sb.append(resultDesc + ";"); + resultState = RESULT_OK; +// logger.debug(resultDesc);//i18nlog + } else { + for (int i = 0; i < pidArr.length; i++) { + ProcessUtil.killProcess(pidArr[i]);// 杀进程 + } + for (int i = 0; i < Contants.max_times; i++) { + pidArr = ProcessUtil.getProcessIdByFile(new File(pidFileStr)); + isExist = false; + if (pidArr != null && pidArr.length > 0) { + for (int j = 0; j < pidArr.length; j++) { + isExist = ProcessUtil + .isProcessExistByPid(pidArr[j]); + if (isExist) {// 只要有一个PID存在,就认为是停用进程失败 + break; + } + } + } + if (!isExist) { + break; + } + try {// 如果停用进程失败,让当前线程暂停几秒,再重试 + Thread + .sleep(1000 * Contants.max_delay_seconds); + } catch (InterruptedException e) { + logger.error(Utils.printExceptionStack(e)); + continue; + } + } + resultState = !isExist ? RESULT_OK : RESULT_FAIL; +// resultDesc = !isExist ? "停用“" + pidFileStr + "”成功" +// : "停用“" + pidFileStr +// + "”失败, 进程存在,请查看是否有守护进程"; +// resultDesc = !isExist ? "Deactivation of“" + pidFileStr + "”succeeded" +// : "Deactivate“" + pidFileStr +// + "”Failed, process exists, see if there is a daemon"; + resultDesc = !isExist ? "i18n_client.AgentCommand.deactivate_n81i“" + pidFileStr + "”i18n_client.AgentCommand.killProcSuccess4_n81i" + : "i18n_client.AgentCommand.deactivate_n81i“" + pidFileStr + + "”i18n_client.AgentCommand.killProcFail2_n81i"; + sb.append(resultDesc + ";"); +// logger.debug(resultDesc);//i18nlog + if (resultState == RESULT_FAIL) { + break; + } + } + } + + }//for end +// resultDesc = resultState == RESULT_OK ? "停用进程成功,详情信息如下:" + sb.toString() : "停用进程失败,详情信息如下:" + sb.toString(); +// resultDesc = resultState == RESULT_OK ? "Deactivation process is successful. Details are as follows:" + sb.toString() : "Deactivation process failed, details are as follows:" + sb.toString(); + resultDesc = resultState == RESULT_OK ? "i18n_client.AgentCommand.killProcSuccess5_n81i:" + sb.toString() : "i18n_client.AgentCommand.killProcFail3_n81i:" + sb.toString(); + } + } catch (Exception e) { +// resultDesc = "停用进程失败:出现异常," + e.getMessage() + ",详细信息请查看日志"; + resultDesc = "i18n_client.AgentCommand.killProcFail4_n81i," + e.getMessage() + ",i18n_client.AgentCommand.execFailDesc10.showDetail_n81i"; + resultState = RESULT_FAIL; + logger.error("Disable process set exception:" + Utils.printExceptionStack(e)); + } +// logger.info("停用进程集结果描述信息 >> " + resultDesc);//i18nlog + logger.info("停用进程集结束……"); + + return resultState + RESULT_SEPRATOR + resultDesc; + } + + /** + * Agent原生支持命令,启动进程 + * @param execList 命令参数对象集 + * @param isRestart 当前运行的文件或命令,是否是重新启动,若是则不用判断进程是否存在,直接执行 + * @return + */ + public String startCmd(List<ParamCmdExec> execList, Date startTime, boolean isRestart, long stepState){ + logger.info("启动开始……"); + String resultDesc = ""; + StringBuffer sb = new StringBuffer(); + long resultState = RESULT_FAIL; + try { + if(execList==null || execList.size()<=0){ +// resultDesc = "执行成功:未指定内容,不需要执行"; +// resultDesc = "Execution success: unspecified content, no need to execute"; + resultDesc = "i18n_client.AgentCommand.startCmdSuccess1_n81i"; + resultState = RESULT_OK; + logger.debug(resultDesc); + } else { + List<String> returnFileList = new ArrayList<String>(); + + for(ParamCmdExec exec : execList){ + if (stepState != RESULT_START_OK + && stepState != RESULT_START_FAIL) {// 若还未执行过,则继续执行,否则,只进行回传文件 + /** + * 步骤1、判断执行文件是否存在且可执行 + */ + if(exec.getExecCmd()==null || exec.getExecCmd().trim().length()<=0){ +// sb.append("执行“" + exec.getExecCmd() + "”失败,执行命令为空;"); +// sb.append("Execute“" + exec.getExecCmd() + "”Failure, the result file is empty;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.startCmdFail1_n81i;"); + resultState = RESULT_FAIL; + break; + } + if(exec.getExecResult()==null || exec.getExecResult().trim().length()<=0){ +// sb.append("执行“" + exec.getExecCmd() + "”失败,结果文件为空;"); +// sb.append("Execute“" + exec.getExecCmd() + "”Failure, the result file is empty;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.startCmdFail2_n81i;"); + resultState = RESULT_FAIL; + break; + } + // 2013-4-26 由于DC改为Windows服务后升级要支持命令,若命令复杂的话,无法正确判断,做不作此步判断,待以后确定执行方案后考虑此步要不要 + /*boolean existFlag= ProcessUtil.isFileOrCmdExist(exec.getExecCmd()); + if(!existFlag){ + sb.append("执行“" + exec.getExecCmd() + "”失败,执行文件不存在或不是可执行命令;"); + resultState = RESULT_FAIL; + break; + }*/ + // 判断用户和密码是否正确 + /*boolean flag = ProcessUtil.checkUserPass(exec.getUsername(), exec.getParam1()); + if (!flag) { + sb.append("执行“" + exec.getExecCmd() + "”失败,用户名或密码不正确;"); + resultState = RESULT_FAIL; + break; + }*/ + // 判断用户名是否正确 + if(!ProcessUtil.checkUserOrGroupExist(exec.getUsername(), null)){ +// sb.append("执行“" + exec.getExecCmd() + "”失败,用户名不正确;"); +// sb.append("Execute“" + exec.getExecCmd() + "”Failure, incorrect username"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.startCmdFail3_n81i"); + resultState = RESULT_FAIL; + break; + } + //判断用户是否有执行命令的权限 + //------------待完成su - -c "[ -x jzz_test.py ];echo $?" nmstest; + /** + * 步骤2、判断是否常驻内存 + * (1) 常驻内存,判断进程是否存在,是否强制执行; + * (2) 非常驻内存,直接执行 + */ + boolean residentFlag = false; + if ("Y".equals(handleYesOrNoField(exec.getResidentFlag()))) { + residentFlag = true; + } + // 如果不是重启操作,则判断进程是否存在,反之,不判断进程是否存在,直接进行下面的执行部分 + if (residentFlag && !isRestart) {//----常驻内存,针对PID判断操作,execResult存放PID的文件 + //----步骤2-1-0、判断进程是否存在: 先判断进程PID文件是否存在--不存在认为进程不存在,存在判断进程PID是否存在 + File pidFile = new File(exec.getExecResult()); + boolean isExist = false; + String[] pidArr = null; + if(pidFile.exists()){ + pidArr = ProcessUtil.getProcessIdByFile(pidFile); + if (pidArr != null) { + for(int i=0; i<pidArr.length; i++){ + isExist = ProcessUtil.isProcessExistByPid(pidArr[i]); + if(isExist){//如果有一个PID存在,就认为进程存在 + break; + } + } + } + } + // ----步骤2-1-1、进程存在:则判断是否是强制执行; 进程不存在:则直接执行 + if (isExist) { + // -------进程存在:强制执行,则杀进程继续执行 + if ("Y".equals(handleYesOrNoField(exec.getForceExec()))) { + for (int i = 0; i < pidArr.length; i++) { + ProcessUtil.killProcess(pidArr[i]);// 杀进程 + } + }else{// --------进程存在:非强制执行,则不执行(continue, 跳过下面执行的部分) + resultState = RESULT_OK; +// sb.append("执行“" + exec.getExecCmd() + "”成功,进程原本存在,不用执行;"); +// sb.append("Execute“" + exec.getExecCmd() + "”Execution success: unspecified content, no need to execute;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.startCmdSuccess2_n81i;"); + continue; + } + } + } + /** + * 步骤3、执行文件或命令部分 + * A、常驻内存,结果文件存放PID,查看是否成功; + * B、非常驻内存,结果文件存放结果标识,解析结果文件判断是否成功 + */ + String resultMsg = ProcessUtil.runExec(exec.getExecCmd(), exec.getExecParams(), exec.getUsername(), exec.getParam1()); + // -------------步骤3-0、暂停最终结果获取最大等待时间(单位秒) + long delay = 3; + if (exec.getMaxWaitTime() != null + && !"".equals(exec.getMaxWaitTime().trim())) { + delay = Long.parseLong(exec.getMaxWaitTime().trim()); + } + if(delay>0){ + synchronized (this) { + logger.debug("wait: " + delay + " seconds"); + this.wait(delay * 1000); + } + } + // -------------步骤3-1、判断进程启动成功与否 + if (residentFlag) {// ---常驻内存,针对PID判断操作 + File pidFile = new File(exec.getExecResult()); + boolean isExist = false; + if (pidFile.exists()) { + String[] pidArr = ProcessUtil.getProcessIdByFile(pidFile); + isExist = false; + String notExitPids = null; + if (pidArr != null) { + for (int i = 0; i < pidArr.length; i++) { + isExist = ProcessUtil.isProcessExistByPid(pidArr[i]); + if (!isExist) {// 如果有一个PID不存在,就认为启动不成功 + notExitPids = pidArr[i]; + break; + } + } + } + resultState = isExist ? RESULT_OK : RESULT_FAIL; + if(isExist){ +// sb.append("执行“" + exec.getExecCmd() + "”成功;"); +// sb.append("Execute“" + exec.getExecCmd() + "”success;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.success_n81i;"); + }else{ +// sb.append("执行“" + exec.getExecCmd() + "”失败, " + (notExitPids==null ? "PID为空;" : ("PID“"+notExitPids+"”不存在;"))); +// sb.append("Execute" + exec.getExecCmd() + "”failed, " + (notExitPids==null ? "PID is empty;" : ("PID is empty“"+notExitPids+"”do not exist;"))); + sb.append("i18n_client.AgentCommand.exec_n81i" + exec.getExecCmd() + "”failed, " + (notExitPids==null ? "i18n_client.AgentCommand.startCmdFail4_n81i;" : ("PID “"+notExitPids+"”i18n_client.AgentCommand.execFailDesc8_n81i;"))); + } + } else { + resultState = RESULT_FAIL; +// sb.append("Failure to execute“" + exec.getExecCmd() + "”process PID file“" + pidFile.getAbsolutePath() + "”do not exist;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.startCmdFail6_n81i“" + pidFile.getAbsolutePath() + "”i18n_client.AgentCommand.execFailDesc8_n81i;"); + } + } else {// ---非常驻内存,解析结果文件:结果标识(0 成功 1失败)|结果描述 + File resultFile = new File(exec.getExecResult()); + if (resultFile.exists()) { + String[] result = FileWrUtil.cfgFileReader(resultFile); + if (result != null && result.length > 0) { + String[] res = result[0].split("\\|"); + if (res != null && res.length >= 1) { + resultState = Long.parseLong(res[0]); + logger.debug("startCmd resultState-->" + resultState); +// String tt = (resultState == RESULT_OK ? "成功" : "失败"); + String tt = (resultState == RESULT_OK ? "Success" : "Failed"); + if(res.length >= 2){ +// sb.append("Execute“" + exec.getExecCmd() + "”" + tt + "," + res[1] + ";"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”" + tt + "," + res[1] + ";"); + }else{ +// sb.append("Execute“" + exec.getExecCmd() + "”" + tt + ";"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”" + tt + ";"); + } + } + } else { + resultState = RESULT_FAIL; +// sb.append("Failure to execute“" + exec.getExecCmd() + "”result file is not written in result file;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.startCmdFail7_n81i;"); + } + } else { + resultState = RESULT_FAIL; +// sb.append("Failure to execute“" + exec.getExecCmd() + "”result file“" + resultFile.getAbsolutePath() + "”does not exist;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.startCmdFail8_n81i“" + resultFile.getAbsolutePath() + "”i18n_client.AgentCommand.execFailDesc8_n81i;"); + } + }// -------------步骤3-1结束 + if(resultMsg!=null && resultMsg.length()>0){ + sb.append(resultMsg + ";"); + } + }else{ + resultState = (stepState == RESULT_START_OK ? RESULT_OK : RESULT_FAIL); + } + + /** + * 步骤4 判断是否回传文件 + */ + if(exec.getReturnFlag()!=null && "Y".equalsIgnoreCase(exec.getReturnFlag().trim())){ + returnFileList.add(exec.getReturnPath()); + } + + if(resultState == RESULT_FAIL){//如果有一个失败,就停止执行 + break; + } + }// for end + + /** + * 步骤5 如果有回传文件,则回传文件并修改结果为中间结果;如果无回传文件,不回传且结果为最终结果 + */ + if(returnFileList.size()>0){ + ReturnFilePO rfPO = new ReturnFilePO(); + rfPO.setTaskId(command.getExecId()); + rfPO.setTaskType(command.getExecType()); + rfPO.setUuid(Contants.AGENT_HOST_UUID); + rfPO.setState(resultState); + //rfPO.setFilePaths(returnFileList); + rfPO.setStartTime(startTime); + rfPO.setEndTime(new Date()); + rfPO.setIsLoop(command.getIsLoop()); + TaskReturnHandle.startTaskReturnFileThread(rfPO, returnFileList); + resultState = (resultState == RESULT_OK) ? RESULT_START_OK : RESULT_START_FAIL; + } + + if(resultState == RESULT_OK || resultState == RESULT_START_OK){ +// resultDesc = "执行成功,详细信息如下:" + sb.toString(); +// resultDesc = "Execution succeeded, details are as follows:" + sb.toString(); + resultDesc = "i18n_client.AgentCommand.startCmdSuccess4_n81i:" + sb.toString(); + }else{ +// resultDesc = "执行失败,详细信息如下:" + sb.toString(); +// resultDesc = "Execution failed with the following details:" + sb.toString(); + resultDesc = "i18n_client.AgentCommand.startCmdFail9_n81i:" + sb.toString(); + } +// logger.debug(resultDesc);//i18nlog + } + + } catch (Exception e) { +// resultDesc = "执行失败:出现异常," + e.getMessage() + ",详细信息请查看日志"; +// resultDesc = "Execution failed: An exception occurred," + e.getMessage() + ",see the logs for details"; + resultDesc = "i18n_client.AgentCommand.startCmdFail10_n81i," + e.getMessage() + ",i18n_client.AgentCommand.execFailDesc10.showDetail_n81i"; + resultState = RESULT_FAIL; + logger.error("Start abnormity: " + Utils.printExceptionStack(e)); + } +// logger.info("启动结果描述信息 >> " + resultDesc);//i18nlog + logger.info("启动结束……"); + + return resultState + RESULT_SEPRATOR + resultDesc; + } + + /** + * 可执行命令,单次执行命令 + * @param execList 命令参数对象集 + * @return + */ + public String singleExecCmd(List<ParamCmdExec> execList, Date startTime, long stepState){ + logger.info("单次命令执行开始……"); + String resultDesc = ""; + StringBuffer sb = new StringBuffer(); + long resultState = RESULT_FAIL; + try { + if(execList==null || execList.size()<=0){ +// resultDesc = "执行成功:未指定内容,不需要执行"; + resultDesc = "Execution succeeded: no content specified, no need to execute"; + resultState = RESULT_OK; + logger.debug(resultDesc); + } else { + List<String> returnFileList = new ArrayList<String>(); + for(ParamCmdExec exec : execList){ + if (stepState != RESULT_START_OK + && stepState != RESULT_START_FAIL) {// 若还未执行过,则继续执行,否则,只进行回传文件 + /** + * 步骤1、必要的空判断 + */ + if(exec.getExecCmd()==null || exec.getExecCmd().trim().length()<=0){ +// sb.append("执行“" + exec.getExecCmd() + "”失败,执行命令为空;"); + sb.append("The execution of“" + exec.getExecCmd() + "”failed and the execution command was empty;"); + resultState = RESULT_FAIL; + break; + } + // 判断用户和密码是否正确 + /*boolean flag = ProcessUtil.checkUserPass(exec.getUsername(), exec.getParam1()); + if (!flag) { + sb.append("执行“" + exec.getExecCmd() + "”失败,用户名或密码不正确;"); + resultState = RESULT_FAIL; + break; + }*/ + // 判断用户名是否正确 + if(!ProcessUtil.checkUserOrGroupExist(exec.getUsername(), null)){ +// sb.append("执行“" + exec.getExecCmd() + "”失败,用户名不正确;"); +// sb.append("Failure to execute“" + exec.getExecCmd() + "” with incorrect user name;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "” i18n_client.AgentCommand.singleCmdFail2_n81i;"); + resultState = RESULT_FAIL; + break; + } + //判断用户是否有执行命令的权限 + //------------待完成su - -c "[ -x jzz_test.py ];echo $?" nmstest; + /** + * 步骤2、执行命令部分 + */ + final String execCmd = exec.getExecCmd(); + final String username = exec.getUsername(); + final String pass = exec.getParam1(); + final String threadName = Thread.currentThread().getName(); + Future<String> future = Common.service.submit(new Callable<String>(){ + @Override + public String call() throws Exception { + thread = Thread.currentThread(); + Thread.currentThread().setName(threadName); + String result = ProcessUtil.runExecGetResult(execCmd, username, pass); + return result; + } + }); + // ----获取最大等待时间(单位秒) + long delay = 3; + if (exec.getMaxWaitTime() != null + && !"".equals(exec.getMaxWaitTime().trim())) { + delay = Long.parseLong(exec.getMaxWaitTime().trim()); + logger.debug("singleExecCmd Timeout time value: " + delay + " seconds"); + } + // ----超过一定时间,终止执行线程,返回结果超时 + try { + String result = future.get(delay, TimeUnit.SECONDS); + logger.debug("singleExecCmd result-->" + result); + // ---解析结果:结果标识(0 成功 1失败)|结果描述 + if (result != null && !result.isEmpty()) { + String[] res = result.split("\\|"); + if (res != null && res.length >= 1) { + resultState = Long.parseLong(res[0]); + logger.debug("singleExecCmd resultState-->" + resultState); +// String tt = (resultState == RESULT_OK ? "成功" : "失败"); +// String tt = (resultState == RESULT_OK ? "Success" : "Failed"); + String tt = (resultState == RESULT_OK ? "i18n_client.AgentCommand.success_n81i" : "i18n_client.AgentCommand.fail_n81i"); + if(res.length >= 2){ +// sb.append("Execute“" + exec.getExecCmd() + "”" + tt + "," + res[1] + ";"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”" + tt + "," + res[1] + ";"); + }else{ +// sb.append("Execute“" + exec.getExecCmd() + "”" + tt + ";"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”" + tt + ";"); + } + } + } else { + resultState = RESULT_FAIL; +// sb.append("Execute“" + exec.getExecCmd() + "”failed"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.singleCmdFail3_n81i"); + } + } catch (TimeoutException e) { + if(thread!=null && thread.isAlive()){ + thread.stop(); + logger.debug(execCmd + "---singleExecCmd Timeout stop thread--" + thread.isAlive()); + } + future.cancel(true); + resultState = RESULT_FAIL; +// sb.append("执行“" + exec.getExecCmd() + "”失败, 超时;"); +// sb.append("Failed to execute“" + exec.getExecCmd() + "”timeout;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.singleCmdFail4_n81i;"); + logger.debug("---------singleExecCmd timeout----------"); + }catch (InterruptedException e) { + if(thread!=null && thread.isAlive()){ + thread.stop(); + logger.debug(execCmd + "---singleExecCmd Interrupted stop thread--" + thread.isAlive()); + } + future.cancel(true); + resultState = RESULT_FAIL; +// sb.append("Failure to execute“" + exec.getExecCmd() + "”thread was interrupted;"); + sb.append("i18n_client.AgentCommand.exec_n81i“" + exec.getExecCmd() + "”i18n_client.AgentCommand.singleCmdFail5_n81i;"); + logger.debug("---------singleExecCmd Interrupted----------"); + } + }else{ + resultState = (stepState == RESULT_START_OK ? RESULT_OK : RESULT_FAIL); + } + + /** + * 步骤3 判断是否回传文件 + */ + if(exec.getReturnFlag()!=null && "Y".equalsIgnoreCase(exec.getReturnFlag().trim())){ + returnFileList.add(exec.getReturnPath()); + } + + if(resultState == RESULT_FAIL){//如果有一个失败,就停止执行 + break; + } + }// for end + + /** + * 步骤4 如果有回传文件,则回传文件并修改结果为中间结果;如果无回传文件,不回传且结果为最终结果 + */ + if(returnFileList.size()>0){ + ReturnFilePO rfPO = new ReturnFilePO(); + rfPO.setTaskId(command.getExecId()); + rfPO.setTaskType(command.getExecType()); + rfPO.setUuid(Contants.AGENT_HOST_UUID); + rfPO.setState(resultState); + //rfPO.setFilePaths(returnFileList); + rfPO.setStartTime(startTime); + rfPO.setEndTime(new Date()); + rfPO.setIsLoop(command.getIsLoop()); + TaskReturnHandle.startTaskReturnFileThread(rfPO, returnFileList); + resultState = (resultState == RESULT_OK) ? RESULT_START_OK : RESULT_START_FAIL; + } + + if(resultState == RESULT_OK || resultState == RESULT_START_OK){ +// resultDesc = "执行成功,详细信息如下:" + sb.toString(); +// resultDesc = "The execution was successful. The details are as follows:" + sb.toString(); + resultDesc = "i18n_client.AgentCommand.singleCmdSuccess2_n81i:" + sb.toString(); + }else{ +// resultDesc = "执行失败,详细信息如下:" + sb.toString(); +// resultDesc = "Execution failed with the following details:" + sb.toString(); + resultDesc = "i18n_client.AgentCommand.singleCmdFail6_n81i:" + sb.toString(); + } + } + + } catch (Exception e) { +// resultDesc = "执行失败:出现异常," + e.getMessage() + ",详细信息请查看日志"; +// resultDesc = "Execution failed: An exception occurred," + e.getMessage() + ", See the logs for details"; + resultDesc = "i18n_client.AgentCommand.singleCmdFail7_n81i," + e.getMessage() + ",i18n_client.AgentCommand.execFailDesc10.showDetail_n81i"; + resultState = RESULT_FAIL; + logger.error("Single command execution exception: " + Utils.printExceptionStack(e)); + } +// logger.info("单次命令执行结果描述信息 >> " + resultDesc);//i18nlog + logger.info("单次命令执行结束……"); + + return resultState + RESULT_SEPRATOR + resultDesc; + } + + /** + * 取得备份文件的名称:原文件名_version_bak_压缩文件的相应后缀 + * @param oldFileName + * @param version + * @param isAbs + * @return + */ + private String getBakFileName(String oldFileName, long version, boolean isAbs){ + String fileName = ""; + if(oldFileName!=null){ + fileName += oldFileName + "_"; + } + fileName += version + "_bak" + CompressFileMgr.getCompressSuffixByOs(isAbs); + + return fileName; + } + + /** + * 处理相对和绝对文件路径:如果文件本身是绝对路径不做处理;如果文件是相对路径则相对parent下 + * @param filepath 相对或绝对路径的文件 + * @param parent 相对路径文件的父目录 + * @return + * @throws Exception + */ + private String getFilePath(String filepath, String parent) throws Exception{ + if(filepath!=null && filepath.trim().length()>0){ + File file = new File(filepath); + if(file.isAbsolute()){ + return file.getCanonicalPath(); + }else if(parent!=null && parent.trim().length()>0){ + File parentFile = new File(parent); + if(!parentFile.isDirectory()){ + parent = parentFile.getParent(); + } + return new File(parent + File.separator + filepath).getCanonicalPath(); + }else { + return file.getCanonicalPath(); + } + } + return null; + } + + /** + * 删除文件,先对删除的文件做处理:如果是绝对路径直接删除;如果是相对路径则相应处理 + * @param dels 将要删除的文件集 + * @param oppositeDelDir 如果删除文件是相对路径,则为相对路径文件的父目录 + * @return 删除文件的描述信息 + * @throws Exception + */ + private String delete(String[] dels, String oppositeDelDir) throws Exception{ + StringBuffer sb = new StringBuffer(); + if(dels!=null && dels.length>0){ + for(String del : dels){ + if(del==null || del.trim().length()<=0){ + continue; + } + del = getFilePath(del, oppositeDelDir); + if(del==null){ + continue; + } + File file = new File(del); + if(file.exists()){ + FileUtil.delDir(file); +// sb.append("删除”" + file.getCanonicalPath() + "“成功;"); +// sb.append("Delete”" + file.getCanonicalPath() + "“success;"); + sb.append("i18n_client.AgentCommand.deleteSuccess_n81i”" + file.getCanonicalPath() + "“i18n_client.AgentCommand.success_n81i;"); + }else{ +// sb.append("删除”" + file.getCanonicalPath() + "“,文件不存在;"); +// sb.append("Delete”" + file.getCanonicalPath() + "“,the file does not exist;"); + sb.append("i18n_client.AgentCommand.deleteFail_n81i”" + file.getCanonicalPath() + "“,i18n_client.AgentCommand.deleteFail.noFile_n81i;"); + } + } + } + if(sb.length()>0){ + sb.deleteCharAt(sb.length()-1); + } + return sb.toString(); + } + + /** + * 对是否字段(Y\N)的默认值处理 + * @param field + * @return + */ + private String handleYesOrNoField(String field){ + if(field==null || field.trim().length()<=0){ + return "N"; + }else if("Y".equalsIgnoreCase(field.trim())){ + return "Y"; + }else{ + return "N"; + } + } + + /** + * 升级中的覆盖更新参数处理: + * *逆向任务,按恢复到的版本和本地备份目录来处理覆盖源文件;恢复目录,如果是相对则相对升级的覆盖目录,如果是绝对则不变 + * *升级任务,按升级文件的路径处理源文件 + * @param cfuList 升级参数列表 + * @param reVersion 恢复到的版本 + * @param upgradePath 升级文件的路径 + * @return 覆盖更新数组集 + * @throws Exception + */ + private ParamCoverUpdate[] handleCoverUpdates(List<ParamUpgrade> cfuList, + Long reVersion, String upgradePath) throws Exception { + List<ParamCoverUpdate> pcuList = new ArrayList<ParamCoverUpdate>(); + for (ParamUpgrade cfu : cfuList) { + if (reVersion != null && reVersion.longValue() > 0) {//逆向任务,恢复 + for (ParamCoverUpdate update : cfu.getRecoverys()) { + //必须先处理恢复目录 + update.setCover(getFilePath(update.getCover(), cfu.getCover())); + //再处理恢复源文件 + update.setSource(getRecoverSource(update, reVersion)); + pcuList.add(update); + } + } else {//升级任务 + ParamCoverUpdate update = new ParamCoverUpdate(); + update = new ParamCoverUpdate(); + update.setSource(getFilePath(cfu.getFileName(), upgradePath)); + update.setCover(cfu.getCover()); + update.setIsCreateCover(cfu.getIsCreateCover()); + update.setIsAbs(cfu.getIsAbs()); + update.setDelete(cfu.getDelete()); + + pcuList.add(update); + } + } + ParamCoverUpdate[] updates = new ParamCoverUpdate[cfuList.size()]; + return pcuList.toArray(updates); + } + + /** + * 升级中的恢复参数的源处理:source应为 localBackupPath + source + bakFileName(coverFileName_version_bak_压缩后缀) + * @param update 覆盖更新对象 + * @param reVersion 恢复到的版本 + * @return 恢复参数的源文件 + * @throws Exception + */ + private String getRecoverSource(ParamCoverUpdate update, Long reVersion) + throws Exception { + // 逆向任务,source是原任务的备份目标目录(相对的),cover是原任务的备份过的文件 + // source还可以是操作人员自己备份的文件(完整的绝对路径且必须存在),如果source文件不存在,则按上面默认的方法重新拼写 + String source = update.getSource(); + logger.debug("getRecoverSource source----" + update.getSource()); + logger.debug("getRecoverSource cover----" + update.getCover()); + if (update.getSource() != null + && !new File(update.getSource()).exists()) { + String oldFileName = ""; + if (update.getCover() != null) { + oldFileName = new File(update.getCover()).getCanonicalFile().getName(); + } + boolean isAbs = false; + if ("Y".equals(handleYesOrNoField(update.getIsAbs()))) { + isAbs = true; + } + source = Contants.localBackupPath + File.separator + + update.getSource() + File.separator + + getBakFileName(oldFileName, reVersion, isAbs); + } + return source; + } + + private void backup(File srcFile, File destDir, String[] excepts) throws Exception{ + if (!srcFile.exists()) { + return; + } + if (!srcFile.isDirectory()) { + boolean flag = true; + if (excepts != null && excepts.length > 0) { + for (String except : excepts) { + if (srcFile.getCanonicalPath().equalsIgnoreCase(except)) { + flag = false; + break; + } + } + } + if (flag) { + FileUtils.copyFileToDirectory(srcFile, destDir); + } + } else if (srcFile.isDirectory()) { + destDir = new File(destDir.getAbsolutePath() + File.separator + + srcFile.getName()); + for (File f : srcFile.listFiles()) { + boolean flag = true; + if (excepts != null && excepts.length > 0) { + for (String except : excepts) { + if (f.getCanonicalPath().equalsIgnoreCase(except)) { + flag = false; + break; + } + } + } + if (flag) { + if (!f.isDirectory()) { + FileUtils.copyFileToDirectory(f, destDir); + } else if (f.isDirectory()) { + backup(f, new File(destDir.getAbsolutePath()), excepts); + } + } + } + } + } + +} diff --git a/src/com/nis/nmsclient/thread/task/LoopTaskThread.java b/src/com/nis/nmsclient/thread/task/LoopTaskThread.java new file mode 100644 index 0000000..b3e8a36 --- /dev/null +++ b/src/com/nis/nmsclient/thread/task/LoopTaskThread.java @@ -0,0 +1,106 @@ +package com.nis.nmsclient.thread.task; + +import java.util.Date; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.model.CommandPO; +import com.nis.nmsclient.util.Utils; + +public class LoopTaskThread extends Thread{ + Logger logger = Logger.getLogger(LoopTaskThread.class); + + private String threadName; + private long loopDelay; + private CommandPO command; + + private long i = 0; + private Future<?> future = null; + private Thread thread; + + private boolean isCancle; + + public LoopTaskThread(String threadName, CommandPO command, long loopDelay, Future<?> singleFuture, Thread singleThread){ + this.threadName = threadName; + this.loopDelay = loopDelay; + this.command = command; + this.future = singleFuture; + this.thread = singleThread; + + isCancle = false; + } + + public synchronized void cancle() { + isCancle = true; + } + + public void run() { + i++; +// Thread.currentThread().setName(threadName + " 周期" + i); + Thread.currentThread().setName(threadName + " Cycle" + i); + long et = System.currentTimeMillis();// 本次开始时间,即上次执行结束时间 + long st = et - (i * loopDelay * 60 * 1000);// 上次开始时间 + try { + if (i == 1 && future != null + && !future.isCancelled() + && !future.isDone()) { + try { + future.get(1, TimeUnit.MICROSECONDS); + } catch (TimeoutException e) { + if(thread!=null && thread.isAlive()){ + thread.stop(); + logger.debug("LoopTaskThread run Timeout stop singleThread--" + thread.isAlive()); + } + future.cancel(true); + } + + } + if(!isCancle){ + // 周期开始执行 + future = Common.scheduled.schedule(new Runnable() { + public void run() { + thread = Thread.currentThread(); +// Thread.currentThread().setName(threadName + " 周期" + i); + Thread.currentThread().setName(threadName + " Cycle" + i); + new AgentCommand(command).exec(); + } + }, 0, TimeUnit.MILLISECONDS); + try { + future.get(loopDelay, TimeUnit.MINUTES); + } catch (TimeoutException e) { + if(thread!=null && thread.isAlive()){ + thread.stop(); + logger.debug("LoopTaskThread run Timeout stop thread--" + thread.isAlive()); + } + future.cancel(true); + logger.debug("---------LoopTaskThread run timeout----------"); + TaskResultOper.sendTaskResult(command.getExecId(), + command.getExecType(), + AgentCommand.RESULT_FAIL, +// "本周期任务执行超时", "", new Date(st), +// "this task execution timeout", "", new Date(st), + "i18n_client.LoopTaskThread.loopTaskOuttime_n81i", "", new Date(st), + new Date(et), false, command.getIsLoop()); + }catch (InterruptedException e) { + if(thread!=null && thread.isAlive()){ + thread.stop(); + logger.debug("LoopTaskThread run Interrupted stop thread--" + thread.isAlive()); + } + future.cancel(true); + logger.debug("---------LoopTaskThread run Interrupted----------"); + } + } + + if(thread!=null){ + logger.debug("LoopTaskThread run thread state--" + thread.isAlive()); + } + } catch (Exception e) { + logger.info(Utils.printExceptionStack(e)); + } + } +} + diff --git a/src/com/nis/nmsclient/thread/task/TaskReqHandle.java b/src/com/nis/nmsclient/thread/task/TaskReqHandle.java new file mode 100644 index 0000000..3381742 --- /dev/null +++ b/src/com/nis/nmsclient/thread/task/TaskReqHandle.java @@ -0,0 +1,397 @@ +package com.nis.nmsclient.thread.task; + +import java.io.File; +import java.io.IOException; +import java.util.Date; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import net.sf.json.JSONObject; + +import org.apache.commons.io.FileUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.model.CommandPO; +import com.nis.nmsclient.model.ParamFilePush; +import com.nis.nmsclient.model.ParamUpgrade; +import com.nis.nmsclient.model.Task4; +import com.nis.nmsclient.model.Task6; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.ProcessUtil; +import com.nis.nmsclient.util.Utils; + +public class TaskReqHandle { + Logger logger = Logger.getLogger(TaskReqHandle.class); + private Thread singleThread; + + /** + * 任务请求处理步骤1:分析任务请求参数,分不同任务类型处理 + */ + public void taskHandle(String str){ + Date execTime = new Date(); + boolean flag = true; + int taskType = 0; + long taskId = 0; + String threadName = null; + CommandPO command = null; + try { + JSONObject jsonObj = JSONObject.fromObject(str); + if(str.contains("typeInfo")){ + taskType = jsonObj.getInt("typeInfo"); + } + if(str.contains("taskInfo")){ + JSONObject jsonObj2 = jsonObj.getJSONObject("taskInfo"); + Object obj = null; + /** + * 任务类型:2 非流文本数据获取,3 流文本数据获取,4 命令执行,5 shell注册, 6升级 + */ + switch (taskType) { + case 4: + obj = JSONObject.toBean(jsonObj2,Task4.class); + Task4 task4 = (Task4) obj; + taskId = task4.getTaskId(); + /** + * 命令类型:1 Agent原生支持命令,2可执行命令(2 脚本,3 shell命令) + */ + if(task4.getCommandType() == 1){ +// threadName = "原生命令 id:" + task4.getTaskId() + ">>" + task4.getCommandName(); + threadName = "Native command ID:" + task4.getTaskId() + ">>" + task4.getCommandName(); + }else if(task4.getCommandType() == 2){ +// threadName = "可执行命令 id:" + task4.getTaskId(); + threadName = "Executable command ID:" + task4.getTaskId(); + } + command = new CommandPO(); + command.setExecId(task4.getTaskId()); + command.setExecType(task4.getTaskType()); + command.setCommandName(task4.getCommandName()); + command.setCommandParam(task4.getCommandParam()); + command.setExecState(task4.getState()); + command.setExecVersion(null); + command.setIsLoop(task4.getIsLoop()); + + handleTaskThread(task4.getTaskId(), task4.getStartTime(), task4.getEndTime(), task4 + .getIsLoop(), task4.getLoopDelay(), command, threadName, task4.getMissionState()); + + break; + case 6: + obj = JSONObject.toBean(jsonObj2,Task6.class); + Task6 task6 = (Task6) obj; + taskId = task6.getTaskId(); +// threadName = "升级 id:" + task6.getTaskId() + ">>" + task6.getCommandName(); + threadName = "Upgrade ID:" + task6.getTaskId() + ">>" + task6.getCommandName(); + command = new CommandPO(); + command.setExecId(task6.getTaskId()); + command.setExecType(task6.getTaskType()); + command.setCommandName(task6.getCommandName()); + command.setCommandParam(task6.getCommandParam()); + command.setExecState(task6.getState()); + command.setExecVersion(task6.getVersion()); + command.setSrcPath(getUpgradeTaskPushPath(task6.getTaskId())); + + handleTaskThread(task6.getTaskId(), task6.getUpgradeTime(), null, 0, 0, command, threadName, 0); + break; + default: + flag = false; + break; + } + }else{ + flag = false; + } + } catch (Exception e) { + logger.error(Utils.printExceptionStack(e)); + flag = false; + } + + if(!flag){ + TaskResultOper.sendTaskResult(taskId, taskType, +// AgentCommand.RESULT_FAIL, "发送内容格式不正确", "", execTime, new Date(), false, -1l); +// AgentCommand.RESULT_FAIL, "Incorrect content format", "", execTime, new Date(), false, -1l); + AgentCommand.RESULT_FAIL, "i18n_client.TaskReqHandle.sendInfoFormatErr_n81i", "", execTime, new Date(), false, -1l); + } + } + + /** + * 文件推送处理 + */ + public String filePush(CommonSocket socket, String taskParam, long taskId, boolean isUpgrade){ + String msg = null; + StringBuffer sb = new StringBuffer(); + File tempDir = null; + try { + tempDir = new File(Contants.localTempPath + File.separator + + "filepush_" + taskId); + if (!tempDir.exists()) { + tempDir.mkdirs(); + } + // ------步骤1:接收Md5校验的推送文件到临时目录 + int flag = socket.bpReceiveFileByBathMd5(tempDir.getAbsolutePath()); + + if (flag == 0){// ------步骤2:接收成功,与参数比对 + if(taskParam==null || "".equals(taskParam)){ + msg = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + "i18n_client.TaskReqHandle.pushFileParamIsNull_n81i"; +// logger.info(msg);//i18nlog + return msg; + } + // ------步骤2-1:解析参数 + String[] params = taskParam.trim().split(AgentCommand.PARAM_SEPRATOR); + if (params != null && params.length >= 1) { + for (int i = 0; i < params.length; i++) { + //2012-4-28 任务参数中对路径的格式化将在界面上进行,原因此处会对转义字符的\也转换为/,故replace("\\", "/")去掉 + params[i] = params[i].trim().replaceAll("[\n\t\r]","");//.replace("\\", "/");//[\\s*\n\t\r] + logger.debug("filePush-->param: " + params[i]); + ParamFilePush fParam = null; + if(isUpgrade){ + ParamUpgrade cfu = (ParamUpgrade) JSONObject.toBean(JSONObject + .fromObject(params[i]), ParamUpgrade.class); + fParam = new ParamFilePush(); + fParam.setFileName(cfu.getFileName()); + fParam.setUsername(cfu.getUsername()); + fParam.setGroupName(cfu.getGroupName()); + fParam.setParam1(cfu.getParam1()); + }else{ + fParam = (ParamFilePush) JSONObject.toBean( + JSONObject.fromObject(params[i]), + ParamFilePush.class); + } + if(fParam.getDestPath()==null || fParam.getDestPath().trim().length()<=0){ + fParam.setDestPath(getUpgradeTaskPushPath(taskId));//设置默认推送目的地 + logger.debug("filePush-->destPath: " + fParam.getDestPath()); + } + if(fParam.getFileName()==null || fParam.getFileName().trim().length()<=0){ +// msg = "推送文件名参数为空"; +// msg = "File push parameters are empty"; + msg = "i18n_client.TaskReqHandle.pushFileNameParamIsNull_n81i"; +// logger.debug(msg);//i18nlog + break; + } + /*if(!ProcessUtil.checkUserPass(fParam.getUsername(), fParam.getParam1())){ + msg = "[" + fParam.getFileName() + "]推送文件的用户名或密码不正确;"; + logger.debug(msg); + break; + }*/ + // 判断用户名是否正确 + if(!ProcessUtil.checkUserOrGroupExist(fParam.getUsername(), fParam.getGroupName())){ +// msg = "[" + fParam.getFileName() + "]推送文件的属主或属群不正确;"; +// msg = "[" + fParam.getFileName() + "]The owner or group of the push file is incorrect;"; + msg = "[" + fParam.getFileName() + "]i18n_client.TaskReqHandle.userGroupErr_n81i;"; +// logger.debug(msg);//i18nlog + break; + } + // ------步骤2-2:文件存在并与Md5值比较文件是否完整 + File pushFile = new File(tempDir.getAbsolutePath() + + File.separator + fParam.getFileName()); + if (!pushFile.exists()){ +// msg = "推送临时文件不存在,请检查推送文件名称与参数文件名(" +// + fParam.getFileName() + ")是否一致"; +// msg = "The push temporary file does not exist. Please check whether the push file name is consistent with the parameter file name(" +// + fParam.getFileName() + ")"; + msg = "i18n_client.TaskReqHandle.pushFileNotExists_n81i(" + + fParam.getFileName() + ")"; +// logger.warn(msg + "--" + pushFile.getAbsolutePath());//i18nlog + break; + } + // ------步骤2-3:判断推送目录是否存在,不存在创建 + File destFile = new File(fParam.getDestPath() + + File.separator + fParam.getFileName()); + if(!destFile.getParentFile().exists()){ + destFile.getParentFile().mkdirs(); + } + // ------步骤2-4:判断是否直接覆盖 + if (fParam.getIsCover() != null + && "Y".equalsIgnoreCase(fParam.getIsCover())) {// 覆盖,则直接Copy并赋权限与所有者 + if (destFile.exists()) { + //destFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(destFile); + logger.debug("filePush delete file--" + destFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(destFile); + } + msg = copyAndSetPermission(pushFile + .getCanonicalPath(), destFile + .getCanonicalPath(), fParam.getUsername(), + fParam.getGroupName(), fParam + .getPermisson()); + } else if (!destFile.exists()) {// 不覆盖,则判断文件不存在的话,再Copy并赋权限与所有者 + msg = copyAndSetPermission(pushFile + .getCanonicalPath(), destFile + .getCanonicalPath(), fParam.getUsername(), + fParam.getGroupName(), fParam + .getPermisson()); + } + if(msg==null || msg.length()<=0){ +// sb.append("[" + fParam.getFileName() + "]成功推送到[" + fParam.getDestPath() + "];"); +// sb.append("[" + fParam.getFileName() + "]successfully pushed to[" + fParam.getDestPath() + "];"); + sb.append("[" + fParam.getFileName() + "]i18n_client.TaskReqHandle.successPush_n81i[" + fParam.getDestPath() + "];"); + logger.debug("推送文件" + (i+1) + "成功---" + pushFile.getCanonicalPath()); + }else{ +// msg = msg+"[" + fParam.getFileName() + "]推送失败;";//文件推送失败的具体原因 + msg = msg+"[" + fParam.getFileName() + "]i18n_client.TaskReqHandle.pushFail_n81i;";//文件推送失败的具体原因 + logger.debug("推送文件" + (i+1) + "失败---" + pushFile.getCanonicalPath()); + break; + } + }//for end + } else { +// msg = "文件推送参数不正确"; +// msg = "File push parameter is incorrect"; + msg = "i18n_client.TaskReqHandle.pushParamErr_n81i"; +// logger.warn(msg + "<" + taskParam + ">");//i18nlog + } + //所有文件推送成功,删除临时接收文件目录 + if(msg==null || msg.length()<=0){ + if(tempDir!=null && tempDir.exists()){ + try { + logger.debug("删除临时目录--" + tempDir.getAbsolutePath()); + FileUtils.deleteDirectory(tempDir); + FileUtil.checkParentDirExist(tempDir); + } catch (IOException e) { + } + } + } + }else { + socket.close(); + } + + if(msg == null){ + msg = Contants.COMMON_MSG_SUCCESS + Contants.COMMON_MSG_SEPRATOR + sb.toString(); + }else { + sb.append(msg); + msg = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + sb.toString(); + } + + } catch (Exception e) { + logger.error("Receive push file exception:" + Utils.printExceptionStack(e)); +// msg = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + "接收推送文件异常," + e.getMessage(); +// msg = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + "Received push file exception," + e.getMessage(); + msg = Contants.COMMON_MSG_FAIL + Contants.COMMON_MSG_SEPRATOR + "i18n_client.TaskReqHandle.reciveFileErr_n81i," + e.getMessage(); + return msg; + }finally{ + if(tempDir!=null && tempDir.exists() && tempDir.listFiles().length==0){ + try { + FileUtils.deleteDirectory(tempDir); + logger.debug("finally删除临时目录--" + tempDir.getAbsolutePath()); + FileUtil.checkParentDirExist(tempDir); + } catch (IOException e) { + } + } + } + + return msg; + } + + /** + * 文件推送部分的拷备工作,由临时文件目录拷备到推送的最终目的地,并赋相应的权限组 + */ + private String copyAndSetPermission(String source, String destFile, String user, String group, String permission) throws Exception{ + String result = null; + if (source != null && destFile != null) { + // 根据操作系统确定获取进程ID的方式 + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + FileUtils.copyFile(new File(source), new File( + destFile));//目标路径不存在自动创建 + } else if (os.startsWith("Linux")) { + StringBuffer sb = new StringBuffer(); + //source destFile都不能含有空格 + source = source.replace(" ", "\\ "); + destFile = destFile.replace(" ", "\\ "); + sb.append("\\cp -f " + source + " " + destFile + ";");//2015-11-6 hyx: cp - f修改成\\cp -f (有时候如果不加\\会提示是否,就会有问题) + if (permission != null && !"".equals(permission.trim())) { + sb.append("chmod " + permission + " " + + destFile + ";"); + } + if (user != null && !"".equals(user.trim())) { + sb.append("chown " + user + " " + destFile + ";"); + } + if (group != null && !"".equals(group.trim())) { + sb.append("chgrp " + group + " " + destFile); + } + result = ProcessUtil.execLinuxCmd(sb.toString()); + } else { + throw new IOException("unknown operating system: " + os); + } + }else{ +// result = "源文件或目标文件为空"; +// result = "The source file or target file is empty"; + result = "i18n_client.TaskReqHandle.sourceOrTargetIsNull_n81i"; + } + + return result; + } + + + /** + * 任务请求处理步骤2:将分析包装好的任务,统一判断处理并添加到线程中执行 + */ + public void handleTaskThread(Long taskId, Long startTime, Long endTime, + long isLoop, long loopDelay, final CommandPO command, + final String threadName, long missionState) { + if(missionState == AgentCommand.MISSION_CANCEL_START){//如果任务状态为,撤消任务 + logger.warn("The task is in the revocation, and the ID is not processed:" + taskId); + return; + } + if(Common.getTaskFuture(taskId)!=null){//当前任务已存在执行,则不执行该当前任务 + logger.warn("The task already exists to execute the ID:" + taskId); + return; + } + // 设置任务结束时间,且当前时间已超过任务结束时间 + if (endTime != null && endTime.longValue() > 0 + && endTime.longValue() <= System.currentTimeMillis()) { + logger.warn("The task has expired ID:" + taskId); + return; + } + long delay = 0; + if (startTime != null) { + delay = startTime - System.currentTimeMillis(); + } + ScheduledFuture<?> taskFuture = null; + LoopTaskThread loopTaskThread = null; + if (isLoop == 0) {// 非周期任务 + taskFuture = Common.scheduled.schedule(new Runnable() { + public void run() { + Thread.currentThread().setName(threadName); + new AgentCommand(command).exec(); + } + }, delay, TimeUnit.MILLISECONDS); + } else { + Future<?> singleFuture = null; + if(delay <= 0){//开始时间之后接到任务,先执行一次,第二次按周期点执行 + long now = System.currentTimeMillis(); + long cnt = (now - startTime)/(loopDelay * 60 * 1000); + if((now - startTime)%(loopDelay * 60 * 1000)!=0){ + delay = startTime + loopDelay *60 *1000 * (cnt + 1) - System.currentTimeMillis(); + ///仅执行一次的,并在周期执行代码中第一次执行判断单次执行完成与否,未完成结束掉 + singleFuture = Common.scheduled.schedule(new Runnable() { + public void run() { + singleThread = Thread.currentThread(); +// Thread.currentThread().setName(threadName + " 周期单次"); + Thread.currentThread().setName(threadName + " Periodic Single Time"); + new AgentCommand(command).exec(); + } + }, 0, TimeUnit.MILLISECONDS); + } + } + loopTaskThread = new LoopTaskThread(threadName, command, loopDelay, singleFuture, singleThread); + taskFuture = Common.scheduled.scheduleAtFixedRate(loopTaskThread, delay, loopDelay * 60 * 1000, TimeUnit.MILLISECONDS); + // 周期任务,若设置结束时间,则添加取消线程 + if (endTime != null && endTime.longValue() > 0) { + long endDelay = endTime.longValue() - System.currentTimeMillis(); + if (endDelay > 0) { + Common.cancleTaskFuture(taskId, endDelay); + } + }// 取消线程结束 + + } + // 将正在执行的任务添加到全局变量,目的是避免重复执行任务 + Common.putTaskFuture(taskId, taskFuture, loopTaskThread); + } + + public static String getUpgradeTaskPushPath(long taskId){ + return Contants.localUploadsPath + File.separator + taskId; + } +} +
\ No newline at end of file diff --git a/src/com/nis/nmsclient/thread/task/TaskResultOper.java b/src/com/nis/nmsclient/thread/task/TaskResultOper.java new file mode 100644 index 0000000..ee4130f --- /dev/null +++ b/src/com/nis/nmsclient/thread/task/TaskResultOper.java @@ -0,0 +1,327 @@ +package com.nis.nmsclient.thread.task; + +import java.io.File; +import java.util.Date; +import java.util.concurrent.Future; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.common.VersionCfg; +import com.nis.nmsclient.config.DetecConfOper; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.thread.socket.SSLClient; +import com.nis.nmsclient.thread.socket.ServerCollectData; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.FileWrUtil; +import com.nis.nmsclient.util.Utils; +import com.nis.nmsclient.util.ZipUtil; + +public class TaskResultOper { + static Logger logger = Logger.getLogger(DetecConfOper.class); + + /** + * Agent在启动时,发送所有之前发送失败的任务结果 + */ + public static void initSendAllTaskResult(){ + try { + //针对结果文件过多时打包上传未完成的文件继续上传 + File taskDir = new File(Contants.localTaskPath); + if (!taskDir.exists()) { + return; + } + File[] zipArr = FileUtil.getFilesEndWith(taskDir, ".zip"); + if (zipArr != null && zipArr.length > 0) { + for (File file : zipArr) { + if (!file.getName().startsWith(CommonSocket.BP_TYPE_TASK_RESULT)) { + continue; + } + Future<?> future = Common.service.submit(new SSLClient(Thread + .currentThread().getName(), + CommonSocket.REQ_BP_UPLOAD_FIFE, new String[] { + CommonSocket.BP_TYPE_TASK_RESULT, file.getAbsolutePath() })); + future.get(); + } + } + //------------------------------------- + + File resultDir = new File(getTaskResultPath()); + if(!resultDir.exists()){ + return; + } + File[] fileArr = FileUtil.getFilesEndWith(resultDir, Contants.TASK_RESULT_FILE_SUFFIX); + if(fileArr == null || fileArr.length == 0){ + /* + * 当任务正常执行完成或者取消后则从全局变量移除 + */ + Common.removeCancelAndDoneTaskFuture(); + return; + } + //--- 将所有任务结果文件一起打包,发送 + if(fileArr.length > Contants.COMMON_ZIP_MIN_SIZE){ + //与Server通信 + Future<?> serFuture = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), + CommonSocket.REQ_HAND_SHAKE, null)); + if (!Contants.isSucessByResult((String) serFuture.get())) { + return; + } + + int zipCnt = fileArr.length/Contants.COMMON_ZIP_MAX_SIZE; + if(zipCnt>0){//2013-5-6 未上传的结果文件太多时,将结果文件压缩为多个文件 + for(int i=0; i<fileArr.length/Contants.COMMON_ZIP_MAX_SIZE; i++){ + // 组织每次压缩的文件数组 + File[] resultFiles = new File[Contants.COMMON_ZIP_MAX_SIZE]; + int start = i * Contants.COMMON_ZIP_MAX_SIZE; + int end = (i + 1) * Contants.COMMON_ZIP_MAX_SIZE; + for(int j=start,k=0; j<end; j++,k++){ + resultFiles[k] = fileArr[j]; + } + // 压缩并发送任务结果 + String compressFileStr = Contants.localTaskPath + + File.separator + + CommonSocket.addTimeTagForFileName(CommonSocket.BP_TYPE_TASK_RESULT, null, true) + + ".zip"; + // 2013-03-22 由于DC再次获取未保存任务结果这个功能的实现,现修改将任务结果和回传文件压缩时不删除文件,而是将其移动到相应的日期目录 + ZipUtil.zipWithMoveFile(resultDir.listFiles(), compressFileStr, true); + //发送 + Future<?> future = Common.service.submit(new SSLClient(Thread.currentThread() + .getName(), CommonSocket.REQ_BP_UPLOAD_FIFE, + new String[] { CommonSocket.BP_TYPE_TASK_RESULT, compressFileStr })); + future.get(); + } + }else{ + // 压缩并发送任务结果 + String compressFileStr = Contants.localTaskPath + + File.separator + + CommonSocket.addTimeTagForFileName(CommonSocket.BP_TYPE_TASK_RESULT, null, true) + + ".zip"; + // 2013-03-22 由于DC再次获取未保存任务结果这个功能的实现,现修改将任务结果和回传文件压缩时不删除文件,而是将其移动到相应的日期目录 + ZipUtil.zipWithMoveFile(resultDir.listFiles(), compressFileStr, true); + //发送 + Future<?> future = Common.service.submit(new SSLClient(Thread.currentThread() + .getName(), CommonSocket.REQ_BP_UPLOAD_FIFE, + new String[] { CommonSocket.BP_TYPE_TASK_RESULT, compressFileStr })); + future.get(); + } + }else{//-- 按正常的一个结果一个结果的发送 + fileArr = FileUtil.sortASCByFileName(fileArr); //按文件名升序排列,任务结果文件名都有时间后缀(ms) + StringBuffer sb = new StringBuffer(); + for(File file : fileArr){ + sb.delete(0, sb.length()); + if(!file.exists() || !file.isFile()){ + continue; + } + String[] resultArr = FileWrUtil.cfgFileReader(file); + if(resultArr!=null && resultArr.length>0){ + for(String res : resultArr){ + sb.append(res + ";"); + } + sb.deleteCharAt(sb.length()-1); + Future<?> future = Common.service.submit(new SSLClient( +// "上传任务结果", + "Upload Task Results", + CommonSocket.REQ_TASK_RESULT, sb.toString())); + String msg = (String) future.get(); + if (Contants.isSucessByResult(msg)) { + // 移动上传成功的任务结果到指定日期目录 + ServerCollectData.moveTaskResultToDateDir(file); + } + }else{ + // 移动上传成功的任务结果到指定日期目录 + ServerCollectData.moveTaskResultToDateDir(file); + } + } + } + } catch (Exception e) { + logger.error("Upload task result exception:" + Utils.printExceptionStack(e)); + } + } + + /** + * 处理Agent自动升级的最终结果文件,即升级后是否启动成功 + * Agent升级的临时结果文件,初始写入状态为升级失败: + * 1、当启动失败后将其临时文件后缀改为任务结果文件的后缀; + * 2、当启动成功后先修改文件第一行的后两项内容为执行状态与描述为成功,再改其后缀。 + * + * @param isSuccess + */ + public static void handerAgentUpgradeResult(boolean isSuccess){ + try { + File dir = new File(getTaskResultPath()); + if(!dir.exists()){ + return; + } + File[] fileArr = FileUtil.getFilesEndWith(dir, Contants.TASK_RESULT_AGENTTMPFILE_SUFFIX); + fileArr = FileUtil.sortASCByFileName(fileArr); //按文件名升序排列,任务结果文件名都有时间后缀(ms) + if (fileArr != null && fileArr.length > 0) { + for(int i=0; i<fileArr.length; i++){ + if (isSuccess && i == fileArr.length-1) {// 如果启动成功处理其结果内容 + try {// 本层try是为了防止其中一个结果文件不正常,影响其他结果文件不能正常修改 + String[] msgs = FileWrUtil.cfgFileReader(fileArr[i]); + if (msgs != null && msgs.length > 0) { + int descIndex = msgs[0] + .lastIndexOf(Contants.COMMON_MSG_SEPRATOR); + int stateIndex = msgs[0].substring(0, descIndex) + .lastIndexOf(Contants.COMMON_MSG_SEPRATOR); + msgs[0] = msgs[0].substring(0, stateIndex) + + Contants.COMMON_MSG_SEPRATOR + AgentCommand.RESULT_OK +// + Contants.COMMON_MSG_SEPRATOR + "重启成功"; + + Contants.COMMON_MSG_SEPRATOR + "i18n_client.TaskResultOper.restart_n81i"; + + FileWrUtil.cfgFilePrinter(fileArr[i], Contants.charset, msgs); + + int taskIdIndex = msgs[0].indexOf(Contants.COMMON_MSG_SEPRATOR); + //处理写入当前更新的版本信息 + String taskId = msgs[0].substring(0, taskIdIndex); + Long curVer = Long.parseLong(VersionCfg + .getValue(VersionCfg.NAGENT_VERSION)); + if (curVer < Long.parseLong(taskId.trim())) { + VersionCfg.setValue(VersionCfg.NAGENT_VERSION, taskId); + logger.info("NC更新为版本" + taskId); + } + } + } catch (Exception e) { + logger.error("Handling the exception of the NC upgrade result file:" + Utils.printExceptionStack(e)); + } + } + String fileStr = fileArr[i].getAbsolutePath(); + int index = fileStr.lastIndexOf(Contants.TASK_RESULT_AGENTTMPFILE_SUFFIX); + fileStr = fileStr.substring(0, index); + fileArr[i].renameTo(new File(fileStr + Contants.TASK_RESULT_FILE_SUFFIX)); + } + } + } catch (Exception e) { + logger.error("Handling the exception of the NC upgrade result file:" + Utils.printExceptionStack(e)); + } + } + + /** + * 发送任务执行结果:若发送失败写入文件 + */ + /*private static void sendTaskResult(long taskId, long taskType, String msg) { + try{ + Future<?> future = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), + CommonSocket.REQ_TASK_RESULT, msg)); + + String result = (String) future.get(); + + if (!Contants.isSucessByResult(result)) {//失败 + File file = new File(getTaskResultFile(taskType, taskId)); + if(!file.getParentFile().exists()){ + file.getParentFile().mkdirs(); + } + FileWrUtil.cfgFilePrinter(file, Contants.charset, new String[]{msg}); + } + }catch (Exception e) { + logger.error("发送任务结果异常:" + Utils.printExceptionStack(e)); + } + }*/ + + /** + * 发送任务执行结果:判断是否是Server升级,若是直接写入文件,若不是则发送结果 + * @param taskId 任务ID + * @param taskType 任务类型 + * @param resultState 执行结果状态 + * @param resultDesc 执行结果描述 + * @param resultConfig + * @param startTime 开始执行时间 + * @param endTime 执行结束时间 + * @param isServer 是否是Server升级 + * @param isLoop 是否是循环任务 + */ + /*public static void sendTaskResult(long taskId, long taskType, + long resultState, String resultDesc, String resultConfig, + Date startTime, Date endTime, boolean isServer, long isLoop) { + try { + String msg = getTaskResultMsg(taskId, taskType, resultState, + resultDesc, resultConfig, startTime, endTime, isLoop); + if(isServer){//如果是Server升级,直接写入文件 + File file = new File(getTaskResultFile(taskType, taskId)); + if(!file.getParentFile().exists()){ + file.getParentFile().mkdirs(); + } + FileWrUtil.cfgFilePrinter(file, Contants.charset, new String[]{msg}); + }else{//反之,发送任务结果 + sendTaskResult(taskId, taskType, msg); + } + } catch (Exception e) { + logger.error("发送任务结果异常:" + Utils.printExceptionStack(e)); + } + }*/ + + /** + * 发送任务结果: 将结果保存到文件,等待DC主动来收集 + * @date Jan 15, 2013 + * @author zhenzhen + * @version + */ + public static void sendTaskResult(long taskId, long taskType, + long resultState, String resultDesc, String resultConfig, + Date startTime, Date endTime, boolean isServer, long isLoop) { + try { + // 2013-4-9 为了防止多步操作时结果文件名重复,所以暂停50ms为了使时间后缀不一样 + if (resultState > AgentCommand.RESULT_SEND_OK) { + try {Thread.sleep(50);} catch (Exception ignored) { } + } + + String msg = getTaskResultMsg(taskId, taskType, resultState, + resultDesc, resultConfig, startTime, endTime, isLoop); + File file = new File(getTaskResultFile(taskType, taskId)); + if(!file.getParentFile().exists()){ + file.getParentFile().mkdirs(); + } + FileWrUtil.cfgFilePrinter(file, Contants.charset, new String[]{msg}); + } catch (Exception e) { + logger.error("Send task result exception:" + Utils.printExceptionStack(e)); + } + } + + /** + * 按指定的分隔符和顺序拼写任务执行结果信息 + */ + public static String getTaskResultMsg(long taskId, long taskType, + Long resultState, String resultDesc, String resultConfig, + Date startTime, Date endTime, long isLoop) { + StringBuffer sb = new StringBuffer(); + sb.append(taskId); + sb.append(Contants.COMMON_MSG_SEPRATOR); + sb.append(taskType); + sb.append(Contants.COMMON_MSG_SEPRATOR); + sb.append(Contants.AGENT_HOST_UUID); + sb.append(Contants.COMMON_MSG_SEPRATOR); + sb.append(isLoop); + sb.append(Contants.COMMON_MSG_SEPRATOR); + sb.append(startTime.getTime()); + sb.append(Contants.COMMON_MSG_SEPRATOR); + sb.append(endTime.getTime()); + sb.append(Contants.COMMON_MSG_SEPRATOR); + sb.append(resultConfig); + sb.append(Contants.COMMON_MSG_SEPRATOR); + sb.append(resultState); + sb.append(Contants.COMMON_MSG_SEPRATOR); + sb.append(resultDesc); + + return sb.toString(); + } + + public static String getTaskResultFile(long taskType, long taskId){ + return getTaskResultFileNoSuffix(taskType, taskId) + "_" + System.currentTimeMillis() + + Contants.TASK_RESULT_FILE_SUFFIX; + } + + public static String getAgentUpgradeResultTempFile(long taskType, long taskId){ + return getTaskResultFileNoSuffix(taskType, taskId) + + Contants.TASK_RESULT_AGENTTMPFILE_SUFFIX; + } + + private static String getTaskResultFileNoSuffix(long taskType, long taskId){ + return getTaskResultPath() + File.separator + "tasktype" + taskType + "_" + taskId; + } + + public static String getTaskResultPath(){ + return Contants.localTaskResultPath; + } +} diff --git a/src/com/nis/nmsclient/thread/task/TaskReturnHandle.java b/src/com/nis/nmsclient/thread/task/TaskReturnHandle.java new file mode 100644 index 0000000..495df18 --- /dev/null +++ b/src/com/nis/nmsclient/thread/task/TaskReturnHandle.java @@ -0,0 +1,351 @@ +package com.nis.nmsclient.thread.task; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import net.sf.json.JSONObject; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.model.ReturnFilePO; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.util.CompressFileMgr; +import com.nis.nmsclient.util.FileWrUtil; +import com.nis.nmsclient.util.Utils; + +public class TaskReturnHandle { + Logger logger = Logger.getLogger(TaskReturnHandle.class); + + /*public void sendAllTaskReturnFile(){ + try { + //针对回传文件过多时打包上传未完成的文件继续上传 + File taskDir = new File(Contants.localTaskPath); + if (!taskDir.exists()) { + return; + } + File[] zipArr = FileUtil.getFilesEndWith(taskDir, ".zip"); + if (zipArr != null && zipArr.length > 0) { + for (File file : zipArr) { + if (!file.getName().startsWith(CommonSocket.BP_TYPE_TASK_RETURN)) { + continue; + } + Future<?> future = Common.service.submit(new SSLClient(Thread.currentThread() + .getName(), CommonSocket.REQ_BP_UPLOAD_FIFE, + new String[] { CommonSocket.BP_TYPE_TASK_RETURN, + file.getAbsolutePath() })); + future.get(); + } + } + //---------------------------------- + + File returnDir = new File(Contants.localTaskReturnPath); + if(!returnDir.exists()){ + return; + } + File[] fileArr = FileUtil.getFilesEndWith(returnDir, Contants.TASK_RETURN_FILE_SUFFIX); + if(fileArr == null || fileArr.length == 0){ + return; + } + //--- 将所有任务的回传文件及回传信息保存文件一起打包,发送 + if(fileArr.length > Contants.COMMON_MAX_RETURN_CNT){ + //与Server通信 + Future<?> serFuture = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), + CommonSocket.REQ_HAND_SHAKE, null)); + if (!Contants.isSucessByResult((String) serFuture.get())) { + return; + } + //压缩并删除原文件 + String compressFileStr = Contants.localTaskPath + + File.separator + + CommonSocket.addTimeTagForFileName(CommonSocket.BP_TYPE_TASK_RETURN, + null) + + ".zip"; + ZipUtil.zipWithDelFile(returnDir.listFiles(), compressFileStr, false); + //发送 + Future<?> future = Common.service.submit(new SSLClient(Thread.currentThread() + .getName(), CommonSocket.REQ_BP_UPLOAD_FIFE, + new String[] { CommonSocket.BP_TYPE_TASK_RETURN, + compressFileStr })); + future.get(); + }else{//-- 按正常的一个任务一个任务的回传 + fileArr = FileUtil.sortASCByModify(fileArr); //修改日期升序排序 + for(File file : fileArr){ + if(!file.exists() || !file.isFile()){ + continue; + } + String[] resultArr = FileWrUtil.cfgFileReader(file); + if (resultArr != null && resultArr.length > 0) { + JSONObject jsonObject = JSONObject.fromObject(resultArr[0]); + ReturnFilePO rfPo = (ReturnFilePO) JSONObject.toBean(jsonObject, ReturnFilePO.class); + sendTaskReturnFile(rfPo); + }else{ + //file.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(file); + logger.debug("TaskReturnHadle.sendAllTaskReturnFile()()任务回传临时文件(记录任务结果信息)删除:"+file.getAbsolutePath()); + + } + } + } + } catch (Exception e) { + logger.error(Utils.printExceptionStack(e)); + } + }*/ + + public static void startTaskReturnFileThread(final ReturnFilePO rfPo, final List<String> filePaths) { + Common.service.execute(new Runnable() { + @Override + public void run() { + Thread.currentThread().setName("Backpass File Processing ID:" + rfPo.getTaskId()); + TaskReturnHandle tReturnHandle = new TaskReturnHandle(); + ReturnFilePO rfPo2 = tReturnHandle.taskReturnFileHandle(rfPo, filePaths); + //tReturnHandle.sendTaskReturnFile(rfPo2); + } + }); + } + + /** + * 回传文件的统一处理:将回传文件移动到统一回传位置,处理后一个任务只有一个回传文件,修改回传文件名,将任务回传信息写入文件 + */ + public ReturnFilePO taskReturnFileHandle(ReturnFilePO rfPo, List<String> filePaths){ + if(rfPo==null || filePaths==null || filePaths.size()<=0){ + logger.warn("No return file, no return"); + return null; + } + File tempDir = null; + try { + File file = new File(getTaskReturnFile(rfPo.getTaskType(), + rfPo.getTaskId(), rfPo.getIsLoop())); + if (file.exists() && file.length()>0) {// 如果存在,说明之前已经整理过回传文件了,本次不做操作 + return null; + }else if(!file.getParentFile().exists()){// 创建回传文件目录 + file.getParentFile().mkdirs(); + } + + StringBuffer sb = new StringBuffer(); + tempDir = new File(Contants.localTempPath + File.separator + + "return_" + rfPo.getTaskId()); + if(!tempDir.exists()){ + tempDir.mkdirs(); + } + /** + * 处理回传文件:1、过滤不存在或文件路径为空的文件 2、对文件重命名移动到临时目录 + */ + for(String returnPath: filePaths){ + if (StringUtils.isEmpty(returnPath)) { +// sb.append("回传“" + returnPath + "”失败,回传文件路径值为空;"); +// sb.append("Backpass“" + returnPath + "” failed, the return file path value is empty;"); + sb.append("i18n_client.TaskReturnHandle.backpass_n81i“" + returnPath + "” i18n_client.TaskReturnHandle.backFail1_n81i;"); + continue; + } + File returnFile = new File(returnPath); + if (!returnFile.exists()) { +// sb.append("Backpass“" + returnPath + "” failed, return file does not exist;"); + sb.append("i18n_client.TaskReturnHandle.backpass_n81i“" + returnPath + "” i18n_client.TaskReturnHandle.backFail2_n81i;"); + continue; + } + //回传文件取别名:原文件名_T任务ID_时间戳 + String aliasName = CommonSocket.addTimeTagForFileName( + returnFile.getName(), "T" + rfPo.getTaskId(), returnFile.isFile()); + //---- 移动回传文件到临时目录,并重命名为:原文件名_T任务ID_时间戳 + File returnTmpFile = new File(tempDir.getCanonicalPath() + + File.separator + + aliasName); + if (returnFile.isDirectory()) { + FileUtils.copyDirectory(returnFile, returnTmpFile); + } else { + FileUtils.copyFile(returnFile, returnTmpFile); + } + } + + /** + * 将回传的所有文件压缩放到统一回传位置 + */ + String returnFileName = null; + //---- 若回传文件的个数等于1,则把临时目录下的一个文件:按文件夹的话压缩到统一回传位置,文件的话直接移动到统一回传位置 + File[] files = tempDir.listFiles(); + if(files.length==1){ + returnFileName = files[0].getName(); + File destFile = new File(Contants.localTaskReturnPath + File.separator + files[0].getName()); + if (files[0].isDirectory()) { + String compressFileStr = destFile.getAbsolutePath() + CompressFileMgr.getCompressSuffixByOs(false); + returnFileName = new File(compressFileStr).getName(); + new CompressFileMgr().compressFile(files[0] + .getAbsolutePath(), compressFileStr, null, false); + } else { + FileUtils.copyFile(files[0], destFile, false);// 复制并修改文件日期 + } + }else if(files.length > 1){//---- 若回传文件的个数大于1,则把临时目录整个压缩到统一回传位置 + String compressFileStr = Contants.localTaskReturnPath + File.separator + tempDir.getName() + CompressFileMgr.getCompressSuffixByOs(false); + returnFileName = new File(compressFileStr).getName(); + new CompressFileMgr().compressFile(tempDir + .getAbsolutePath(), compressFileStr, null, false); + } + + rfPo.setReturnFileName(returnFileName); + rfPo.setResDesc(sb.toString()); + + /** + * 将信息写入文件 + */ + if (!file.exists()) { + String[] values = new String[] { JSONObject.fromObject( + rfPo).toString() }; + FileWrUtil.cfgFilePrinter(file, Contants.charset, + values); + } + + return rfPo; + } catch (Exception e) { + logger.error("Handling backpass file exceptions:" + Utils.printExceptionStack(e)); + return null; + } finally { + if(tempDir!=null && tempDir.exists()){ + try { + logger.debug("删除临时目录--" + tempDir.getAbsolutePath()); + FileUtils.deleteDirectory(tempDir); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + } + + /** + * 回传文件:先将信息写入临时文件,再判断与Server端通信是否成功 + * 1、通信成功:回传文件,发送最终结果;删除临时文件 + * 2、通信失败:保留临时文件,直接返回 + * @param rfPo 回传文件实体类 + */ + /*public void sendTaskReturnFile(ReturnFilePO rfPo) { + if(rfPo==null){ + logger.debug("回传文件实体对象为空, 不用回传"); + return; + } + try { + File file = new File(getTaskReturnFile(rfPo.getTaskType(), + rfPo.getTaskId())); + + //--回传文件名和回传描述信息均为空时,则无回传文件 + if(StringUtil.isEmpty(rfPo.getReturnFileName()) && StringUtil.isEmpty(rfPo.getResDesc())){ + logger.warn("无回传文件, 不用回传"); + if(file.exists()){ + //file.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(file); + logger.debug("TaskReturnHandle.sendTaskReturnFile()成功发送任务回传文件后删除:"+file.getAbsolutePath()); + } + return; + } + //--回传文件名为空,但回传描述信息不为空,则进行步骤4发送任务结果、删除文件 + + *//** + * 步骤1、将信息写入文件 + *//* + if (!file.exists()) { + String[] values = new String[] { JSONObject.fromObject( + rfPo).toString() }; + FileWrUtil.cfgFilePrinter(file, Contants.charset, + values); + } + *//** + * 步骤2、与Server通信 + *//* + Future<?> serFuture = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), + CommonSocket.REQ_HAND_SHAKE, null)); + if (!Contants.isSucessByResult((String) serFuture.get())) { + return; + } + *//** + * 步骤3、回传文件 + *//* + StringBuffer sb = new StringBuffer(); + if(rfPo.getResDesc()!=null){//取已有的结果描述信息 + sb.append(rfPo.getResDesc()); + } + //准备回传文件,回传文件名不为空即有回传的文件时,再回传 + boolean success = false; + if(rfPo.getReturnFileName()!=null && rfPo.getReturnFileName().trim().length()>0){ + for(int i=0; i<Contants.max_times; i++){//回传失败,尝试几次 + Future<?> future = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), + CommonSocket.REQ_TASK_RETURNFILE, rfPo)); + String msg = (String) future.get(); + success = Contants.isSucessByResult(msg); + if(success){ + sb.append("回传成功;"); + break; + } + + try {// 如果更新失败,让当前线程暂停几秒,再重试 + Thread.sleep(1000 * Contants.max_delay_seconds); + } catch (InterruptedException e) { + logger.error(Utils.printExceptionStack(e)); + continue; + } + } + }else{ + success = true; + } + + *//** + * 步骤4、判断文件是否回传完成 + *//* + if(success){ + *//** + * 步骤4-1、发送任务结果 + *//* + TaskResultOper.sendTaskResult(rfPo.getTaskId(), rfPo.getTaskType(), + rfPo.getState(), sb.toString(), "", rfPo.getStartTime(), + rfPo.getEndTime(), false, rfPo.getIsLoop()); + *//** + * 步骤4-2、删除保存回传文件信息的文件 + *//* + if(file.exists()){ + //file.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(file); + logger.debug("TaskReturnHandle.sendTaskReturnFile()删除保存回传文件信息的文件:"+file.getAbsolutePath()); + } + *//** + * 步骤4-3、正常回传完成,删除文件 + *//* + File curReturnFile = new File(Contants.localTaskReturnPath + File.separator + rfPo.getReturnFileName()); + if(curReturnFile.exists()){ + //curReturnFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(curReturnFile); + logger.debug("TaskReturnHandle.sendTaskReturnFile()正常回传完成,删除文件:"+curReturnFile.getAbsolutePath()); + } + } + } catch (Exception e) { + logger.error(Utils.printExceptionStack(e)); + } + }*/ + + /** + * 取任务回传临时记录任务信息文件的文件名: 若是周期任务,加时间后缀taskreturn_taskId_taskType_time.return;若未周期任务, taskreturn_taskId_taskType.return + */ + public static String getTaskReturnFile(long taskType, long taskId, long isLoop) { + //isLoop 是否周期任务: 0 非周期, 1 周期 + if(isLoop==0){ + return Contants.localTaskReturnPath + File.separator + "tasktype" + + taskType + "_" + taskId + + Contants.TASK_RETURN_FILE_SUFFIX; + }else{ + return Contants.localTaskReturnPath + File.separator + "tasktype" + + taskType + "_" + taskId + "_" + + System.currentTimeMillis() + + Contants.TASK_RETURN_FILE_SUFFIX; + } + + } +} diff --git a/src/com/nis/nmsclient/thread/timer/DelLocalFileThread.java b/src/com/nis/nmsclient/thread/timer/DelLocalFileThread.java new file mode 100644 index 0000000..dd68c3e --- /dev/null +++ b/src/com/nis/nmsclient/thread/timer/DelLocalFileThread.java @@ -0,0 +1,197 @@ +package com.nis.nmsclient.thread.timer; + +import java.io.File; +import java.io.IOException; +import java.util.Date; + +import org.apache.commons.io.FileUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.Utils; +import com.sun.org.apache.bcel.internal.generic.NEW; + +public class DelLocalFileThread implements Runnable { + Logger logger = Logger.getLogger(DelLocalFileThread.class); + private String name; + + public DelLocalFileThread(String name){ + this.name = name; + } + + @Override + public void run() { + Thread.currentThread().setName(name); + delLogFile(); + delDataFile(); + delTempFile(); + delUpgradeFile(); + + } + + /** + * 删除日志文件 + */ + public void delLogFile() { + long curDate = System.currentTimeMillis(); + // 删除指定天数之前的日志文件 + File logs = new File(Contants.localLogsPath); + if (!logs.exists() || !logs.isDirectory()) { + return; + } + for (File f : logs.listFiles()) { + long diff = DateUtil.getDaysFromBeginToEnd(f.lastModified(), + curDate); + + if (f.isFile() && diff > Contants.COMMON_DEL_LOG_DAYS) { + //f.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(f); + logger.info("删除日志文件" + f.getAbsolutePath()); + //FileUtil.checkParentDirExist(f); + } + } + + } + + /** + * 清理数据文件(包括监测数据和任务文件) + */ + public void delDataFile(){ + long curDateMillis = System.currentTimeMillis(); + // == 1、删除指定分钟之前的所有监测文件 + File doneFile = new File(Contants.localDataDonePath); + if (doneFile.exists()) { + //---删除打包上传的数据 + long timeMillis = curDateMillis - Contants.COMMON_DEL_DATA_HOURS + * 60 * 60 * 1000; + File[] files = FileUtil.getFilesEndWithBeforeMillis(doneFile, ".zip", + timeMillis); + if (files != null && files.length > 0) { + for (File f : files) { + FileUtil.delDir(f); + logger.debug("delDataFile 删除打包文件--" + f.getAbsolutePath()); + } + } + //---删除正常上传的数据文件 + File[] doneDirs = FileUtil.getDirectoryArray(doneFile); + delDataFileCallBack(curDateMillis, doneDirs, Contants.COMMON_DEL_DATA_HOURS); + } + File errorFile = new File(Contants.localDataErrorPath); + if (errorFile.exists()) { + File[] errorDirs = FileUtil.getDirectoryArray(errorFile); + delDataFileCallBack(curDateMillis, errorDirs, Contants.COMMON_DEL_DATA_HOURS); + } + + // == 2、删除指定分钟之前的所有任务相关的文件 + doneFile = new File(Contants.localTaskDonePath); + if (doneFile.exists()) { + //---删除打包上传的任务结果和回传文件 + long timeMillis = curDateMillis - Contants.COMMON_DEL_TASK_HOURS + * 60 * 60 * 1000; + File[] files = FileUtil.getFilesEndWithBeforeMillis(doneFile, ".zip", + timeMillis); + if (files != null && files.length > 0) { + for (File f : files) { + FileUtil.delDir(f); + logger.debug("delDataFile 删除打包文件2--" + f.getAbsolutePath()); + } + } + //---删除正常上传的任务结果和回传文件 + File[] doneDirs = FileUtil.getDirectoryArray(doneFile); + delDataFileCallBack(curDateMillis, doneDirs, Contants.COMMON_DEL_TASK_HOURS); + } + errorFile = new File(Contants.localTaskErrorPath); + if (errorFile.exists()) { + File[] errorDirs = FileUtil.getDirectoryArray(errorFile); + delDataFileCallBack(curDateMillis, errorDirs, Contants.COMMON_DEL_TASK_HOURS); + } + } + + /** + * 清理数据文件的递归回调函数 + */ + public void delDataFileCallBack(long curDateMillis, File[] dirs, int delHours) { + if (dirs == null || dirs.length == 0) { + return; + } + for (File dir : dirs) { + long timeMillis = curDateMillis - delHours + * 60 * 60 * 1000; + File[] sonDirs = FileUtil.getDirsBeforeDateName(dir, DateUtil + .getStingDate(DateUtil.YYYYMMDD, new Date(timeMillis))); + delDataFileCallBack(curDateMillis, sonDirs, delHours); + + File[] files = FileUtil.getFilesBeforeMillis(dir,timeMillis); + if (files != null && files.length > 0) { + for (File f : files) { + FileUtil.delDir(f); + logger.debug("删除文件--" + f.getAbsolutePath()); + } + } + + if (files == null && files.length > 0) { + logger.info("删除文件夹" + dir.getAbsolutePath() + "下的文件:文件" + + files.length + "个"); + } + + if (dir.exists() && dir.listFiles().length <= 0) { + FileUtil.delDir(dir); + logger.info("删除文件夹" + dir.getAbsolutePath()); + } + } + } + + /** + * 清理临时目录的文件 + */ + public void delTempFile() { + try { + long curDate = System.currentTimeMillis(); + // 删除指定日期之前的临时文件 + File temp = new File(Contants.localTempPath); + if (!temp.exists() || !temp.isDirectory()) { + return; + } + for (File f : temp.listFiles()) { + long diff = DateUtil.getDaysFromBeginToEnd(f.lastModified(), + curDate); + if (f.exists() && diff > Contants.COMMON_DEL_TEMP_DAYS) { + //使用删除文件公共方法 + FileUtil.delDir(f); + logger.info("删除临时文件或文件夹" + f.getAbsolutePath()); + } + } + } catch (Exception e) { + logger.error(Utils.printExceptionStack(e)); + } + } + + /** + * 清理UPLOAD目录下的文件 + */ + public void delUpgradeFile() { + try { + long curDate = System.currentTimeMillis(); + // 删除指定日期之前的升级文件 + File uploads = new File(Contants.localUploadsPath); + if (!uploads.exists() || !uploads.isDirectory()) { + return; + } + for (File f : uploads.listFiles()) { + long diff = DateUtil.getDaysFromBeginToEnd(f.lastModified(), + curDate); + if (f.exists() && diff > Contants.COMMON_DEL_UPGRADEFILE_DAYS) { + //使用删除文件公共方法 + FileUtil.delDir(f); + logger.info("删除升级文件或文件夹" + f.getAbsolutePath()); + } + } + } catch (Exception e) { + logger.error(Utils.printExceptionStack(e)); + } + + } +} diff --git a/src/com/nis/nmsclient/thread/upload/BusinessType.java b/src/com/nis/nmsclient/thread/upload/BusinessType.java new file mode 100644 index 0000000..35cd052 --- /dev/null +++ b/src/com/nis/nmsclient/thread/upload/BusinessType.java @@ -0,0 +1,41 @@ +package com.nis.nmsclient.thread.upload; + +/** + * 消息类型 + * @author nanfang + * + */ +public enum BusinessType { + + HeartBeat("HeartBeat",0),//心跳 + DetectZip("DetectZip",1), // 监测数据zip + DetectData("DetectData",2),// 监测数据 + ObjTaskResult("ObjTaskResult",3),//任务结果 + FileTaskReturn("FileTaskReturn",4);//回传文件 + + + private final String name; + private final int type; + + private BusinessType(String name ,int type) { + this.type = type; + this.name = name; + } + + public int getType() { + return this.type; + } + + public String getName(){ + return this.name; + } + + public static BusinessType getType(int type) { + for (BusinessType t : BusinessType.values()) { + if (t.getType() == type) { + return t; + } + } + return null; + } +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/thread/upload/DataSendThread.java b/src/com/nis/nmsclient/thread/upload/DataSendThread.java new file mode 100644 index 0000000..bb51d43 --- /dev/null +++ b/src/com/nis/nmsclient/thread/upload/DataSendThread.java @@ -0,0 +1,589 @@ +package com.nis.nmsclient.thread.upload; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.common.StopWatch; +import com.nis.nmsclient.model.ReturnFilePO; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.thread.socket.SSLCertOper; +import com.nis.nmsclient.thread.task.TaskResultOper; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.FileWrUtil; +import com.nis.nmsclient.util.StringUtil; +import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream; + +import net.sf.json.JSONObject; + +/** + * 数据发送线程 + * 1、暂时只发送监测数据,csv或zip + * 2、间隔 10 秒启动一次,同时具备心跳的功能 + * 3、实现断线重连 + * @author dell + * + */ +public class DataSendThread implements Runnable{ + public static final Logger logger = Logger.getLogger(DataSendThread.class); + private Socket socket; + private OutputStream os; + private InputStream is; + private String host; + private int port; + + public DataSendThread(String host,int port) { + this.host = host; + this.port = port; + } + + + public void init() throws Exception { + SSLContext ctx = SSLCertOper.getSSLContext(); + SSLSocketFactory ssf = ctx.getSocketFactory(); + socket = (SSLSocket) ssf.createSocket(host,port); + logger.debug("create socket success."); + + //2014-1-23 hyx 如果建立socket成功,但是startHandshake握手失败,且未设置超时时间时,则会一直阻塞 + socket.setSoTimeout(1000 * 60 * Contants.SOCKET_TIMEOUT_MINUTES); + ((SSLSocket) socket).startHandshake(); + logger.debug("handshake success."); + os = socket.getOutputStream(); + is = socket.getInputStream(); + } + + + @Override + public void run() { + Thread.currentThread().setName("DataSendThread"); + logger.debug("开始"); + StopWatch sw = new StopWatch(); + sw.start(); + try { + //重连 + if(socket == null || socket.isClosed()|| !socket.isConnected()|| os == null || is ==null ){ + init(); + } + //发送心跳 + sendHeartBeat(); + //发送监测数据 + sendDetectData(); + //发送任务回传文件 + sendTaskReturnFile(); + //发送任务结果 + sendTaskResult(); + + } catch (SSLException | SocketException e){ + logger.error("SocketException|SSLException",e); + try { + init(); + } catch (Exception e1) { } + } catch (Exception e) { + logger.error("",e); + } + sw.end(); + logger.debug("耗时:"+sw.toString(sw.total())); + logger.debug("结束"); + } + + + + /** + * 发送监测数据 + */ + private void sendDetectData(){ + StopWatch sw = new StopWatch(); + try { + File dataDir = new File(Contants.localDataFilePath); + if (!dataDir.exists()) { + logger.warn("数据目录 : " + dataDir.getAbsolutePath() + " 不存在!!!"); + } else{ + long total = 0; + List<File> allFiles = new ArrayList<File>(); + File[] dataDirs = FileUtil.getDirectoryArray(dataDir); + // ---- 数据处理 + total = handleNullDataFile(allFiles, dataDirs); + logger.info("本次收集监测数据文件总数:" + total + ", 正常数据:" + allFiles.size() + ", 空数据:" + (total - allFiles.size())); + total = allFiles.size();// 正常的要上传的数据个数 + + if(total > 0){ + for (int i = 0; i < total; i++) { + File tem = allFiles.get(i); + this.sendData(tem, BusinessType.DetectData); + String res = this.readLine(); + if(CommonSocket.SUCCESS.equalsIgnoreCase(res)){//发送成功 + this.moveDetecDataToDateDir(tem); + } + } + } + } + } catch (Exception e) { + logger.error("",e); + } + sw.end(); + logger.debug("耗时:"+sw.toString(sw.total())); + logger.debug("结束"); + } + + + /** + * 发送任务结果 + */ + private void sendTaskResult() { + StopWatch sw = new StopWatch(); + try { + logger.debug("传送任务结果开始 ~~~~~~~"); + long startTime = System.currentTimeMillis(); + // == 1、针对结果文件过多时打包上传未完成的文件继续上传 + File taskDir = new File(Contants.localTaskPath); + if (!taskDir.exists()) { + return; + } + + // == 2、检查当前结果文件数量,批量发送文件或打包上传 + File resultDir = new File(TaskResultOper.getTaskResultPath()); + if(!resultDir.exists()){ + return; + } + // == 3 + File[] fileArr = FileUtil.getFilesEndWith(resultDir, Contants.TASK_RESULT_FILE_SUFFIX); + fileArr = FileUtil.sortASCByFileName(fileArr); + List<String> results = new LinkedList<String>(); + StringBuffer sb = new StringBuffer(); + for(File file : fileArr){ + sb.delete(0, sb.length()); + if(!file.exists() || !file.isFile()){ + continue; + } + String[] resultArr = FileWrUtil.cfgFileReader(file); + if(resultArr!=null && resultArr.length>0){ + for(String res : resultArr){ + sb.append(res + ";"); + } + sb.deleteCharAt(sb.length()-1); + results.add(sb.toString()); + } + } + if(results.size() >0 ){ + logger.debug("sendTaskResult-->" + Arrays.toString(results.toArray())); + //发送任务结果请求 + this.sendObject(results, BusinessType.ObjTaskResult); + String res = this.readLine(); + if (CommonSocket.SUCCESS.equalsIgnoreCase(res)) { + // 移动上传成功的任务结果到指定日期目录 + moveTaskResultToDateDir(fileArr); + } + } + sw.end(); + logger.info("本次收集传送任务结果总数:" + fileArr.length + ",用时:" + sw.toString(sw.total())); + } catch (Exception e) { + logger.error("",e); + } + logger.debug("结束"); + } + + + private void sendTaskReturnFile(){ + StopWatch sw = new StopWatch(); + logger.debug("传送回传文件开始 ~~~~~~~"); + try { + // == 1、针对回传文件过多时打包上传未完成的文件继续上传 + File taskDir = new File(Contants.localTaskPath); + if (!taskDir.exists()) { + return; + } + + // == 2、检查当前回传文件数量,单个发送文件或打包上传 + File returnDir = new File(Contants.localTaskReturnPath); + if(!returnDir.exists()){ + return; + } + File[] fileArr = FileUtil.getFilesEndWith(returnDir, Contants.TASK_RETURN_FILE_SUFFIX); + if(fileArr == null || fileArr.length == 0){ + return; + } + + // == 3、发送 + fileArr = FileUtil.sortASCByModify(fileArr); //修改日期升序排序 + for(File file : fileArr){ + if(!file.exists() || !file.isFile()){ + continue; + } + String[] resultArr = FileWrUtil.cfgFileReader(file); + if (resultArr == null || resultArr.length <= 0) { + continue; + } + JSONObject jsonObject = JSONObject.fromObject(resultArr[0]); + ReturnFilePO rfPo = (ReturnFilePO) JSONObject.toBean(jsonObject, ReturnFilePO.class); + + //--回传文件名和回传描述信息均为空时,则无回传文件 + if(StringUtil.isEmpty(rfPo.getReturnFileName()) && StringUtil.isEmpty(rfPo.getResDesc())){ + logger.warn("无回传文件, 不用回传"); + FileUtil.delDir(file); + continue; + } + //--回传文件名为空,但回传描述信息不为空,则进行步骤2发送任务结果、删除文件 + /** + * 步骤1、回传文件 + */ + StringBuffer sb = new StringBuffer(); + if(rfPo.getResDesc()!=null){//取已有的结果描述信息 + sb.append(rfPo.getResDesc()); + } + //准备回传文件,回传文件名不为空即有回传的文件时,再回传 + if(rfPo.getReturnFileName()!=null && rfPo.getReturnFileName().trim().length()>0){ + //发送回传文件请求 + String msg = TaskResultOper.getTaskResultMsg(rfPo + .getTaskId(), rfPo.getTaskType(), null, null, null, rfPo + .getStartTime(), rfPo.getEndTime(), rfPo.getIsLoop()); + File returnFile = new File(Contants.localTaskReturnPath + File.separator + rfPo.getReturnFileName()); + String res = this.sendReturnFile(msg, returnFile, BusinessType.FileTaskReturn); + if(CommonSocket.SUCCESS.equals(res)){ + /** + * 步骤2-1、发送任务结果 + */ + TaskResultOper.sendTaskResult(rfPo.getTaskId(), rfPo.getTaskType(), + rfPo.getState(), sb.toString(), "", rfPo.getStartTime(), + rfPo.getEndTime(), false, rfPo.getIsLoop()); + /** + * 步骤2-2、移动上传成功的 保存回传文件信息的文件 和 回传文件 到指定日期目录 + */ + moveTaskReturnToDateDir(file, rfPo.getReturnFileName()); + } + } + } + sw.end(); + logger.info("本次收集传送任务回传总数:" + fileArr.length + ",用时:" + sw.toString(sw.total())); + } catch (Exception e) { + logger.error("send Task Return File error",e); + } + logger.debug("结束"); + } + + + + /** + * 发送心跳 + * @throws IOException + */ + private void sendHeartBeat() throws IOException{ + byte[] msg = (System.currentTimeMillis()+"").getBytes(); + int len = msg.length; + int t = BusinessType.HeartBeat.getType(); + os.write(Common.intToByteArray(len)); + os.write(0);//消息类型 + os.write(t);//业务类型 + os.write(msg); + os.flush(); + String res = readLine(); + logger.debug("HeartBeat :" + res); + } + + /*** + * 发送任务回传文件 + * @param msg + * @param file + * @param type + * @throws IOException + */ + private String sendReturnFile(String msg,File file,BusinessType type) throws IOException{ + String name = file.getName(); + byte[] nameByte = name.getBytes(); + if(nameByte.length > Byte.MAX_VALUE){ + throw new IllegalArgumentException("file name too long,max length is 127"); + } + byte[] msgBytes = msg.getBytes(); + int msgLen = msgBytes.length; + int totalLen = (int)file.length() + msgBytes.length +4; + int t = type.getType(); + os.write(Common.intToByteArray(totalLen)); + os.write(nameByte.length);//文件名的长度 + os.write(t);//业务类型 + os.write(nameByte);//文件名 + os.write(Common.intToByteArray(msgLen));//消息头长度 + os.write(msgBytes);//消息头 + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + IOUtils.copy(fis, os);//文件内容 + os.flush(); + } finally { + if(fis != null){ + fis.close(); + } + } + String res = readLine(); + logger.debug("sendReturnFile :" + res); + return res; + } + + private void sendObject(Object data,BusinessType type) throws IOException{ + ByteOutputStream bos = null; + ObjectOutputStream oos = null; + try { + bos = new ByteOutputStream(); + oos = new ObjectOutputStream(bos); + oos.writeObject(data); + byte[] bytes = bos.getBytes(); + int len = bytes.length; + int t = type.getType(); + os.write(Common.intToByteArray(len)); + os.write(0); + os.write(t); + os.write(bytes); + } finally { + if(bos != null){ + bos.close(); + } + if(oos != null){ + oos.close(); + } + } + + } + + /** + * 发送数据 + * @param data + * @param type + * @throws IOException + */ + private void sendData(byte[] data,BusinessType type) throws IOException{ + int len = data.length; + int t = type.getType(); + os.write(Common.intToByteArray(len)); + os.write(0); + os.write(t); + os.write(data); + } + + /** + * 发送数据 + * @param file + * @param bt + * @throws IOException + */ + private void sendData(File file,BusinessType bt) throws IOException{ + int len = (int)file.length(); + int t = bt.getType(); + os.write(Common.intToByteArray(len)); + os.write(0); + os.write(t); + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + IOUtils.copy(fis, os); + os.flush(); + } finally { + if(fis != null){ + fis.close(); + } + } + } + + + /** + * 发送文件 包括 文件名 + * @param file + * @param type + * @throws IOException + */ + private void sendFile(File file ,BusinessType type) throws IOException{ + String name = file.getName(); + byte[] nameByte = name.getBytes(); + if(nameByte.length > Byte.MAX_VALUE){ + throw new IllegalArgumentException("file name too long,max length is 127"); + } + int len = (int)file.length(); + os.write(Common.intToByteArray(len));//文件长度 + os.write(nameByte.length);//文件名长度 + os.write((byte)type.getType());//业务类型 + os.write(name.getBytes());//文件名 + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + IOUtils.copy(fis, os); + os.flush(); + } finally { + if(fis != null){ + fis.close(); + } + } + + String res = readLine(); + logger.debug("HeartBeat :" + res); + } + + private String readLine() throws IOException{ + BufferedReader br = new BufferedReader(new InputStreamReader(is, Contants.charset)); + String str = br.readLine(); + logger.debug("recieve : " + str); + return str; + } + + /** + * 移动上传成功的数据文件到指定日期目录 + * 完整文件到目录:.../done/type_procIden/yyyyMMdd + * 0大小文件到目录: .../error/type_procIden/yyyyMMdd + */ + public static void moveDetecDataToDateDir(File... allFiles){ + if(allFiles==null || allFiles.length==0){ + return; + } + for (File file : allFiles) { + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = ""; + if (file.length() > 0) { + newDir = Contants.localDataDonePath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } else { + newDir = Contants.localDataErrorPath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } + // -- 文件移动 + FileUtil.moveFile(file, newDir, true); + } + } + + /** + * 遍历所有准备上传的数据文件,将空数据文件移动到指定目录,并记录所有文件总数 + * @param allFiles 所有非空文件集合 + * @param dataDirs 所有数据目录 + * @return 所有文件个数(包括空文件) + * @throws Exception + */ + private long handleNullDataFile(List<File> allFiles, File[] dataDirs) throws Exception { + long total = 0l; + for(File dir : dataDirs){ + File[] files = FileUtil.getFilesEndWith(dir, ".csv"); + if(files==null || files.length==0){ + continue; + } + files = FileUtil.sortASCByModify(files); // 修改日期升序排序 + total += files.length; + for (File file : files) { + if (file.length() > 0) { + allFiles.add(file); + continue; + } + //--- 处理空文件数据:移动空文件数据到指定日期目录 + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = Contants.localDataErrorPath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + FileUtil.moveFile(file, newDir, true); + } + } + return total; + } + + + /** + * 移动上传成功的任务结果到指定日期目录 + * 完整文件到目录:.../done/result/yyyyMMdd + * 0大小文件到目录: .../error/result/yyyyMMdd + */ + public static void moveTaskResultToDateDir(File... fileArr){ + if(fileArr==null || fileArr.length==0){ + return; + } + for (File file : fileArr) { + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = ""; + if (file.length() > 0) { + newDir = Contants.localTaskDonePath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } else { + newDir = Contants.localTaskErrorPath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } + // -- 文件移动 + FileUtil.moveFile(file, newDir, true); + } + } + + /** + * 移动上传成功的 保存回传文件信息的文件 和 回传文件 到指定日期目录 + * 完整文件到目录:.../done/return/yyyyMMdd + * 0大小文件到目录: .../error/return/yyyyMMdd + */ + public static void moveTaskReturnToDateDir(File file, String returnFileName){ + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = Contants.localTaskDonePath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + // -- 文件移动 + FileUtil.moveFile(file, newDir, true);// 保留任务信息的临时文件.return + if(returnFileName!=null && !"".equals(returnFileName)){// 实际回传的文件 + File curReturnFile = new File(Contants.localTaskReturnPath + File.separator + returnFileName); + FileUtil.moveFile(curReturnFile, newDir, true); + } + + } + + + public static void main(String[] args) throws Exception { + + DataSendThread.logger.debug("--------------开始-----------------"); + + int threadSize = 1;//默认开10个线程 + int interval = 10;//间隔 60 s + if(args != null&&args.length >0){ + threadSize = Integer.valueOf(args[0]); + } + if(args != null&&args.length >1){ + interval = Integer.valueOf(args[1]); + } + + ScheduledExecutorService stp = Executors.newScheduledThreadPool(100); + for(int i = 0;i< threadSize;i++){ + DataSendThread dst = new DataSendThread("10.0.6.108", 9527); + stp.scheduleWithFixedDelay(dst, 0, interval, TimeUnit.SECONDS); + } + } + +} diff --git a/src/com/nis/nmsclient/thread/upload/UploadDataThread.java b/src/com/nis/nmsclient/thread/upload/UploadDataThread.java new file mode 100644 index 0000000..e786553 --- /dev/null +++ b/src/com/nis/nmsclient/thread/upload/UploadDataThread.java @@ -0,0 +1,158 @@ +package com.nis.nmsclient.thread.upload; + +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Future; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.thread.socket.SSLClient; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileUtil; +import com.nis.nmsclient.util.Utils; +import com.nis.nmsclient.util.ZipUtil; + +/** + * 用于定时扫描并上传监测数据文件【数据收集方式改为DC主动后,此类废弃】 + * + **/ +public class UploadDataThread implements Runnable { + Logger logger = Logger.getLogger(UploadDataThread.class); + private String name; + + public UploadDataThread(String name) { + this.name = name; + } + + public void run() { + long startTime = System.currentTimeMillis(); + Thread.currentThread().setName(name); + logger.debug("上传数据开始 ~~~~~~~"); + try { + //针对数据文件过多时打包上传未完成的文件继续上传 + File parDir = new File(Contants.localDataCollection); + if(!parDir.exists()){ + return; + } + File[] fileArr = FileUtil.getFilesEndWith(parDir, ".zip"); + if (fileArr != null && fileArr.length > 0) { + for (File file : fileArr) { + if (!file.getName().startsWith(CommonSocket.BP_TYPE_DETECT_DATA)) { + continue; + } + Future<?> future = Common.service.submit(new SSLClient(name, + CommonSocket.REQ_BP_UPLOAD_FIFE, new String[] { + CommonSocket.BP_TYPE_DETECT_DATA, + file.getAbsolutePath() })); + future.get(); + } + } + //---------------------------------------- + + File dataDir = new File(Contants.localDataFilePath); + if (!dataDir.exists()) { + logger.warn("Data directory“" + dataDir.getAbsolutePath() + "”Non-existent!!!"); + return; + } + + long total = 0; + List<File> allFiles = new ArrayList<File>(); + File[] dataDirs = FileUtil.getDirectoryArray(dataDir); + for(File dir : dataDirs){ + File[] files = FileUtil.getFilesEndWith(dir, ".csv"); + if(files==null || files.length==0){ + continue; + } + files = FileUtil.sortASCByModify(files); // 修改日期升序排序 + //allFiles.addAll(Arrays.asList(files)); + total += files.length; + for (File file : files) { + if (file.length() > 0) { + allFiles.add(file); + continue; + } + //--- 处理空文件数据:移动空文件数据到指定日期目录 + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = Contants.localDataErrorPath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + FileUtil.moveFile(file, newDir, true); + } + } + logger.info("本次轮循数据文件总数:" + total + ", 正常数据:" + allFiles.size() + ", 空数据:" + (total-allFiles.size())); + total = allFiles.size();//正常的要上传的数据个数 + + //--- 将所有数据文件一起打包,发送 + if(total>Contants.COMMON_ZIP_MIN_SIZE){ + //与Server通信 + Future<?> serFuture = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), + CommonSocket.REQ_HAND_SHAKE, null)); + if (!Contants.isSucessByResult((String) serFuture.get())) { + logger.debug("UploadDataThread--ServerHandShake--fail return"); + return; + } + //压缩并删除原文件 + String compressFileStr = Contants.localDataCollection + + File.separator + + CommonSocket.addTimeTagForFileName( + CommonSocket.BP_TYPE_DETECT_DATA, null, true) + ".zip"; + ZipUtil.zipWithDelFile(dataDirs, compressFileStr, true); + //发送 + Future<?> future = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), + CommonSocket.REQ_BP_UPLOAD_FIFE, new String[]{CommonSocket.BP_TYPE_DETECT_DATA, compressFileStr})); + future.get(); + logger.info("-----本次轮循将所有数据打包上传"); + } else if (total > 0) {// -- 按正常所有监测数据批量上传 + Future<?> future = Common.service.submit(new SSLClient(name, + CommonSocket.REQ_UPLOAD_DATAS, new Object[] { + dataDir.getParent(), allFiles })); + String msg = (String) future.get(); + if (Contants.isSucessByResult(msg)) { + /** + * 移动上传成功的文件到指定日期目录 + * 完整文件到目录:.../done/type_procIden/yyyyMMdd + * 0大小文件到目录: .../error/type_procIden/yyyyMMdd + */ + for (File file : allFiles) { + String dirTime = DateUtil.getStingDate( + DateUtil.YYYYMMDD, + new Date(file.lastModified())); + String newDir = ""; + if (file.length() > 0) { + newDir = Contants.localDataDonePath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } else { + newDir = Contants.localDataErrorPath + + File.separator + + file.getParentFile().getName() + + File.separator + dirTime; + } + // -- 文件移动 + FileUtil.moveFile(file, newDir, true); + } + } + logger.info("-----本次轮循上传数据总数:" + total + ",用时:" + + (System.currentTimeMillis() - startTime) + "ms"); + }else{ + logger.info("-----本次轮循未上传数据"); + } + + } catch (Exception e) { + logger.error("Upload data exception:" + Utils.printExceptionStack(e)); + } + logger.debug("上传数据结束 ~~~~~~~"); + } + +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/util/CompressFileMgr.java b/src/com/nis/nmsclient/util/CompressFileMgr.java new file mode 100644 index 0000000..3be2549 --- /dev/null +++ b/src/com/nis/nmsclient/util/CompressFileMgr.java @@ -0,0 +1,135 @@ +package com.nis.nmsclient.util; + +import java.io.File; + +import org.apache.log4j.Logger; + +import com.nis.nmsclient.util.GzipUtil; +import com.nis.nmsclient.util.RarUtil; +import com.nis.nmsclient.util.ZipUtil; + +/** + * 文件解压缩的统一处理 + * @date Mar 20, 2012 + * @version + */ +public class CompressFileMgr { + static Logger logger = Logger.getLogger(CompressFileMgr.class); + + /** + * 文件压缩 + * @param sourcePath 源文件或目录 + * @param destFile 压缩后的文件 + * @param excludes 源目录中不要压缩的文件列表 + * @param isAbs 相对路径还是绝对路径压缩 + * @return + * @throws Exception + */ + public boolean compressFile(String sourcePath, String destFile, + String[] excludes, boolean isAbs) throws Exception { + boolean returnFlag = true; + File folder = new File(sourcePath); + if (!folder.exists()) { + return false; + } + if (destFile.length() == (destFile.lastIndexOf(".zip") + 4)) {// 判断是否zip包 + ZipUtil.zip(sourcePath, destFile, excludes); + } else if (destFile.length() == (destFile.lastIndexOf(".gz") + 3)) {// 判断是否gzip包 + GzipUtil.gzipByCmd(sourcePath, destFile, excludes, isAbs); + } else if (destFile.length() == (destFile.lastIndexOf(".tar") + 4)) {// 判断是否tar包 + GzipUtil.tarByCmd(sourcePath, destFile, excludes, isAbs); + } else { + throw new Exception("unable to compress this compressed file"); + } + + return returnFlag; + } + + /** + * 文件解压,如果sourcePath是一个目录,则解压它下面的所有压缩文件 + * @param sourcePath 需要解压的文件或需要解压文件的目录 + * @param destPath 解压到的目标路径 + * @param isAbs 相对路径还是绝对路径解压 + * @return + * @throws Exception + */ + public boolean decompressFile(String sourcePath, String destPath, boolean isAbs) + throws Exception { + logger.debug("decompressFile start……"); + boolean returnFlag = true; + logger.debug("decompressFile sourcePath-----" + sourcePath); + logger.debug("decompressFile destPath-----" + destPath); + File folder = new File(sourcePath); + if (!folder.exists()) { + return false; + } + if (folder.isDirectory()) { + String files[] = folder.list(); + String fileAbs = null; + for (int i = 0; i < files.length; i++) { + fileAbs = sourcePath + File.separator + files[i]; + decompressFile(fileAbs, destPath, isAbs); + } + } else { + decompress(sourcePath, destPath, isAbs); + } + + logger.debug("decompressFile end!"); + return returnFlag; + } + + /** + * 解压文件,只针对单个压缩文件 + * @param sourceFile 需要解压的文件 + * @param destPath 解压到的目标路径 + * @param isAbs 相对路径还是绝对路径解压 + * @throws Exception + */ + private void decompress(String sourceFile, String destPath, boolean isAbs) + throws Exception { + logger.debug("decompress start……"); + logger.debug("decompress sourceFile---" + sourceFile); + logger.debug("decompress 1-----"+(sourceFile.length() == (sourceFile.lastIndexOf(".zip") + 4))); + logger.debug("decompress 2-----"+(sourceFile.length() == (sourceFile.lastIndexOf(".rar") + 4))); + logger.debug("decompress 3-----"+(sourceFile.length() == (sourceFile.lastIndexOf(".gz") + 3))); + if (sourceFile.length() == (sourceFile.lastIndexOf(".zip") + 4)) {// 判断是否zip包 + ZipUtil.unZip(sourceFile, destPath); + } else if (sourceFile.length() == (sourceFile.lastIndexOf(".rar") + 4)) {// 判断是否rar包 + RarUtil.unRar(sourceFile, destPath); + } else if (sourceFile.length() == (sourceFile.lastIndexOf(".gz") + 3)) {// 判断是否gzip包 + GzipUtil.unGzipByCmd(sourceFile, destPath, isAbs); + } else if (sourceFile.length() == (sourceFile.lastIndexOf(".tar") + 4)) {// 判断是否tar包 + GzipUtil.unTarByCmd(sourceFile, destPath, isAbs); + } else { + throw new Exception("unable to decompress this decompressed file"); + } + logger.debug("decompress end!"); + } + + public static String getCompressSuffixByOs(boolean isAbs){ + String suffix = ".zip"; + //根据操作系统确定获取进程ID的方式 + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + suffix = ".zip"; + }else if (os.startsWith("Linux")){ + suffix = (isAbs ? "_absolute" : "_relative") + ".tar.gz"; + } + return suffix; + } + + public static boolean isCompressFile(File file){ + boolean flag = false; + if(file.isFile()){ + String fileName = file.getName(); + if (".rar".equalsIgnoreCase(fileName.substring(fileName.length() - 4)) + || ".zip".equalsIgnoreCase(fileName.substring(fileName.length() - 4)) + || ".tar".equalsIgnoreCase(fileName.substring(fileName.length() - 4)) + || ".gz".equalsIgnoreCase(fileName.substring(fileName.length() - 3))) { + flag = true; + } + } + return flag; + + } +} diff --git a/src/com/nis/nmsclient/util/DESUtil.java b/src/com/nis/nmsclient/util/DESUtil.java new file mode 100644 index 0000000..a93b11f --- /dev/null +++ b/src/com/nis/nmsclient/util/DESUtil.java @@ -0,0 +1,83 @@ +package com.nis.nmsclient.util; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import javax.crypto.spec.IvParameterSpec; + +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +/** + * 通过DES加密解密实现一个String字符串的加密和解密. + * + */ +public class DESUtil { + private final static String key = "longstar"; + + /** + * DES加密方法 + * + */ + public static String desEncrypt(String message) throws Exception { + Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); + + DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("ASCII")); + + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(desKeySpec); + IvParameterSpec iv = new IvParameterSpec(key.getBytes("ASCII")); + cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); + + byte data[] = message.getBytes("ASCII"); + byte[] encryptedData = cipher.doFinal(data); + + return getBASE64(encryptedData); + } + + /** + * DES解密方法 + * + */ + public static String desDecrypt(String message) throws Exception { + Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); + + DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("ASCII")); + + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(desKeySpec); + IvParameterSpec iv = new IvParameterSpec(key.getBytes("ASCII")); + cipher.init(Cipher.DECRYPT_MODE, secretKey, iv); + + byte data[] = getFromBASE64(message); + byte[] encryptedData = cipher.doFinal(data); + + return new String(encryptedData); + } + + // 对base64编码的string解码成byte数组 + private static byte[] getFromBASE64(String s) { + if (s == null) + return null; + BASE64Decoder decoder = new BASE64Decoder(); + try { + byte[] b = decoder.decodeBuffer(s); + return b; + } catch (Exception e) { + return null; + } + } + + //将 byte数组 进行 BASE64 编码 + private static String getBASE64(byte[] b) { + if (b == null) + return null; + try { + String returnstr = (new BASE64Encoder()).encode(b); + return returnstr; + } catch (Exception e) { + return null; + } + } +} diff --git a/src/com/nis/nmsclient/util/DateUtil.java b/src/com/nis/nmsclient/util/DateUtil.java new file mode 100644 index 0000000..fbc9e0e --- /dev/null +++ b/src/com/nis/nmsclient/util/DateUtil.java @@ -0,0 +1,142 @@ +package com.nis.nmsclient.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.log4j.Logger; + +public class DateUtil { + static Logger logger = Logger.getLogger(DateUtil.class); + /** + * 处理日期时,用到参数。格式24小时制yyyy-MM-dd HH:mm:ss + */ + public static final SimpleDateFormat YYYY_MM_DD_HH24_MM_SS = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss"); + /** + * 处理日期时,用到参数。格式24小时制yyyyMMddHHmmss + */ + public static final SimpleDateFormat YYYYMMDDHH24MMSS = new SimpleDateFormat( + "yyyyMMddHHmmss"); + /** + * 处理日期时,用到参数。格式为yyyy-MM-dd + */ + public static final SimpleDateFormat YYYY_MM_DD = new SimpleDateFormat( + "yyyy-MM-dd"); + /** + * 处理日期时,用到参数。格式为yyyyMMdd + */ + public static final SimpleDateFormat YYYYMMDD = new SimpleDateFormat( + "yyyyMMdd"); + + + /** + * 获得当前日期 + * + * @return + */ + public static String getCurrentDate(SimpleDateFormat sf) { + if(sf==null){ + sf = YYYY_MM_DD; + } + return sf.format(new Date()); + } + + /** + * 获得某日期的指定格式的字符串 + * @param sf + * @param date + * @return + */ + public static String getStingDate(SimpleDateFormat sf, Date date) { + if(date==null){ + date = new Date(); + } + if(sf==null){ + sf = YYYY_MM_DD; + } + + return sf.format(date); + } + + public static long getDaysFromBeginToEnd(SimpleDateFormat dateFormat, + String begin, String end) { + Date beginD = null; + Date endD = null; + long days = 0; + try { + if (begin != null && !"".equals(begin)) { + beginD = dateFormat.parse(begin); + } else { + beginD = new Date(); + } + if (end != null && !"".equals(end)) { + endD = dateFormat.parse(end); + } else { + endD = new Date(); + } + days = getDaysFromBeginToEnd(beginD, endD); + } catch (ParseException e) { + logger.error(Utils.printExceptionStack(e)); + return days; + } + + return days; + + } + + public static long getDaysFromBeginToEnd(Date begin, Date end) { + long days = 0; + if (begin != null && end != null) { + days = getDaysFromBeginToEnd(begin.getTime(), end.getTime()); + } + + return days; + + } + + public static long getDaysFromBeginToEnd(long begin, long end) { + return (end - begin) / (24 * 60 * 60 * 1000); + } + + public static long getMinutesFromBeginToEnd(SimpleDateFormat dateFormat, + String begin, String end) { + Date beginD = null; + Date endD = null; + long days = 0; + try { + if (begin != null && !"".equals(begin)) { + beginD = dateFormat.parse(begin); + } else { + beginD = new Date(); + } + if (end != null && !"".equals(end)) { + endD = dateFormat.parse(end); + } else { + endD = new Date(); + } + days = getMinutesFromBeginToEnd(beginD, endD); + } catch (ParseException e) { + logger.error(Utils.printExceptionStack(e)); + return days; + } + + return days; + + } + + public static long getMinutesFromBeginToEnd(Date begin, Date end) { + long days = 0; + if (begin != null && end != null) { + days = getMinutesFromBeginToEnd(begin.getTime(), end.getTime()); + } + + return days; + + } + + public static long getMinutesFromBeginToEnd(long begin, long end) { + return (end - begin) / (60 * 1000); + } + +} diff --git a/src/com/nis/nmsclient/util/FileUtil.java b/src/com/nis/nmsclient/util/FileUtil.java new file mode 100644 index 0000000..7f8eee7 --- /dev/null +++ b/src/com/nis/nmsclient/util/FileUtil.java @@ -0,0 +1,477 @@ +package com.nis.nmsclient.util; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.Arrays; +import java.util.Comparator; + +import org.apache.commons.io.FileUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Contants; + +/** + * 文件操作类:检索、排序 + * + */ +public class FileUtil { + static Logger logger = Logger.getLogger(FileUtil.class); + + /** + * 获取子目录列表 + * @param file + * @return + */ + public static File[] getDirectoryArray(File file) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory()) { + return true; + } else + return false; + } + }); + } + + + /** + * 获取指定全部或部分名称的文件 + * @param file + * @param azz + * @return + */ + public static File[] getFilesArray(File file, final String azz) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory()) { + return false; + } + return name.indexOf(azz) != -1; // 过滤出指定全部名称或部分名称的文件 + } + }); + } + + /** + * 获取指定前缀的文件 + * @param file + * @param suffix + * @return + */ + public static File[] getFilesStartWith(File file, final String prefix) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory()) { + return false; + } + return name.startsWith(prefix); // 过滤出注定前缀名称的文件 + } + }); + } + + /** + * 获取指定时间段指定前缀的文件 + * @param file + * @param suffix + * @return + */ + public static File[] getFilesStartWithByMillis(File file, final String prefix, final long sTimeMillis, final long eTimeMillis) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory()) { + return false; + } + if (sTimeMillis > 0 && eTimeMillis > 0) { + if (new File(dir, name).lastModified() < sTimeMillis + || new File(dir, name).lastModified() > eTimeMillis) {// 不在指定时间段 + return false; + } + } + return name.startsWith(prefix); // 过滤出注定前缀名称的文件 + } + }); + } + + /** + * 获取指定后缀名的文件 + * @param file + * @param suffix + * @return + */ + public static File[] getFilesEndWith(File file, final String suffix) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory()) { + return false; + } + return name.endsWith(suffix); // 过滤出注定后缀名称的文件 + } + }); + } + + /** + * 获取指定时间修改的指定后缀名的文件 + * @param file + * @param suffix + * @return + */ + public static File[] getFilesEndWithBeforeMillis(File file, final String suffix, final long timeMillis) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory() || new File(dir,name).lastModified() > timeMillis) { + return false; + } + return name.endsWith(suffix); // 过滤出注定后缀名称的文件 + } + }); + } + + /** + * 获取指定时间修改的文件 + * @return + */ + public static File[] getFilesBeforeMillis(File file, final long timeMillis) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory() || new File(dir,name).lastModified() > timeMillis) { + return false; + } + return true; + } + }); + } + + /** + * 获取指定毫秒之后修改过的文件 + * @param file + * @param timeMillis + * @return + */ + public static File[] getFilesAfterMillis(File file, final long timeMillis) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).lastModified() >= timeMillis) { + return true; + } else + return false; + } + }); + } + + /** + * 获取指定时间名称及之前的文件夹 + * @param file + * @param suffix + * @return + */ + public static File[] getDirsBeforeDateName(File file, final String yyyyMMddName) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory() && name.compareTo(yyyyMMddName)<=0) { + return true; + } + return false; + } + }); + } + + /** + * 获取指定时间名称及之后的文件夹 + * @param file + * @param suffix + * @return + */ + public static File[] getDirsAfterDateName(File file, final String yyyyMMddName) { + if (!file.isDirectory()) { + new Exception(file.getAbsolutePath() + " Not A Directory"); + } + return file.listFiles(new FilenameFilter() { + // 使用匿名内部类重写accept方法; + public boolean accept(File dir, String name) { + if (new File(dir, name).isDirectory() && name.compareTo(yyyyMMddName)>=0) { + return true; + } + return false; + } + }); + } + + /** + * 文件数组按最后修改日期排序,升序 + * @param files + * @return + */ + public static File[] sortASCByModify(File[] files) { + Arrays.sort(files, new Comparator<File>(){ + public int compare(File arg0, File arg1) { + if(arg0.lastModified() > arg1.lastModified()){ + return 1; + }else if (arg0.lastModified() < arg1.lastModified()){ + return -1; + }else { + return 0; + } + } + }); + return files; + } + + /** + * 文件数组按最后修改日期排序,降序 + * @param files + * @return + */ + public static File[] sortDescByModify(File[] files) { + Arrays.sort(files, new Comparator<File>(){ + public int compare(File arg0, File arg1) { + if(arg0.lastModified() > arg1.lastModified()){ + return -1; + }else if (arg0.lastModified() < arg1.lastModified()){ + return 1; + }else { + return 0; + } + } + }); + return files; + } + + /** + * 文件数组按名称排序,升序 + * @param files + * @return + */ + public static File [] sortASCByFileName(File[] files) { + Arrays.sort(files, new Comparator<File>(){ + public int compare(File arg0, File arg1) { + return arg0.getName().compareTo(arg1.getName()); + } + }); + return files; + } + /** + * 文件数组按名称排序,降序 + * @param files + * @return + */ + public static File [] sortDescByFileName(File[] files) { + Arrays.sort(files, new Comparator<File>(){ + public int compare(File arg0, File arg1) { + return arg1.getName().compareTo(arg0.getName()); + } + }); + return files; + } + + /** + * 将文件移动到指定文件夹 + * + * @param f + * 源文件 + * @param newDir + * 新目录 + * @param flag + * 是否覆盖 true:覆盖 false:不覆盖 + */ + public static void moveFile(File f, String newDir, boolean flag) { + if (!f.exists()) { + logger.debug("文件已不存在,无法移动!" + f.getAbsolutePath()); + return; + } + File fileDir = new File(newDir); // 备份目录 + if (!fileDir.exists()) { // 检查并创建新目录 + fileDir.mkdirs(); + } + File dtnFile = new File(fileDir.getAbsolutePath() + File.separator + + f.getName()); // 制定目标文件路径以及文件名 + if (dtnFile.exists() && flag) { // 检查并删除已存在文件 + //dtnFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(dtnFile); + logger.debug("moveFile 删除已存在文件--" + dtnFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(dtnFile); + } + try { + FileUtils.copyFile(f, dtnFile); // 移动文件 + logger.debug("文件 From 》 " + f.getAbsolutePath() + + "\n To 》 " + dtnFile.getAbsolutePath()); + if (f.exists()) { + logger.debug("删除源文件" + f.getAbsolutePath()); + //f.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(f); + //FileUtil.checkParentDirExist(f); + } else { + logger.debug("源文件不存在!不用删了!" + f.getAbsolutePath()); + return; + } + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + + /** + * 删除文件或文件夹 + */ + public static void delDir(File file) { + try {//文件在可删范围并且不在禁删范围 + if (file.exists() && isIncludeDelRange(file) && !isExcludeDelRange(file)) { + if (!file.isDirectory()) { + file.delete(); + logger.debug("FileUtil.delDir(File file)删除文件--" + file.getAbsolutePath()); + FileUtil.checkParentDirExist(file); + } else if (file.isDirectory()) { + delDir2(file); + } + } + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + } + + /** + * 递归删除文件夹及其下的所有文件 + */ + private static void delDir2(File file) throws IOException { + if (!file.exists()) { + return; + } + if (!file.isDirectory()) { + file.delete(); + logger.debug("FileUtil.delDir2(File file)删除文件--" + file.getAbsolutePath()); + FileUtil.checkParentDirExist(file); + } else if (file.isDirectory()) { + if (!isExcludeDelRange(file)) {// 文件不在禁删范围 + for (File f : file.listFiles()) { + delDir2(f); + } + file.delete(); + logger.debug("FileUtil.delDir2(File file)删除文件夹--" + file.getAbsolutePath()); + FileUtil.checkParentDirExist(file); + } + } + } + + /** + * 检查文件是否在可删范围内 + * @param file + * @return true:是,false:否 + */ + public static boolean isIncludeDelRange(File file) throws IOException{ + boolean flag = false; + String path = file.getCanonicalPath(); + if(Contants.COMMON_DEL_PATH_INCLUDE!=null){ + for(String include : Contants.COMMON_DEL_PATH_INCLUDE){ + if(path.startsWith(include)){ + flag = true; + break; + } + } + }else{//删除范围参数为空,则返回在删除范围 + flag = true; + } + return flag; + } + + /** + * 检查文件是否在禁删范围内 + * @param file + * @return true:是,false:否 + */ + public static boolean isExcludeDelRange(File file) throws IOException{ + boolean flag = false; + String path = file.getCanonicalPath(); + if(Contants.COMMON_DEL_PATH_EXCLUDE!=null){ + for(String exclude : Contants.COMMON_DEL_PATH_EXCLUDE){ + if(path.startsWith(exclude)){ + flag = true; + break; + } + } + }else{//禁删参数为空,则返回不在禁删范围 + flag = false; + } + return flag; + } + + public static void checkParentDirExist(File file){ + logger.debug("检查父目录是否存在---" +file.getParentFile().exists() + "---" + file.getParent()); + } + + /** + * 格式化处理路径 + * @param path + * @return + */ + public static String handlerPath(String path){ + File file = new File(path); + try { + path = file.getCanonicalPath(); + } catch (IOException e) { + logger.error(Utils.printExceptionStack(e)); + } + + return path; + } + + public static File[] getAll(File dir, int level) { + logger.info(getLevel(level) + dir.getName()); + + level++; + File[] files = dir.listFiles(); + for (int x = 0; x < files.length; x++) { + if (files[x].isDirectory()) + getAll(files[x], level); + else + logger.debug(getLevel(level) + files[x].getName()); + } + return files; + } + + public static String getLevel(int level) { + StringBuilder sb = new StringBuilder(); + sb.append("|--"); + + for (int x = 0; x < level; x++) { + sb.insert(0, "| "); + } + return sb.toString(); + } + +} diff --git a/src/com/nis/nmsclient/util/FileWrUtil.java b/src/com/nis/nmsclient/util/FileWrUtil.java new file mode 100644 index 0000000..8ebf75c --- /dev/null +++ b/src/com/nis/nmsclient/util/FileWrUtil.java @@ -0,0 +1,285 @@ +package com.nis.nmsclient.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +import com.Ostermiller.util.ExcelCSVParser; +import com.Ostermiller.util.ExcelCSVPrinter; +import com.nis.nmsclient.util.io.UnicodeReader; + +public class FileWrUtil { + static Logger logger = Logger.getLogger(FileWrUtil.class); + + /** + * 根据文件编码添加文件内容前缀 + * @param file + * @param encoding + */ + protected static boolean addFileHeadByEncoding(File file, String encoding) throws Exception{ + FileOutputStream fos = null; + boolean flag = false; + try{ + byte[] head = null; + if("UTF-8".equalsIgnoreCase(encoding)){ + head = new byte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF}; + }else if("UTF-16BE".equalsIgnoreCase(encoding)){ + head = new byte[]{(byte)0xFE,(byte)0xFF}; + }else if("UTF-16LE".equalsIgnoreCase(encoding)){ + head = new byte[]{(byte)0xFF,(byte)0xFE}; + }else if("UTF-32BE".equalsIgnoreCase(encoding)){ + head = new byte[]{(byte)0x00,(byte)0x00,(byte)0xFE,(byte)0xFF}; + }else if("UTF-32LE".equalsIgnoreCase(encoding)){ + head = new byte[]{(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00}; + } + + if(head!=null){ + fos = new FileOutputStream(file); + fos.write(head); + fos.flush(); + + flag = true; + } + } catch (IOException e) { + throw e; + }finally { + if(fos!=null){ + try { + fos.close(); + } catch (IOException e) { + } + } + } + + return flag; + } + + /** + * 写入文件, .cfg\.ini\.txt + * + */ + public static boolean cfgFilePrinter(File file, String charset, String[] values) throws Exception{ + OutputStreamWriter fos = null; + try { + if(addFileHeadByEncoding(file, charset)){ + fos = new OutputStreamWriter( + new FileOutputStream(file,true), charset); + }else{ + fos = new OutputStreamWriter( + new FileOutputStream(file), charset); + } + for(String val : values){ + fos.write(val); + fos.write("\n"); + } + fos.flush(); + } catch (IOException e) { + throw e; + }finally { + if(fos!=null){ + try { + fos.close(); + } catch (IOException e) { + } + } + } + + return true; + } + + /** + * 追加内容到文件, .cfg\.ini\.txt + * + */ + public static boolean cfgFileAppender(File file, String charset, String[] values) throws Exception{ + OutputStreamWriter fos = null; + try { + fos = new OutputStreamWriter( + new FileOutputStream(file, true), charset); + for(String val : values){ + fos.write(val); + fos.write("\n"); + } + fos.flush(); + } catch (IOException e) { + throw e; + }finally { + if(fos!=null){ + try { + fos.close(); + } catch (IOException e) { + } + } + } + + return true; + } + + /** + * 根据文件的编码读取文件内容, .cfg\.ini\.txt + * + */ + public static String[] cfgFileReader(File file) throws Exception{ + BufferedReader br = null; + ArrayList<String> list = new ArrayList<String>(); + try { + + br = new BufferedReader(new UnicodeReader(new FileInputStream( + file), Charset.defaultCharset().name())); + String str = null; + while((str=br.readLine())!=null){ + list.add(str); + } + } catch (IOException e) { + throw e; + }finally { + if(br!=null){ + try { + br.close(); + } catch (IOException e) { + } + } + } + + String[] values = new String[list.size()]; + return list.toArray(values); + } + + /** + * 写CSV文件,只写入一行 + * + */ + public static boolean csvFilePrinter(File file, String charset, String[] values) throws Exception{ + OutputStreamWriter fos = null; + try { + fos = new OutputStreamWriter( + new FileOutputStream(file), charset); + + + ExcelCSVPrinter ecsvp = new ExcelCSVPrinter(fos); + ecsvp.changeDelimiter(','); + ecsvp.setAutoFlush(true); + ecsvp.writeln(values); + + fos.flush(); + } catch (IOException e) { + throw e; + }finally { + if(fos!=null){ + try { + fos.close(); + } catch (IOException e) { + } + } + } + + return true; + } + + /** + * 写CSV文件,写入多行 + * + */ + public static boolean csvFilePrinter(File file, String charset, List<String[]> values) throws Exception{ + OutputStreamWriter fos = null; + try { + fos = new OutputStreamWriter( + new FileOutputStream(file), charset); + + + ExcelCSVPrinter ecsvp = new ExcelCSVPrinter(fos); + ecsvp.changeDelimiter(','); + ecsvp.setAutoFlush(true); + for(String[] val : values){ + ecsvp.writeln(val); + } + + fos.flush(); + } catch (IOException e) { + throw e; + }finally { + if(fos!=null){ + try { + fos.close(); + } catch (IOException e) { + } + } + } + + return true; + } + + /** + * 解析CSV文件中的指定行 + * + */ + public static String[] csvFileParser(File file, String charset, int rowNum) throws Exception{ + Reader in = null; + String[] currLine = null; + try { + //创建解析信息流 + in = new InputStreamReader(new FileInputStream(file),charset); + + ExcelCSVParser csvParser = new ExcelCSVParser(in); + while((currLine=csvParser.getLine())!=null){ + if(rowNum != csvParser.getLastLineNumber()){ + currLine = null; + } + } + + } catch (IOException e) { + throw e; + }finally { + if(in!=null){ + try { + in.close(); + } catch (IOException e) { + } + } + } + + return currLine; + } + + /** + * 解析CSV文件的所有行 + * + */ + public static List<String[]> csvFileParser(File file, String charset) throws Exception{ + Reader in = null; + List<String[]> allLineList = new ArrayList<String[]>(); + try { + //创建解析信息流 + in = new InputStreamReader(new FileInputStream(file),charset); + + ExcelCSVParser csvParser = new ExcelCSVParser(in); + String[] currLine = null; + while((currLine=csvParser.getLine())!=null){ + allLineList.add(currLine); + } + + } catch (IOException e) { + throw e; + }finally { + if(in!=null){ + try { + in.close(); + } catch (IOException e) { + } + } + } + + return allLineList; + } + +} diff --git a/src/com/nis/nmsclient/util/GzipUtil.java b/src/com/nis/nmsclient/util/GzipUtil.java new file mode 100644 index 0000000..75dce1b --- /dev/null +++ b/src/com/nis/nmsclient/util/GzipUtil.java @@ -0,0 +1,680 @@ +package com.nis.nmsclient.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; + +import com.ice.tar.TarEntry; +import com.ice.tar.TarInputStream; +import com.ice.tar.TarOutputStream; +import com.nis.nmsclient.common.Contants; + +/** + * gzip文件压缩与解压缩,对文件tar归档与解归档工具类 + * + */ +public class GzipUtil { + static Logger logger = Logger.getLogger(GzipUtil.class); + + /** + * 使用命令对单个gz压缩包解压 + * @param srcFileStr 需要解压的gz文件 + * @param destDir 解压后的目标路径 + * @param isAbs 解压文件时 true 按绝对路径解压, false 进入目标路径后解压 + * @throws Exception + */ + public static void unGzipByCmd(String srcFileStr, String destDir, boolean isAbs) throws Exception{ + logger.debug("unGzip start……"); + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + try { + logger.debug("unGzipByCmd srcFile---" + srcFileStr); + logger.debug("unGzipByCmd destDir---" + destDir); + + File srcFile = new File(srcFileStr); + File descFile = new File(destDir); + if(!srcFile.exists()){ + throw new Exception("source file not exist"); + } + if(!srcFile.isFile()){ + throw new Exception("source file is not a file"); + } + if(!descFile.exists()){ + descFile.mkdirs(); + } + if(!descFile.isDirectory()){ + throw new Exception("compress destination path is not a directory"); + } + String tarFile = srcFile.getParent() + File.separator + srcFile.getName().substring(0, srcFile.getName().length()-3); + StringBuffer sb = new StringBuffer(); + sb.append("gunzip " + srcFileStr); + sb.append(";tar xvpPf " + tarFile); + if(!isAbs){ + sb.append(" -C " + destDir); + }else{ + sb.append(" -C /"); + } + sb.append(";gzip " + tarFile); + logger.debug("unGzipByCmd cmd--->" + sb.toString()); + + String[] shellCmd = new String[] { "/bin/bash", "-c", sb.toString() }; + process = Runtime.getRuntime().exec(shellCmd); + process.getOutputStream().close(); + + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) { + logger.debug("unGzipByCmd--->" + line); + } + while ((line = errorReader.readLine()) != null) { + logger.debug("unGzipByCmd error--->" + line); + throw new IOException(line); + } + + logger.debug("unGzipByCmd end……"); + } catch (Exception e) { + throw e; + } finally { + try { + if (bReader != null) { + bReader.close(); + } + if (errorReader != null) { + errorReader.close(); + } + if (process != null) { + process.destroy(); + } + } catch (Exception e) { + } + } + + } + + /** + * 使用命令将单个文件或一个目录压缩成Gzip格式 + * @param srcPath 需要压缩的文件目录或文件 + * @param destFileStr 压缩后的目标文件 + * @param excludes 排除的目录或文件(全是绝对路径),不包含到压缩包的 + * @param isAbs 压缩文件时 true 按绝对路径压缩(含有完成的路径压缩包), false 进入目标路径后压缩 + * @throws Exception + */ + public static void gzipByCmd(String srcPath, String destFileStr, String[] excludes, boolean isAbs) throws Exception{ + logger.debug("gzipByCmd start……"); + OutputStreamWriter fos = null; + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + File excludeFile = null; + boolean flag = true; + try { + logger.debug("gzipByCmd srcPath---" + srcPath); + logger.debug("gzipByCmd destFileStr---" + destFileStr); + + File srcFile = new File(srcPath); + File descFile = new File(destFileStr); + if(!srcFile.exists()){ + throw new Exception("decompress file not exist"); + } + if(!descFile.getParentFile().exists()){ + descFile.getParentFile().mkdirs(); + } + StringBuffer sb = new StringBuffer(); + if(!isAbs){ + if(srcFile.isFile()){ + sb.append("cd " + srcFile.getParentFile().getCanonicalPath() + ";"); + }else{ + sb.append("cd " + srcFile.getCanonicalPath() + ";"); + } + } + sb.append("tar -czvpPf " + destFileStr); + if(excludes!=null && excludes.length>0){ + if(!isAbs){ + for (int i = 0; i < excludes.length; i++) { + int index = excludes[i].indexOf(srcFile + .getCanonicalPath()); + logger.debug("gzipByCmd index--->" + index + "---src=" +srcFile + .getCanonicalPath()); + int start = index + srcFile.getCanonicalPath().length() + 1; + logger.debug("gzipByCmd start--->" + start + "--length=" + excludes[i].length() +"---exclude=" + excludes[i]); + if (index != -1 && start <= excludes[i].length()) { + excludes[i] = excludes[i].substring(start, + excludes[i].length()); + logger.debug("gzipByCmd exclude--->" + excludes[i]); + } + } + } + excludeFile = new File(Contants.localTempPath + File.separator + "excludelist_" + System.currentTimeMillis() + ".temp"); + // 2012-11-21 修改 由于使用FileWrUtil写的文件(有文件头的),Linux下无法正确识别 + fos = new OutputStreamWriter( + new FileOutputStream(excludeFile, true), System.getProperty("file.encoding")); + logger.debug("gzipByCmd ---- " + System.getProperty("file.encoding")); + for(String val : excludes){ + fos.write(val); + fos.write("\n"); + } + fos.flush(); + //FileWrUtil.cfgFilePrinter(excludeFile, Contants.charset, excludes); + sb.append(" -X " + excludeFile.getCanonicalPath()); + } + if(!isAbs){ + if(srcFile.isFile()){ + sb.append(" " + srcFile.getName()); + }else{ + sb.append(" *"); + } + }else{ + sb.append(" " + srcFile.getCanonicalPath()); + } + logger.debug("gzipByCmd cmd--->" + sb.toString()); + + String[] shellCmd = new String[] { "/bin/bash", "-c", sb.toString() }; + process = Runtime.getRuntime().exec(shellCmd); + process.getOutputStream().close(); + + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) { + logger.debug("gzipByCmd--->" + line); + } + while ((line = errorReader.readLine()) != null) { + logger.debug("gzipByCmd error--->" + line); + flag = false; + throw new IOException(line); + } + + logger.debug("gzipByCmd end……"); + } catch (Exception e) { + throw e; + } finally { + try { + if(fos!=null){ + fos.close(); + } + if(excludeFile!=null && excludeFile.exists()){ + //excludeFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(excludeFile); + logger.debug("GzipUtil.gzipByCmd()--delete excludeFile=" + excludeFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(excludeFile); + } + if (bReader != null) { + bReader.close(); + } + if (errorReader != null) { + errorReader.close(); + } + if (process != null) { + process.destroy(); + } + if(!flag){ + File destFile = new File(destFileStr); + if(destFile.exists()){ + //destFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(destFile); + logger.debug("GzipUtil.gzipByCmd()--delete destFile=" + destFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(destFile); + } + } + } catch (Exception e) { + } + } + + } + + /** + * 使用命令对单个tar压缩包解压 + * @param srcFileStr 需要解压的gz文件 + * @param destDir 解压后的目标路径 + * @param isAbs 解压文件时 true 按绝对路径解压, false 进入目标路径后解压 + * @throws Exception + */ + public static void unTarByCmd(String srcFileStr, String destDir, boolean isAbs) throws Exception{ + logger.debug("unTarByCmd start……"); + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + try { + logger.debug("unTarByCmd srcFile---" + srcFileStr); + logger.debug("unTarByCmd destDir---" + destDir); + + File srcFile = new File(srcFileStr); + File descFile = new File(destDir); + if(!srcFile.exists()){ + throw new Exception("source file not exist"); + } + if(!srcFile.isFile()){ + throw new Exception("source file is not a file"); + } + if(!descFile.exists()){ + descFile.mkdirs(); + } + if(!descFile.isDirectory()){ + throw new Exception("compress destination path is not a directory"); + } + StringBuffer sb = new StringBuffer(); + sb.append("tar xvpPf " + srcFileStr); + if(!isAbs){ + sb.append(" -C " + destDir); + }else{ + sb.append(" -C /"); + } + logger.debug("unTarByCmd cmd--->" + sb.toString()); + + String[] shellCmd = new String[] { "/bin/bash", "-c", sb.toString() }; + process = Runtime.getRuntime().exec(shellCmd); + process.getOutputStream().close(); + + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) { + logger.debug("unTarByCmd--->" + line); + } + while ((line = errorReader.readLine()) != null) { + logger.debug("unTarByCmd--->" + line); + throw new IOException(line); + } + + logger.debug("unTarByCmd end……"); + } catch (Exception e) { + throw e; + } finally { + try { + if (bReader != null) { + bReader.close(); + } + if (errorReader != null) { + errorReader.close(); + } + if (process != null) { + process.destroy(); + } + } catch (Exception e) { + } + } + + } + + /** + * 使用命令将单个文件或一个目录压缩成tar格式 + * @param srcPath 需要压缩的文件目录或文件 + * @param destFileStr 压缩后的目标文件 + * @param excludes 排除的目录或文件(全是绝对路径),不包含到压缩包的 + * @param isAbs 压缩文件时 true 按绝对路径压缩(含有完成的路径压缩包), false 进入目标路径后压缩 + * @throws Exception + */ + public static void tarByCmd(String srcPath, String destFileStr, String[] excludes, boolean isAbs) throws Exception{ + logger.debug("tarByCmd start……"); + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + File excludeFile = null; + boolean flag = true; + try { + logger.debug("tarByCmd srcPath---" + srcPath); + logger.debug("tarByCmd destFileStr---" + destFileStr); + + File srcFile = new File(srcPath); + File descFile = new File(destFileStr); + if(!srcFile.exists()){ + throw new Exception("decompress file not exist"); + } + if(!descFile.getParentFile().exists()){ + descFile.getParentFile().mkdirs(); + } + StringBuffer sb = new StringBuffer(); + if(!isAbs){ + if(srcFile.isFile()){ + sb.append("cd " + srcFile.getParentFile().getCanonicalPath() + ";"); + }else{ + sb.append("cd " + srcFile.getCanonicalPath() + ";"); + } + } + sb.append("tar -cvpPf " + destFileStr); + if(excludes!=null && excludes.length>0){ + if(!isAbs){ + for (int i = 0; i < excludes.length; i++) { + int index = excludes[i].indexOf(srcFile + .getCanonicalPath()); + logger.debug("tarByCmd index--->" + index + "---src=" +srcFile + .getCanonicalPath()); + int start = index + srcFile.getCanonicalPath().length() + 1; + logger.debug("tarByCmd start--->" + start + "--length=" + excludes[i].length() +"---exclude=" + excludes[i]); + if (index != -1 && start <= excludes[i].length()) { + excludes[i] = excludes[i].substring(start, + excludes[i].length()); + logger.debug("tarByCmd exclude--->" + excludes[i]); + } + } + } + excludeFile = new File(Contants.localTempPath + File.separator + "excludelist_" + System.currentTimeMillis() + ".temp"); + FileWrUtil.cfgFilePrinter(excludeFile, Contants.charset, excludes); + sb.append(" -X " + excludeFile.getCanonicalPath()); + } + if(!isAbs){ + if(srcFile.isFile()){ + sb.append(" " + srcFile.getName()); + }else{ + sb.append(" *"); + } + }else{ + sb.append(" " + srcFile.getCanonicalPath()); + } + logger.debug("tarByCmd cmd--->" + sb.toString()); + + String[] shellCmd = new String[] { "/bin/bash", "-c", sb.toString() }; + process = Runtime.getRuntime().exec(shellCmd); + process.getOutputStream().close(); + + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) { + logger.debug("tarByCmd--->" + line); + } + while ((line = errorReader.readLine()) != null) { + logger.debug("tarByCmd error--->" + line); + flag = false; + throw new IOException(line); + } + + logger.debug("tarByCmd end……"); + } catch (Exception e) { + throw e; + } finally { + try { + if(excludeFile!=null && excludeFile.exists()){ + //excludeFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(excludeFile); + logger.debug("GzipUtil.tarByCmd()--delete excludeFile=" + excludeFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(excludeFile); + } + if (bReader != null) { + bReader.close(); + } + if (errorReader != null) { + errorReader.close(); + } + if (process != null) { + process.destroy(); + } + if(!flag){ + File destFile = new File(destFileStr); + if(destFile.exists()){ + //destFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(destFile); + logger.debug("GzipUtil.tarByCmd()--delete destFile=" + destFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(destFile); + } + } + } catch (Exception e) { + } + } + } + + /** + * 对单个gz压缩包解压 + * @param srcFile 需要解压的gz文件 + * @param destDir 解压后的目标路径 + * @throws Exception + */ + public static void unGzip(String srcFile, String destDir) throws Exception{ + logger.debug("unGzip start……"); + OutputStream out = null; + GZIPInputStream gis = null; + File tempFile = new File(destDir + File.separator + System.currentTimeMillis() + ".tar"); + try { + logger.debug("unGzip tempFile----" + tempFile.getAbsolutePath()); + logger.debug("unGzip srcFile---" + srcFile); + logger.debug("unGzip destDir---" + destDir); + gis = new GZIPInputStream(new FileInputStream(new File(srcFile))); + + if(!tempFile.getParentFile().exists()){ + tempFile.getParentFile().mkdirs(); + } + out = new FileOutputStream(tempFile); + logger.debug("unGzip tempFile---------" + tempFile.getAbsolutePath()); + byte[] buf = new byte[1024 * 2]; + int len = 0; + while ((len = gis.read(buf)) != -1) { + logger.debug("unGzip len---------" + len); + out.write(buf, 0, len); + } + out.flush(); + + //tar包解归档 + GzipUtil.unTar(tempFile.getAbsolutePath(), destDir); + + logger.debug("unGzip end……"); + } catch (Exception e) { + throw e; + } finally { + try { + if(gis!=null) gis.close(); + if(out!=null) out.close(); + } catch (Exception e) { + e.printStackTrace(); + } + logger.debug("tempFile.delete() start……" + tempFile.getAbsolutePath()); + if(tempFile.exists()){ + //tempFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(tempFile); + logger.debug("unGzip delete file --" + tempFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(tempFile); + } + logger.debug("tempFile.delete() end……" + tempFile.getAbsolutePath()); + } + + } + + /** + * 将单个文件或一个目录压缩成Gzip格式 + * + * @param srcPath 需要压缩的文件目录或文件 + * @param destFile 压缩后的目标文件 + * @throws Exception + */ + public static void gzip(String srcPath, String destFile) throws Exception { + File tempFile = new File(new File(destFile).getParent() + File.separator + System.currentTimeMillis() + ".tar"); + GZIPOutputStream gzout = null; + FileInputStream tarin = null; + try{ + //tar包归档 + GzipUtil.tar(srcPath, tempFile.getAbsolutePath()); + + //建立gzip压缩输出流 + gzout = new GZIPOutputStream(new FileOutputStream(destFile)); + //打开需压缩文件作为文件输入流 + tarin = new FileInputStream(tempFile); + int len; + byte[] buf = new byte[1024 * 2]; + while ((len = tarin.read(buf)) != -1) { + gzout.write(buf, 0, len); + } + gzout.flush(); + + }catch (Exception e) { + throw e; + }finally { + if(tarin!=null) tarin.close(); + if(gzout!=null) gzout.close(); + if(tempFile.exists()){ + //tempFile.delete_bak(); + //使用删除文件公共方法 + FileUtil.delDir(tempFile); + logger.debug("GzipUtil.gzip()--delete tempFile=" + tempFile.getAbsolutePath()); + //FileUtil.checkParentDirExist(tempFile); + } + } + } + + + /** + * 对单个tar压缩包解压,即解归档 + * + * @param srcFile 需要解压的tar文件 + * @param outpath 解压后的目标路径 + * @throws Exception + */ + public static void unTar(String srcFile, String outpath) throws Exception{ + logger.debug("unTar start……"); + TarInputStream tis = null; + try { + logger.debug("unTar srcFile---" + srcFile); + logger.debug("unTar outpath---" + outpath); + File file = new File(srcFile); + if(!file.exists()){ +// throw new Exception("解压源文件不存在: " + file.getAbsolutePath()); + throw new Exception("Unzip source file does not exist: " + file.getAbsolutePath()); + } + tis = new TarInputStream(new FileInputStream(file)); + /*关键在于这个TarEntry 的理解, 实际你的tar包里有多少文件就有多少TarEntry*/ + TarEntry tarEntry = null; + while ((tarEntry = tis.getNextEntry()) != null) { + logger.debug("unTar tarEntry---" + tarEntry); + String tempFileName = (outpath + File.separator + tarEntry.getName()).replaceAll("\\\\", "/"); + logger.debug("unTar tempFileName---" + tempFileName); + if (tarEntry.isDirectory()) { + logger.debug("unTar tarEntry is Dir"); + int end = tempFileName.lastIndexOf("/"); + if (end != -1) { + File dir = new File(tempFileName.substring(0, end)); + if (!dir.exists()) { + dir.mkdirs(); + } + } + } else { + logger.debug("unTar tarEntry is file"); + File tempFile = new File(tempFileName); + if(!tempFile.getParentFile().exists()){ + tempFile.getParentFile().mkdirs(); + } + tempFile.createNewFile(); + OutputStream out = new FileOutputStream(tempFile); + IOUtils.copy(tis, out); + out.close(); + } + } + logger.debug("unTar end……"); + } catch (Exception e) { + throw e; + } finally { + try { + if(tis!=null) tis.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + } + + /** + * 将单个文件或一个目录打成tar包,即归档 + * + * @param srcDir 需要压缩的文件目录或文件 + * @param destFile 压缩后的目标文件 + * @throws Exception + */ + public static void tar(String srcDir, String destFile) throws Exception { + TarOutputStream tout = null; + try{ + //建立tar压缩输出流 + tout = new TarOutputStream(new FileOutputStream(destFile)); + File srcFile = new File(srcDir); + if (!srcFile.exists()) { +// throw new Exception("压缩目录或文件不存在: " + srcFile.getAbsolutePath()); + throw new Exception("Compressed directories or files do not exist: " + srcFile.getAbsolutePath()); + } + if(srcFile.isDirectory()){ + tar(tout,srcFile,srcFile.getName()); + }else{ + tar(tout,srcFile,""); + } + }catch (Exception e) { + throw e; + }finally { + if(tout!=null) tout.close(); + } + } + + /** + * tar压缩 + * @param out: tar压缩流 + * @param srcFile: 需要压缩的目录或文件 + * @param base: 需要压缩的文件在压缩后的tar包内的路径 + * @throws Exception + */ + public static void tar(TarOutputStream tout, File srcFile, String base) throws Exception{ + if (!srcFile.exists()) { +// throw new Exception("压缩目录或文件不存在: " + srcFile.getAbsolutePath()); + throw new Exception("Compressed directories or files do not exist: " + srcFile.getAbsolutePath()); + } + if (srcFile.isDirectory()) { + File[] files = srcFile.listFiles(); + base = base.length() == 0 ? "" : base + "/"; + if (base.length() > 0) { + TarEntry tarEn = new TarEntry(srcFile); //此处必须使用new TarEntry(File file); + tarEn.setName(base); //此处需重置名称,默认是带全路径的,否则打包后会带全路径 + tout.putNextEntry(tarEn); + } + for (int i = 0; i < files.length; i++) { + tar(tout, files[i], base + files[i].getName()); + } + } else { + base = base.length() == 0 ? srcFile.getName() : base; + TarEntry tarEn = new TarEntry(srcFile); + tarEn.setName(base); + tout.putNextEntry(tarEn); + FileInputStream fis = null; + try{ + fis = new FileInputStream(srcFile); + IOUtils.copy(fis, tout); + }catch (IOException e) { + throw e; + }finally{ + if(fis!=null) fis.close(); + } + } + tout.closeEntry(); + } + + + public static void main(String[] args) { + try { + long tt = System.currentTimeMillis(); + //tar("D:\\temp\\test", "d:\\temp\\t1.tar"); + //unTar("D:\\temp\\t1.tar", "D:\temp\\t1"); + + //gzip("D:\\temp\\t1\\gd-2.0.350000", "d:\\temp\\test\\t1.tar.gz"); + unGzip("d:\\temp\\nms.tar.gz", "D:\\temp\\t1"); + System.out.println(System.currentTimeMillis()-tt); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} + diff --git a/src/com/nis/nmsclient/util/MD5Util.java b/src/com/nis/nmsclient/util/MD5Util.java new file mode 100644 index 0000000..7d2ac4f --- /dev/null +++ b/src/com/nis/nmsclient/util/MD5Util.java @@ -0,0 +1,99 @@ +package com.nis.nmsclient.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class MD5Util { + /** + * 默认的密码字符串组合,apache校验下载的文件的正确性用的就是默认的这个组合 + */ + protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', + '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + protected static MessageDigest messagedigest = null; + static { + try { + messagedigest = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException nsaex) { + System.err.println(MD5Util.class.getName() + + "初始化失败,MessageDigest不支持MD5Util。"); + nsaex.printStackTrace(); + } + } + + public static void main(String[] args) throws IOException { + long begin = System.currentTimeMillis(); + + // 2EA3E66AC37DF7610F5BD322EC4FFE48 670M 11s kuri双核1.66G 2G内存 + File big = new File("I:/大型安装程序的压缩版本/Rational rose 2003.rar"); + + String md5 = getFileMD5String(big); + + long end = System.currentTimeMillis(); + System.out.println("md5:" + md5 + " time:" + ((end - begin) / 1000) + + "s"); + } + + /** + * 适用于上G大的文件 + * + * @param file + * @return + * @throws IOException + */ + public static String getFileMD5String(File file) throws IOException { + FileInputStream in = null; + try { + in = new FileInputStream(file); + FileChannel ch = in.getChannel(); + MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, + file.length()); + messagedigest.update(byteBuffer); + return bufferToHex(messagedigest.digest()); + } catch (Exception e) { + throw new IOException(e.getCause()); + }finally{ + if(in!=null){ + in.close(); + } + } + } + + public static String getMD5String(String s) { + return getMD5String(s.getBytes()); + } + + public static String getMD5String(byte[] bytes) { + messagedigest.update(bytes); + return bufferToHex(messagedigest.digest()); + } + + private static String bufferToHex(byte bytes[]) { + return bufferToHex(bytes, 0, bytes.length); + } + + private static String bufferToHex(byte bytes[], int m, int n) { + StringBuffer stringbuffer = new StringBuffer(2 * n); + int k = m + n; + for (int l = m; l < k; l++) { + appendHexPair(bytes[l], stringbuffer); + } + return stringbuffer.toString(); + } + + private static void appendHexPair(byte bt, StringBuffer stringbuffer) { + char c0 = hexDigits[(bt & 0xf0) >> 4]; + char c1 = hexDigits[bt & 0xf]; + stringbuffer.append(c0); + stringbuffer.append(c1); + } + + public static boolean checkPassword(String password, String md5PwdStr) { + String s = getMD5String(password); + return s.equals(md5PwdStr); + } +} diff --git a/src/com/nis/nmsclient/util/ProcessUtil.java b/src/com/nis/nmsclient/util/ProcessUtil.java new file mode 100644 index 0000000..461a8d1 --- /dev/null +++ b/src/com/nis/nmsclient/util/ProcessUtil.java @@ -0,0 +1,1341 @@ +package com.nis.nmsclient.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import org.apache.log4j.Logger; +import com.nis.nmsclient.common.Contants; + +public class ProcessUtil +{ + + static Logger logger = Logger.getLogger(ProcessUtil.class); + private static final String EXEC_CMD_FILE = Contants.LOCAL_SCRIPT_PATH + "/execCmdBySu.sh"; + private static final String CHECK_USERPASS_FILE = Contants.LOCAL_SCRIPT_PATH + + "/check_userpass.sh"; + private static Byte[] oWin = new Byte[0]; + private static Byte[] oLinux = new Byte[0]; + + /** + * 从文件读取PID值 + * + * @param pidFile + * 存放PID的文件 + * @return PID数组 + * @throws Exception + */ + public static String[] getProcessIdByFile(File pidFile) throws Exception + { + String[] pids = null; + if (pidFile.exists()) + { + String[] values = FileWrUtil.cfgFileReader(pidFile); + if (values != null && values.length > 0 && values[0].trim().length() > 0) + { + pids = values[0].trim().split(","); + } + + } + return pids; + } + + /** + * 根据PID按不同操作系统判断进程是否存在 + * + * @param pid + * @return true 存在,false 不存在 + * @throws Exception + */ + public static boolean isProcessExistByPid(String pid) throws Exception + { + boolean flag = false; + // 根据操作系统确定获取进程ID的方式 + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) + { + flag = isWinProcessExistByPid(pid.trim()); + } else if (os.startsWith("Linux")) + { + flag = isLinuxProcessExistByPid(pid.trim()); + } else + { + throw new IOException("unknown operating system: " + os); + } + + return flag; + } + + /** + * 根据PID判断Linux下进程是否存在 + * + * @param pid + * @return + */ + public static boolean isLinuxProcessExistByPid(String pid) + { + String cmd = "ps -p " + pid.trim() + " | grep " + pid.trim() + + " | grep -v defunct | awk '{print $1}'"; + String[] shellCmd1 = new String[] { "/bin/bash", "-c", cmd }; + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + boolean flag = false; + logger.info("isLinuxProcessExistByPid cmd-----" + cmd); + synchronized (oLinux) + { + try + { + // 找到根据进程名获取到的进程号列表 + process = Runtime.getRuntime().exec(shellCmd1); + process.getOutputStream().close(); + + bReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) + { + logger.debug("isLinuxProcessExistByPid line-----" + line); + flag = true; + } + while ((line = errorReader.readLine()) != null) + { + logger.debug("isLinuxProcessExistByPid error line--->" + line); + } + + } catch (IOException e) + { + logger.error(Utils.printExceptionStack(e)); + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (IOException e) + { + logger.error(Utils.printExceptionStack(e)); + } + } + + } + return flag; + } + + /** + * 根据PID判断Windows下进程是否存在 + * + * @param pid + * @return + */ + public static boolean isWinProcessExistByPid(String pid) + { + String[] cmd = new String[] { "cmd.exe", "/C", + "wmic process where processId=" + pid.trim() + " get processId" }; + logger.info("isWinProcessExistByPid cmd-----" + cmd[2]); + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + boolean flag = false; + try + { + synchronized (oWin) + { + process = Runtime.getRuntime().exec(cmd); + process.getOutputStream().close(); + bReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) + { + logger.debug("isWinProcessExistByPid line-----" + line); + if (line.trim().equals(pid.trim())) + { + flag = true; + } + } + while ((line = errorReader.readLine()) != null) + { + logger.debug("isWinProcessExistByPid error line--->" + line); + } + } + + } catch (IOException e) + { + logger.error(Utils.printExceptionStack(e)); + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (IOException e) + { + logger.error(Utils.printExceptionStack(e)); + } + } + + return flag; + } + + /** + * Linux下执行命令 + * + * @param cmd + * @return + * @throws Exception + */ + public static String execLinuxCmd(String cmd) throws Exception + { + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + try + { + // logger.debug("execLinuxCmd start-------" + cmd); + String[] shellCmd = new String[] { "/bin/bash", "-c", cmd }; + process = Runtime.getRuntime().exec(shellCmd); + process.getOutputStream().close(); + + bReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) + { + logger.debug("execLinuxCmd line--->" + line); + } + StringBuffer errorSb = new StringBuffer(); + while ((line = errorReader.readLine()) != null) + { + logger.debug("execLinuxCmd error line--->" + line); + errorSb.append(line + ","); + } + + if (errorSb.toString().length() > 0) + { + errorSb.deleteCharAt(errorSb.length() - 1); + return errorSb.toString(); + } + + // logger.debug("execLinuxCmd end-------" + cmd); + } catch (Exception e) + { + throw e; + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (Exception e1) + { + } + } + return null; + } + + /** + * windows下执行命令 + * + * @param cmd + * @return + * @throws Exception + */ + public static String execWinCmd(String cmd) throws Exception + { + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + try + { + logger.debug("execWinCmd start-------" + cmd); + //cmd = handlerWinSpace(cmd); + String[] cmdArr = new String[] { "cmd.exe", "/C", cmd }; + process = Runtime.getRuntime().exec(cmdArr); + if (cmd.endsWith(".exe")) + { + synchronized (process) + { + process.wait(1000 * 5); + } + process.getOutputStream().close(); + process.getInputStream().close(); + process.getErrorStream().close(); + } else + { + process.getOutputStream().close(); + Charset platform = Charset.forName(System.getProperty("sun.jnu.encoding")); + bReader = new BufferedReader(new InputStreamReader(process.getInputStream(), platform)); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), platform)); + String line = null; + while ((line = bReader.readLine()) != null) + { + logger.debug("execWinCmd line--->" + line); + } + StringBuffer errorSb = new StringBuffer(); + while ((line = errorReader.readLine()) != null) + { + logger.debug("execWinCmd error--->" + line); + errorSb.append(line + ","); + } + if (errorSb.length() > 0) + { + errorSb.deleteCharAt(errorSb.length() - 1); + return errorSb.toString(); + } + } + + logger.debug("execWinCmd end-------" + cmd); + + } catch (Exception e) + { + throw e; + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (Exception e1) + { + } + } + + return null; + } + + /** + * 执行文件或命令,不同的操作系统按相应方式执行 + * + * @param cmd + * 文件全路径或执行命令 + * @param cmdParams + * 执行参数 + * @param username + * 执行用户 + * @param passwd + * 执行用户的密码 + * @return 返回错误输出:若有返回,则执行失败;若返回null,则执行成功 + * @throws IOException + */ + public static String runExec(String cmd, String[] cmdParams, String username, String passwd) + throws IOException + { + return runExec(cmd, cmdParams, username, passwd, false); + } + + /** + * 执行文件或命令,不同的操作系统按相应方式执行 + * + * @param isDaemon + * 若为true, NC守护进程, 不读取输出;若为false, 执行文件或命令,读取输出 + * @return + * @throws IOException + */ + public static String runExec(String cmd, String[] cmdParams, String username, String passwd, + boolean isDaemon) throws IOException + { + // 根据操作系统确定运行方式 + String os = System.getProperty("os.name"); + Process process = null; + try + { + logger.debug("runExec start-------" + cmd); + String error = null; + if (os.startsWith("Windows")) + { + StringBuffer sb = new StringBuffer(); + if (isDaemon) + {// -- 执行NC守护进程脚本 + sb.append("start /b " + handlerWinSpace(cmd)); + if (cmdParams != null && cmdParams.length > 0) + { + // 如果执行参数为数组类型时使用 + for (String param: cmdParams) + { + // 带空格参数的特殊处理 + sb.append(" " + handlerWinSpace(param)); + } + } + sb.append(" >nul 2>&1"); + logger.info("runExec Windows-------" + sb.toString()); + String[] cmdArr = new String[] { "cmd.exe", "/C", sb.toString() }; + process = Runtime.getRuntime().exec(cmdArr); + synchronized (process) + { + process.wait(1000 * 5); + } + process.getOutputStream().close(); + process.getInputStream().close(); + process.getErrorStream().close(); + } else + { + sb.append(handlerWinSpace(cmd)); + if (cmdParams != null && cmdParams.length > 0) + { + // 如果执行参数为数组类型时使用 + for (String param: cmdParams) + { + // 带空格参数的特殊处理 + sb.append(" " + handlerWinSpace(param)); + } + } + logger.info("runExec Windows-------" + sb.toString()); + error = execWinCmd(sb.toString()); + } + } else if (os.startsWith("Linux")) + { + StringBuffer sb = new StringBuffer(); + sb.append("nohup " + cmd.trim()); + if (cmdParams != null && cmdParams.length > 0) + { + // 如果执行参数为数组类型时使用 + for (String param: cmdParams) + { + // 带空格参数的特殊处理 + sb.append(" " + handlerLinuxSpace(param)); + } + } + sb.append(" >/dev/null 2>&1 &"); + logger.info("runExec Linux-------" + sb.toString()); + if (username != null && username.trim().length() > 0) + { + // -- 有密码调用execCmdBySu.sh文件执行 + if (passwd != null && passwd.trim().length() > 0) + { + File file = new File(EXEC_CMD_FILE); + // 执行结果标识参数1、0 表示执行命令后是否添加:echo $? + String temp = file.getCanonicalPath() + " 1 \"" + sb.toString() + "\" " + + username.trim(); + logger.info("runExec-->" + temp); + temp += " " + DESUtil.desDecrypt(passwd.trim()); + sb.delete(0, sb.length()); + sb.append("nohup " + temp + " >/dev/null 2>&1 &"); + } else + { + // -- 无密码自己拼命令 + String temp = "su - -c \"" + sb.toString() + "\" " + username.trim(); + logger.info("runExec-->" + temp); + sb.delete(0, sb.length()); + sb.append(temp); + } + } + error = execLinuxCmd(sb.toString()); + } else + { + throw new IOException("unknown operating system: " + os); + } + + logger.debug("sleep: 10 seconds"); + Thread.sleep(10 * 1000); + + logger.debug("runExec end-------" + cmd); + + return error; + } catch (Exception e) + { + logger.error(Utils.printExceptionStack(e)); +// return "出现异常:" + e.getMessage(); + return "Abnormality:" + e.getMessage(); + } finally + { + try + { + if (process != null) + { + process.destroy(); + } + } catch (Exception e1) + { + } + } + + } + + /** + * 赋权限:若path是目录,给目录下所有文件赋指定的权限 + * + * @param permit + * 权限的整数值 + * @param path + * 需要赋权限的文件或目录 + */ + public static void permit(long permit, File path) + { + // 根据操作系统确定运行方式 + String os = System.getProperty("os.name"); + logger.debug("permit-----path=" + path.getAbsolutePath()); + try + { + if (os.startsWith("Linux") && path != null && path.exists()) + { + if (path.isDirectory() && path.listFiles().length > 0) + { + execLinuxCmd("chmod " + permit + " " + + handlerLinuxSpace(path.getCanonicalPath()) + File.separator + "*"); + File[] files = path.listFiles(); + for (File file: files) + { + if (file.isDirectory()) + { + permit(permit, file); + } + } + } else + { + execLinuxCmd("chmod " + permit + " " + + handlerLinuxSpace(path.getCanonicalPath())); + } + } + } catch (Exception e) + { + logger.error(Utils.printExceptionStack(e)); + } + } + + /** + * 杀进程:根据操作系统以不同的方式停用进程 + * + * @param processId + * @throws IOException + */ + public static void killProcess(String processId) throws IOException + { + // 根据操作系统确定运行方式 + String os = System.getProperty("os.name"); + try + { + if (os.startsWith("Windows")) + { + String cmd = "wmic process where processId=" + processId + " delete"; + logger.debug("killProcess win cmd-------" + cmd); + execWinCmd(cmd); + } else if (os.startsWith("Linux")) + { + String cmd = "kill -9 " + processId; + logger.debug("killProcess linux cmd-------" + cmd); + execLinuxCmd(cmd); + } else + { + throw new IOException("unknown operating system: " + os); + } + Thread.sleep(5 * 1000); + } catch (Exception e) + { + logger.error(Utils.printExceptionStack(e)); + } + } + + /** + * 只能用来运行命令,取得运行命令的输出结果,根据错误输出流来判断命令运行成功与否 如果需切换用户,调用execCmdBySu.sh执行 + * + * @param cmd + * @param username + * @return 成功:0|命令输出信息;失败:1|失败信息 + * @throws Exception + */ + public static String runExecGetResult(String cmd, String username, String passwd) + throws Exception + { + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + String seprator = "|"; + try + { + logger.debug("runExecGetResult start-------" + cmd); + String os = System.getProperty("os.name");// 根据操作系统确定运行方式 + String result = "0" + seprator; + String[] cmdArr = null; + if (os.startsWith("Windows")) + { + // 【&& echo 0 || echo 1】 执行成功输出0,执行失败输出1,为了与Linux下的一致来取执行结果 + String tempCmd = handlerWinSpace(cmd) + " && echo 0 || echo 1"; + logger.info("runExecGetResult-->" + tempCmd); + cmdArr = new String[] { "cmd.exe", "/C", tempCmd }; + } else if (os.startsWith("Linux")) + { + String tempCmd = cmd.trim(); + if (username != null && username.trim().length() > 0) + { + // -- 有密码调用execCmdBySu.sh文件执行 + if (passwd != null && passwd.trim().length() > 0) + { + File file = new File(EXEC_CMD_FILE); + // 执行结果标识参数1、0 表示执行命令后是否添加:echo $? + tempCmd = file.getCanonicalPath() + " 0 \"" + cmd.trim() + "\" " + + username.trim(); + logger.info("runExecGetResult-->" + tempCmd); + tempCmd += " " + DESUtil.desDecrypt(passwd.trim()); + } else + { + // -- 无密码自己拼命令 + tempCmd = "su - -c \"" + cmd.trim() + ";echo $?\" " + username.trim(); + logger.info("runExecGetResult-->" + tempCmd); + } + } else + { + tempCmd += ";echo $?";// 为了与脚本中的echo $?运行命令保持一致 + logger.info("runExecGetResult-->" + tempCmd); + } + cmdArr = new String[] { "/bin/bash", "-c", tempCmd }; + } else + { + throw new IOException("unknown operating system: " + os); + } + process = Runtime.getRuntime().exec(cmdArr); + process.getOutputStream().close(); + bReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + StringBuffer sb = new StringBuffer(); + while ((line = bReader.readLine()) != null) + { + sb.append(line + ","); + logger.debug("runExecGetResult right-->" + line); + } + StringBuffer errorSb = new StringBuffer(); + while ((line = errorReader.readLine()) != null) + { + errorSb.append(line + ","); + logger.debug("runExecGetResult error-->" + line); + } + if (errorSb.length() > 0) + { + errorSb.deleteCharAt(errorSb.length() - 1); + result = "1" + seprator + errorSb.toString(); + } else if (sb.length() > 0) + { + sb.deleteCharAt(sb.length() - 1);// 去掉最后一个逗号 + int lastIndex = sb.lastIndexOf(","); + String flag = ""; + logger.debug("runExecGetResult lastIndex-->" + lastIndex); + if (lastIndex != -1) + { + // 配合运行命令(echo $?),最后一行为结果标识 + flag = sb.substring(lastIndex + 1, sb.length()).trim(); + sb.delete(lastIndex, sb.length());// 删除结果标识和其前面的逗号 + } else + { + flag = sb.toString().trim(); + sb.delete(0, sb.length()); + } + logger.debug("runExecGetResult flag-->" + flag); + // 配合运行命令(echo $?):最后一行若是0,则执行成功,若非0,则失败 + if ("0".equals(flag)) + { + result = "0" + seprator + sb.toString(); + } else + { + result = "1" + seprator + sb.toString(); + } + } + logger.debug("runExecGetResult result-->" + result); + logger.debug("runExecGetResult end-------" + cmd); + + return result; + } catch (Exception e) + { + throw e; + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (Exception e1) + { + } + } + } + + /** + * 验证用户名或用户组是否存在 + * + * @param username + * @param userGroup + * @return + * @throws Exception + */ + public static boolean checkUserOrGroupExist(String username, String userGroup) throws Exception + { + try + { + boolean flag = false; + logger.debug("checkUserOrGroupExist start-------"); + String os = System.getProperty("os.name");// 根据操作系统确定运行方式 + if (os.startsWith("Windows")) + { + flag = true; + } else if (os.startsWith("Linux")) + { + if (username == null && userGroup == null) + { + flag = true; + } else + { + StringBuffer sb = new StringBuffer(); + if (username != null) + { + sb.append("su " + username.trim() + ";"); + } + if (userGroup != null) + { + sb.append("groups " + userGroup.trim() + ";"); + } + if (execLinuxCmd(sb.toString()) == null) + {// 没有返回值,验证通过 + flag = true; + } + } + } else + { + throw new IOException("unknown operating system: " + os); + } + + logger.debug("checkUserOrGroupExist end-------"); + + return flag; + } catch (Exception e) + { + throw e; + } + + } + + /** + * 验证用户名和密码是否正确,调用check_userpass.sh脚本 + * + * @param username + * @param passwd + */ + public static boolean checkUserPass(String username, String passwd) throws Exception + { + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + try + { + boolean flag = false; + logger.debug("checkUserPass start-------"); + String os = System.getProperty("os.name");// 根据操作系统确定运行方式 + if (os.startsWith("Windows")) + { + flag = true; + } else if (os.startsWith("Linux")) + { + File file = new File(CHECK_USERPASS_FILE); + StringBuffer sb = new StringBuffer(); + sb.append(file.getCanonicalPath() + " " + Utils.getLocalIp()); + if (username != null) + { + sb.append(" " + username.trim()); + if (passwd != null) + { + sb.append(" " + DESUtil.desDecrypt(passwd.trim())); + } + } + sb.append(" >/dev/null 2>&1;"); + sb.append("echo $?"); + + String[] cmdArr = new String[] { "/bin/bash", "-c", sb.toString() }; + process = Runtime.getRuntime().exec(cmdArr); + process.getOutputStream().close(); + bReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) + { + logger.debug("checkUserPass line-------" + line); + if (line.trim().equals("0")) + { + flag = true; + } + } + while ((line = errorReader.readLine()) != null) + { + logger.debug("checkUserPass error line--->" + line); + } + } else + { + throw new IOException("unknown operating system: " + os); + } + + logger.debug("runExecGetResult end-------"); + + return flag; + } catch (Exception e) + { + throw e; + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (Exception e1) + { + } + } + } + + /** + * 检查文件或命令是否存在且可执行 + * + * @param cmd + * @return true 是,false 否 + * @throws IOException + */ + public static boolean isFileOrCmdExist(String cmd) throws IOException + { + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + boolean flag = false; + logger.debug("isFileOrCmdExist start-------" + cmd); + try + { + // 根据操作系统确定运行方式 + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) + { + logger.debug("isFileOrCmdExist Windows-------" + cmd); + // 待实现: 目前只处理了文件,执行命令未实现判断 + File startFile = new File(cmd); + if (startFile.exists() && startFile.canExecute()) + { + flag = true; + } + } else if (os.startsWith("Linux")) + { + String cmd1 = "[ -x " + cmd + " ] || which " + cmd + ";echo $?"; + logger.debug("isFileOrCmdExist linux-------" + cmd1); + String[] shellCmd = new String[] { "/bin/bash", "-c", cmd1 }; + process = Runtime.getRuntime().exec(shellCmd); + process.getOutputStream().close(); + + bReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + while ((line = bReader.readLine()) != null) + { + logger.debug("isFileOrCmdExist linux--->" + line); + if (line.trim().equals("0")) + { + flag = true; + } + } + while ((line = errorReader.readLine()) != null) + { + logger.debug("isFileOrCmdExist linux error--->" + line); + } + } else + { + throw new IOException("unknown operating system: " + os); + } + + } catch (Exception e) + { + logger.error(Utils.printExceptionStack(e)); + return false; + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (Exception e1) + { + } + } + logger.debug("isFileOrCmdExist end-------" + cmd); + + return flag; + } + + /** + * + * TODO 处理路径中带有空格 括号的问题 在外部加入"" + * + * @author jinshujuan May 30, 2013 + * @version 1.0 + * @param str + * @return + */ + public static String handlerWinPath(String str) + { + + if (str != null && !str.equals("")) + { + if (str.indexOf(" ") != -1 || str.indexOf("(") != -1 || str.indexOf(")") != -1) + { + str = "\"" + str + "\""; + } + } + logger.debug("handlerWinPath---str=" + str); + return str; + } + + /** + * 对Windows下路径中带空格的特殊处理 + * + * @param str + * @return + */ + public static String handlerWinSpace(String str) + { + /* + * 注意::若最后一级路径出现空格,处理上的存在Bug -- 需要在最后一级也加上\\或/ 如:xcopy /y D:\\Program + * Files\\Test 1\\ D:\\Program Files\\Test 2\\ /s/e 可以正常替换空格 xcopy /y + * D:\\Program Files\\Test 1 D:\\Program Files\\Test 2 /s/e + * 不能正常替换空格,最后一级Test 1和Test 2中的空格替换不了。 + */ + if (str != null) + { + if (str.indexOf(":\\") != -1) + { + // 针对这样的命令, 如: + // D:\Program Files\Test\test.bat >> D:\Program Files\test.log; + // xcopy /y D:\Program Files\Test D:\Program Files\Test2 /s/e + // 先取第一个:\之后,每次再取与\之间的串循环替换空格 + // 若与\之间的串中有:\(/test.bat >> D:/, /Test D:/)则不用替换空格 + int index = str.indexOf(":\\"); + String start = str.substring(0, index + 2); + String end = str.substring(index + 2, str.length()); + while (end.indexOf("\\") != -1) + { + index = end.indexOf("\\"); + String middle = end.substring(0, index + 1); + if (middle.endsWith(":\\")) + { + start += middle; + } else + { + start += middle.replace(" ", "\" \""); + } + end = end.substring(index + 1, end.length()); + } + start += end; + str = start; + } else if (str.indexOf(":/") != -1) + { + // 针对这样的命令, 如: + // D:/Program Files/Test/test.bat >> D:/Program Files/test.log; + // xcopy /y D:/Program Files/Test D:/Program Files/Test2 /s/e + // 先取第一个:/之后,每次再取与/之间的串循环替换空格 + // 若与/之间的串中有:/(/test.bat >> D:/, /Test D:/)或 /(/Test2 /)则不用替换空格 + int index = str.indexOf(":/"); + String start = str.substring(0, index + 2); + String end = str.substring(index + 2, str.length()); + while (end.indexOf("/") != -1) + { + index = end.indexOf("/"); + String middle = end.substring(0, index + 1); + if (middle.endsWith(":/") || middle.endsWith(" /")) + { + start += middle; + } else + { + start += middle.replace(" ", "\" \""); + } + end = end.substring(index + 1, end.length()); + } + start += end; + str = start; + } + } + logger.debug("handlerWinSpace---str=" + str); + return str; + } + + /** + * 对Linux下路径中带空格的特殊处理 + * + * @param str + * @return + */ + public static String handlerLinuxSpace(String str) + { + if (str != null) + { + str = str.trim().replace(" ", "\\ "); + } + return str; + } + + /** + * 根据关键字查找进程PID + * + * @param procSearchKey + * @return pid列表 + * @throws Exception + */ + public static List<String> getProcessIdBySearchKey(String procSearchKey) throws Exception + { + List<String> value = null; + // 根据操作系统确定获取进程ID的方式 + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) + { + value = getWindowsProcessId(procSearchKey); + } else if (os.startsWith("Linux")) + { + value = getLinuxProcessId(procSearchKey); + } else + { + throw new IOException("unknown operating system: " + os); + } + + return value; + } + + /** + * Windows下根据关键字查找进程,关键字不区分大小写 + * + * @param procSearchKey + * @return + */ + public static List<String> getWindowsProcessId(String procSearchKey) + { + // "wmic process get + // Caption,commandLine,Description,ExecutablePath,Name,processId|findstr + // /i " + procSearchKey + "|findstr /v findstr" + String[] cmd = new String[] { + "cmd.exe", + "/C", + "wmic process where \"Caption like '%%" + procSearchKey + + "%%' or CommandLine like '%%" + procSearchKey + + "%%' or Description like '%%" + procSearchKey + + "%%' or ExecutablePath like '%%" + procSearchKey + "%%' or Name like '%%" + + procSearchKey + + "%%'\" get Name,ProcessId,CommandLine|findstr /v wmic|findstr /v findstr" }; + logger.info("getWindowsProcessId-----" + cmd[2]); + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + List<String> processIDList = null; + try + { + synchronized (oWin) + { + process = Runtime.getRuntime().exec(cmd); + process.getOutputStream().close(); + bReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + processIDList = new ArrayList<String>(); + while ((line = bReader.readLine()) != null) + { + logger.debug("getWindowsProcessId ---- line >> " + line); + String[] tmp = line.split("\\s{2,}"); + if (tmp == null) + { + continue; + } + for (int i = 0; i < tmp.length; i++) + { + if (tmp[i].matches("\\d+")) + { + processIDList.add(tmp[i]); + } + } + } + while ((line = errorReader.readLine()) != null) + { + logger.debug("getWindowsProcessId error line--->" + line); + } + } + + } catch (IOException e) + { + logger.error(Utils.printExceptionStack(e)); + return null; + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (IOException e) + { + logger.error(Utils.printExceptionStack(e)); + } + } + + return processIDList; + } + + /** + * Linux下根据关键字查找进程,关键字不区分大小写 + * + * @param procSearchKey + * @return + */ + public static List<String> getLinuxProcessId(String procSearchKey) + { + String cmd = "ps -ef | grep -i '" + procSearchKey.trim() + + "' | grep -v grep | awk '{print $2}'"; + logger.info("getLinuxProcessId-----" + cmd); + String[] shellCmd1 = new String[] { "/bin/bash", "-c", cmd }; + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + List<String> processIDList = null; + synchronized (oLinux) + { + try + { + // 找到根据进程名获取到的进程号列表 + process = Runtime.getRuntime().exec(shellCmd1); + process.getOutputStream().close(); + + bReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + processIDList = new ArrayList<String>(); + while ((line = bReader.readLine()) != null) + { + processIDList.add(line); + logger.debug("getLinuxProcessId ---- line >> " + line); + } + while ((line = errorReader.readLine()) != null) + { + logger.debug("getLinuxProcessId error line--->" + line); + } + } catch (IOException e) + { + logger.error(Utils.printExceptionStack(e)); + } finally + { + try + { + if (bReader != null) + { + bReader.close(); + } + if (errorReader != null) + { + errorReader.close(); + } + if (process != null) + { + process.destroy(); + } + } catch (IOException e) + { + logger.error(Utils.printExceptionStack(e)); + } + } + + } + return processIDList; + } + + /** + * 检查PID是否存在,存在返回PID,不存在返回描述信息 + * 检查逻辑:先检查PID文件,取出PID,验证PID指定进程是否存在,不存在再使用搜索关键字查找进程 isExistFlag: 0 进程不存在,1 + * 进程存在且仅找到一个,2 进程存在且找到多个 + * + * @return 数组:{进程是否存在的标识(0|1|2), 进程PID或者描述信息} + */ + public static Object[] checkPidAndGetPid(String pidFile, String procSearchKey) throws Exception + { + int isExistFlag = 0; + String pidInfo = ""; + if (pidFile != null && !"".equals(pidFile)) + { + File file = new File(pidFile); + if (file.exists()) + { + String[] pidArr = ProcessUtil.getProcessIdByFile(file); + if (pidArr != null && pidArr.length > 0) + {// 目前考虑只有一个PID的情况 + boolean isExist = ProcessUtil.isProcessExistByPid(pidArr[0]); + if (isExist) + { + pidInfo = pidArr[0]; + isExistFlag = 1; + } else + { +// pidInfo = "进程PID\"" + pidArr[0] + "\"不存在"; + pidInfo = "i18n_client.ProcessUtil.processPid_n81i\"" + pidArr[0] + "\"i18n_client.ProcessUtil.notExists_n81i"; + } + } + } else + { +// pidInfo = "PID文件\"" + file.getAbsolutePath() + "\"不存在"; + pidInfo = "i18n_client.ProcessUtil.pidFile_n81i\"" + file.getAbsolutePath() + "\"i18n_client.ProcessUtil.notExists_n81i"; + } + } else + { +// pidInfo = "PID文件字段为空"; + pidInfo = "i18n_client.ProcessUtil.pidFieldNull_n81i"; + } + + if (isExistFlag == 0 && procSearchKey != null && !"".equals(procSearchKey)) + { + // PID文件或PID文件中的PID不存在,则使用进程搜索关键字查找PID + List<String> pidList = ProcessUtil.getProcessIdBySearchKey(procSearchKey); + if (pidList == null || pidList.size() == 0) + { +// pidInfo += (pidInfo.length() > 0 ? ", " : "") + "进程搜索关键字" + procSearchKey + "未找到进程"; + pidInfo += (pidInfo.length() > 0 ? ", " : "") + "i18n_client.ProcessUtil.searchKey_n81i" + procSearchKey + "i18n_client.ProcessUtil.noProcess_n81i"; + } else if (pidList.size() > 1) + { + pidInfo += (pidInfo.length() > 0 ? ", " : "") + "i18n_client.ProcessUtil.searchKey_n81i" + procSearchKey + + " i18n_client.ProcessUtil.findTooMuch_n81i"; + isExistFlag = 2; + } else + {// 只找到一个进程 + pidInfo = pidList.get(0); + isExistFlag = 1; + } + } + + return new Object[] { isExistFlag, pidInfo }; + } + + /* + * public static String getProcessId(String processName, String processPath) + * throws Exception{ String value = null; //根据操作系统确定获取进程ID的方式 String os = + * System.getProperty("os.name"); if (os.startsWith("Windows")) { value = + * getWindowsProcessId(processName, processPath); }else if + * (os.startsWith("Linux")){ value = getLinuxProcessId(processName, + * processPath); } else { throw new IOException("unknown operating system: " + + * os); } + * + * return value; } + * + * public static String getWindowsProcessId(String procName, String + * procPath) { String[] cmd = new String[] { "cmd.exe", "/C", "wmic process + * where \"name='" + procName.trim() + "' and executablepath='" + + * procPath.trim().replace("\\", "\\\\") + "'\" get processid" };// list + * full logger.debug("cmd-----"+cmd[2]); BufferedReader bReader = null; + * Process process = null; String processId = null; try { synchronized + * (oWin) { process = Runtime.getRuntime().exec(cmd); + * process.getOutputStream().close(); bReader = new BufferedReader(new + * InputStreamReader(process .getInputStream())); String line = null; while + * ((line = bReader.readLine()) != null) { logger.debug("line-----" + line); + * if (line.trim().matches("\\d+")) { processId = line.trim(); } } } } catch + * (IOException e) { logger.error(Utils.printExceptionStack(e)); return + * processId; }finally{ try { if (bReader != null) { bReader.close(); } if + * (process != null) { process.destroy(); } } catch (IOException e) { + * logger.error(Utils.printExceptionStack(e)); } } + * + * return processId; } + * + * public static String getLinuxProcessId(String procName, String procPath) { + * String cmd = "ps -ef | grep '" + procName.trim() + "' | grep -v grep | + * awk '{print $2}'"; String[] shellCmd1 = new String[] { "/bin/bash", "-c", + * cmd }; String[] shellCmd2 = new String[] { "/bin/bash", "-c", cmd }; + * BufferedReader bReader = null; List<String> processIDList = null; + * Process process = null; synchronized (oLinux) { try { // 找到根据进程名获取到的进程号列表 + * process = Runtime.getRuntime().exec(shellCmd1); + * process.getOutputStream().close(); + * + * bReader = new BufferedReader(new InputStreamReader(process + * .getInputStream())); String line = null; processIDList = new ArrayList<String>(); + * while ((line = bReader.readLine()) != null) { processIDList.add(line); } } + * catch (IOException e) { logger.error(Utils.printExceptionStack(e)); } + * finally { try { if (bReader != null) { bReader.close(); } if (process != + * null) { process.destroy(); } } catch (IOException e) { + * logger.error(Utils.printExceptionStack(e)); } } + * + * for (int i = 0; i < processIDList.size(); i++) { shellCmd2 = new String[] { + * "/bin/bash", "-c", "lsof -p " + processIDList.get(i) + " | grep 'txt' + * |grep -v grep | awk '{print $NF}'" }; try { process = + * Runtime.getRuntime().exec(shellCmd2); process.getOutputStream().close(); + * bReader = new BufferedReader(new InputStreamReader(process + * .getInputStream())); String line = null; while ((line = + * bReader.readLine()) != null) { if (line.trim().equals(procPath.trim())) + * return processIDList.get(i); } } catch (IOException e) { + * logger.error(Utils.printExceptionStack(e)); } finally { try { if (bReader != + * null) { bReader.close(); } if (process != null) { process.destroy(); } } + * catch (IOException e) { logger.error(Utils.printExceptionStack(e)); } } + * }//for end } return null; } + */ + +} diff --git a/src/com/nis/nmsclient/util/RarUtil.java b/src/com/nis/nmsclient/util/RarUtil.java new file mode 100644 index 0000000..d394411 --- /dev/null +++ b/src/com/nis/nmsclient/util/RarUtil.java @@ -0,0 +1,125 @@ +package com.nis.nmsclient.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; + +import de.innosystec.unrar.Archive; +import de.innosystec.unrar.rarfile.FileHeader; + +/** + * 对rar进行解压缩 + * + */ +public class RarUtil { + static Logger logger = Logger.getLogger(RarUtil.class); + /** + * 对单个rar压缩包解压 + * @param rarFileName 需要解压的rar文件 + * @param destDir 解压后的目标目录 + * @throws Exception + */ + public static void unRar(String rarFileName, String destDir) + throws Exception { + logger.debug("unRar start……"); + Archive archive = null; + FileHeader fh = null; + try { + logger.debug("unRar rarFileName---" + rarFileName); + logger.debug("unRar destDir---" + destDir); + File file = new File(rarFileName); + if(!file.exists()){ +// throw new Exception("解压源文件不存在: " + file.getAbsolutePath()); + throw new Exception("Unzip source file does not exist: " + file.getAbsolutePath()); + } + logger.debug("unRar: get archive……"); + archive = new Archive(file); + logger.debug("unRar: archive =" + archive); + if (archive != null) { + logger.debug("unRar: while start"); + int index = 0; + while ((fh = archive.nextFileHeader()) != null) { + logger.debug("unRar: " + ++index + " start"); + String fileName = fh.getFileNameW().trim(); + if (!existZH(fileName)) { + fileName = fh.getFileNameString().trim(); + } + String path = (destDir + File.separator + fileName) + .replaceAll("\\\\", "/"); + + logger.debug("unRar: path---" + path); + if (fh.isDirectory()) { + //logger.debug("unRar: FileHeader is directory"); + int end = path.lastIndexOf("/"); + if (end != -1) { + File dir = new File(path.substring(0, end)); + if (!dir.exists()) { + dir.mkdirs(); + } + } + }else{ + //logger.debug("unRar: FileHeader is file"); + FileOutputStream os = null; + try{ + File out = new File(path); + if(!out.getParentFile().exists()){ + out.getParentFile().mkdirs(); + } + os = new FileOutputStream(out); + archive.extractFile(fh, os); + }catch (Exception e) { + throw e; + }finally{ + fh = null; + if (os != null) { + os.close(); + os = null; + } + } + } + logger.debug("unRar: " + index + " end"); + } + logger.debug("unRar: while end"); + } + logger.debug("unRar end……"); + } catch (Exception e) { + throw e; + } finally { + fh = null; + try { + if (archive != null) { + archive.close(); + archive = null; + } + } catch (IOException e) { + e.printStackTrace(); + } + + } + + } + + public static boolean existZH(String str) { + String regEx = "[\\u4e00-\\u9fa5]"; + Pattern p = Pattern.compile(regEx); + Matcher m = p.matcher(str); + while (m.find()) { + return true; + } + return false; + } + + public static void main(String[] args) { + try { + unRar("D:\\temp\\logs.rar", "D:\\temp\\log"); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/com/nis/nmsclient/util/StringUtil.java b/src/com/nis/nmsclient/util/StringUtil.java new file mode 100644 index 0000000..cf0b551 --- /dev/null +++ b/src/com/nis/nmsclient/util/StringUtil.java @@ -0,0 +1,528 @@ +/* + * @(#)StringUtil.java 1.0 + * + * Copyright 2010 NIS, Inc. All rights reserved. + * + */ +package com.nis.nmsclient.util; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.util.Collection; +import java.util.Map; +import java.util.UUID; + +import sun.misc.BASE64Encoder; + + +/** +* +* <p>字符串处理工具类.</p> +* @author 中科智源育成信息有限公司 E-mail: [email protected] +* @version 1.0 创建时间:Nov 2, 2010 2:57:56 PM +* +*/ +public final class StringUtil { + /** + * ISO8859_1 编码集 + */ + public static final String CODE_ISO8859_1 = "ISO8859_1"; + /** + * GB2312 编码集 + */ + public static final String CODE_GB2312 = "GB2312"; + /** + * GBK 编码集 + */ + public static final String CODE_GBK = "GBK"; + /** + * UTF-8 编码集 + */ + public static final String CODE_UTF_8 = "UTF-8"; + + private static int size = 0; + + private static final String[] SIMPLIFIED_CASE = { "O", "一", "二", "三", "四", "五", + "六", "七", "八", "九", "十" }; +// private static final String[] SIMPLIFIED_CASE = { "Zero", "One", "Two", "Three", "Four", "Five", +// "Six", "Seven", "Eight", "Nine", "Ten" }; + + private static final String[] TRADITIONAL_CASE = { "零", "壹", "贰", "叁", "肆", "伍", + "陆", "柒", "捌", "玖", "拾" }; +// private static final String[] TRADITIONAL_CASE = { "Zero", "One", "Two", "Three", "Four", "Five", +// "Six", "Seven", "Eight", "Nine", "Ten" }; + + /** + *<p>Description:抑制默认的构造器,避免实例化对象 </p> + */ + private StringUtil() { + + } + + /** + * + * <p>判断一个对象是否为空</p> + * <p> + * <code>object</code>元素判断所有对象是否为空. + * 另外对{@link String}、{@link Collection} 、{@link Map} 进行长度验证,如果长度为0,视为空对象. + * </p> + * <pre> + * String aa = " "; + * List list = new ArrayList() + * LinkedHashSet set = new LinkedHashSet(); + * StringUtil.isEmpty(aa) = true + * StringUtil.isEmpty(list) = true + * StringUtil.isEmpty(set) = true + * StringUtil.isEmpty("\t") = true + * </pre> + * @param object 对象元素 + * @return <code>true</code> 对象为<code>null</code>,<code>false</code> 对象不为<code>null</code>. + */ + public static boolean isEmpty(Object object) { + initSize(object); + return size==0; + + } + + + /** + * + * 判断对象是否有数据存在? 不存在为0、存在不为0的值. + * @param object 对象值 + */ + private static void initSize(Object object){ + + if (object == null) { + size = 0; + } else { + if (object instanceof String) { + size = ((String)object).trim().length(); + } else if (object instanceof Collection) { + size = ((Collection)object).size(); + } else if (object instanceof Map) { + size = ((Map)object).size(); + //其他数据类型 + } else { + size = 1; + } + + } + + } + + /** + * + * <p>如果对象为空时,返回默认值.</p> + * @param object 要判断是否为空的对象 + * @param defaultValue 为空时设的默认值 + * @see #isEmpty(Object) + * @return 获取处理后的数据 + */ + public static Object setDefaultValueIfNull(Object object,Object defaultValue){ + if(isEmpty(object)){ + return defaultValue; + } + return object; + } + + /** + * + * <p>对字符串进行MD5加密.</p> + * <p> + * 一般作为密码的处理方式,首先通过MD5进行加密,然后将字符串进行Base64编码获得所需字符. + * </p> + * <pre> + * String str = "ceshi"; + * StringUtil.md5(str) = "zBfDDNERxyFfyPUfh5Dg4Q==" + * </pre> + * @param msg 要加密的字符串 + * @return 返回加密后的25位字符,如果解析出现异常将返回<code>null</code>. + */ + public static String md5(String msg) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] b = md.digest(msg.getBytes()); + BASE64Encoder encoder = new BASE64Encoder(); + String code = encoder.encode(b); + return code; + } catch (Exception e) { + return null; + } + + } + + /** + * <p>截取处理字符串,当字符串超过指定的截取长度时,用“......”补充</p> + * <pre> + * String str = "中华人民共和国"; + * StringUtil.getMoreString(str, 6) = "中华人民共和......" + * </pre> + * @param text 字符串数据 + * @param length 截取的长度值 + * @return 返回处理后字符 + */ + public static String getMoreString(String text,int length){ + StringBuilder textBuilder = new StringBuilder(); + + if(isEmpty(text)){ + return null; + } + if(text.length()>length){ + text = text.substring(0,length); + textBuilder.append(text).append("......"); + }else { + textBuilder.append(text); + } + + + return textBuilder.toString(); + } + + + /** + * + * <p>通过给定url获取域名地址.</p> + * <p> + * 获得域名信息需去除 http/https/ftp 与 www 一些头信息,获取有效地址. + * </p> + * <pre> + * StringUtil.getDomain("http://www.baidu.com") = "baidu.com" + * </pre> + * @param webSiteUrl url 地址 + * @return 返回截取后的域名地址 + */ + public static String getDomain(String webSiteUrl) { + String url = ""; + + if(isEmpty(webSiteUrl)){ + return url; + } + + + if (webSiteUrl.indexOf("http://") >= 0) { + url = webSiteUrl.substring("http://".length(), webSiteUrl.length()); + } else if (webSiteUrl.indexOf("https://", 0) >= 0) { + url = webSiteUrl.substring("https://".length(), webSiteUrl.length()); + } else if (webSiteUrl.indexOf("ftp://", 0) >= 0) { + url = webSiteUrl.substring("ftp://".length(), webSiteUrl.length()); + } else { + url = webSiteUrl; + } + + if (url.indexOf("/", 0) >= 0) { + url = url.substring(0, url.indexOf("/", 1)); + } + if (url.indexOf("www.") == 0) { + url = url.substring(url.indexOf(".") + 1, url.length()); + } + if (url.indexOf("?") >= 0) { + url = url.substring(0, url.indexOf("?")); + } + + return url; + } + + /** + * + * <p>按照给定规则分隔字符串</p> + * <pre>例子说明:</pre> + * @param str 需要分隔的字符串 + * @param regex 分隔规则 + * @return 返回字符串数组,如果分隔字符串为空返回<code>null</code>. + */ + public static String[] Split(String str,String regex) { + + if(StringUtil.isEmpty(str)){ + return null; + } + + return str.split(regex); + + } + + /** + * + * <p>字符编码转换,需要提供字符串的源编码格式.</p> + * <p> + * 字符串工具类中提供一些字符编码常量: + * {@link #CODE_GB2312}\{@link #CODE_GBK}\{@link #CODE_ISO8859_1}\{@link #CODE_UTF_8} + * </p> + * @param value 要编码的值 + * @param sourceCodingFormat 字符的原始编码格式,具体编码格式可看本类提供的编码样式. + * @param destCodingFormat 要转换字符的编码格式,具体编码格式可看本类提供的编码样式. + * @return 返回编码后的字符串. + * @throws UnsupportedEncodingException + */ + public static String getCodingConversionResult(String value,String sourceCodingFormat, + String destCodingFormat ) throws UnsupportedEncodingException{ + + if(isEmpty(value)){ + return null; + } + + + return new String(value.getBytes(sourceCodingFormat), destCodingFormat); + } + + /** + * + * <p>将url转为utf编码格式url,当url符合utf8格式,不会转换.</p> + * <pre> + * StringUtil.getUTF8URLEncode("http://www.baidu.com/s?param='中国'") = + * "http%3A%2F%2Fwww.baidu.com%2Fs%3Fparam%3D%27%E4%B8%AD%E5%9B%BD%27" + * </pre> + * @see #getUTF8URLDecode(String) + * @param url 字符串url + * @return 返回utf8转换后的字符url + * @throws UnsupportedEncodingException + */ + public static String getUTF8URLEncode(String url)throws UnsupportedEncodingException{ + if(isUtf8Url(url)){ + return url; + } + + return URLEncoder.encode(url, StringUtil.CODE_UTF_8); + + } + + /** + * + * <p>将utf8编码的url解析为原始url.当url不符合utf8格式时,不转换.</p> + * <pre>例子说明:</pre> + * @see #getUTF8URLEncode(String) + * @param url 字符串url + * @return 返回解析后字符url + * @throws UnsupportedEncodingException + */ + + public static String getUTF8URLDecode(String url)throws UnsupportedEncodingException{ + + /*if(!isUtf8Url(url)){ + return url; + }*/ + + return URLDecoder.decode(url, StringUtil.CODE_UTF_8); + + } + + + /** * 编码是否有效 + * @param text + * @return + */ + private static boolean Utf8codeCheck(String text){ + String sign = ""; + if (text.startsWith("%e")){ + + for (int i = 0, p = 0; p != -1; i++) { + p = text.indexOf("%", p); + + if (p != -1){ + p++; + } + sign += p; + } + } + + return sign.equals("147-1"); + } + + /** + * 是否Utf8Url编码 + * @param text + * @return true or false + */ + private static boolean isUtf8Url(String text) { + text = text.toLowerCase(); + int p = text.indexOf("%"); + + if (p != -1 && text.length() - p > 9) { + text = text.substring(p, p + 9); + } + + return Utf8codeCheck(text); + } + + + /** + * + * <p>判断字符串是否是数字格式(包括小数形式).</p> + * <pre> + * String a1 = "12"; + * String a2 = "0.01"; + * String a3 = "0.0.1"; + * String a4 = "123a"; + * StringUtil.isNumeric(a1) = true + * StringUtil.isNumeric(a2) = true + * StringUtil.isNumeric(a3) = false + * StringUtil.isNumeric(a4) = false + * </pre> + * @param numberString 数字格式字符串 + * @return <code>true</code> 符合数字格式(包括小数),<code>false</code> 不符合数字格式. + */ + public static boolean isNumeric(String numberString){ + + if(isEmpty(numberString)){ + return false; + } + + if(numberString.startsWith(".")||numberString.endsWith(".")){ + return false; + } + + int length = numberString.split("\\.").length-1; //判断小数点在字符串中出现的次数。 + + + if(length>1) { //小数点大于1次,不符合数字规范 + + return false; + } + + + for(int i=0; i<numberString.length(); i++){ + if(!Character.isDigit(numberString.charAt(i))&&!".".equals(String.valueOf(numberString.charAt(i)))){ + return false; + } + } + + return true; + } + + /** + * + * <p>将字符串数字转换为简体大写中文格式.</p> + * <pre> + * StringUtil.convertSimplifiedCase("325") = ”三二五" + * </pre> + * @param numberString 数字字符串 + * @return 返回简体大写后的数字 + */ + public static String convertSimplifiedCase(String numberString) { + + StringBuilder simplifiedBuilder = new StringBuilder(); + + if(isEmpty(numberString)){ + return null; + } + + + for (int i = 0; i < numberString.length(); i++) { + String tempNumberString = String.valueOf(numberString.charAt(i)); + if ("0123456789".indexOf(tempNumberString) >= 0) { + int number = Integer.parseInt(tempNumberString); + simplifiedBuilder.append(SIMPLIFIED_CASE[number]); + } else { + simplifiedBuilder.append(tempNumberString); + } + } + + return simplifiedBuilder.toString(); + } + + + /** + * + * <p>把字符串中的数字转换成繁体大写中文的格式.</p> + * <pre> + * StringUtil.convertTraditionalCase("325") = "叁贰伍" + * </pre> + * @param numberString 数字字符串 + * @return 返回繁体大写后的数字 + */ + public static String convertTraditionalCase(String numberString) { + + StringBuilder simplifiedBuilder = new StringBuilder(); + + if(isEmpty(numberString)){ + return null; + } + + + for (int i = 0; i < numberString.length(); i++) { + String tempNumberString = String.valueOf(numberString.charAt(i)); + if ("0123456789".indexOf(tempNumberString) >= 0) { + int number = Integer.parseInt(tempNumberString); + simplifiedBuilder.append(TRADITIONAL_CASE[number]); + } else { + simplifiedBuilder.append(tempNumberString); + } + } + + return simplifiedBuilder.toString(); + } + + /** + * + * <p>创建唯一标识字符串.</p> + * <pre> + * StringUtil.createUUID() = "00000DAF3CFC4E0B8DF2D5BEACB14D75" + * </pre> + * @return 返回标识符字符串 + */ + public static String createUUID() { + String uuid = UUID.randomUUID().toString(); + uuid = uuid.replace("-", ""); + return uuid.toUpperCase(); + } + + + /** + * + * <p>字符串过滤,负责将html的textarea属性获得的字符转换成html格式的字符集.</p> + * @param str 要解析的字符串 + * @return 是解析后的字符串 + */ + public static String htmlFilter(String str) { + StringBuffer stringbuffer = new StringBuffer(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + switch (c) { + + case 39: + stringbuffer.append("'"); + break; + + case 34: + stringbuffer.append("""); + break; + + case 60: + stringbuffer.append("<"); + break; + + case 62: + stringbuffer.append(">"); + break; + + case 38: + stringbuffer.append("&"); + break; + + case 32: + stringbuffer.append(" "); + break; + + case 10: + stringbuffer.append("<br>"); + break; + + case 8220: + stringbuffer.append("“"); + break; + + case 8221: + stringbuffer.append("”"); + break; + + default: + stringbuffer.append(c); + break; + } + } + + return stringbuffer.toString(); + } + +} diff --git a/src/com/nis/nmsclient/util/Utils.java b/src/com/nis/nmsclient/util/Utils.java new file mode 100644 index 0000000..97d5497 --- /dev/null +++ b/src/com/nis/nmsclient/util/Utils.java @@ -0,0 +1,323 @@ +package com.nis.nmsclient.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Enumeration; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +public class Utils { + static Logger logger = Logger.getLogger(Utils.class); + + /** + * 获得本机IP + * + * @return + */ + public static String getLocalIp() { + String nativeip = ""; + try { + //根据操作系统确定获取进程ID的方式 + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + InetAddress ipv4 = InetAddress.getLocalHost(); + nativeip = ipv4.getHostAddress().toString(); + logger.debug("------getLocalIp--nativeip=" + nativeip); + }else if (os.startsWith("Linux")){ + InetAddress ip = null; + boolean findIp = false; + // 根据网卡取本机配置的IP + Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces(); + while (netInterfaces.hasMoreElements()) { + if (findIp) { + break; + } + NetworkInterface ni = netInterfaces.nextElement(); + logger.debug("------getLocalIp--NetWorkName=" + ni.getName()); + Enumeration<InetAddress> ips = ni.getInetAddresses(); + while (ips.hasMoreElements()) + ip = ips.nextElement(); + logger.debug("------getLocalIp--ip.isSiteLocalAddress()=" + + ip.isSiteLocalAddress()); + logger.debug("------getLocalIp--ip.isLoopbackAddress()=" + + ip.isLoopbackAddress()); + logger.debug("------getLocalIp--HostAddress=" + + ip.getHostAddress()); + if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() + && ip.getHostAddress().indexOf(":") == -1) { + findIp = true; + logger.debug("------findIp--" + ip.getHostAddress()); + break; + } + } + if (ip != null) { + nativeip = ip.getHostAddress(); + } + } else { + throw new IOException("unknown operating system: " + os); + } + + } catch (Exception e) { + logger.error(Utils.printExceptionStack(e)); + } + + return nativeip; + } + + public static String getOperateSystem() { + BufferedReader bReader = null; + BufferedReader errorReader = null; + Process process = null; + try { + String os = System.getProperty("os.name");//根据操作系统确定运行方式 + String[] cmdArr = null; + if (os.startsWith("Windows")) { + cmdArr = new String[] { "cmd.exe", "/C", "ver"}; + } else if (os.startsWith("Linux")) { + cmdArr = new String[] { "/bin/bash", "-c", "uname -r;uname -i;lsb_release -d| cut -d: -f2| cut -f2" }; + } else { + throw new IOException("unknown operating system: " + os); + } + process = Runtime.getRuntime().exec(cmdArr); + process.getOutputStream().close(); + bReader = new BufferedReader(new InputStreamReader(process + .getInputStream())); + errorReader = new BufferedReader(new InputStreamReader(process + .getErrorStream())); + String line = null; + StringBuffer sb = new StringBuffer(); + while ((line = bReader.readLine()) != null) { + if(line.trim().length()>0){ + sb.append(line.trim() + ","); + logger.debug("getOperateSystem right-->" + line); + } + } + while ((line = errorReader.readLine()) != null) { + logger.debug("getOperateSystem error-->" + line); + } + if(sb.length() > 0) { + if (os.startsWith("Windows")) { + String osInfo = System.getProperty("sun.arch.data.model");//32位 or 64 位 + sb.append(osInfo+"i18n_client.Utils.bit_n81i"); + }else { + sb.deleteCharAt(sb.length()-1);//去掉最后一个逗号 + } + } + + + return sb.toString(); + } catch (Exception e) { + logger.error("Get the exception of the operating system and the release version", e); + } finally { + try { + if (bReader != null) { + bReader.close(); + } + if (errorReader != null) { + errorReader.close(); + } + if (process != null) { + process.destroy(); + } + } catch (Exception e1) { + } + } + + return null; + } + + public static boolean checkIP(String checkStr) { + try { + String number = checkStr.substring(0, checkStr.indexOf('.')); + if (Integer.parseInt(number) > 255 || Integer.parseInt(number) < 0) { + return false; + } + checkStr = checkStr.substring(checkStr.indexOf('.') + 1); + number = checkStr.substring(0, checkStr.indexOf('.')); + if (Integer.parseInt(number) > 255 || Integer.parseInt(number) < 0) { + return false; + } + + checkStr = checkStr.substring(checkStr.indexOf('.') + 1); + number = checkStr.substring(0, checkStr.indexOf('.')); + if (Integer.parseInt(number) > 255 || Integer.parseInt(number) < 0) { + return false; + } + number = checkStr.substring(checkStr.indexOf('.') + 1); + if (Integer.parseInt(number) > 255 || Integer.parseInt(number) < 0) { + return false; + } else { + return true; + } + } catch (Exception e) { + return false; + } + } + + //测试IP地址是否合法 + public static boolean isIp(String ipAddress){ +// String test = "([1-9]|[1-9]\\d|1\\d{2}|2[0-1]\\d|22[0-3])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"; +// Pattern pattern = Pattern.compile(test); +// Matcher matcher = pattern.matcher(ipAddress); +// return matcher.matches(); + String regex0 = "(2[0-4]\\d)" + "|(25[0-5])"; + String regex1 = "1\\d{2}"; + String regex2 = "[1-9]\\d"; + String regex3 = "\\d"; + String regex = "(" + regex0 + ")|(" + regex1 + ")|(" + regex2 + ")|(" + regex3 + ")"; + regex = "(" + regex + ").(" + regex + ").(" + regex + ").(" + regex + ")"; + String[] str = ipAddress.split("\\.");//根据@拆分IP地址 + if (!Pattern.matches(regex, ipAddress)) + return false; + else if(str!=null && str.length!=4){//如果IP地址拆分后的数组长度不为4则不是正确的IP地址 + return false; + }else{ + return true; + } + } + public static long ipToLong(String strIP) + //将127.0.0.1 形式的IP地址转换成10进制整数,这里没有进行任何错误处理 + { + int j=0; + int i=0; + long [] ip=new long[4]; + int position1=strIP.indexOf("."); + int position2=strIP.indexOf(".",position1+1); + int position3=strIP.indexOf(".",position2+1); + ip[0]=Long.parseLong(strIP.substring(0,position1)); + ip[1]=Long.parseLong(strIP.substring(position1+1,position2)); + ip[2]=Long.parseLong(strIP.substring(position2+1,position3)); + ip[3]=Long.parseLong(strIP.substring(position3+1)); + return (ip[0]<<24)+(ip[1]<<16)+(ip[2]<<8)+ip[3]; + } + public static String longToIP(long longIP) + //将10进制整数形式转换成127.0.0.1形式的IP地址,按主机序 + { + StringBuffer sb=new StringBuffer(""); + sb.append(String.valueOf(longIP>>>24&0xFF));//直接右移24位 + sb.append("."); //将高8位置0,然后右移16位 + sb.append(String.valueOf((longIP&0x00FFFFFF)>>>16)); + sb.append("."); + sb.append(String.valueOf((longIP&0x0000FFFF)>>>8)); + sb.append("."); + sb.append(String.valueOf(longIP&0x000000FF)); + //sb.append("."); + return sb.toString(); + } + //将10进制整数形式转换成127.0.0.1形式的IP地址,按网络序 + public static String longToNetIp(long longIP){ + StringBuffer sb=new StringBuffer(""); + sb.append(String.valueOf(longIP&0x000000FF)); + sb.append("."); + sb.append(String.valueOf((longIP&0x0000FFFF)>>>8)); + sb.append(".");//将高8位置0,然后右移16位 + sb.append(String.valueOf((longIP&0x00FFFFFF)>>>16)); + sb.append("."); + sb.append(String.valueOf(longIP>>>24&0xFF));//直接右移24位 + //sb.append("."); + return sb.toString(); + } + public static long netIpToLong(String strIP) + //将127.0.0.1 形式的IP地址转换成10进制整数,这里没有进行任何错误处理 + { + int j=0; + int i=0; + long [] ip=new long[4]; + int position1=strIP.indexOf("."); + int position2=strIP.indexOf(".",position1+1); + int position3=strIP.indexOf(".",position2+1); + ip[0]=Long.parseLong(strIP.substring(0,position1)); + ip[1]=Long.parseLong(strIP.substring(position1+1,position2)); + ip[2]=Long.parseLong(strIP.substring(position2+1,position3)); + ip[3]=Long.parseLong(strIP.substring(position3+1)); + return (ip[0])+(ip[1]<<8)+(ip[2]<<16)+(ip[3]<<24); + } + public static void main(String argus[]){ + System.out.println(Utils.checkIP("10.a.1.1")); + System.out.println(Utils.isIp("10.1.1.1")); + } + + + public static String printExceptionStack(Exception e){ + StackTraceElement[] ste = e.getStackTrace(); + StringBuffer sb = new StringBuffer(); + sb.append("\n\t" + e.toString() + "\n"); + for(StackTraceElement element : ste){ + sb.append("\t" + element.toString() + "\n"); + } + + return sb.toString(); + } + + + /** + * 根据网口名称获取此网口的Ip地址 + * @param ethName + * @return + */ + public static String getIpAddressByEthName(String ethName) { + String ip = null; + try { + //根据端口名称获取网卡信息 + NetworkInterface netWork = NetworkInterface.getByName(ethName); + //获取此网卡的ip地址,可能包含ipv4和ipv6 + Enumeration<InetAddress> adds = netWork.getInetAddresses(); + while (adds.hasMoreElements()) { + InetAddress add = adds.nextElement(); + String ipStirng = add.getHostAddress(); + // 如果Ip地址长度大于16,说明是ipv6格式地址 + if (ipStirng.length() > 16) { + continue; + } + ip = ipStirng; + } + } catch (Exception e) { + logger.error("Getting IP address failure based on port name",e); + } + return ip; + } + + /** + * 根据ip地址查找端口的名字 + * + * @param ip + * @return + */ + public static String getNetInterfaceNameByIp(String ip) { + byte[] ipArr = Utils.ipStringToByte(ip); + String name = null; + try { + NetworkInterface local = NetworkInterface + .getByInetAddress(InetAddress.getByAddress(ipArr)); + name = local.getName(); + } catch (Exception e) { + logger.error("Getting port name failure based on IP address", e); + } + return name; + } + + /** + * 将string类型的ip地址,转换成数组类型,只支持ipv4 + * + * @param ip + * @return + */ + public static byte[] ipStringToByte(String ip) { + if (!Utils.isIp(ip)) { + logger.error("IP is not legal, can not be converted!"); + return null; + } + String[] ipArr = ip.split("\\."); + byte[] result = new byte[4]; + for (int i = 0; i < ipArr.length; i++) { + int tem = Integer.parseInt(ipArr[i]); + result[i] = (byte) tem; + } + return result; + } + +} diff --git a/src/com/nis/nmsclient/util/ZipUtil.java b/src/com/nis/nmsclient/util/ZipUtil.java new file mode 100644 index 0000000..ee8e984 --- /dev/null +++ b/src/com/nis/nmsclient/util/ZipUtil.java @@ -0,0 +1,321 @@ +package com.nis.nmsclient.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; + +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; +import org.apache.tools.zip.ZipEntry; +import org.apache.tools.zip.ZipFile; +import org.apache.tools.zip.ZipOutputStream; + +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.thread.socket.ServerCollectData; + +public class ZipUtil { + static Logger logger = Logger.getLogger(ZipUtil.class); + /** + * java 解压缩单个zip压缩包 存在文件和目录的汉字处理问题 + * + * @param zipFileName 需要解压的压缩包文件 + * @param destDir 解压缩后的目标路径 + * @throws Exception + */ + public static void unZip(String zipFileName, String destDir) throws Exception { + logger.debug("unZip start……"); + ZipFile zipFile = null; + try{ + zipFile = new ZipFile(zipFileName); + Enumeration en = zipFile.getEntries(); + ZipEntry zipEntry = null; + while (en.hasMoreElements()) { + zipEntry = (ZipEntry) en.nextElement(); + String path = (destDir + File.separator + zipEntry.getName()).replaceAll("\\\\", "/"); + if (zipEntry.isDirectory()) {// 如果得到的是目录 + int end = path.lastIndexOf("/"); + if (end != -1) { + File dir = new File(path.substring(0, end)); + if (!dir.exists()) { + dir.mkdir(); + } + } + } else { + InputStream in = null; + FileOutputStream out = null; + try{ + File f = new File(path); + if(!f.getParentFile().exists()){ + f.getParentFile().mkdirs(); + } + f.createNewFile(); + in = zipFile.getInputStream(zipEntry); + out = new FileOutputStream(f); + IOUtils.copy(in, out); + }catch (Exception e) { + throw e; + }finally{ + if(in!=null) in.close(); + if(out!=null) out.close(); + } + } + }// while end + } catch (Exception e) { + throw e; + }finally { + if(zipFile != null){ + zipFile.close(); + zipFile = null; + } + } + logger.debug("unZip end……"); + } + + /** + * 将单个文件或一个目录打成zip包 + * + * @param srcDir 需要压压缩的文件目录 + * @param destFile 压缩后的目标文件 + * @throws Exception + */ + public static void zip(String srcDir, String destFile, String[] excludes) throws Exception { + ZipOutputStream out = null; + try{ + out = new ZipOutputStream(new FileOutputStream(destFile)); + //out.setEncoding("GBK");//解决linux乱码 + File srcFile = new File(srcDir); + if (!srcFile.exists()) { +// throw new Exception("压缩目录或文件不存在: " + srcFile.getAbsolutePath()); + throw new Exception("Compressed directories or files do not exist: " + srcFile.getAbsolutePath()); + } + if(excludes!=null && excludes.length>0){ + for (int i=0; i<excludes.length; i++) { + File excudeFile = new File(excludes[i]); + excludes[i] = excudeFile.getCanonicalPath(); + } + } + + /* if(srcFile.isDirectory()){ + zip(out,srcFile,srcFile.getName(), excludes); + }else{ + zip(out,srcFile,"", excludes); + }*/ + zip(out,srcFile,"", excludes); + }catch (Exception e) { + throw e; + }finally { + if(out!=null) out.close(); + } + } + + /** + * zip压缩 + * @param out: Zip压缩流 + * @param srcFile: 要压缩的目录或文件 + * @param base: 要压缩文件在zip包内的路径 + * @throws Exception + */ + protected static void zip(ZipOutputStream out, File srcFile, String base, String[] excludes) throws Exception{ + if (!srcFile.exists()) { +// throw new Exception("压缩目录或文件不存在: " + srcFile.getAbsolutePath()); + throw new Exception("Compressed directories or files do not exist: " + srcFile.getAbsolutePath()); + } + + if(excludes!=null && excludes.length>0){ + for(String exclude : excludes){ + if(exclude.equalsIgnoreCase(srcFile.getCanonicalPath())){ + return; + } + } + } + + if (srcFile.isDirectory()) { + File[] files = srcFile.listFiles(); + base = base.length() == 0 ? "" : base + "/"; + if (base.length() > 0) { + out.putNextEntry(new ZipEntry(base)); + /* ZipEntry zipEntry = new ZipEntry(base); + zipEntry.setUnixMode(755);// 解决linux乱码 + out.putNextEntry(zipEntry);*/ + } + for (int i = 0; i < files.length; i++) { + zip(out, files[i], base + files[i].getName(), excludes); + } + } else { + base = base.length() == 0 ? srcFile.getName() : base; + out.putNextEntry(new ZipEntry(base)); + /*ZipEntry zipEntry=new ZipEntry(base); + zipEntry.setUnixMode(644);//解决linux乱码 + out.putNextEntry(zipEntry);*/ + FileInputStream fis = null; + try{ + fis = new FileInputStream(srcFile); + IOUtils.copy(fis, out); + }catch (IOException e) { + throw e; + }finally{ + if(fis!=null) fis.close(); + } + } + out.closeEntry(); + } + + /** + * 将单个文件或一个目录打成zip包,并将原文件删除 + * + * @param srcFiles 需要压压缩的文件列表 + * @param destFile 压缩后的目标文件 + * @param isAddPrefix 是否要添加文件前缀 + * @throws Exception + */ + public static void zipWithDelFile(File[] srcFiles, String destFile, boolean isAddPrefix) throws Exception { + logger.debug("pass ZipUtil zipWithDelFile(File[] srcFiles, String destFile, boolean isAddPrefix):"); + if(srcFiles!=null){ + logger.debug("ZipUtil zipWithDelFile(File[] srcFiles, String destFile, boolean isAddPrefix) srcFiles:"+srcFiles.length); + } + ZipOutputStream out = null; + try{ + out = new ZipOutputStream(new FileOutputStream(destFile)); + //out.setEncoding("GBK");//解决linux乱码 + if (srcFiles==null || srcFiles.length==0) { +// throw new Exception("压缩文件列表为空"); + throw new Exception("The list of compressed files is empty"); + } + for(File file : srcFiles){ + zip(out,file,"", true, isAddPrefix, null); + } + }catch (Exception e) { + throw e; + }finally { + if(out!=null) out.close(); + } + } + + /** + * 将单个文件或一个目录打成zip包,并将原文件删除或移动 + * + * @param srcFiles 需要压压缩的文件列表 + * @param destFile 压缩后的目标文件 + * @param isAddPrefix 是否要添加文件前缀 + * @throws Exception + */ + public static void zipWithMoveFile(File[] srcFiles, String destFile, boolean isAddPrefix) throws Exception { + ZipOutputStream out = null; + try{ + out = new ZipOutputStream(new FileOutputStream(destFile)); + //out.setEncoding("GBK");//解决linux乱码 + if (srcFiles==null || srcFiles.length==0) { +// throw new Exception("压缩文件列表为空"); + throw new Exception("The list of compressed files is empty"); + } + // 2013-03-22 由于DC再次获取未保存任务结果这个功能的实现,现修改将任务结果和回传文件压缩时不删除文件,而是将其移动到相应的日期目录 + String dataType = null; + String destFileName = new File(destFile).getName(); + if(destFileName.startsWith(CommonSocket.BP_TYPE_TASK_RESULT)){ + dataType = CommonSocket.BP_TYPE_TASK_RESULT; + }else if(destFileName.startsWith(CommonSocket.BP_TYPE_TASK_RETURN)){ + dataType = CommonSocket.BP_TYPE_TASK_RETURN; + }else if(destFileName.startsWith(CommonSocket.BP_TYPE_DETECT_DATA)){ + dataType = CommonSocket.BP_TYPE_DETECT_DATA; + } + logger.debug("zipWithMoveFile --- dataType = " + dataType); + for(File file : srcFiles){ + // 2013-5-6 针对监测数据打包文件个数的限制,即srcFiles传来的是一定个数的文件,不是所有监测的目录,所以压缩文件中的文件名要加上文件的父目录名 + if(CommonSocket.BP_TYPE_DETECT_DATA.equalsIgnoreCase(dataType) && file.isFile()){ + zip(out, file, file.getParentFile().getName() + "_" + file.getName(), true, isAddPrefix, dataType); + }else{ + zip(out,file,"", true, isAddPrefix, dataType); + } + } + }catch (Exception e) { + throw e; + }finally { + if(out!=null) out.close(); + } + } + + /** + * zip压缩 + * @param out: Zip压缩流 + * @param srcFile: 要压缩的文件或目录 + * @param base: 要压缩文件在zip包内的路径 + * @param isDel 是否删除压缩的文件, 若dataType为null,则直接删除,若dataType不为null, 则移动到指定目录 + * @param isAddPrefix 是否要添加文件前缀,true 如果是文件则将父文件夹的名称加到文件名的前缀,作为压缩后的文件名 + * @throws Exception + */ + protected static void zip(ZipOutputStream out, File srcFile, String base, boolean isDel, boolean isAddPrefix, String dataType) throws Exception{ + if (!srcFile.exists()) { +// throw new Exception("压缩目录或文件不存在: " + srcFile.getAbsolutePath()); + throw new Exception("Compressed directories or files do not exist: " + srcFile.getAbsolutePath()); + } + logger.debug("pass ZipUtil zip"); + + if (srcFile.isDirectory()) { + File[] files = srcFile.listFiles(); + base = base.length() == 0 ? "" : base + "/"; + if (base.length() > 0) { + out.putNextEntry(new ZipEntry(base)); + /* ZipEntry zipEntry = new ZipEntry(base); + zipEntry.setUnixMode(755);// 解决linux乱码 + out.putNextEntry(zipEntry);*/ + } + for (int i = 0; i < files.length; i++) { + String fileName = files[i].getName(); + if(isAddPrefix){ + fileName = files[i].getParentFile().getName() + "_" + files[i].getName(); + } + zip(out, files[i], base + fileName, isDel, isAddPrefix, dataType); + } + } else{ + base = base.length() == 0 ? srcFile.getName() : base; + out.putNextEntry(new ZipEntry(base)); + /*ZipEntry zipEntry=new ZipEntry(base); + zipEntry.setUnixMode(644);//解决linux乱码 + out.putNextEntry(zipEntry);*/ + FileInputStream fis = null; + try{ + fis = new FileInputStream(srcFile); + IOUtils.copy(fis, out); + }catch (IOException e) { + throw e; + }finally{ + if(fis!=null) fis.close(); + } + if(srcFile.exists() && isDel){ + // 2013-03-22 由于DC再次获取未保存任务结果这个功能的实现,现修改将任务结果和回传文件压缩时不删除文件,而是将其移动到相应的日期目录 + if(CommonSocket.BP_TYPE_TASK_RESULT.equalsIgnoreCase(dataType)){ + ServerCollectData.moveTaskResultToDateDir(srcFile); + }else if(CommonSocket.BP_TYPE_TASK_RETURN.equalsIgnoreCase(dataType)){ + ServerCollectData.moveTaskReturnToDateDir(srcFile, null); + }else if(CommonSocket.BP_TYPE_DETECT_DATA.equalsIgnoreCase(dataType)){ + ServerCollectData.moveDetecDataToDateDir(srcFile); + }else { + FileUtil.delDir(srcFile); + logger.debug("ZipUtil.zip()----delete srcFile=" + srcFile.getAbsolutePath()); + } + } + } + out.closeEntry(); + } + + public static void main(String[] args) { + try { + File f = new File("D:/work/create_tablespace"); + System.out.println(f.getPath()); + long tt = System.currentTimeMillis(); + /*String[] excludes = new String[3]; + excludes[0] = "D:\\temp\\t1\\test\\src"; + excludes[1] = "D:\\temp\\t1\\test\\WebRoot\\WEB-INF\\lib\\jdom.jar"; + excludes[2] = "D:\\temp\\t1\\test\\ziptest_code.zip"; + ZipUtil.zip("D:\\temp\\t1", "D:\\temp\\test\\t1.zip", excludes); + //ZipUtil.unZip("D:\\temp\\test\\ziptest_code.zip", "D:\\temp"); + System.out.println(System.currentTimeMillis()-tt);*/ + ZipUtil.zipWithDelFile(new File("D:\\nmstest\\logs\\").listFiles(), "D:\\test\\nmsserver.log.zip", true); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/com/nis/nmsclient/util/file/BufferedRandomAccessFile.java b/src/com/nis/nmsclient/util/file/BufferedRandomAccessFile.java new file mode 100644 index 0000000..ca78182 --- /dev/null +++ b/src/com/nis/nmsclient/util/file/BufferedRandomAccessFile.java @@ -0,0 +1,313 @@ +package com.nis.nmsclient.util.file; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ResourceBundle; + +/** + * <p>Title: BufferedRandomAccessFile</p> + * <p>Description: this class provide Buffered Read & Write by extend RandomAccessFile</p> + * <p>Copyright: Copyright (c) 2002 Cui Zhixiang </p> + * <p>Company: soho </p> + * @author Cui Zhixiang + * @version 1.0, 2002/10/12 + */ + +public class BufferedRandomAccessFile extends RandomAccessFile { + + static ResourceBundle res = ResourceBundle.getBundle(Res.class.getName()); + private static final int DEFAULT_BUFFER_BIT_LEN = 10; + private static final int DEFAULT_BUFFER_SIZE = 1 << DEFAULT_BUFFER_BIT_LEN; + + protected byte buf[]; + protected int bufbitlen; + protected int bufsize; + protected long bufmask; + protected boolean bufdirty; + protected int bufusedsize; + protected long curpos; + + protected long bufstartpos; + protected long bufendpos; + protected long fileendpos; + + protected boolean append; + protected String filename; + protected long initfilelen; + + public BufferedRandomAccessFile(String name) throws IOException { + this(name, res.getString("r"), DEFAULT_BUFFER_BIT_LEN); + } + + public BufferedRandomAccessFile(File file) throws IOException, FileNotFoundException { + this(file.getPath(), res.getString("r"), DEFAULT_BUFFER_BIT_LEN); + } + + public BufferedRandomAccessFile(String name, int bufbitlen) throws IOException { + this(name, res.getString("r"), bufbitlen); + } + + public BufferedRandomAccessFile(File file, int bufbitlen) throws IOException, FileNotFoundException { + this(file.getPath(), res.getString("r"), bufbitlen); + } + + public BufferedRandomAccessFile(String name, String mode) throws IOException { + this(name, mode, DEFAULT_BUFFER_BIT_LEN); + } + + public BufferedRandomAccessFile(File file, String mode) throws IOException, FileNotFoundException { + this(file.getPath(), mode, DEFAULT_BUFFER_BIT_LEN); + } + + public BufferedRandomAccessFile(String name, String mode, int bufbitlen) throws IOException { + super(name, mode); + this.init(name, mode, bufbitlen); + } + + public BufferedRandomAccessFile(File file, String mode, int bufbitlen) throws IOException, FileNotFoundException { + this(file.getPath(), mode, bufbitlen); + } + + private void init(String name, String mode, int bufbitlen) throws IOException { + if (mode.equals(res.getString("r")) == true) { + this.append = false; + } else { + this.append = true; + } + + this.filename = name; + this.initfilelen = super.length(); + this.fileendpos = this.initfilelen - 1; + this.curpos = super.getFilePointer(); + + if (bufbitlen < 0) { + throw new IllegalArgumentException(res.getString("bufbitlen_size_must_0")); + } + + this.bufbitlen = bufbitlen; + this.bufsize = 1 << bufbitlen; + this.buf = new byte[this.bufsize]; + this.bufmask = ~((long)this.bufsize - 1L); + this.bufdirty = false; + this.bufusedsize = 0; + this.bufstartpos = -1; + this.bufendpos = -1; + } + + private void flushbuf() throws IOException { + if (this.bufdirty == true) { + if (super.getFilePointer() != this.bufstartpos) { + super.seek(this.bufstartpos); + } + super.write(this.buf, 0, this.bufusedsize); + this.bufdirty = false; + } + } + + private int fillbuf() throws IOException { + super.seek(this.bufstartpos); + this.bufdirty = false; + return super.read(this.buf); + } + + public byte read(long pos) throws IOException { + if (pos < this.bufstartpos || pos > this.bufendpos) { + this.flushbuf(); + this.seek(pos); + + if ((pos < this.bufstartpos) || (pos > this.bufendpos)) { + throw new IOException(); + } + } + this.curpos = pos; + return this.buf[(int)(pos - this.bufstartpos)]; + } + + public boolean write(byte bw) throws IOException { + return this.write(bw, this.curpos); + } + + public boolean append(byte bw) throws IOException { + return this.write(bw, this.fileendpos + 1); + } + + public boolean write(byte bw, long pos) throws IOException { + + if ((pos >= this.bufstartpos) && (pos <= this.bufendpos)) { // write pos in buf + this.buf[(int)(pos - this.bufstartpos)] = bw; + this.bufdirty = true; + + if (pos == this.fileendpos + 1) { // write pos is append pos + this.fileendpos++; + this.bufusedsize++; + } + } else { // write pos not in buf + this.seek(pos); + + if ((pos >= 0) && (pos <= this.fileendpos) && (this.fileendpos != 0)) { // write pos is modify file + this.buf[(int)(pos - this.bufstartpos)] = bw; + + } else if (((pos == 0) && (this.fileendpos == 0)) || (pos == this.fileendpos + 1)) { // write pos is append pos + this.buf[0] = bw; + this.fileendpos++; + this.bufusedsize = 1; + } else { + throw new IndexOutOfBoundsException(); + } + this.bufdirty = true; + } + this.curpos = pos; + return true; + } + + public void write(byte b[], int off, int len) throws IOException { + + long writeendpos = this.curpos + len - 1; + + if (writeendpos <= this.bufendpos) { // b[] in cur buf + System.arraycopy(b, off, this.buf, (int)(this.curpos - this.bufstartpos), len); + this.bufdirty = true; + this.bufusedsize = (int)(writeendpos - this.bufstartpos + 1);//(int)(this.curpos - this.bufstartpos + len - 1); + + } else { // b[] not in cur buf + super.seek(this.curpos); + super.write(b, off, len); + } + + if (writeendpos > this.fileendpos) + this.fileendpos = writeendpos; + + this.seek(writeendpos+1); + } + + public int read(byte b[], int off, int len) throws IOException { + + long readendpos = this.curpos + len - 1; + + if (readendpos <= this.bufendpos && readendpos <= this.fileendpos ) { // read in buf + System.arraycopy(this.buf, (int)(this.curpos - this.bufstartpos), b, off, len); + } else { // read b[] size > buf[] + + if (readendpos > this.fileendpos) { // read b[] part in file + len = (int)(this.length() - this.curpos + 1); + } + + super.seek(this.curpos); + len = super.read(b, off, len); + readendpos = this.curpos + len - 1; + } + this.seek(readendpos + 1); + return len; + } + + public void write(byte b[]) throws IOException { + this.write(b, 0, b.length); + } + + public int read(byte b[]) throws IOException { + return this.read(b, 0, b.length); + } + + public void seek(long pos) throws IOException { + + if ((pos < this.bufstartpos) || (pos > this.bufendpos)) { // seek pos not in buf + this.flushbuf(); + + if ((pos >= 0) && (pos <= this.fileendpos) && (this.fileendpos != 0)) { // seek pos in file (file length > 0) + this.bufstartpos = pos & this.bufmask; + this.bufusedsize = this.fillbuf(); + + } else if (((pos == 0) && (this.fileendpos == 0)) || (pos == this.fileendpos + 1)) { // seek pos is append pos + + this.bufstartpos = pos; + this.bufusedsize = 0; + } + this.bufendpos = this.bufstartpos + this.bufsize - 1; + } + this.curpos = pos; + } + + public long length() throws IOException { + return this.max(this.fileendpos + 1, this.initfilelen); + } + + public void setLength(long newLength) throws IOException { + if (newLength > 0) { + this.fileendpos = newLength - 1; + } else { + this.fileendpos = 0; + } + super.setLength(newLength); + } + public long getFilePointer() throws IOException { + return this.curpos; + } + + private long max(long a, long b) { + if (a > b) return a; + return b; + } + + public void close() throws IOException { + this.flushbuf(); + super.close(); + } + + public static void main(String[] args) throws IOException { + long readfilelen = 0; + BufferedRandomAccessFile brafReadFile, brafWriteFile; + + brafReadFile = new BufferedRandomAccessFile("C:\\WINNT\\Fonts\\STKAITI.TTF"); + readfilelen = brafReadFile.initfilelen; + brafWriteFile = new BufferedRandomAccessFile(".\\STKAITI.001", "rw", 10); + + byte buf[] = new byte[1024]; + int readcount; + + long start = System.currentTimeMillis(); + + while((readcount = brafReadFile.read(buf)) != -1) { + brafWriteFile.write(buf, 0, readcount); + } + + brafWriteFile.close(); + brafReadFile.close(); + + System.out.println("BufferedRandomAccessFile Copy & Write File: " + + brafReadFile.filename + + " FileSize: " + + java.lang.Integer.toString((int)readfilelen >> 1024) + + " (KB) " + + "Spend: " + +(double)(System.currentTimeMillis()-start) / 1000 + + "(s)"); + + java.io.FileInputStream fdin = new java.io.FileInputStream("C:\\WINNT\\Fonts\\STKAITI.TTF"); + java.io.BufferedInputStream bis = new java.io.BufferedInputStream(fdin, 1024); + java.io.DataInputStream dis = new java.io.DataInputStream(bis); + + java.io.FileOutputStream fdout = new java.io.FileOutputStream(".\\STKAITI.002"); + java.io.BufferedOutputStream bos = new java.io.BufferedOutputStream(fdout, 1024); + java.io.DataOutputStream dos = new java.io.DataOutputStream(bos); + + start = System.currentTimeMillis(); + + for (int i = 0; i < readfilelen; i++) { + dos.write(dis.readByte()); + } + + dos.close(); + dis.close(); + + System.out.println("DataBufferedios Copy & Write File: " + + brafReadFile.filename + + " FileSize: " + + java.lang.Integer.toString((int)readfilelen >> 1024) + + " (KB) " + + "Spend: " + + (double)(System.currentTimeMillis()-start) / 1000 + + "(s)"); + } +} diff --git a/src/com/nis/nmsclient/util/file/Res.java b/src/com/nis/nmsclient/util/file/Res.java new file mode 100644 index 0000000..7e61830 --- /dev/null +++ b/src/com/nis/nmsclient/util/file/Res.java @@ -0,0 +1,17 @@ +package com.nis.nmsclient.util.file; + +public class Res extends java.util.ListResourceBundle { + static final Object[][] contents = new String[][]{ + { "r", "r" }, + { "bufbitlen_size_must_0", "bufbitlen size must >= 0" }, + { "rw", "rw" }, + { "BufferedRandomAccess", "BufferedRandomAccessFile Copy & Write File: " }, + { "FileSize_", " FileSize: " }, + { "_KB_", " (KB) " }, + { "Spend_", "Spend: " }, + { "_s_", "(s)" }, + { "DataBufferedios_Copy", "DataBufferedios Copy & Write File: " }}; + public Object[][] getContents() { + return contents; + } +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/util/io/UnicodeInputStream.java b/src/com/nis/nmsclient/util/io/UnicodeInputStream.java new file mode 100644 index 0000000..9e61d42 --- /dev/null +++ b/src/com/nis/nmsclient/util/io/UnicodeInputStream.java @@ -0,0 +1,118 @@ +package com.nis.nmsclient.util.io; +/** + version: 1.1 / 2007-01-25 + - changed BOM recognition ordering (longer boms first) + + Original pseudocode : Thomas Weidenfeller + Implementation tweaked: Aki Nieminen + + http://www.unicode.org/unicode/faq/utf_bom.html + BOMs in byte length ordering: + 00 00 FE FF = UTF-32, big-endian + FF FE 00 00 = UTF-32, little-endian + EF BB BF = UTF-8, + FE FF = UTF-16, big-endian + FF FE = UTF-16, little-endian + + Win2k Notepad: + Unicode format = UTF-16LE + ***/ + +import java.io.*; + +/** + * This inputstream will recognize unicode BOM marks and will skip bytes if + * getEncoding() method is called before any of the read(...) methods. + * + * Usage pattern: String enc = "ISO-8859-1"; // or NULL to use systemdefault + * FileInputStream fis = new FileInputStream(file); UnicodeInputStream uin = new + * UnicodeInputStream(fis, enc); enc = uin.getEncoding(); // check and skip + * possible BOM bytes InputStreamReader in; if (enc == null) in = new + * InputStreamReader(uin); else in = new InputStreamReader(uin, enc); + */ +public class UnicodeInputStream extends InputStream { + PushbackInputStream internalIn; + boolean isInited = false; + String defaultEnc; + String encoding; + + private static final int BOM_SIZE = 4; + + UnicodeInputStream(InputStream in, String defaultEnc) { + internalIn = new PushbackInputStream(in, BOM_SIZE); + this.defaultEnc = defaultEnc; + } + + public String getDefaultEncoding() { + return defaultEnc; + } + + public String getEncoding() { + if (!isInited) { + try { + init(); + } catch (IOException ex) { + IllegalStateException ise = new IllegalStateException( + "Init method failed."); + ise.initCause(ise); + throw ise; + } + } + return encoding; + } + + /** + * Read-ahead four bytes and check for BOM marks. Extra bytes are unread + * back to the stream, only BOM bytes are skipped. + */ + protected void init() throws IOException { + if (isInited) + return; + + byte bom[] = new byte[BOM_SIZE]; + int n, unread; + n = internalIn.read(bom, 0, bom.length); + + if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) + && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) { + encoding = "UTF-32BE"; + unread = n - 4; + } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) + && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) { + encoding = "UTF-32LE"; + unread = n - 4; + } else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) + && (bom[2] == (byte) 0xBF)) { + encoding = "UTF-8"; + unread = n - 3; + } else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) { + encoding = "UTF-16BE"; + unread = n - 2; + } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) { + encoding = "UTF-16LE"; + unread = n - 2; + } else { + // Unicode BOM mark not found, unread all bytes + encoding = defaultEnc; + unread = n; + } + // System.out.println("read=" + n + ", unread=" + unread); + + if (unread > 0) + internalIn.unread(bom, (n - unread), unread); + + isInited = true; + } + + public void close() throws IOException { + // init(); + isInited = true; + internalIn.close(); + } + + public int read() throws IOException { + // init(); + isInited = true; + return internalIn.read(); + } +} diff --git a/src/com/nis/nmsclient/util/io/UnicodeReader.java b/src/com/nis/nmsclient/util/io/UnicodeReader.java new file mode 100644 index 0000000..c4169b5 --- /dev/null +++ b/src/com/nis/nmsclient/util/io/UnicodeReader.java @@ -0,0 +1,120 @@ +package com.nis.nmsclient.util.io; +/** + version: 1.1 / 2007-01-25 + - changed BOM recognition ordering (longer boms first) + + Original pseudocode : Thomas Weidenfeller + Implementation tweaked: Aki Nieminen + + http://www.unicode.org/unicode/faq/utf_bom.html + BOMs: + 00 00 FE FF = UTF-32, big-endian + FF FE 00 00 = UTF-32, little-endian + EF BB BF = UTF-8, + FE FF = UTF-16, big-endian + FF FE = UTF-16, little-endian + + Win2k Notepad: + Unicode format = UTF-16LE + ***/ + +import java.io.*; + +/** + * Generic unicode textreader, which will use BOM mark to identify the encoding + * to be used. If BOM is not found then use a given default or system encoding. + */ +public class UnicodeReader extends Reader { + PushbackInputStream internalIn; + InputStreamReader internalIn2 = null; + String defaultEnc; + + private static final int BOM_SIZE = 4; + + /** + * + * @param in + * inputstream to be read + * @param defaultEnc + * default encoding if stream does not have BOM marker. Give NULL + * to use system-level default. + */ + public UnicodeReader(InputStream in, String defaultEnc) { + internalIn = new PushbackInputStream(in, BOM_SIZE); + this.defaultEnc = defaultEnc; + } + + public String getDefaultEncoding() { + return defaultEnc; + } + + /** + * Get stream encoding or NULL if stream is uninitialized. Call init() or + * read() method to initialize it. + */ + public String getEncoding() { + if (internalIn2 == null) + return null; + return internalIn2.getEncoding(); + } + + /** + * Read-ahead four bytes and check for BOM marks. Extra bytes are unread + * back to the stream, only BOM bytes are skipped. + */ + protected void init() throws IOException { + if (internalIn2 != null) + return; + + String encoding; + byte bom[] = new byte[BOM_SIZE]; + int n, unread; + n = internalIn.read(bom, 0, bom.length); + + if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) + && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) { + encoding = "UTF-32BE"; + unread = n - 4; + } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) + && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) { + encoding = "UTF-32LE"; + unread = n - 4; + } else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) + && (bom[2] == (byte) 0xBF)) { + encoding = "UTF-8"; + unread = n - 3; + } else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) { + encoding = "UTF-16BE"; + unread = n - 2; + } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) { + encoding = "UTF-16LE"; + unread = n - 2; + } else { + // Unicode BOM mark not found, unread all bytes + encoding = defaultEnc; + unread = n; + } + // System.out.println("read=" + n + ", unread=" + unread); + + if (unread > 0) + internalIn.unread(bom, (n - unread), unread); + + // Use given encoding + if (encoding == null) { + internalIn2 = new InputStreamReader(internalIn); + } else { + internalIn2 = new InputStreamReader(internalIn, encoding); + } + } + + public void close() throws IOException { + init(); + internalIn2.close(); + } + + public int read(char[] cbuf, int off, int len) throws IOException { + init(); + return internalIn2.read(cbuf, off, len); + } + +}
\ No newline at end of file diff --git a/src/com/nis/nmsclient/util/log4j/MyDailyRollingFileAppender.java b/src/com/nis/nmsclient/util/log4j/MyDailyRollingFileAppender.java new file mode 100644 index 0000000..b003cc4 --- /dev/null +++ b/src/com/nis/nmsclient/util/log4j/MyDailyRollingFileAppender.java @@ -0,0 +1,14 @@ +package com.nis.nmsclient.util.log4j; + +import org.apache.log4j.DailyRollingFileAppender; +import org.apache.log4j.Priority; + +public class MyDailyRollingFileAppender extends DailyRollingFileAppender { + + @Override + public boolean isAsSevereAsThreshold(Priority priority) { + // 只判断相等,不判断优先级 + return this.getThreshold().equals(priority); + } + +} diff --git a/src/com/nis/nmsclient/util/log4j/MyRollingFileAppender.java b/src/com/nis/nmsclient/util/log4j/MyRollingFileAppender.java new file mode 100644 index 0000000..133c592 --- /dev/null +++ b/src/com/nis/nmsclient/util/log4j/MyRollingFileAppender.java @@ -0,0 +1,14 @@ +package com.nis.nmsclient.util.log4j; + +import org.apache.log4j.Priority; +import org.apache.log4j.RollingFileAppender; + +public class MyRollingFileAppender extends RollingFileAppender { + + @Override + public boolean isAsSevereAsThreshold(Priority priority) { + // 只判断相等,不判断优先级 + return this.getThreshold().equals(priority); + } + +} |
