Repository: fnet123/clover Branch: master Commit: e7c8873ef9c9 Files: 323 Total size: 1.2 MB Directory structure: gitextract_k4y1i56_/ ├── README.md ├── clover/ │ ├── .gitignore │ ├── README.md │ ├── clover-admin/ │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── gome/ │ │ │ │ ├── clover/ │ │ │ │ │ ├── listener/ │ │ │ │ │ │ └── Log4jConfigListener.java │ │ │ │ │ └── servlet/ │ │ │ │ │ └── CloverServletHandle.java │ │ │ │ └── testclover/ │ │ │ │ └── spring/ │ │ │ │ ├── RemoteCronJobWithSpringAnnotation.java │ │ │ │ ├── RemoteFixedDateJobWithSpring.java │ │ │ │ ├── RemoteFixedDateJobWithSpringAnnotation.java │ │ │ │ ├── RemoteJobWithSpring.java │ │ │ │ └── TestProperties.java │ │ │ ├── resources/ │ │ │ │ ├── bak_log4j.properties │ │ │ │ ├── conf/ │ │ │ │ │ └── config.properties │ │ │ │ ├── log4j.xml │ │ │ │ └── spring/ │ │ │ │ └── spring-config.xml │ │ │ └── webapp/ │ │ │ ├── WEB-INF/ │ │ │ │ └── web.xml │ │ │ ├── common/ │ │ │ │ ├── head.jsp │ │ │ │ └── nav.jsp │ │ │ ├── contactList.jsp │ │ │ ├── css/ │ │ │ │ └── style.css │ │ │ ├── error.jsp │ │ │ ├── index.jsp │ │ │ ├── jobList.jsp │ │ │ ├── js/ │ │ │ │ ├── DatePicker/ │ │ │ │ │ ├── DatePicker.htm │ │ │ │ │ ├── WdatePicker.js │ │ │ │ │ ├── calendar.js │ │ │ │ │ ├── config.js │ │ │ │ │ ├── lang/ │ │ │ │ │ │ ├── en.js │ │ │ │ │ │ ├── zh-cn.js │ │ │ │ │ │ └── zh-tw.js │ │ │ │ │ └── skin/ │ │ │ │ │ ├── WdatePicker.css │ │ │ │ │ ├── default/ │ │ │ │ │ │ └── datepicker.css │ │ │ │ │ ├── ext/ │ │ │ │ │ │ └── datepicker.css │ │ │ │ │ └── whyGreen/ │ │ │ │ │ └── datepicker.css │ │ │ │ ├── Map.js │ │ │ │ ├── bootstrap-popover.js │ │ │ │ ├── bootstrap-tooltip.js │ │ │ │ ├── exporting.js │ │ │ │ ├── highcharts.js │ │ │ │ ├── html5.js │ │ │ │ ├── jquery.validate.js │ │ │ │ ├── ui.datepicker-zh-CN.js │ │ │ │ └── ui.datepicker.js │ │ │ ├── logList.jsp │ │ │ ├── login.jsp │ │ │ ├── monitorList.jsp │ │ │ ├── register.jsp │ │ │ └── zkList.jsp │ │ └── test/ │ │ └── java/ │ │ └── TestAnnotationWithSpring.java │ ├── clover-client/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── com/ │ │ └── gome/ │ │ └── bg/ │ │ └── clover/ │ │ └── client/ │ │ ├── job/ │ │ │ ├── LocalJob.java │ │ │ ├── RemoteJob.java │ │ │ ├── SimpleJob.java │ │ │ └── TransactionJob.java │ │ └── module/ │ │ └── SchedulerClientInitial.java │ ├── clover-common/ │ │ └── pom.xml │ ├── clover-core/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── gome/ │ │ │ └── clover/ │ │ │ ├── common/ │ │ │ │ ├── annotation/ │ │ │ │ │ ├── CloverConfigBeanDefinitionParser.java │ │ │ │ │ ├── CloverConfigInit.java │ │ │ │ │ ├── CloverJobAnnotation.java │ │ │ │ │ ├── CloverJobAnnotationBean.java │ │ │ │ │ ├── CloverJobBeanDefinitionParser.java │ │ │ │ │ └── CloverJobNamespaceHandler.java │ │ │ │ ├── cache/ │ │ │ │ │ ├── LRUCache.java │ │ │ │ │ └── LRUCache2.java │ │ │ │ ├── compile/ │ │ │ │ │ ├── CreateAndCompileClassFile.java │ │ │ │ │ ├── DynamicClassLoader.java │ │ │ │ │ └── MyClassLoader.java │ │ │ │ ├── compress/ │ │ │ │ │ └── CompressUtil.java │ │ │ │ ├── encryption/ │ │ │ │ │ ├── DesUtil.java │ │ │ │ │ └── MD5Util.java │ │ │ │ ├── exception/ │ │ │ │ │ └── AppException.java │ │ │ │ ├── file/ │ │ │ │ │ └── ConfigFile.java │ │ │ │ ├── hash/ │ │ │ │ │ └── HashTimes.java │ │ │ │ ├── mongodb/ │ │ │ │ │ ├── BuildMongoDBData.java │ │ │ │ │ ├── DBTableInfo.java │ │ │ │ │ └── MongoDBUtil.java │ │ │ │ ├── netty/ │ │ │ │ │ ├── client/ │ │ │ │ │ │ ├── ObjectReqClient.java │ │ │ │ │ │ └── SubReqClientHandel.java │ │ │ │ │ ├── protol/ │ │ │ │ │ │ ├── SubScribeResp.java │ │ │ │ │ │ └── SubscribeReq.java │ │ │ │ │ └── server/ │ │ │ │ │ ├── ObjectRespServer.java │ │ │ │ │ └── SubReqServerHandel.java │ │ │ │ ├── rocketmq/ │ │ │ │ │ ├── ConsumerUtil.java │ │ │ │ │ └── ProducerUtil.java │ │ │ │ ├── rpc/ │ │ │ │ │ ├── HttpRequestEntity.java │ │ │ │ │ ├── HttpRequestHandler.java │ │ │ │ │ ├── HttpResponseEntity.java │ │ │ │ │ ├── QueueDaemon.java │ │ │ │ │ └── QueueServer.java │ │ │ │ ├── systeminfo/ │ │ │ │ │ ├── IMonitorService.java │ │ │ │ │ ├── MonitorInfoBean.java │ │ │ │ │ ├── MonitorServiceImpl.java │ │ │ │ │ ├── SystemInfoUtil.java │ │ │ │ │ └── WindowsInfoUtil.java │ │ │ │ ├── thread/ │ │ │ │ │ └── MyThreadPool.java │ │ │ │ ├── tools/ │ │ │ │ │ ├── ClassUtil.java │ │ │ │ │ ├── CommonConstants.java │ │ │ │ │ ├── ConfigUtil.java │ │ │ │ │ ├── DateUtil.java │ │ │ │ │ ├── HttpRequest.java │ │ │ │ │ ├── IpUtil.java │ │ │ │ │ ├── KeyGen.java │ │ │ │ │ ├── List2StringUtil.java │ │ │ │ │ ├── NetUtils.java │ │ │ │ │ ├── NettyUtil.java │ │ │ │ │ ├── ProgressUtil.java │ │ │ │ │ ├── PropertiesUtil.java │ │ │ │ │ ├── RandomNumUtil.java │ │ │ │ │ ├── SendMailUtil.java │ │ │ │ │ └── StringUtil.java │ │ │ │ ├── zeromq/ │ │ │ │ │ ├── AsyncSendMsg.java │ │ │ │ │ ├── AsyncStartZeroMQ.java │ │ │ │ │ ├── AsyncZMQPull.java │ │ │ │ │ ├── ZeroMQEntity.java │ │ │ │ │ ├── ZeroMQPub.java │ │ │ │ │ ├── ZeroMQPull.java │ │ │ │ │ ├── ZeroMQPush.java │ │ │ │ │ └── ZeroMQSub.java │ │ │ │ └── zk/ │ │ │ │ ├── ClientDict.java │ │ │ │ ├── ClientListener.java │ │ │ │ ├── ClientNodes.java │ │ │ │ ├── CommonNodes.java │ │ │ │ ├── ServerDict.java │ │ │ │ ├── ServerListener.java │ │ │ │ ├── ServerNodes.java │ │ │ │ ├── ZKConnect.java │ │ │ │ ├── ZKManager.java │ │ │ │ ├── ZKUtil.java │ │ │ │ └── ZooKeeperWatch.java │ │ │ └── core/ │ │ │ ├── job/ │ │ │ │ ├── ClientJob.java │ │ │ │ ├── ClientJobBuilder.java │ │ │ │ ├── ClientJobFactory.java │ │ │ │ ├── MyJobListener.java │ │ │ │ ├── ServerJob.java │ │ │ │ └── ServerJobFactory.java │ │ │ ├── module/ │ │ │ │ ├── AbstractModuleScheduler.java │ │ │ │ ├── ModuleSchedulerClient.java │ │ │ │ └── ModuleSchedulerServer.java │ │ │ ├── monitor/ │ │ │ │ ├── client/ │ │ │ │ │ └── ClientHeartBeat.java │ │ │ │ └── server/ │ │ │ │ └── ServerHeartBeat.java │ │ │ └── scheduler/ │ │ │ └── MyScheduler.java │ │ └── resources/ │ │ ├── META-INF/ │ │ │ ├── cloverjob-1.0.0.xsd │ │ │ ├── spring.handlers │ │ │ └── spring.schemas │ │ ├── commonConfig.properties │ │ ├── dev/ │ │ │ ├── commonConfig.properties │ │ │ ├── mongoDBConfig.properties │ │ │ ├── redisConfig.properties │ │ │ └── zkConfig.properties │ │ ├── mongoDBConfig.properties │ │ ├── redisConfig.properties │ │ ├── uat/ │ │ │ ├── commonConfig.properties │ │ │ ├── mongoDBConfig.properties │ │ │ ├── redisConfig.properties │ │ │ └── zkConfig.properties │ │ └── zkConfig.properties │ ├── clover-examples/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── com/ │ │ └── gome/ │ │ └── clover/ │ │ ├── DeleteGomeVipAdPlanJob.java │ │ ├── ObjectToByte.java │ │ ├── TestEum.java │ │ ├── TestThread.java │ │ ├── akka/ │ │ │ └── serverclient/ │ │ │ └── pubsub/ │ │ │ ├── MyActorSystem.java │ │ │ ├── PublisherActor.java │ │ │ ├── WorkerTaskA.java │ │ │ └── WorkerTaskB.java │ │ ├── common/ │ │ │ └── compile/ │ │ │ └── TestCompile.java │ │ ├── cron/ │ │ │ └── TestCron.java │ │ ├── job/ │ │ │ ├── MyJob.java │ │ │ ├── MyJob1.java │ │ │ └── MyJobWithSimpleJob.java │ │ ├── json/ │ │ │ └── TestJson.java │ │ ├── mongo/ │ │ │ └── TestMongoDB.java │ │ ├── scheduler/ │ │ │ ├── TestSchedulerWithInsertMongoDB.java │ │ │ └── TestSchedulerWithRegister.java │ │ ├── systeminfo/ │ │ │ └── TestMem.java │ │ ├── thread/ │ │ │ ├── MyThread.java │ │ │ ├── TestMyThreadPool.java │ │ │ ├── ThreadDemo.java │ │ │ ├── ThreadPool.java │ │ │ └── ThreadPoolTest.java │ │ ├── time/ │ │ │ └── TestTime.java │ │ ├── zeromq/ │ │ │ ├── Helper.java │ │ │ ├── Pub.java │ │ │ ├── Publisher.java │ │ │ ├── RandomNum.java │ │ │ ├── Sub1.java │ │ │ ├── Subscriber.java │ │ │ ├── TestPubsubTcp.java │ │ │ └── TestReqrepTcp.java │ │ └── zk/ │ │ ├── CuratorDemo.java │ │ ├── CuratorTest.java │ │ ├── MonitorServerZKListener.java │ │ ├── SyncServer.java │ │ └── TestZK.java │ ├── clover-monitor/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── com/ │ │ └── gome/ │ │ └── clover/ │ │ └── monitor/ │ │ ├── MonitorHeartBeat.java │ │ ├── MonitorTimerTask.java │ │ ├── ServerHeartBeatBak.java │ │ └── ServerTimerTask.java │ ├── clover-server/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── com/ │ │ └── gome/ │ │ └── clover/ │ │ └── server/ │ │ └── module/ │ │ └── SchedulerServerInitial.java │ └── pom.xml ├── docs/ │ ├── clover结构图.vsd │ ├── clover部署结构图/ │ │ ├── clover部署结构图 - pre.vsd │ │ ├── clover部署结构图 - sit.vsd │ │ ├── clover部署结构图 - uat.vsd │ │ └── clover部署结构图.vsd │ ├── clover部署结构图.vsd │ └── clover项目技术分享和使用_2014121_V1.0.pptx └── test-clover/ ├── .classpath ├── .idea/ │ ├── .name │ ├── artifacts/ │ │ ├── test_clover_war.xml │ │ └── test_clover_war_exploded.xml │ ├── compiler.xml │ ├── copyright/ │ │ └── profiles_settings.xml │ ├── encodings.xml │ ├── libraries/ │ │ ├── Maven__aopalliance_aopalliance_1_0.xml │ │ ├── Maven__c3p0_c3p0_0_9_1_1.xml │ │ ├── Maven__com_101tec_zkclient_0_3.xml │ │ ├── Maven__com_alibaba_fastjson_1_1_31.xml │ │ ├── Maven__com_alibaba_rocketmq_rocketmq_client_3_1_8.xml │ │ ├── Maven__com_alibaba_rocketmq_rocketmq_common_3_1_8.xml │ │ ├── Maven__com_alibaba_rocketmq_rocketmq_remoting_3_1_8.xml │ │ ├── Maven__com_github_jnr_jnr_constants_0_8_2.xml │ │ ├── Maven__com_gome_clover_client_dev_1_0.xml │ │ ├── Maven__com_gome_clover_core_dev_1_0.xml │ │ ├── Maven__com_google_guava_guava_16_0_1.xml │ │ ├── Maven__com_google_protobuf_protobuf_java_2_4_1.xml │ │ ├── Maven__com_sun_jdmk_jmxtools_1_2_1.xml │ │ ├── Maven__com_sun_jmx_jmxri_1_2_1.xml │ │ ├── Maven__com_sun_tools_1_5_0.xml │ │ ├── Maven__com_typesafe_akka_akka_actor_2_0_2.xml │ │ ├── Maven__com_typesafe_akka_akka_actor_2_10_2_1_0.xml │ │ ├── Maven__com_typesafe_akka_akka_zeromq_2_10_2_1_0.xml │ │ ├── Maven__com_typesafe_config_1_0_0.xml │ │ ├── Maven__com_yammer_metrics_metrics_core_2_2_0.xml │ │ ├── Maven__commons_logging_commons_logging_1_1_1.xml │ │ ├── Maven__io_netty_netty_all_4_0_21_Final.xml │ │ ├── Maven__javax_activation_activation_1_1.xml │ │ ├── Maven__javax_jms_jms_1_1.xml │ │ ├── Maven__javax_mail_mail_1_5_0_b01.xml │ │ ├── Maven__javax_servlet_servlet_api_2_4.xml │ │ ├── Maven__jline_jline_0_9_94.xml │ │ ├── Maven__junit_junit_3_8_1.xml │ │ ├── Maven__junit_junit_4_11.xml │ │ ├── Maven__log4j_log4j_1_2_15.xml │ │ ├── Maven__net_java_dev_jna_jna_3_0_9.xml │ │ ├── Maven__net_sf_jopt_simple_jopt_simple_3_2.xml │ │ ├── Maven__org_apache_commons_com_springsource_org_apache_commons_codec_1_6_0.xml │ │ ├── Maven__org_apache_commons_com_springsource_org_apache_commons_logging_1_1_1.xml │ │ ├── Maven__org_apache_commons_commons_pool2_2_0.xml │ │ ├── Maven__org_apache_curator_curator_client_2_7_0.xml │ │ ├── Maven__org_apache_curator_curator_framework_2_7_0.xml │ │ ├── Maven__org_apache_httpcomponents_com_springsource_org_apache_httpcomponents_httpclient_4_2_1.xml │ │ ├── Maven__org_apache_httpcomponents_com_springsource_org_apache_httpcomponents_httpclient_cache_4_2_1.xml │ │ ├── Maven__org_apache_httpcomponents_com_springsource_org_apache_httpcomponents_httpcore_4_2_1.xml │ │ ├── Maven__org_apache_httpcomponents_com_springsource_org_apache_httpcomponents_httpmime_4_2_1.xml │ │ ├── Maven__org_apache_kafka_kafka_2_9_2_0_8_1_1.xml │ │ ├── Maven__org_apache_zookeeper_zookeeper_3_4_5.xml │ │ ├── Maven__org_hamcrest_hamcrest_core_1_3.xml │ │ ├── Maven__org_jboss_netty_netty_3_2_2_Final.xml │ │ ├── Maven__org_jboss_netty_netty_3_2_9_Final.xml │ │ ├── Maven__org_mongodb_mongo_java_driver_2_11_3.xml │ │ ├── Maven__org_quartz_scheduler_quartz_2_2_1.xml │ │ ├── Maven__org_scala_lang_scala_library_2_9_2.xml │ │ ├── Maven__org_slf4j_slf4j_api_1_6_6.xml │ │ ├── Maven__org_slf4j_slf4j_log4j12_1_6_1.xml │ │ ├── Maven__org_springframework_spring_aop_3_2_4_RELEASE.xml │ │ ├── Maven__org_springframework_spring_beans_3_2_4_RELEASE.xml │ │ ├── Maven__org_springframework_spring_context_3_2_4_RELEASE.xml │ │ ├── Maven__org_springframework_spring_core_3_2_4_RELEASE.xml │ │ ├── Maven__org_springframework_spring_expression_3_2_4_RELEASE.xml │ │ ├── Maven__org_springframework_spring_web_3_2_4_RELEASE.xml │ │ ├── Maven__org_springframework_spring_webmvc_3_2_4_RELEASE.xml │ │ ├── Maven__org_xerial_snappy_snappy_java_1_1_1_6.xml │ │ ├── Maven__org_zeromq_jeromq_0_3_4.xml │ │ ├── Maven__org_zeromq_zeromq_scala_binding_2_10_0_0_7.xml │ │ ├── Maven__redis_clients_jedis_2_6_0.xml │ │ ├── clover_client_dev_1_0.xml │ │ └── clover_core_dev_1_0.xml │ ├── misc.xml │ ├── modules.xml │ ├── scopes/ │ │ └── scope_settings.xml │ ├── vcs.xml │ └── workspace.xml ├── .myeclipse/ │ └── profiler/ │ └── RomoteCronJob.xml ├── .mymetadata ├── .project ├── .settings/ │ ├── .jsdtscope │ ├── com.genuitec.eclipse.j2eedt.core.prefs │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ ├── org.eclipse.m2e.core.prefs │ ├── org.eclipse.wst.common.component │ ├── org.eclipse.wst.common.project.facet.core.xml │ ├── org.eclipse.wst.jsdt.ui.superType.container │ └── org.eclipse.wst.jsdt.ui.superType.name ├── pom.xml ├── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── gome/ │ │ └── testclover/ │ │ ├── init/ │ │ │ ├── InitAllJobWithServlet.java │ │ │ ├── InitServletWithSchedulerClientInitial.java │ │ │ ├── InitServletWithStartup.java │ │ │ └── InitSpringAnnotationWithStartup.java │ │ ├── localjob/ │ │ │ ├── CronLocalJob.java │ │ │ ├── FixedTimeLocalJob.java │ │ │ └── LocalJobTest.java │ │ ├── remotejob/ │ │ │ └── RemoteCronJob.java │ │ └── spring/ │ │ ├── MyRemoteJob.java │ │ ├── RemoteCronJobWithSpringAnnotation.java │ │ ├── RemoteFixedDateJobWithSpringAnnotation.java │ │ ├── RemoteJob1WithSpring.java │ │ ├── RemoteJob1WithSpringAnnotation.java │ │ ├── RemoteJob2WithSpring.java │ │ ├── RemoteJob2WithSpringAnnotation.java │ │ ├── RemoteJob3WithSpring.java │ │ ├── RemoteJob3WithSpringAnnotation.java │ │ ├── RemoteJobWithSpring.java │ │ └── RemoteJobWithSpringAnnotation.java │ ├── resources/ │ │ └── spring-config.xml │ └── webapp/ │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── WEB-INF/ │ │ └── web.xml │ └── index.jsp └── test-clover.iml ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # clover clover 1、开发server和client端 定时向zk集群发送心跳数据包,利用Java自带的timer程序实现该功能 2、开发整天的monitor程序,用来定时向zk中获取server和client端的心跳数据信息,如果超过指定时间没有收到最新的数据包,那么任务server端或者client端死掉了,此时要删除该server或client端节点,发邮件通知相关人员,记录异常日志到系统日志文件和MongoDB中 3、client端接受创建job请求,将job信息创建到client服务端,并根据job时间规则运行,并将任务信息存储到MongoDB中 4、当client端job运行时候,封装执行任务信息,发送到指定客户端机器,更新client端job执行时间和状态,如不在需要继续运行,那删除job并从MongoDB中删除相关任务信息 5、client端接受删除job请求,client服务端,立即执行删除job并将任务信息从MongoDB中删除 6、client端接受更新job请求,client服务端,立即执行删除job并创建新job,并将任务信息从MongoDB中删除,然后再存储新job信息 7、第一版 使用Netty做消息通讯中间件,存储消息放入Redis中,服务器开启Http请求,客户端 通过 发送Http请求到服务器来处理请求,由于任务太多 redis处理能力不行,放弃该方案 第二版 使用Netty RPC框架,自己开发一个Server端和Client,各种启动指定端口,由于 必须要求Server端和Client必须启动才能进行消息发送,所以感觉非常不灵活,因为放弃该方案 第三版 使用架构组推荐的rocketmq,通过使用发现,很严重问题,消息会重复发送,经常会收到重复的消息,在测试的时候发现,经常发生消息异常和报错,跟架构组刘婷峰沟通说,可能是机器性能不行了,他也不知道具体原因,感觉非常不靠谱,果断放弃 第四版 使用 zeromq,通过在网上查资料,对比各种mq后,发现zeromq是最轻量级,出现消息是最快的,经过测试完全能满足业务,果断使用 8、由于项目中使用zk,自己开发zk使用工具类,定制server端增删改查zk消息以及定制client端增删改查zk消息,功能测试zk,目前打算增加zk watch功能 9、开发server和client端 定时向zk集群发送心跳数据包,利用Java自带的timer程序实现该功能 10、开发整天的monitor程序,用来定时向zk中获取server和client端的心跳数据信息,如果超过指定时间没有收到最新的数据包,那么任务server端或者client端死掉了,此时要删除该server或client端节点,发邮件通知相关人员,记录异常日志到系统日志文件和MongoDB中 11、开发console控制台管理,可以查看任务动态运行状态和次数信息 12、zk管理页面,查看server和client端节点信息,更新和删除节点信息 13、job管理页面,查看job详细信息 14、联系人管理页面,增删改查联系人信息 15、log日志管理页面,根据系统报错记录的日志信息,在页面中可以详细查看 ================================================ FILE: clover/.gitignore ================================================ # maven ignore target/ # eclipse ignore .settings/ .project .classpath # idea ignore .idea/ *.ipr *.iml *.iws # temp ignore *.log *.cache *.diff *.patch *.tmp # system ignore .DS_Store Thumbs.db # package ignore (optional) # *.jar # *.war # *.zip # *.tar # *.tar.gz ================================================ FILE: clover/README.md ================================================ #clover 1、开发server和client端 定时向zk集群发送心跳数据包,利用Java自带的timer程序实现该功能 2、开发整天的monitor程序,用来定时向zk中获取server和client端的心跳数据信息,如果超过指定时间没有收到最新的数据包,那么任务server端或者client端死掉了,此时要删除该server或client端节点,发邮件通知相关人员,记录异常日志到系统日志文件和MongoDB中 3、client端接受创建job请求,将job信息创建到client服务端,并根据job时间规则运行,并将任务信息存储到MongoDB中 4、当client端job运行时候,封装执行任务信息,发送到指定客户端机器,更新client端job执行时间和状态,如不在需要继续运行,那删除job并从MongoDB中删除相关任务信息 5、client端接受删除job请求,client服务端,立即执行删除job并将任务信息从MongoDB中删除 6、client端接受更新job请求,client服务端,立即执行删除job并创建新job,并将任务信息从MongoDB中删除,然后再存储新job信息 7、第一版 使用Netty做消息通讯中间件,存储消息放入Redis中,服务器开启Http请求,客户端 通过 发送Http请求到服务器来处理请求,由于任务太多 redis处理能力不行,放弃该方案 第二版 使用Netty RPC框架,自己开发一个Server端和Client,各种启动指定端口,由于 必须要求Server端和Client必须启动才能进行消息发送,所以感觉非常不灵活,因为放弃该方案 第三版 使用架构组推荐的rocketmq,通过使用发现,很严重问题,消息会重复发送,经常会收到重复的消息,在测试的时候发现,经常发生消息异常和报错,跟架构组刘婷峰沟通说,可能是机器性能不行了,他也不知道具体原因,感觉非常不靠谱,果断放弃 第四版 使用 zeromq,通过在网上查资料,对比各种mq后,发现zeromq是最轻量级,出现消息是最快的,经过测试完全能满足业务,果断使用 8、由于项目中使用zk,自己开发zk使用工具类,定制server端增删改查zk消息以及定制client端增删改查zk消息,功能测试zk,目前打算增加zk watch功能 9、开发server和client端 定时向zk集群发送心跳数据包,利用Java自带的timer程序实现该功能 10、开发整天的monitor程序,用来定时向zk中获取server和client端的心跳数据信息,如果超过指定时间没有收到最新的数据包,那么任务server端或者client端死掉了,此时要删除该server或client端节点,发邮件通知相关人员,记录异常日志到系统日志文件和MongoDB中 11、开发console控制台管理,可以查看任务动态运行状态和次数信息 12、zk管理页面,查看server和client端节点信息,更新和删除节点信息 13、job管理页面,查看job详细信息 14、联系人管理页面,增删改查联系人信息 15、log日志管理页面,根据系统报错记录的日志信息,在页面中可以详细查看 ================================================ FILE: clover/clover-admin/pom.xml ================================================ 4.0.0 com.gome clover 1.0 clover-admin clover-admin war clover-admin src/main/resources true com.gome clover-core ${clover.version} com.gome clover-monitor ${clover.version} com.gome clover-client ${clover.version} com.gome clover-server ${clover.version} org.springframework spring-webmvc javax.servlet servlet-api 2.4 provided junit junit 4.11 test org.springframework org.springframework.test 3.2.4.RELEASE ================================================ FILE: clover/clover-admin/src/main/java/com/gome/clover/listener/Log4jConfigListener.java ================================================ package com.gome.clover.listener; import org.apache.log4j.LogManager; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.xml.DOMConfigurator; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Log4j ConfigListener * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 10:55 */ public class Log4jConfigListener implements ServletContextListener{ public static final String CONFIG_LOCATION_PARAM = "log4jConfigLocation"; public static final String XML_FILE_EXTENSION = ".xml"; public void contextDestroyed(ServletContextEvent event) { LogManager.shutdown(); } public void contextInitialized(ServletContextEvent event) { String location = event.getServletContext().getInitParameter(CONFIG_LOCATION_PARAM); if (location != null) { if (!location.startsWith("/")) { location = "/" + location; } location = event.getServletContext().getRealPath(location); //如果是xml结尾就用DOM解析,否则就用properties解析 if (location.toLowerCase().endsWith(XML_FILE_EXTENSION)) { DOMConfigurator.configure(location); }else { PropertyConfigurator.configure(location); } } } } ================================================ FILE: clover/clover-admin/src/main/java/com/gome/clover/servlet/CloverServletHandle.java ================================================ package com.gome.clover.servlet; import com.alibaba.fastjson.JSONObject; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.common.zeromq.AsyncSendMsg; import com.gome.clover.common.zeromq.ZeroMQEntity; import com.gome.clover.common.zeromq.ZeroMQPull; import com.gome.clover.common.zk.ZKUtil; import com.gome.clover.core.module.ModuleSchedulerServer; import com.gome.clover.core.monitor.server.ServerHeartBeat; import com.gome.clover.monitor.MonitorHeartBeat; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.util.JSON; import org.apache.curator.framework.CuratorFramework; import org.apache.zookeeper.CreateMode; import org.bson.types.ObjectId; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.impl.StdSchedulerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.text.ParseException; import java.util.Date; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Clover Servlet Handle * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/24 * Time: 11:30 */ public class CloverServletHandle extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(CloverServletHandle.class); private static final CuratorFramework curatorFramework = ZKUtil.create(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action = request.getParameter("action"); request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); if ("handleJobAdd".equals(action)) { out.println(handleJobAdd(request)); } else if ("handleJobUpdate".equals(action)) { } else if ("handleJobDataDelete".equals(action)) { String id = request.getParameter("id"); out.println(handleJobDataDelete(id)); } else if ("handleJobDelete".equals(action)) { String id = request.getParameter("id"); out.println(handleJobDelete(id)); } else if ("handleJobDetail".equals(action)) { String id = request.getParameter("id"); out.println(handleJobDetail(id)); } else if ("handleLogDetail".equals(action)) { String id = request.getParameter("id"); out.println(handleLogDetail(id)); } else if ("handleContactAdd".equals(action)) { out.println(handleContactAdd(request)); } else if ("handleContactUpdate".equals(action)) { out.println(handleContactUpdate(request)); } else if ("handleContactDelete".equals(action)) { out.println(handleContactDelete(request)); } else if ("handleContactDetail".equals(action)) { out.println(handleContactDetail(request)); } else if ("handleStartupCloverServer".equals(action)) { out.println(handleStartupCloverServer()); } else if ("handleStopCloverServer".equals(action)) { out.println(handleStopCloverServer()); } else if ("handleStartupServerHeartBeat".equals(action)) { out.println(handleStartupServerHeartBeat()); } else if ("handleStopServerHeartBeat".equals(action)) { out.println(handleStopServerHeartBeat()); } else if ("handleStartupMonitorHeartBeat".equals(action)) { out.println(handleStartupMonitorHeartBeat()); } else if ("handleStopMonitorHeartBeat".equals(action)) { out.println(handleStopMonitorHeartBeat()); } out.flush(); out.close(); } private String handleJobAdd(HttpServletRequest request) { try { BasicDBObject basicDBObject = new BasicDBObject(); basicDBObject.put("jobGroup", request.getParameter("jobGroup")); basicDBObject.put("jobName", request.getParameter("jobName")); basicDBObject.put("jobType", request.getParameter("jobType")); basicDBObject.put("jobStrategy", request.getParameter("jobStrategy")); basicDBObject.put("executeType", request.getParameter("executeType")); basicDBObject.put("jobClassName", request.getParameter("jobClassName")); basicDBObject.put("startTime", request.getParameter("startTime")); basicDBObject.put("cronExpression", request.getParameter("cronExpression")); String ip = request.getParameter("ip"); String port = request.getParameter("port"); basicDBObject.put("ip", ip); basicDBObject.put("port", port); basicDBObject.put("fixedClientIps", request.getParameter("fixedClientIps")); basicDBObject.put("fixedServerIps", request.getParameter("fixedServerIps")); String msg = JSON.serialize(basicDBObject); ZeroMQEntity zeroMQEntity = new ZeroMQEntity(CommonConstants.MODULE_TYPE_CLIENT_WITH_ADMIN, ip, null, msg); //AsyncSendMsg.send(ip, port, com.alibaba.fastjson.JSON.toJSONString(zeroMQEntity)); return "1"; } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleJobAdd(HttpServletRequest request) error,", e); return "-1"; } } private String handleJobDataDelete(String id) { try { return MongoDBUtil.INSTANCE.delete(new BasicDBObject( DBTableInfo.COL_ID, new ObjectId(id)), DBTableInfo.TBL_CLOVER_JOB) ? "1" : "-1"; } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleContactDetail(" + id + ") error,", e); return "-1"; } } private String handleJobDelete(String id) { try { DBObject dbObject = MongoDBUtil.INSTANCE.findOneByCondition(new BasicDBObject( DBTableInfo.COL_ID, new ObjectId(id)), DBTableInfo.TBL_CLOVER_JOB); if (null != dbObject) { MongoDBUtil.INSTANCE.delete(new BasicDBObject( DBTableInfo.COL_ID, new ObjectId(id)), DBTableInfo.TBL_CLOVER_JOB); String serverIp = (String) dbObject.get(DBTableInfo.COL_SERVER_IP); String jobKey = (String) dbObject.get(DBTableInfo.COL_JOB_KEY); String jobGroup = jobKey.substring(0, jobKey.lastIndexOf(".")); String jobName = jobKey.substring(jobKey.lastIndexOf(".") + 1); if (IpUtil.getLocalIP().equals(serverIp)) { try { Scheduler scheduler = new StdSchedulerFactory().getScheduler(); JobKey jobKey4Delete = new JobKey(jobName, jobGroup); if (scheduler.checkExists(jobKey4Delete)) { return scheduler.deleteJob(jobKey4Delete) ? "1" : "-1"; } } catch (SchedulerException e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverServletHandle-->>handleJobDelete(" + id + ") error," + e.getMessage()); return "-1"; } } else if (!StringUtil.isEmpty(serverIp)) { BasicDBObject basicDBObject = new BasicDBObject(); basicDBObject.put("jobGroup", jobGroup); basicDBObject.put("jobName", jobName); String msg = JSON.serialize(basicDBObject); ZeroMQEntity zeroMQEntity = new ZeroMQEntity(CommonConstants.MODULE_TYPE_SERVER_WITH_ADMIN, serverIp, null, msg); String serverPathStr = CommonConstants.ZK_ROOT_PATH + "/" + CommonConstants.MODULE_TYPE_SERVER; String port = ZKUtil.getDataByParameter(serverPathStr, "ip", serverIp, "port"); if (!StringUtil.isEmpty(port)) { return "-1"; //AsyncSendMsg.send(serverIp, port, com.alibaba.fastjson.JSON.toJSONString(zeroMQEntity)) ? "1" : "-1"; } else { return "-1"; } } } else { return "-1"; } } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleJobDelete(" + id + ") error,", e); return "-1"; } return "-1"; } private String handleJobDetail(String id) { try { DBObject dbObject = MongoDBUtil.INSTANCE.findOneByCondition(new BasicDBObject( DBTableInfo.COL_ID, new ObjectId(id)), DBTableInfo.TBL_CLOVER_JOB); if (null != dbObject) { //构造json对象 JSONObject json = new JSONObject(); json.put("jobKey", dbObject.get(DBTableInfo.COL_JOB_KEY)); json.put("jobType", dbObject.get(DBTableInfo.COL_JOB_TYPE)); json.put("executeType", dbObject.get(DBTableInfo.COL_EXECUTE_TYPE)); json.put("jobStrategy", dbObject.get(DBTableInfo.COL_JOB_STRATEGY)); json.put("startTime", dbObject.get(DBTableInfo.COL_START_TIME)); String cronExpressionStr = (String) dbObject.get(DBTableInfo.COL_CRON_EXPRESSION); json.put("cronExpression", cronExpressionStr); String nextValidTime = ""; if (!StringUtil.isEmpty(cronExpressionStr)) { if (null != dbObject.get(DBTableInfo.COL_CRON_EXPRESSION)) { try { nextValidTime = DateUtil.formatWithDefaultPattern( DateUtil.getNextValidTimeAfter(cronExpressionStr, new Date())); } catch (ParseException e) { e.printStackTrace(); logger.error("CloverServletHandle-->>handleJobDetail(" + id + ") error," + e.getMessage()); } } } json.put("nextValidTime", nextValidTime); /* String classPath = System.getProperty("user.dir"); MyClassLoader cl = new MyClassLoader(classPath); String className = "com.gome.clover.job.MyJobWithSimpleJob"; CreateAndCompileClassFile.compileAndLoading(classPath,className); try { Class cls=cl.loadClass(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } json.put("jobInfo", JSON.toJSONString((ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64( (String) dbObject.get(DBTableInfo.COL_JOB_INFO)))));*/ json.put("ip", dbObject.get(DBTableInfo.COL_IP)); json.put("fixedClientIps", dbObject.get(DBTableInfo.COL_FIXED_CLIENT_IPS)); json.put("fixedServerIps", dbObject.get(DBTableInfo.COL_FIXED_SERVER_IPS)); json.put("executeStartTime", dbObject.get(DBTableInfo.COL_EXECUTE_START_TIME)); json.put("executeEndTime", dbObject.get(DBTableInfo.COL_EXECUTE_END_TIME)); json.put("times", dbObject.get(DBTableInfo.COL_TIMES)); json.put("failTimes", dbObject.get(DBTableInfo.COL_FAIL_TIMES)); json.put("status", CommonConstants.JOB_STATUS_1.equals(dbObject.get(DBTableInfo.COL_STATUS)) ? "初始化状态" : "运行中状态"); json.put("ts", dbObject.get(DBTableInfo.COL_TS)); return json.toString(); } else { return ""; } } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleJobDetail(" + id + ") error,", e); return "-1"; } } private String handleLogDetail(String id) { try { DBObject dbObject = MongoDBUtil.INSTANCE.findOneByCondition(new BasicDBObject( DBTableInfo.COL_ID, new ObjectId(id)), DBTableInfo.TBL_CLOVER_LOG); if (null != dbObject) { //构造json对象 JSONObject json = new JSONObject(); json.put("systemId", dbObject.get(DBTableInfo.COL_SYSTEM_ID)); json.put("ip", dbObject.get(DBTableInfo.COL_IP)); json.put("jobKey", dbObject.get(DBTableInfo.COL_JOB_KEY)); json.put("execMethod", dbObject.get(DBTableInfo.COL_EXEC_METHOD)); json.put("execResult", dbObject.get(DBTableInfo.COL_EXEC_RESULT)); json.put("execTime", dbObject.get(DBTableInfo.COL_EXEC_TIME)); json.put("ts", dbObject.get(DBTableInfo.COL_TS)); return json.toString(); } else { return ""; } } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleLogDetail(" + id + ") error,", e); return "-1"; } } private String handleContactAdd(HttpServletRequest request) { try { BasicDBObject document = new BasicDBObject(); String systemId = request.getParameter("systemId"); document.put(DBTableInfo.COL_SYSTEM_ID, StringUtil.isEmpty(systemId) ? "" : systemId); String ip = request.getParameter("ip"); document.put(DBTableInfo.COL_IP, StringUtil.isEmpty(ip) ? "" : ip); String jobKey = request.getParameter("jobKey"); document.put(DBTableInfo.COL_JOB_KEY, StringUtil.isEmpty(jobKey) ? "" : jobKey); String contacter = request.getParameter("contacter"); document.put(DBTableInfo.COL_CONTACTER, StringUtil.isEmpty(contacter) ? "" : contacter); String email = request.getParameter("email"); document.put(DBTableInfo.COL_EMAIL, StringUtil.isEmpty(email) ? "" : email); String mobile = request.getParameter("mobile"); document.put(DBTableInfo.COL_MOBILE, StringUtil.isEmpty(mobile) ? "" : mobile); document.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); return MongoDBUtil.INSTANCE.insertOrUpdate(document, DBTableInfo.TBL_CLOVER_CONTACT) ? "1" : "-1"; } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleContactAdd(HttpServletRequest request) error,", e); return "-1"; } } private String handleContactUpdate(HttpServletRequest request) { try { BasicDBObject document = new BasicDBObject(); String id = request.getParameter("id"); String systemId = request.getParameter("systemId"); document.put(DBTableInfo.COL_SYSTEM_ID, StringUtil.isEmpty(systemId) ? "" : systemId); String ip = request.getParameter("ip"); document.put(DBTableInfo.COL_IP, StringUtil.isEmpty(ip) ? "" : ip); String jobKey = request.getParameter("jobKey"); document.put(DBTableInfo.COL_JOB_KEY, StringUtil.isEmpty(jobKey) ? "" : jobKey); String contacter = request.getParameter("contacter"); document.put(DBTableInfo.COL_CONTACTER, StringUtil.isEmpty(contacter) ? "" : contacter); String email = request.getParameter("email"); document.put(DBTableInfo.COL_EMAIL, StringUtil.isEmpty(email) ? "" : email); String mobile = request.getParameter("mobile"); document.put(DBTableInfo.COL_MOBILE, StringUtil.isEmpty(mobile) ? "" : mobile); document.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); return MongoDBUtil.INSTANCE.update(new BasicDBObject( DBTableInfo.COL_ID, new ObjectId(id)), document, DBTableInfo.TBL_CLOVER_CONTACT) ? "1" : "-1"; } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleContactUpdate(HttpServletRequest request) error,", e); return "-1"; } } private String handleContactDelete(HttpServletRequest request) { try { String id = request.getParameter("id"); return MongoDBUtil.INSTANCE.delete(new BasicDBObject( DBTableInfo.COL_ID, new ObjectId(id)), DBTableInfo.TBL_CLOVER_CONTACT) ? "1" : "-1"; } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleContactDelete(HttpServletRequest request) error,", e); return "-1"; } } private String handleContactDetail(HttpServletRequest request) { try { String id = request.getParameter("id"); DBObject dbObject = MongoDBUtil.INSTANCE.findOneByCondition(new BasicDBObject( DBTableInfo.COL_ID, new ObjectId(id)), DBTableInfo.TBL_CLOVER_CONTACT); if (null != dbObject) { //构造json对象 JSONObject json = new JSONObject(); json.put(DBTableInfo.COL_SYSTEM_ID, dbObject.get(DBTableInfo.COL_SYSTEM_ID)); json.put(DBTableInfo.COL_IP, dbObject.get(DBTableInfo.COL_IP)); json.put(DBTableInfo.COL_JOB_KEY, dbObject.get(DBTableInfo.COL_JOB_KEY)); json.put(DBTableInfo.COL_CONTACTER, dbObject.get(DBTableInfo.COL_CONTACTER)); json.put(DBTableInfo.COL_EMAIL, dbObject.get(DBTableInfo.COL_EMAIL)); json.put(DBTableInfo.COL_MOBILE, dbObject.get(DBTableInfo.COL_MOBILE)); json.put(DBTableInfo.COL_TS, dbObject.get(DBTableInfo.COL_TS)); return json.toString(); } else { return ""; } } catch (Exception e) { if (logger.isDebugEnabled()) System.err.println(e.getMessage()); logger.error("CloverServletHandle-->>handleContactDetail(HttpServletRequest request) error,", e); return "-1"; } } private String handleStartupCloverServer() { try { if (!curatorFramework.isStarted()) curatorFramework.start(); String serverDataStr = ZKUtil.getData(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP()); BasicDBObject serverData; if (!StringUtil.isEmpty(serverDataStr)) { serverData = (BasicDBObject) JSON.parse(serverDataStr); serverData.put("cloverServerStatus", "1"); serverData.put("cloverServerTS", DateUtil.currentDateTime()); } else { serverData = new BasicDBObject(); serverData.put("cloverServerStatus", "1"); serverData.put("cloverServerTS", DateUtil.currentDateTime()); } ZKUtil.setPath(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP(), serverData.toString(), CreateMode.EPHEMERAL); ModuleSchedulerServer.getInstance().startup(); return "1"; } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverServletHandle-->>handleStartupCloverServer() error,", e); return "-1"; } } private String handleStopCloverServer() { try { if (!curatorFramework.isStarted()) curatorFramework.start(); String serverDataStr = ZKUtil.getData(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP()); BasicDBObject serverData; if (!StringUtil.isEmpty(serverDataStr)) { serverData = (BasicDBObject) JSON.parse(serverDataStr); serverData.put("cloverServerStatus", "0"); serverData.put("cloverServerTS", DateUtil.currentDateTime()); } else { serverData = new BasicDBObject(); serverData.put("cloverServerStatus", "0"); serverData.put("cloverServerTS", DateUtil.currentDateTime()); } ZKUtil.setPath(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP(), serverData.toString(), CreateMode.EPHEMERAL); ModuleSchedulerServer.getInstance().stop(); ZeroMQPull.INSTANCE.stop(IpUtil.getLocalIP(),CommonConstants.ZMQ_SERVER_PORT); return "1"; } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverServletHandle-->>handleStopCloverServer() error,", e); return "-1"; } } private String handleStartupServerHeartBeat() { try { if (!curatorFramework.isStarted()) curatorFramework.start(); String serverDataStr = ZKUtil.getData(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP()); BasicDBObject serverData; if (!StringUtil.isEmpty(serverDataStr)) { serverData = (BasicDBObject) JSON.parse(serverDataStr); serverData.put("serverHeartBeatStatus", "1"); serverData.put("serverHeartBeatTS", DateUtil.currentDateTime()); } else { serverData = new BasicDBObject(); serverData.put("serverHeartBeatStatus", "1"); serverData.put("serverHeartBeatTS", DateUtil.currentDateTime()); } ZKUtil.setPath(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP(), serverData.toString(), CreateMode.EPHEMERAL); ServerHeartBeat.INSTNACE.startup(); return "1"; } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverServletHandle-->>startupMonitorHeartBeat() error,", e); return "-1"; } } private String handleStopServerHeartBeat() { try { if (!curatorFramework.isStarted()) curatorFramework.start(); String serverDataStr = ZKUtil.getData(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP()); BasicDBObject serverData; if (!StringUtil.isEmpty(serverDataStr)) { serverData = (BasicDBObject) JSON.parse(serverDataStr); serverData.put("serverHeartBeatStatus", "0"); serverData.put("serverHeartBeatTS", DateUtil.currentDateTime()); } else { serverData = new BasicDBObject(); serverData.put("serverHeartBeatStatus", "0"); serverData.put("serverHeartBeatTS", DateUtil.currentDateTime()); } ZKUtil.setPath(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP(), serverData.toString(), CreateMode.EPHEMERAL); ServerHeartBeat.INSTNACE.stop(); return "1"; } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverServletHandle-->>startupMonitorHeartBeat() error,", e); return "-1"; } } private String handleStartupMonitorHeartBeat() { try { if (!curatorFramework.isStarted()) curatorFramework.start(); String serverDataStr = ZKUtil.getData(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP()); BasicDBObject serverData; if (!StringUtil.isEmpty(serverDataStr)) { serverData = (BasicDBObject) JSON.parse(serverDataStr); serverData.put("monitorHeartBeatStatus", "1"); serverData.put("monitorHeartBeatTS", DateUtil.currentDateTime()); } else { serverData = new BasicDBObject(); serverData.put("monitorHeartBeatStatus", "1"); serverData.put("monitorHeartBeatTS", DateUtil.currentDateTime()); } ZKUtil.setPath(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP(), serverData.toString(), CreateMode.EPHEMERAL); MonitorHeartBeat.INSTNACE.startup(); return "1"; } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverServletHandle-->>startupMonitorHeartBeat() error,", e); return "-1"; } } private String handleStopMonitorHeartBeat() { try { if (!curatorFramework.isStarted()) curatorFramework.start(); String serverDataStr = ZKUtil.getData(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP()); BasicDBObject serverData; if (!StringUtil.isEmpty(serverDataStr)) { serverData = (BasicDBObject) JSON.parse(serverDataStr); serverData.put("monitorHeartBeatStatus", "0"); serverData.put("monitorHeartBeatTS", DateUtil.currentDateTime()); } else { serverData = new BasicDBObject(); serverData.put("monitorHeartBeatStatus", "0"); serverData.put("monitorHeartBeatTS", DateUtil.currentDateTime()); } ZKUtil.setPath(curatorFramework, CommonConstants.ZK_ROOT_PATH + "/monitor/server/" + IpUtil.getLocalIP(), serverData.toString(), CreateMode.EPHEMERAL); MonitorHeartBeat.INSTNACE.stop(); return "1"; } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverServletHandle-->>startupMonitorHeartBeat() error,", e); return "-1"; } } } ================================================ FILE: clover/clover-admin/src/main/java/com/gome/testclover/spring/RemoteCronJobWithSpringAnnotation.java ================================================ package com.gome.testclover.spring; import com.gome.bg.clover.client.job.RemoteJob; import com.gome.clover.common.annotation.CloverJobAnnotation; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.core.job.ClientJob; import org.quartz.JobExecutionContext; import org.springframework.stereotype.Component; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Log4j ConfigListener * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 10:55 */ @Component @CloverJobAnnotation(jobGroup = "RemoteJobWithSpringAnnotationGroup",jobName = "RemoteJobWithSpringAnnotationName", jobType = ClientJob.JobType.REMOTE,executeType = ClientJob.ExecuteType.ADD,cronExpression="0/10 * * * * ?") public class RemoteCronJobWithSpringAnnotation extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJobWithSpringAnnotation--->>>executeJob(JobExecutionContext) @"+ DateUtil.currentDateTime()); } } ================================================ FILE: clover/clover-admin/src/main/java/com/gome/testclover/spring/RemoteFixedDateJobWithSpring.java ================================================ package com.gome.testclover.spring; import com.gome.bg.clover.client.job.RemoteJob; import com.gome.clover.common.tools.DateUtil; import org.quartz.JobExecutionContext; public class RemoteFixedDateJobWithSpring extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteFixedDateJobWithSpring--->>>executeJob(JobExecutionContext) @"+ DateUtil.currentDateTime()); } } ================================================ FILE: clover/clover-admin/src/main/java/com/gome/testclover/spring/RemoteFixedDateJobWithSpringAnnotation.java ================================================ package com.gome.testclover.spring; import com.gome.bg.clover.client.job.RemoteJob; import com.gome.clover.common.annotation.CloverJobAnnotation; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.core.job.ClientJob; import org.quartz.JobExecutionContext; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Log4j ConfigListener * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 10:55 */ //@Component @CloverJobAnnotation(jobGroup = "RemoteJobWithSpringAnnotationGroup",jobName = "RemoteJobWithSpringAnnotationName", jobType = ClientJob.JobType.REMOTE,executeType = ClientJob.ExecuteType.ADD,startTime="2014-12-12 12:12:12") public class RemoteFixedDateJobWithSpringAnnotation extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJobWithSpringAnnotation--->>>executeJob(JobExecutionContext) @"+ DateUtil.currentDateTime()); } } ================================================ FILE: clover/clover-admin/src/main/java/com/gome/testclover/spring/RemoteJobWithSpring.java ================================================ package com.gome.testclover.spring; import com.gome.bg.clover.client.job.RemoteJob; import com.gome.clover.common.tools.DateUtil; import org.quartz.JobExecutionContext; public class RemoteJobWithSpring extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJobWithSpring--->>>executeJob(JobExecutionContext) @"+ DateUtil.currentDateTime()); } } ================================================ FILE: clover/clover-admin/src/main/java/com/gome/testclover/spring/TestProperties.java ================================================ package com.gome.testclover.spring; import com.gome.clover.common.tools.PropertiesUtil; import java.util.Properties; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2015/1/7 * Time: 16:49 */ public class TestProperties { public static void main(String[] args) { Properties properties = PropertiesUtil.loadProperties("conf/config.properties"); String cloverServerStatus = (String) properties.get("cloverServerStatus"); System.err.println(""+cloverServerStatus); properties.setProperty("cloverServerStatus","1"); PropertiesUtil.writePropertiesFile("conf/config.properties",properties); properties = PropertiesUtil.loadProperties("conf/config.properties"); System.err.println(""+properties.get("cloverServerStatus")); } } ================================================ FILE: clover/clover-admin/src/main/resources/bak_log4j.properties ================================================ #将ibatis log4j运行级别调到DEBUG可以在控制台打印出ibatis运行的sql语句 log4j.rootLogger=debug,stdout,logfile ### 把日志信息输出到控制台 ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender #log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout ### 把日志信息输出到文件:jbit.log ### log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=/export/home/tomcat/logs/clover.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n ###显示SQL语句部分 log4j.logger.com.ibatis=DEBUG log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG ================================================ FILE: clover/clover-admin/src/main/resources/conf/config.properties ================================================ cloverServerStatus=0 cloverServerTS serverHeartBeatStatus=0 serverHeartBeatTS monitorHeartBeatStatus=0 monitorHeartBeatTS ================================================ FILE: clover/clover-admin/src/main/resources/log4j.xml ================================================ ================================================ FILE: clover/clover-admin/src/main/resources/spring/spring-config.xml ================================================ ================================================ FILE: clover/clover-admin/src/main/webapp/WEB-INF/web.xml ================================================ encodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 forceEncoding true encodingFilter /* log4jConfigLocation /WEB-INF/classes/log4j.xml com.gome.clover.listener.Log4jConfigListener cloverServletHandle com.gome.clover.servlet.CloverServletHandle 0 cloverServletHandle /servlet/cloverServletHandle.do ================================================ FILE: clover/clover-admin/src/main/webapp/common/head.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path; %> clover manager system ================================================ FILE: clover/clover-admin/src/main/webapp/common/nav.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path; %> ================================================ FILE: clover/clover-admin/src/main/webapp/contactList.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="com.gome.clover.common.mongodb.DBTableInfo" %> <%@ page import="com.gome.clover.common.mongodb.MongoDBUtil" %> <%@ page import="com.gome.clover.common.tools.StringUtil" %> <%@ page import="com.mongodb.BasicDBObject" %> <%@ page import="com.mongodb.DBCursor" %> <%@ page import="com.mongodb.DBObject" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; String qSystemId = request.getParameter("qSystemId"); String qJobKey = request.getParameter("qJobKey"); String qIp = request.getParameter("qIp"); String qExecMethod = request.getParameter("qExecMethod"); DBObject condition = new BasicDBObject(); if (!StringUtil.isEmpty(qSystemId)) condition.put(DBTableInfo.COL_SYSTEM_ID, qSystemId); if (!StringUtil.isEmpty(qJobKey)) condition.put(DBTableInfo.COL_JOB_KEY, qJobKey); if (!StringUtil.isEmpty(qIp)) condition.put(DBTableInfo.COL_IP, qIp); if (!StringUtil.isEmpty(qExecMethod)) condition.put(DBTableInfo.COL_EXEC_METHOD, qExecMethod); DBCursor dbCursor = MongoDBUtil.INSTANCE.findByCondition(condition,DBTableInfo.TBL_CLOVER_CONTACT); %>
System Id: "> ip: "> Job Key: "> Exec Method: ">
新建
<% if(null!=dbCursor && dbCursor.size()>0){ while (dbCursor.hasNext()) { DBObject tempDBObject = dbCursor.next(); %> <% } }else { %> <% } %>
systemId ip jobKey contacter email mobile ts 操作
<%=tempDBObject.get(DBTableInfo.COL_SYSTEM_ID)%> <%=tempDBObject.get(DBTableInfo.COL_IP)%> <%=tempDBObject.get(DBTableInfo.COL_JOB_KEY)%> <%=tempDBObject.get(DBTableInfo.COL_CONTACTER)%> <%=tempDBObject.get(DBTableInfo.COL_EMAIL)%> <%=tempDBObject.get(DBTableInfo.COL_MOBILE)%> <%=tempDBObject.get(DBTableInfo.COL_TS)%> 修改 删除 查看
暂无相关记录
================================================ FILE: clover/clover-admin/src/main/webapp/css/style.css ================================================ body {padding-top:60px; padding-bottom:40px;} .sidebar-nav {padding:9px 0;} /*pagin&&pagin-m*/ .pagin a,.pagin span{float:left;height:20px;padding:3px 10px;border:1px solid #ccc;margin-left:2px;font-family:arial;line-height:20px;font-size:14px;overflow:hidden;-moz-border-radius:5px;-webkit-border-radius:5px;} .pagin .text,.pagin .current{border:none;padding:4px 11px;} .pagin a:link,.pagin a:visited{color:#005aa0;} .pagin a:hover,.pagin a:active{background:#005aa0;color:#fff;text-decoration:none;} .pagin .current,.pagin .current:link,.pagin .current:visited{color:#f60;font-weight:bold;} .pagin b{dispaly:block;position:absolute;top:9px;width:5px;height:9px;background-image:url(i/bg_hotsale.gif);background-repeat:no-repeat;overflow:hidden;} .pagin .prev,.pagin .next,.pagin .prev-disabled,.pagin .next-disabled{position:relative;padding-top:5px;height:18px;line-height:18px;} .pagin .prev-disabled,.pagin .next-disabled{color:#ccc;cursor:default;} .pagin .prev,.pagin .prev-disabled{padding-left:12px;} .pagin .prev b{left:3px;background-position:-68px -608px;} .pagin .prev-disabled b{left:3px;background-position:-80px -608px;} .pagin .next,.pagin .next-disabled{padding-right:12px;} .pagin .next b{right:3px;background-position:-62px -608px;} .pagin .next-disabled b{right:3px;background-position:-74px -608px;} .pagin-m a,.pagin-m span{height:14px;line-height:14px;font-size:12px;} .pagin-m b{top:5px;} .pagin-m .prev,.pagin-m .next,.pagin-m .prev-disabled,.pagin-m .next-disabled{padding-top:3px;height:14px;line-height:14px;*line-height:16px;} .float_div{ border:2px solid #3694e0; background:#fff; width:600px; height:400px;} .float_div h2{ background:url(i/float_divbg.gif); margin:1px; height:30px; line-height:30px; color:#fff; text-indent:10px;} .float_div span{ font-size:12px; width:50px; text-align:right; padding-right:10px; overflow:hidden; float:right; font-family:Arial, Helvetica, sans-serif;} .float_div span a{ color:#f0ff00;} /**/ ================================================ FILE: clover/clover-admin/src/main/webapp/error.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

404! 您请求的内容不存在 出错了: 出错了系统错误!

================================================ FILE: clover/clover-admin/src/main/webapp/index.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path; %>
================================================ FILE: clover/clover-admin/src/main/webapp/jobList.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="com.gome.clover.common.mongodb.DBTableInfo" %> <%@ page import="com.gome.clover.common.mongodb.MongoDBUtil" %> <%@ page import="com.gome.clover.common.tools.CommonConstants" %> <%@ page import="com.gome.clover.common.tools.DateUtil" %> <%@ page import="com.gome.clover.common.tools.StringUtil" %> <%@ page import="com.mongodb.BasicDBObject" %> <%@ page import="com.mongodb.DBCursor" %> <%@ page import="com.mongodb.DBObject" %> <%@ page import="java.util.Date" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path; String qJobKey = request.getParameter("qJobKey"); String qJobType = request.getParameter("qJobType"); String qIp = request.getParameter("qIp"); String qStatus = request.getParameter("qStatus"); DBObject condition = new BasicDBObject(); if (!StringUtil.isEmpty(qJobKey)) condition.put(DBTableInfo.COL_JOB_KEY, qJobKey); if (!StringUtil.isEmpty(qJobType)) condition.put(DBTableInfo.COL_JOB_TYPE, qJobType); if (!StringUtil.isEmpty(qIp)) condition.put(DBTableInfo.COL_IP, qIp); if (!StringUtil.isEmpty(qStatus)) condition.put(DBTableInfo.COL_STATUS, qStatus); DBCursor dbCursor = MongoDBUtil.INSTANCE.findByCondition(condition,DBTableInfo.TBL_CLOVER_JOB); %>
Job Key: "/> ip: "/>
新建
<% if(null!=dbCursor && dbCursor.size()>0){ while (dbCursor.hasNext()) { DBObject tempDBObject = dbCursor.next(); String nextValidTime = ""; if(tempDBObject.containsField(DBTableInfo.COL_CRON_EXPRESSION) && StringUtil.isNotBlank((String)tempDBObject.get(DBTableInfo.COL_CRON_EXPRESSION))) { nextValidTime = DateUtil.formatWithDefaultPattern( DateUtil.getNextValidTimeAfter((String) tempDBObject.get(DBTableInfo.COL_CRON_EXPRESSION), new Date())); } %> <% } }else { %> <% } %>
Job Key Job Type Start Time Cron Expression Client Ip Server Ip Execute Start Time Execute End Time times Fail Times status ts 操作
<%=tempDBObject.get(DBTableInfo.COL_JOB_KEY)%> <%=tempDBObject.get(DBTableInfo.COL_JOB_TYPE)%> <%=tempDBObject.get(DBTableInfo.COL_START_TIME)%> <% if(null!= nextValidTime && nextValidTime.length()>0){ %> <%=tempDBObject.get(DBTableInfo.COL_CRON_EXPRESSION)%> <% } %> <%=tempDBObject.get(DBTableInfo.COL_CLIENT_IP)%> <%=tempDBObject.get(DBTableInfo.COL_SERVER_IP)%> <%=tempDBObject.get(DBTableInfo.COL_EXECUTE_START_TIME)%> <%=tempDBObject.get(DBTableInfo.COL_EXECUTE_END_TIME)%> <%=tempDBObject.get(DBTableInfo.COL_TIMES)%> <%=tempDBObject.get(DBTableInfo.COL_FAIL_TIMES)%> <%=CommonConstants.JOB_STATUS_1.equals(tempDBObject.get(DBTableInfo.COL_STATUS))? "初始化状态":"运行中状态"%> <%=tempDBObject.get(DBTableInfo.COL_TS)%> <%-- 修改--%> 查看 删除
暂无相关记录
================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/DatePicker.htm ================================================ DatePicker ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/WdatePicker.js ================================================ /* * jdDate by beiqiu */ var $dp,WdatePicker; (function() { var _ = { $wdate:true, $dpPath:"", $crossFrame:true, doubleCalendar:false, enableKeyboard:true, autoUpdateOnChanged:null, whichDayIsfirstWeek:4, position:{}, lang:"auto", skin:"ext", dateFmt:"yyyy-MM-dd", realDateFmt:"yyyy-MM-dd", realTimeFmt:"HH:mm:ss", realFullFmt:"%Date %Time", minDate:"1900-01-01 00:00:00", maxDate:"2099-12-31 23:59:59", startDate:"", alwaysUseStartDate:false, yearOffset:1911, firstDayOfWeek:0, isShowWeek:false, highLineWeekDay:true, isShowClear:true, isShowToday:true, isShowOK:true, isShowOthers:true, readOnly:false, errDealMode:0, autoPickDate:null, qsEnabled:true, specialDates:null,specialDays:null,disabledDates:null,disabledDays:null,opposite:false,onpicking:null,onpicked:null,onclearing:null,oncleared:null,ychanging:null,ychanged:null,Mchanging:null,Mchanged:null,dchanging:null,dchanged:null,Hchanging:null,Hchanged:null,mchanging:null,mchanged:null,schanging:null,schanged:null,eCont:null,vel:null,errMsg:"",quickSel:[],has:{}}; WdatePicker = U; var X = window,O = "document",J = "documentElement",C = "getElementsByTagName",V,A,T,I,b; switch (navigator.appName) {case"Microsoft Internet Explorer":T = true;break;case"Opera":b = true;break;default:I = true;break } A = L(); if (_.$wdate)M(A + "skin/WdatePicker.css"); V = X; if (_.$crossFrame) { try { while (V.parent[O] != V[O] && V.parent[O][C]("frameset").length == 0)V = V.parent } catch(P) { } } if (!V.$dp)V.$dp = {ff:I,ie:T,opera:b,el:null,win:X,status:0,defMinDate:_.minDate,defMaxDate:_.maxDate,flatCfgs:[]}; B(); if ($dp.status == 0)Z(X, function() { U(null, true) }); if (!X[O].docMD) { E(X[O], "onmousedown", D); X[O].docMD = true } if (!V[O].docMD) { E(V[O], "onmousedown", D); V[O].docMD = true } E(X, "onunload", function() { if ($dp.dd)Q($dp.dd, "none") }); function B() { V.$dp = V.$dp || {}; obj = {$:function($) { return(typeof $ == "string") ? X[O].getElementById($) : $ },$D:function($, _) { return this.$DV(this.$($).value, _) },$DV:function(_, $) { if (_ != "") { this.dt = $dp.cal.splitDate(_, $dp.cal.dateFmt); if ($)for (var B in $)if (this.dt[B] === undefined)this.errMsg = "invalid property:" + B; else { this.dt[B] += $[B]; if (B == "M") { var C = $["M"] > 0 ? 1 : 0,A = new Date(this.dt["y"], this.dt["M"], 0).getDate(); this.dt["d"] = Math.min(A + C, this.dt["d"]) } } if (this.dt.refresh())return this.dt } return"" },show:function() { Q(this.dd, "block") },hide:function() { Q(this.dd, "none") },attachEvent:E}; for (var $ in obj)V.$dp[$] = obj[$]; $dp = V.$dp } function E(A, $, _) { if (T)A.attachEvent($, _); else { var B = $.replace(/on/, ""); _._ieEmuEventHandler = function($) { return _($) }; A.addEventListener(B, _._ieEmuEventHandler, false) } } function L() { var _,A,$ = X[O][C]("script"); for (var B = 0; B < $.length; B++) { _ = $[B].src.substring(0, $[B].src.toLowerCase().indexOf("wdatepicker.js")); A = _.lastIndexOf("/"); if (A > 0)_ = _.substring(0, A + 1); if (_)break } return _ } function F(F) { var E,C; if (F.substring(0, 1) != "/" && F.indexOf("://") == -1) { E = V.location.href; C = location.href; if (E.indexOf("?") > -1)E = E.substring(0, E.indexOf("?")); if (C.indexOf("?") > -1)C = C.substring(0, C.indexOf("?")); var G,I,$ = "",D = "",A = "",J,H,B = ""; for (J = 0; J < Math.max(E.length, C.length); J++) { G = E.charAt(J).toLowerCase(); I = C.charAt(J).toLowerCase(); if (G == I) { if (G == "/")H = J } else { $ = E.substring(H + 1, E.length); $ = $.substring(0, $.lastIndexOf("/")); D = C.substring(H + 1, C.length); D = D.substring(0, D.lastIndexOf("/")); break } } if ($ != "")for (J = 0; J < $.split("/").length; J++)B += "../"; if (D != "")B += D + "/"; F = E.substring(0, E.lastIndexOf("/") + 1) + B + F } _.$dpPath = F } function M(A, $, B) { var D = X[O][C]("HEAD").item(0),_ = X[O].createElement("link"); if (D) { _.href = A; _.rel = "stylesheet"; _.type = "text/css"; if ($)_.title = $; if (B)_.charset = B; D.appendChild(_) } } function Z($, _) { E($, "onload", _) } function G($) { $ = $ || V; var A = 0,_ = 0; while ($ != V) { var D = $.parent[O][C]("iframe"); for (var F = 0; F < D.length; F++) { try { if (D[F].contentWindow == $) { var E = W(D[F]); A += E.left; _ += E.top; break } } catch(B) { } } $ = $.parent } return{"leftM":A,"topM":_} } function W(F) { if (F.getBoundingClientRect)return F.getBoundingClientRect(); else { var A = {ROOT_TAG:/^body|html$/i,OP_SCROLL:/^(?:inline|table-row)$/i},E = false,H = null,_ = F.offsetTop,G = F.offsetLeft,D = F.offsetWidth,B = F.offsetHeight,C = F.offsetParent; if (C != F)while (C) { G += C.offsetLeft; _ += C.offsetTop; if (S(C, "position").toLowerCase() == "fixed")E = true; else if (C.tagName.toLowerCase() == "body")H = C.ownerDocument.defaultView; C = C.offsetParent } C = F.parentNode; while (C.tagName && !A.ROOT_TAG.test(C.tagName)) { if (C.scrollTop || C.scrollLeft)if (!A.OP_SCROLL.test(Q(C)))if (!b || C.style.overflow !== "visible") { G -= C.scrollLeft; _ -= C.scrollTop } C = C.parentNode } if (!E) { var $ = a(H); G -= $.left; _ -= $.top } D += G; B += _; return{"left":G,"top":_,"right":D,"bottom":B} } } function N($) { $ = $ || V; var B = $[O],A = ($.innerWidth) ? $.innerWidth : (B[J] && B[J].clientWidth) ? B[J].clientWidth : B.body.offsetWidth,_ = ($.innerHeight) ? $.innerHeight : (B[J] && B[J].clientHeight) ? B[J].clientHeight : B.body.offsetHeight; return{"width":A,"height":_} } function a($) { $ = $ || V; var B = $[O],A = B[J],_ = B.body; B = (A && A.scrollTop != null && (A.scrollTop > _.scrollTop || A.scrollLeft > _.scrollLeft)) ? A : _; return{"top":B.scrollTop,"left":B.scrollLeft} } function D($) { src = $ ? ($.srcElement || $.target) : null; if ($dp && $dp.cal && !$dp.eCont && $dp.dd && src != $dp.el && $dp.dd.style.display == "block")$dp.cal.close() } function Y() { $dp.status = 2; H() } function H() { if ($dp.flatCfgs.length > 0) { var $ = $dp.flatCfgs.shift(); $.el = {innerHTML:""}; $.autoPickDate = true; $.qsEnabled = false; K($) } } var R,$; function U(J, C) { $dp.win = X; B(); J = J || {}; if (C) { if (!G()) { $ = $ || setInterval(function() { if (V[O].readyState == "complete")clearInterval($); U(null, true) }, 50); return } if ($dp.status == 0) { $dp.status = 1; K({el:{innerHTML:""}}, true) } else return } else if (J.eCont) { J.eCont = $dp.$(J.eCont); $dp.flatCfgs.push(J); if ($dp.status == 2)H() } else { if ($dp.status == 0) { U(null, true); return } if ($dp.status != 2)return; var F = D(); if (F) { $dp.srcEl = F.srcElement || F.target; F.cancelBubble = true } J.el = $dp.$(J.el || $dp.srcEl); if (!J.el || J.el["My97Mark"] === true || J.el.disabled || (J.el == $dp.el && Q($dp.dd) != "none" && $dp.dd.style.left != "-1970px")) { J.el["My97Mark"] = false; return } K(J); if (J.el.nodeType == 1 && J.el["My97Mark"] === undefined) { $dp.el["My97Mark"] = false; var _,A; if (F.type == "focus") { _ = "onclick"; A = "onfocus" } else { _ = "onfocus"; A = "onclick" } E(J.el, _, J.el[A]) } } function G() { if (T && V != X && V[O].readyState != "complete")return false; return true } function D() { if (I) { func = D.caller; while (func != null) { var $ = func.arguments[0]; if ($ && ($ + "").indexOf("Event") >= 0)return $; func = func.caller } return null } return event } } function S(_, $) { return _.currentStyle ? _.currentStyle[$] : document.defaultView.getComputedStyle(_, false)[$] } function Q(_, $) { if (_)if ($ != null)_.style.display = $; else return S(_, "display") } function K(H, $) { for (var D in _)if (D.substring(0, 1) != "$")$dp[D] = _[D]; for (D in H)if ($dp[D] !== undefined)$dp[D] = H[D]; var E = $dp.el ? $dp.el.nodeName : "INPUT"; if ($ || $dp.eCont || new RegExp(/input|textarea|div|span|p|a/ig).test(E))$dp.elProp = E == "INPUT" ? "value" : "innerHTML"; else return; if ($dp.lang == "auto")$dp.lang = T ? navigator.browserLanguage.toLowerCase() : navigator.language.toLowerCase(); if (!$dp.dd || $dp.eCont || ($dp.lang && $dp.realLang && $dp.realLang.name != $dp.lang && $dp.getLangIndex && $dp.getLangIndex($dp.lang) >= 0)) { if ($dp.dd && !$dp.eCont)V[O].body.removeChild($dp.dd); if (_.$dpPath == "")F(A); var B = ""; if ($dp.eCont) { $dp.eCont.innerHTML = B; Z($dp.eCont.childNodes[0], Y) } else { $dp.dd = V[O].createElement("DIV"); $dp.dd.style.cssText = "position:absolute;z-index:19700"; $dp.dd.innerHTML = B; V[O].body.appendChild($dp.dd); Z($dp.dd.childNodes[0], Y); if ($)$dp.dd.style.left = $dp.dd.style.top = "-1970px"; else { $dp.show(); C() } } } else if ($dp.cal) { $dp.show(); $dp.cal.init(); if (!$dp.eCont)C() } function C() { var F = $dp.position.left,B = $dp.position.top,C = $dp.el; if (C != $dp.srcEl && (Q(C) == "none" || C.type == "hidden"))C = $dp.srcEl; var H = W(C),$ = G(X),D = N(V),A = a(V),E = $dp.dd.offsetHeight,_ = $dp.dd.offsetWidth; if (isNaN(B)) { if (B == "above" || (B != "under" && (($.topM + H.bottom + E > D.height) && ($.topM + H.top - E > 0))))B = A.top + $.topM + H.top - E - 3; else B = A.top + $.topM + Math.min(H.bottom, D.height - E); B += T ? -1 : 1 } else B += A.top + $.topM; if (isNaN(F))F = A.left + Math.min($.leftM + H.left, D.width - _ - 5) - (T ? 2 : 0); else F += A.left + $.leftM; $dp.dd.style.top = B + "px"; $dp.dd.style.left = F + "px" } } })() ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/calendar.js ================================================ /* * My97 DatePicker 4.7 Beta5 * License: http://www.my97.net/dp/license.asp */ eval(function(B,D,A,G,E,F){function C(A){return A<62?String.fromCharCode(A+=A<26?65:A<52?71:-4):A<63?'_':A<64?'$':C(A>>6)+C(A&63)}while(A>0)E[C(G--)]=D[--A];return B.replace(/[\w\$]+/g,function(A){return E[A]==F[A]?A:E[A]})}('l f;e(FP){FD.Co.__defineSetter__("Fd",9(c){e(!c){q.Bq();}4 c;});FD.Co.__defineGetter__("FL",9(){l c=q.GG;DH(c.FZ!=V){c=c.parentNode;}4 c;});HTMLElement.Co.C8=9(b,A){l c=b.6(/Ez/,"");A.El=9(c){GA.BZ=c;4 A();};q.addEventListener(c,A.El,2);};}9 EX(){f=q;q.Cj=[];d=Bs.createElement("m");d._="EN";d.BW=\'
&Dw;
\';GC(d,9(){C5();});c();j.Bb=[Bs,d.BV,d.BA,d.CT,d.DF,d.DR,d.CR,d.Bp,d.Bc];p(l A=U;A=U?BS+V:V;e(BS%Y==U){d.BA.Bw();4;}d.BA.1=k.T+V;d.BA.CK();};}}EX.Co={Fj:9(){BS=U;j.cal=q;e(j.Cz&&j.g.Cz!=u){j.g.Cz=s;j.g.D6();}c();q.FC();k=q.E2=o BN();BI=o BN();BF=q.B8=o BN();q.Bl=q.CW(j.Bl);q.CL=j.CL==u?(j.n.Bu&&j.n.Bu?2:s):j.CL;j.CD=j.CD==u?(j.D4&&j.n.N?2:s):j.CD;q.D8=q.Cs("disabledDates");q.FK=q.Cs("disabledDays");q.E$=q.Cs("specialDates");q.Fk=q.Cs("specialDays");q.Bd=q.DB(j.Bd,j.Bd!=j.Eq?j.Bk:j.CY,j.Eq);q.Bh=q.DB(j.Bh,j.Bh!=j.GB?j.Bk:j.CY,j.GB);e(q.Bd.By(q.Bh)>U){j.EE=0.err_1;}e(q.Ba()){q.Ep();q.CH=j.g[j.BH];}r{q.Bx(2,W);}Dz(k);d.Fx.BW=0.timeStr;d.CR.1=0.clearStr;d.Bp.1=0.todayStr;d.Bc.1=0.okStr;d.Bc.BT=!f.BB(BF);q.Ef();q.E5();e(j.EE){alert(j.EE);}q.EL();e(j.g.FZ==V&&j.g.D5===EH){j.C8(j.g,"EP",EK);}f.$=j.g;C5();9 c(){l b,c;p(b=U;(c=Bs.Dj("link")[b]);b++){e(c.rel.8("y")!=-V&&c.F6){c.BT=s;e(c.F6==j.skin){c.BT=2;}}}}},Ep:9(){l b=q.CE();e(b!=U){l c;e(b>U){c=q.Bh;}r{c=q.Bd;}e(j.n.DO){k.T=c.T;k.K=c.K;k.N=c.N;}e(j.n.Bu){k.H=c.H;k.Q=c.Q;k.S=c.S;}}},C2:9(K,F,Ee,b,D,B,A,Ed,G){l E;e(K&&K.Ba){E=K;}r{E=o BN();e(K!=""){F=F||j.Bl;l J,Dk=U,I,C=/C9|Cu|Db|T|CC|Ce|Dy|K|Bm|N|%CV|FA|H|E9|Q|Ff|S|CG|D|FY|Cy|Dl/BR,CI=F.ES(C);C.DL=U;e(G){I=K.D9(/\\Cy+/);}r{l c=U,H="^";DH((I=C.DP(F))!==u){e(c>=U){H+=F.Ca(c,I.DN);}c=I.DN-c;c=C.DL;Cp(I[U]){t"C9":H+="(\\\\N{BL})";z;t"Cu":H+="(\\\\N{X})";z;t"CC":t"Ce":t"CG":t"D":H+="(\\\\D+)";z;F$:H+="(\\\\N\\\\N?)";z;}}H+=".*c";I=o Dd(H).DP(K);Dk=V;}e(I){p(J=U;J=U){c=c.6(/%CV/BR,"U");b.N=U;b.K=Cn(b.K)+V;}b.Be();}4 b;},Ba:9(){l A,b;e(j.alwaysUseStartDate||(j.Eb!=""&&j.g[j.BH]=="")){A=q.CW(j.Eb);b=j.Bk;}r{A=j.g[j.BH];b=q.Bl;}k.CA(q.C2(A,b));e(A!=""){l c=V;e(j.n.DO&&!q.EQ(k)){k.T=BI.T;k.K=BI.K;k.N=BI.N;c=U;}e(j.n.Bu&&!q.Do(k)){k.H=BI.H;k.Q=BI.Q;k.S=BI.S;c=U;}4 c&&q.BB(k);}4 V;},EQ:9(c){e(c.T!=u){c=CQ(c.T,BL)+"-"+c.K+"-"+c.N;}4 c.ES(/^((\\N{W}(([Et][048])|([E6][26]))[\\-\\/\\S]?((((U?[E8])|(V[Fb]))[\\-\\/\\S]?((U?[V-a])|([V-W][U-a])|(X[Fa])))|(((U?[Ev])|(EA))[\\-\\/\\S]?((U?[V-a])|([V-W][U-a])|(Cd)))|(U?W[\\-\\/\\S]?((U?[V-a])|([V-W][U-a])))))|(\\N{W}(([Et][1235679])|([E6][01345789]))[\\-\\/\\S]?((((U?[E8])|(V[Fb]))[\\-\\/\\S]?((U?[V-a])|([V-W][U-a])|(X[Fa])))|(((U?[Ev])|(EA))[\\-\\/\\S]?((U?[V-a])|([V-W][U-a])|(Cd)))|(U?W[\\-\\/\\S]?((U?[V-a])|(V[U-a])|(W[U-Dh]))))))(\\S(((U?[U-a])|([V-W][U-X]))\\:([U-Y]?[U-a])((\\S)|(\\:([U-Y]?[U-a])))))?c/);},Do:9(c){e(c.H!=u){c=c.H+":"+c.Q+":"+c.S;}4 c.ES(/^([U-a]|([U-V][U-a])|([W][U-X])):([U-a]|([U-Y][U-a])):([U-a]|([U-Y][U-a]))c/);},CE:9(b,c){b=b||k;l A=b.By(q.Bd,c);e(A>U){A=b.By(q.Bh,c);e(AV){C-=Z;}G.L("");G.L("");e(j.Fg){G.L(""+A[U]+"");}p(b=U;b"+A[(B+b)%Z+V]+"");}G.L("");p(b=V,F=C;b");p(c=U;c"+Dx(J,j.F8==U?V:U)+"");}G.L(""+J.N+"");}r{G.L(">");}}G.L("");}G.L("");4 G.P();},Fe:9(b){l c=q.D3(b,q.D8);4(q.D8&&j.Fo)?!c:c;},E3:9(c){4 q.D2(c,q.FK);},F0:9(c){4 q.D3(c,q.E$,V);},FV:9(c){4 q.D2(c,q.Fk,V);},D3:9(c,b){4 b?b.Fz(q.DI(j.Bk,c)):U;},D2:9(b,c){4 c?c.Fz(b):U;},Cq:9(R,M,Dn,Eh,Bv){l S=o B$(),Df=Bv?"Dn"+R:R;E1=k[R];S.L("\');p(l P=U;P"+(R=="K"?0.B2[k[R]-V]:k[R])+"");}S.L("");}S.L("");k[R]=E1;4 S.P();},De:9(b,A){e(b){l c=b.offsetLeft;e(Ei){c=b.getBoundingClientRect().Bz;}A.y.Bz=c;}},_fM:9(c){q.De(c,d.C7);d.C7.BW=q.Cq("K",W,BQ,"O+P*BQ+V",c==d.Br);},Dq:9(A,c){l b=o B$();c=Cl(c,k.T-Y);b.L(q.Cq("T",W,Y,c+"+O+P*Y",A==d.B6));b.L("\\u2190\\FEc+B9?"x=\'BG\' CB=\\"q._=\'Ci\'\\" B0=\\"q._=\'BG\'\\" C_=\'e(BZ.Bq)BZ.Bq();BZ.Dg=s;f.Dq(U,"+(c+B9)+")\'":"x=\'D0\'");b.L(">\\u2192");q.De(A,d.Cb);d.Cb.BW=b.P();},DV:9(c,A,b){d[c+"D"].BW=q.Cq(c,BQ,A,b);},_fH:9(){q.DV("H",BL,"O * BQ + P");},_fm:9(){q.DV("Q",W,"O * Cd + P * Y");},_fs:9(){q.DV("S",V,"P * B9");},EC:9(c){q.Fv();l C=q.Cj,B=C.y,A=o B$();A.L("");A.L(\'\'+0.quickStr+"");e(!c){A.L(\'\\FE\');}A.L("");p(l b=U;b\');A.L("&Dw;"+q.DI(u,C[b]));A.L("");}r{A.L("&Dw;");}}A.L("");d.BK.BW=A.P();},FC:9(){c(/Dl/);c(/FY|Cy/);c(/CG|D/);c(/C9|Cu|Db|T/);c(/CC|Ce|Dy|K/);c(/Bm|N/);c(/FA|H/);c(/E9|Q/);c(/Ff|S/);j.n.DO=(j.n.T||j.n.K||j.n.N)?s:2;j.n.Bu=(j.n.H||j.n.Q||j.n.S)?s:2;j.CY=j.CY.6(/%BO/,j.GD).6(/%Time/,j.Fp);e(j.n.DO){e(j.n.Bu){j.Bk=j.CY;}r{j.Bk=j.GD;}}r{j.Bk=j.Fp;}9 c(b){l c=(b+"").EB(V,W);j.n[c]=b.DP(j.Bl)?(j.n.Cw=c,s):2;}},Ef:9(){l c=U;j.n.T?(c=V,Bj(d.BA,d.DW,d.DA)):v(d.BA,d.DW,d.DA);j.n.K?(c=V,Bj(d.BV,d.Cx,d.DX)):v(d.BV,d.Cx,d.DX);c?Bj(d.D1):v(d.D1);e(j.n.Bu){Bj(d.Cv);DS(d.CT,j.n.H);DS(d.DF,j.n.Q);DS(d.DR,j.n.S);}r{v(d.Cv);}CS(d.CR,j.E0);CS(d.Bp,j.FI);CS(d.Bc,j.D4);CS(d.EO,(!j.Fy&&j.n.N&&j.qsEnabled));e(j.Fn||!(j.E0||j.FI||j.D4)){v(d.C0);}r{Bj(d.C0);}},Bx:9(B,c){l b=j.g,D=FP?"x":"_";e(B){C(b);}r{e(c==u){c=j.errDealMode;}Cp(c){t U:e(confirm(0.errAlertMsg)){b[j.BH]=q.CH;C(b);}r{A(b);}z;t V:b[j.BH]=q.CH;C(b);z;t W:A(b);z;}}9 C(c){l A=c._;e(A){l b=A.6(/F2/BR,"");e(A!=b){c.FU(D,b);}}}9 A(c){c.FU(D,c._+" F2");}},Bf:9(c,G,E){E=E||BF;l H,F=[c+c,c],b,C=E[c],A=9(c){4 CQ(C,c.5);};Cp(c){t"Dl":C=Bi(E);z;t"D":l B=Bi(E)+V;A=9(c){4 c.5==W?0.aLongWeekStr[B]:0.F9[B];};z;t"Cy":C=Dx(E);z;t"T":F=["C9","Cu","Db","T"];G=G||F[U];A=9(c){4 CQ((c.5-V&&c!="T"&&!j.n[c]){e("Hms".8(c)>-V){C=U;}r{C=V;}}l D=[];p(H=U;H=U){D[H]=A(b);G=G.6(b,"{"+H+"}");}}p(H=U;H=U){l b=o BN();b.CA(B);b.N=U;b.K=Cn(b.K)+V;b.Be();D=D.6(/%CV/BR,b.N);}l A="ydHmswW";p(l c=U;c");c.L(q.C4());c.L("");k.B4("K",V);c.L(q.C4());d.Br=d.BV.FJ(s);d.B6=d.BA.FJ(s);d.DE.EV(d.Br);d.DE.EV(d.B6);d.Br.1=0.B2[k.K-V];d.Br.DU=k.K;d.B6.1=k.T;EJ("Fu,Fl");d.Br._=d.B6._="Da";k.B4("K",-V);c.L("");d.Cg.BW=c.P();}r{d._="EN";d.Cg.BW=q.C4();}e(!j.n.N){q.EC(s);DG(d.BK);}r{v(d.BK);}q.FB();},FB:9(){l C=parent.Bs.Dj("iframe");p(l B=U;B=b){c+=b;d.y.Bo=c;}r{d.y.Bo=A;}C[B].y.Bo=D7.max(c,d.CJ)+"Fw";}}d.BK.y.Cm=d.Cg.FM;d.BK.y.Bo=d.Cg.CJ;},Di:9(){k.N=D7.min(o BO(k.T,k.K,U).CU(),k.N);q.B1();e(!j.Fn){e(q.BB(k)){f.Bx(s);j.g.D5=s;j.g.Bw();v(j.Bm);}r{f.Bx(2);}}e(j.Ec){Bn("Ec");}r{e(q.CH!=j.g[j.BH]&&j.g.GE){DK(j.g,"Eo");}}},E5:9(){d.CR.7=9(){e(!Bn("onclearing")){j.g[j.BH]="";f.C$("");j.g.D5=s;j.g.Bw();v(j.Bm);e(j.F3){Bn("F3");}r{e(f.CH!=j.g[j.BH]&&j.g.GE){DK(j.g,"Eo");}}}};d.Bc.7=9(){CP();};e(q.BB(BI)){d.Bp.BT=2;d.Bp.7=9(){k.CA(BI);CP();};}r{d.Bp.BT=s;}},Fv:9(){l H,B,C,A,F=[],E=Y,b=j.FF.5,G=j.n.Cw;e(b>E){b=E;}r{e(G=="Q"||G=="S"){F=[U,D$,Cd,Ft,Fm,-60,-Ft,-Cd,-D$,-V];}r{p(H=U;H=U){BY=C1(BY,U,Fm);}}}e(BF[R]!=BY&&!Bn(R+"changing")){l F_=\'Bg("\'+R+\'",\'+BY+")",DQ=f.CE();e(DQ==U){Cc(F_);}r{e(DQU){EU(f.Bh);}}}d.Bc.BT=!f.BB(BF);e("yMd".8(R)>=U){f.EL();}Bn(R+"changed");}9 EU(c){Dz(f.BB(c)?c:BF);}}9 Dz(c){Bg("T",c.T);Bg("K",c.K);Bg("N",c.N);Bg("H",c.H);Bg("Q",c.Q);Bg("S",c.S);}9 CP(A,D,F,c,E,B){l C=o BN(k.T,k.K,k.N,k.H,k.Q,k.S);k.Ba(A,D,F,c,E,B);e(!Bn("onpicking")){l b=C.T==A&&C.K==D&&C.N==F;e(!b&&Ch.5!=U){M("T",A);M("K",D);M("N",F);f.$=j.g;e(j.CD){f.B1();}}e(f.CL||b||Ch.5==U){f.Di();}}r{k=C;}}9 Bn(c){l b;e(j[c]){b=j[c].ET(j.g,j);}4 b;}9 Bg(b,c){e(c==u){c=k[b];}BF[b]=k[b]=c;e("yHms".8(b)>=U){d[b+"BE"].1=c;}e(b=="K"){d.BV.DU=c;d.BV.1=0.B2[c-V];}}9 C1(A,b,c){e(Ac){A=c;}}4 A;}9 GC(c,b){c.C8("EP",9(){l A=BZ,c=(A.Dv==EH)?A.EG:A.Dv;e(c==a){b();}});}9 CQ(c,b){c=c+"";DH(c.5=U?C:Y;p(l c=U;c<=C;c++){A=b.CZ(c);D=q[A]-B[A];e(D>U){4 V;}r{e(D=U){l c=q.N;e(A=="K"){q.N=V;}q[A]+=b;q.Be();q.N=c;}}};9 Cn(c){4 parseInt(c,B9);}9 CO(c,b){4 Cl(Cn(c),b);}9 3(b,c,A){4 CO(b,Cl(c,A));}9 Cl(c,b){4 c==u||FW(c)?b:c;}9 DK(c,b){e(Ei){c.DK("Ez"+b);}r{l A=Bs.createEvent("HTMLEvents");A.initEvent(b,s,s);c.dispatchEvent(A);}}9 DY(A){l c,b,B="T,K,H,Q,S,Fl,Fu".D9(",");p(b=U;b=FQ&&C<=40){l b;e(f.$==j.g||f.$==d.Bc){e(j.n.N){b="N";e(C==FR){k[b]-=Z;}r{e(C==FO){k[b]+=V;}r{e(C==FQ){k[b]-=V;}r{k[b]+=Z;}}}k.Be();M("T",k.T);M("K",k.K);M("N",k[b]);DM(B);4;}r{b=j.n.Cw;d[b+"BE"].Bw();}}b=b||DY(f.$);e(b){e(C==FR||C==FO){k[b]+=V;}r{k[b]-=V;}k.Be();f.$.1=k[b];C6.ET(f.$,s);f.$.Fh();}}r{e(f.$==j.g&&j.Bm.y.CM=="DD"){4;}e(C==a){l D=A.Ct;p(l c=U;c=48&&C<=57)||(C>=96&&C<=105)||C==Dh||C==46)){DM(B);}}','J|K|M|a|c|d|i|j|m|p|s|y|0|1|2|3|5|7|9|_|$|$d|if|$c|el|td|tr|$dp|$dt|var|div|has|new|for|this|else|true|case|null|hide|divs|class|style|break|$lang|value|false|pInt3|return|length|replace|onclick|indexOf|function|className|currFocus|yI|checkValid|table|L|I|$sdt|menu|elProp|$tdt|input|qsDivSel|4|id|DPDate|Date|arr|6|g|$ny|disabled|button|MI|innerHTML|ipts|pv|event|loadDate|focusArr|okI|minDate|refresh|getP|sv|maxDate|getDay|show|realFmt|dateFmt|dd|callFunc|height|todayI|preventDefault|rMI|document|9700|st|isR|focus|mark|compareWith|left|onmouseout|update|aMonStr|border|attr|cellpadding|ryI|tmpEval|date|10|cellspacing|sb|loadFromDate|onmouseover|MMMM|autoUpdateOnChanged|checkRange|float|DD|oldValue|Q|offsetHeight|onblur|autoPickDate|display|nowrap|pInt2|day_Click|doStr|clearI|shorH|HI|getDate|ld|doExp|menuSel|realFullFmt|charAt|substring|yD|eval|30|MMM|12|dDiv|arguments|menuOn|QS|yMdHms|rtn|width|pInt|prototype|switch|_f|100|_initRe|nextCtrl|yyy|tDiv|minUnit|leftImg|W|readOnly|bDiv|makeInRange|splitDate|navImg|_fd|hideSel|_blur|MD|attachEvent|yyyy|onmousedown|setRealValue|navRightImg|doCustomDate|type|none|rMD|mI|showB|while|getDateStr|href|fireEvent|lastIndex|_cancelKey|index|sd|exec|rv|sI|disHMS|ps|realValue|_fHMS|navLeftImg|rightImg|_foundInput|setDisp|yminput|yy|dpButton|RegExp|_fMyPos|fp|cancelBubble|8|pickDate|getElementsByTagName|P|w|getNewDateStr|r|isTime|close|_fy|align|getMinutes|span|getHours|which|nbsp|getWeek|MM|_setAll|invalidMenu|titleDiv|testDay|testDate|isShowOK|My97Mark|blur|Math|ddateRe|split|getSeconds|15|11|slice|_fillQS|maxlength|errMsg|getFullYear|keyCode|undefined|updownEvent|_inputBindEvent|_tab|draw|btns|WdateDiv|qsDiv|onkeydown|isDate|getMonth|match|call|_setFrom|appendChild|upButton|My97DP|showDiv|right|toLowerCase|startDate|onpicked|N|O|initShowAndHide|HD|e|$IE|v|readonly|_ieEmuEventHandler|2000|body|change|_makeDateInRange|defMinDate|_focus|downButton|02468|highLineWeekDay|469|isShowOthers|valign|oldv|on|isShowClear|bak|newdate|testDisDay|yearOffset|initBtn|13579|MTitle|13578|mm|yminputfocus|sdateRe|HH|autoSize|_dealFmt|Event|xd7|quickSel|mD|coverDate|isShowToday|cloneNode|ddayRe|srcElement|offsetWidth|aLongMonStr|39|$FF|37|38|spans|checkAndUpdate|setAttribute|testSpeDay|isNaN|13|WW|nodeType|01|02|tm|returnValue|testDisDate|ss|isShowWeek|select|tE|init|sdayRe|ry|59|eCont|opposite|realTimeFmt|re|sD|top|45|rM|initQS|px|timeSpan|doubleCalendar|test|testSpeDate|center|WdateFmtErr|oncleared|WdayTable|block|title|valueOf|firstDayOfWeek|aWeekStr|func|default|window|defMaxDate|attachTabEvent|realDateFmt|onchange|setDate|target'.split('|'),383,390,{},{})) ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/config.js ================================================ var langList = [ {name:'en', charset:'UTF-8'}, {name:'zh-cn', charset:'UTF-8'}, {name:'zh-tw', charset:'UTF-8'} ]; var skinList = [ {name:'default', charset:'UTF-8'}, {name:'whyGreen', charset:'UTF-8'}, {name:'ext', charset:'UTF-8'} ]; ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/lang/en.js ================================================ var $lang={ errAlertMsg: "Invalid date or the date out of range,redo or not?", aWeekStr: ["wk", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], aLongWeekStr:["wk","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"], aMonStr: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], aLongMonStr: ["January","February","March","April","May","June","July","August","September","October","November","December"], clearStr: "Clear", todayStr: "Today", okStr: "OK", updateStr: "OK", timeStr: "Time", quickStr: "Quick Selection", err_1: 'MinDate Cannot be bigger than MaxDate!' } ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/lang/zh-cn.js ================================================ var $lang={ errAlertMsg: "\u4E0D\u5408\u6CD5\u7684\u65E5\u671F\u683C\u5F0F\u6216\u8005\u65E5\u671F\u8D85\u51FA\u9650\u5B9A\u8303\u56F4,\u9700\u8981\u64A4\u9500\u5417?", aWeekStr: ["\u5468","\u65E5","\u4E00","\u4E8C","\u4E09","\u56DB","\u4E94","\u516D"], aLongWeekStr:["\u5468","\u661F\u671F\u65E5","\u661F\u671F\u4E00","\u661F\u671F\u4E8C","\u661F\u671F\u4E09","\u661F\u671F\u56DB","\u661F\u671F\u4E94","\u661F\u671F\u516D"], aMonStr: ["\u4E00\u6708","\u4E8C\u6708","\u4E09\u6708","\u56DB\u6708","\u4E94\u6708","\u516D\u6708","\u4E03\u6708","\u516B\u6708","\u4E5D\u6708","\u5341\u6708","\u5341\u4E00","\u5341\u4E8C"], aLongMonStr: ["\u4E00\u6708","\u4E8C\u6708","\u4E09\u6708","\u56DB\u6708","\u4E94\u6708","\u516D\u6708","\u4E03\u6708","\u516B\u6708","\u4E5D\u6708","\u5341\u6708","\u5341\u4E00\u6708","\u5341\u4E8C\u6708"], clearStr: "\u6E05\u7A7A", todayStr: "\u4ECA\u5929", okStr: "\u786E\u5B9A", updateStr: "\u786E\u5B9A", timeStr: "\u65F6\u95F4", quickStr: "\u5FEB\u901F\u9009\u62E9", err_1: '\u6700\u5C0F\u65E5\u671F\u4E0D\u80FD\u5927\u4E8E\u6700\u5927\u65E5\u671F!' } ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/lang/zh-tw.js ================================================ var $lang={ errAlertMsg: "\u4E0D\u5408\u6CD5\u7684\u65E5\u671F\u683C\u5F0F\u6216\u8005\u65E5\u671F\u8D85\u51FA\u9650\u5B9A\u7BC4\u570D,\u9700\u8981\u64A4\u92B7\u55CE?", aWeekStr: ["\u5468","\u65E5","\u4E00","\u4E8C","\u4E09","\u56DB","\u4E94","\u516D"], aLongWeekStr:["\u5468","\u661F\u671F\u65E5","\u661F\u671F\u4E00","\u661F\u671F\u4E8C","\u661F\u671F\u4E09","\u661F\u671F\u56DB","\u661F\u671F\u4E94","\u661F\u671F\u516D"], aMonStr: ["\u4E00\u6708","\u4E8C\u6708","\u4E09\u6708","\u56DB\u6708","\u4E94\u6708","\u516D\u6708","\u4E03\u6708","\u516B\u6708","\u4E5D\u6708","\u5341\u6708","\u5341\u4E00","\u5341\u4E8C"], aLongMonStr: ["\u4E00\u6708","\u4E8C\u6708","\u4E09\u6708","\u56DB\u6708","\u4E94\u6708","\u516D\u6708","\u4E03\u6708","\u516B\u6708","\u4E5D\u6708","\u5341\u6708","\u5341\u4E00\u6708","\u5341\u4E8C\u6708"], clearStr: "\u6E05\u7A7A", todayStr: "\u4ECA\u5929", okStr: "\u78BA\u5B9A", updateStr: "\u78BA\u5B9A", timeStr: "\u6642\u9593", quickStr: "\u5FEB\u901F\u9078\u64C7", err_1: '\u6700\u5C0F\u65E5\u671F\u4E0D\u80FD\u5927\u65BC\u6700\u5927\u65E5\u671F!' } ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/skin/WdatePicker.css ================================================ .Wdate{ border:#999 1px solid; height:20px; background:#fff url(datePicker.gif) no-repeat right; } .WdateFmtErr{ font-weight:bold; color:red; } ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/skin/default/datepicker.css ================================================ /* * My97 DatePicker 4.7 */ .WdateDiv{ width:180px; background-color:#FFFFFF; border:#bbb 1px solid; padding:2px; } .WdateDiv2{ width:360px; } .WdateDiv *{font-size:9pt;} .WdateDiv .NavImg a{ display:block; cursor:pointer; height:16px; width:16px; } .WdateDiv .NavImgll a{ float:left; background:transparent url(img.gif) no-repeat scroll 0 0; } .WdateDiv .NavImgl a{ float:left; background:transparent url(img.gif) no-repeat scroll -16px 0; } .WdateDiv .NavImgr a{ float:right; background:transparent url(img.gif) no-repeat scroll -32px 0; } .WdateDiv .NavImgrr a{ float:right; background:transparent url(img.gif) no-repeat scroll -48px 0; } .WdateDiv #dpTitle{ height:24px; margin-bottom:2px; padding:1px; } .WdateDiv .yminput{ margin-top:2px; text-align:center; height:20px; border:0px; width:50px; cursor:pointer; } .WdateDiv .yminputfocus{ margin-top:2px; text-align:center; font-weight:bold; height:20px; color:blue; border:#ccc 1px solid; width:50px; } .WdateDiv .menuSel{ z-index:1; position:absolute; background-color:#FFFFFF; border:#ccc 1px solid; display:none; } .WdateDiv .menu{ cursor:pointer; background-color:#fff; } .WdateDiv .menuOn{ cursor:pointer; background-color:#BEEBEE; } .WdateDiv .invalidMenu{ color:#aaa; } .WdateDiv .YMenu{ margin-top:20px; } .WdateDiv .MMenu{ margin-top:20px; *width:62px; } .WdateDiv .hhMenu{ margin-top:-90px; margin-left:26px; } .WdateDiv .mmMenu{ margin-top:-46px; margin-left:26px; } .WdateDiv .ssMenu{ margin-top:-24px; margin-left:26px; } .WdateDiv .Wweek { text-align:center; background:#DAF3F5; border-right:#BDEBEE 1px solid; } .WdateDiv .MTitle{ background-color:#BDEBEE; } .WdateDiv .WdayTable2{ border-collapse:collapse; border:#c5d9e8 1px solid; } .WdateDiv .WdayTable2 table{ border:0; } .WdateDiv .WdayTable{ line-height:20px; border:#c5d9e8 1px solid; } .WdateDiv .WdayTable td{ text-align:center; } .WdateDiv .Wday{ cursor:pointer; } .WdateDiv .WdayOn{ cursor:pointer; background-color:#C0EBEF; } .WdateDiv .Wwday{ cursor:pointer; color:#FF2F2F; } .WdateDiv .WwdayOn{ cursor:pointer; color:#000; background-color:#C0EBEF; } .WdateDiv .Wtoday{ cursor:pointer; color:blue; } .WdateDiv .Wselday{ background-color:#A9E4E9; } .WdateDiv .WspecialDay{ background-color:#66F4DF; } .WdateDiv .WotherDay{ cursor:pointer; color:#6A6AFF; } .WdateDiv .WotherDayOn{ cursor:pointer; background-color:#C0EBEF; } .WdateDiv .WinvalidDay{ color:#aaa; } .WdateDiv #dpTime{ float:left; margin-top:3px; margin-right:30px; } .WdateDiv #dpTime #dpTimeStr{ margin-left:1px; } .WdateDiv #dpTime input{ width:18px; height:20px; text-align:center; border:#ccc 1px solid; } .WdateDiv #dpTime .tB{ border-right:0px; } .WdateDiv #dpTime .tE{ border-left:0; border-right:0; } .WdateDiv #dpTime .tm{ width:7px; border-left:0; border-right:0; } .WdateDiv #dpTime #dpTimeUp{ height:10px; width:13px; border:0px; background:url(img.gif) no-repeat -32px -16px; } .WdateDiv #dpTime #dpTimeDown{ height:10px; width:13px; border:0px; background:url(img.gif) no-repeat -48px -16px; } .WdateDiv #dpQS { float:left; margin-right:3px; margin-top:3px; background:url(img.gif) no-repeat 0px -16px; width:20px; height:20px; cursor:pointer; } .WdateDiv #dpControl { text-align:right; } .WdateDiv .dpButton{ height:20px; width:45px; border:#ccc 1px solid; margin-top:2px; margin-right:1px; } ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/skin/ext/datepicker.css ================================================ /* ѡ DIV */ .WdateDiv{ width:180px; background-color:#fff; border:1px solid #718BB7; } /* ˫Ŀ */ .WdateDiv2{ width:360px; } .WdateDiv *{font-size:9pt;} /**************************** * ͼ ȫAǩ ***************************/ .WdateDiv .NavImg a{ margin-top:3px; cursor:pointer; display:block; width:15px; height:15px; } .WdateDiv .NavImgll a{ background:url(left-btn2.gif) no-repeat center center; float:left; margin-left:2px; } .WdateDiv .NavImgl a{ background:url(left-btn.gif) no-repeat center center; float:left; margin-left:2px; } .WdateDiv .NavImgr a{ background:url(right-btn.gif) no-repeat center center; float:right; margin-right:2px; } .WdateDiv .NavImgrr a{ background:url(right-btn2.gif) no-repeat center center; float:right; margin-right:2px; } /**************************** * · ***************************/ /* · DIV */ .WdateDiv #dpTitle{ height:22px; background:transparent url(hd-sprite.gif) repeat-x scroll 0 -83px; color:#FFFFFF; font-family:"sans serif",tahoma,verdana,helvetica; font-size:12px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; padding-top:2px; } /* · INPUT */ .WdateDiv .yminput{ margin-top:2px; text-align:center; border:0px; height:20px; width:50px; color:#FFF; background-color:transparent; cursor:pointer; } /* ·ýʱʽ INPUT */ .WdateDiv .yminputfocus{ margin-top:2px; text-align:center; border:#939393 1px solid; font-weight:bold; color:#034c50; height:16px; width:50px; } /* ˵ѡ DIV */ .WdateDiv .menuSel{ z-index:1; position:absolute; background-color:#FFFFFF; border:1px solid #718BB7; display:none; } /* ˵ʽ TD */ .WdateDiv .menu{ cursor:pointer; background-color:#fff; color:#11777C; } /* ˵mouseoverʽ TD */ .WdateDiv .menuOn{ cursor:pointer; background-color: #B3CEEF; } /* ˵Чʱʽ TD */ .WdateDiv .invalidMenu{ color:#aaa; } /* ѡƫ DIV */ .WdateDiv .YMenu{ margin-top:16px; } /* ѡƫ DIV */ .WdateDiv .MMenu{ margin-top:16px; *width:62px; } /* ʱѡλ DIV */ .WdateDiv .hhMenu{ margin-top:-90px; margin-left:26px; } /* ѡλ DIV */ .WdateDiv .mmMenu{ margin-top:-46px; margin-left:26px; } /* ѡλ DIV */ .WdateDiv .ssMenu{ margin-top:-24px; margin-left:26px; } /**************************** * ***************************/ .WdateDiv .Wweek { text-align:center; background:#DAF3F5; border-right:#BDEBEE 1px solid; } /**************************** * , ***************************/ /* TR */ .WdateDiv .MTitle{ color:#233D6D; background:#DFECFB url(glass-bg.gif) repeat-x scroll left top; color:#233D6D; cursor:default; font-size:10px; padding-top:2px; } .WdateDiv .MTitle td{ border-bottom:1px solid #A3BAD9; } .WdateDiv .WdayTable2{ border-collapse:collapse; border:black 1px solid; } .WdateDiv .WdayTable2 table{ border:0; } /* TABLE */ .WdateDiv .WdayTable{ line-height:20px; color:black; } .WdateDiv .WdayTable td{ text-align:center; } /* ڸʽ TD */ .WdateDiv .Wday{ cursor:pointer; } /* ڸmouseoverʽ TD */ .WdateDiv .WdayOn{ cursor:pointer; background-color:#B3CEEF; } /* ĩڸʽ TD */ .WdateDiv .Wwday{ cursor:pointer; color:#ab1e1e; } /* ĩڸmouseoverʽ TD */ .WdateDiv .WwdayOn{ cursor:pointer; background-color:#B3CEEF; } .WdateDiv .Wtoday{ cursor:pointer; color:red; } .WdateDiv .Wselday{ background-color:#B3CEEF; } .WdateDiv .WspecialDay{ background-color:#66F4DF; } /* ·ݵ */ .WdateDiv .WotherDay{ cursor:pointer; color:#AAAAAA; } /* ·ݵmouseoverʽ */ .WdateDiv .WotherDayOn{ cursor:pointer; background-color:#B3CEEF; } /* Чڵʽ,ڷΧڸʽ,ѡ */ .WdateDiv .WinvalidDay{ color:#aaa; } /**************************** * ʱ ***************************/ /* ʱ DIV */ .WdateDiv #dpTime{ width:120px; text-align:left; margin-left:32px; height:20px; line-height:20px; padding-top:1px; } /* ʱ SPAN */ .WdateDiv #dpTime #dpTimeStr{ margin-left:1px; color:#233D6D; } /* ʱ INPUT */ .WdateDiv #dpTime input{ height:16px; width:18px; text-align:center; color:#333; border:#A3BAD9 1px solid; } /* ʱ ʱ INPUT */ .WdateDiv #dpTime .tB{ border-right:0px; } /* ʱ ֺͼ ':' INPUT */ .WdateDiv #dpTime .tE{ border-left:0; border-right:0; } /* ʱ INPUT */ .WdateDiv #dpTime .tm{ width:7px; border-left:0; border-right:0; } /* ʱұߵϰť BUTTON */ .WdateDiv #dpTime #dpTimeUp{ height:8px; width:13px; border:0px; background:url(img.gif) no-repeat -32px -16px; cursor:pointer; margin-bottom:0; padding-bottom:0; } /* ʱұߵ°ť BUTTON */ .WdateDiv #dpTime #dpTimeDown{ height:8px; width:13px; border:0px; background:url(img.gif) no-repeat -48px -16px; cursor:pointer; margin-top:0; padding-top:0; } /**************************** * ***************************/ .WdateDiv #dpQS { float:left; margin-left:3px; margin-top:9px; background:url(dateselect.gif) no-repeat; width:20px; height:20px; cursor:pointer; } .WdateDiv #dpControl { text-align:right; margin-top:3px; background:#DFECFB url(glass-bg.gif) repeat-x scroll left top; border-top:1px solid #A3BAD9; padding:4px; } .WdateDiv .dpButton{ width:44px; height:22px; background:#083772 none repeat scroll 0 0; border-color:#3366CC #000055 #000055 #3366CC; border-style:solid; border-width:1px; color:white; cursor:pointer; } ================================================ FILE: clover/clover-admin/src/main/webapp/js/DatePicker/skin/whyGreen/datepicker.css ================================================ /* * My97 DatePicker 4.7 Skin:whyGreen */ .WdateDiv{ width:180px; background-color:#fff; border:#C5E1E4 1px solid; padding:2px; } .WdateDiv2{ width:360px; } .WdateDiv *{font-size:9pt;} .WdateDiv .NavImg a{ cursor:pointer; display:block; width:16px; height:16px; margin-top:1px; } .WdateDiv .NavImgll a{ float:left; background:url(img.gif) no-repeat; } .WdateDiv .NavImgl a{ float:left; background:url(img.gif) no-repeat -16px 0px; } .WdateDiv .NavImgr a{ float:right; background:url(img.gif) no-repeat -32px 0px; } .WdateDiv .NavImgrr a{ float:right; background:url(img.gif) no-repeat -48px 0px; } .WdateDiv #dpTitle{ height:24px; padding:1px; border:#c5d9e8 1px solid; background:url(bg.jpg); margin-bottom:2px; } .WdateDiv .yminput{ margin-top:2px; text-align:center; border:0px; height:20px; width:50px; color:#034c50; background-color:transparent; cursor:pointer; } .WdateDiv .yminputfocus{ margin-top:2px; text-align:center; border:#939393 1px solid; font-weight:bold; color:#034c50; height:20px; width:50px; } .WdateDiv .menuSel{ z-index:1; position:absolute; background-color:#FFFFFF; border:#A3C6C8 1px solid; display:none; } .WdateDiv .menu{ cursor:pointer; background-color:#fff; color:#11777C; } .WdateDiv .menuOn{ cursor:pointer; background-color:#BEEBEE; } .WdateDiv .invalidMenu{ color:#aaa; } .WdateDiv .YMenu{ margin-top:20px; } .WdateDiv .MMenu{ margin-top:20px; *width:62px; } .WdateDiv .hhMenu{ margin-top:-90px; margin-left:26px; } .WdateDiv .mmMenu{ margin-top:-46px; margin-left:26px; } .WdateDiv .ssMenu{ margin-top:-24px; margin-left:26px; } .WdateDiv .Wweek { text-align:center; background:#DAF3F5; border-right:#BDEBEE 1px solid; } .WdateDiv .MTitle{ color:#13777e; background-color:#bdebee; } .WdateDiv .WdayTable2{ border-collapse:collapse; border:#BEE9F0 1px solid; } .WdateDiv .WdayTable2 table{ border:0; } .WdateDiv .WdayTable{ line-height:20px; color:#13777e; background-color:#edfbfb; border:#BEE9F0 1px solid; } .WdateDiv .WdayTable td{ text-align:center; } .WdateDiv .Wday{ cursor:pointer; } .WdateDiv .WdayOn{ cursor:pointer; background-color:#74d2d9 ; } .WdateDiv .Wwday{ cursor:pointer; color:#ab1e1e; } .WdateDiv .WwdayOn{ cursor:pointer; background-color:#74d2d9; } .WdateDiv .Wtoday{ cursor:pointer; color:blue; } .WdateDiv .Wselday{ background-color:#A7E2E7; } .WdateDiv .WspecialDay{ background-color:#66F4DF; } .WdateDiv .WotherDay{ cursor:pointer; color:#0099CC; } .WdateDiv .WotherDayOn{ cursor:pointer; background-color:#C0EBEF; } .WdateDiv .WinvalidDay{ color:#aaa; } .WdateDiv #dpTime{ float:left; margin-top:3px; margin-right:30px; } .WdateDiv #dpTime #dpTimeStr{ margin-left:1px; color:#497F7F; } .WdateDiv #dpTime input{ height:20px; width:18px; text-align:center; color:#333; border:#61CAD0 1px solid; } .WdateDiv #dpTime .tB{ border-right:0px; } .WdateDiv #dpTime .tE{ border-left:0; border-right:0; } .WdateDiv #dpTime .tm{ width:7px; border-left:0; border-right:0; } .WdateDiv #dpTime #dpTimeUp{ height:10px; width:13px; border:0px; background:url(img.gif) no-repeat -32px -16px; } .WdateDiv #dpTime #dpTimeDown{ height:10px; width:13px; border:0px; background:url(img.gif) no-repeat -48px -16px; } .WdateDiv #dpQS { float:left; margin-right:3px; margin-top:3px; background:url(img.gif) no-repeat 0px -16px; width:20px; height:20px; cursor:pointer; } .WdateDiv #dpControl { text-align:right; margin-top:3px; } .WdateDiv .dpButton{ height:20px; width:45px; margin-top:2px; border:#38B1B9 1px solid; background-color:#CFEBEE; color:#08575B; } ================================================ FILE: clover/clover-admin/src/main/webapp/js/Map.js ================================================ /* * MAP对象,实现MAP功能 * * 接口: * size() 获取MAP元素个数 * isEmpty() 判断MAP是否为空 * clear() 删除MAP所有元素 * put(key, value) 向MAP中增加元素(key, value) * remove(key) 删除指定KEY的元素,成功返回True,失败返回False * get(key) 获取指定KEY的元素值VALUE,失败返回NULL * element(index) 获取指定索引的元素(使用element.key,element.value获取KEY和VALUE),失败返回NULL * containsKey(key) 判断MAP中是否含有指定KEY的元素 * containsValue(value) 判断MAP中是否含有指定VALUE的元素 * values() 获取MAP中所有VALUE的数组(ARRAY) * keys() 获取MAP中所有KEY的数组(ARRAY) * * 例子: * var map = new Map(); * * map.put("key", "value"); * var val = map.get("key") * …… * */ function Map() { this.elements = new Array(); //获取MAP元素个数 this.size = function() { return this.elements.length; }; //判断MAP是否为空 this.isEmpty = function() { return (this.elements.length < 1); }; //删除MAP所有元素 this.clear = function() { this.elements = new Array(); }; //向MAP中增加元素(key, value) this.put = function(_key, _value) { this.elements.push( { key : _key, value : _value }); }; //删除指定KEY的元素,成功返回True,失败返回False this.removeByKey = function(_key) { var bln = false; try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].key == _key) { this.elements.splice(i, 1); return true; } } } catch (e) { bln = false; } return bln; }; //删除指定VALUE的元素,成功返回True,失败返回False this.removeByValue = function(_value) {//removeByValueAndKey var bln = false; try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].value == _value) { this.elements.splice(i, 1); return true; } } } catch (e) { bln = false; } return bln; }; //删除指定VALUE的元素,成功返回True,失败返回False this.removeByValueAndKey = function(_key,_value) { var bln = false; try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].value == _value && this.elements[i].key == _key) { this.elements.splice(i, 1); return true; } } } catch (e) { bln = false; } return bln; }; //获取指定KEY的元素值VALUE,失败返回NULL this.get = function(_key) { try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].key == _key) { return this.elements[i].value; } } } catch (e) { return false; } return false; }; //获取指定索引的元素(使用element.key,element.value获取KEY和VALUE),失败返回NULL this.element = function(_index) { if (_index < 0 || _index >= this.elements.length) { return null; } return this.elements[_index]; }; //判断MAP中是否含有指定KEY的元素 this.containsKey = function(_key) { var bln = false; try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].key == _key) { bln = true; } } } catch (e) { bln = false; } return bln; }; //判断MAP中是否含有指定VALUE的元素 this.containsValue = function(_value) { var bln = false; try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].value == _value) { bln = true; } } } catch (e) { bln = false; } return bln; }; //判断MAP中是否含有指定VALUE的元素 this.containsObj = function(_key,_value) { var bln = false; try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].value == _value && this.elements[i].key == _key) { bln = true; } } } catch (e) { bln = false; } return bln; }; //获取MAP中所有VALUE的数组(ARRAY) this.values = function() { var arr = new Array(); for (i = 0; i < this.elements.length; i++) { arr.push(this.elements[i].value); } return arr; }; //获取MAP中所有VALUE的数组(ARRAY) this.valuesByKey = function(_key) { var arr = new Array(); for (i = 0; i < this.elements.length; i++) { if (this.elements[i].key == _key) { arr.push(this.elements[i].value); } } return arr; }; //获取MAP中所有KEY的数组(ARRAY) this.keys = function() { var arr = new Array(); for (i = 0; i < this.elements.length; i++) { arr.push(this.elements[i].key); } return arr; }; //获取key通过value this.keysByValue = function(_value) { var arr = new Array(); for (i = 0; i < this.elements.length; i++) { if(_value == this.elements[i].value){ arr.push(this.elements[i].key); } } return arr; }; //获取MAP中所有KEY的数组(ARRAY) this.keysRemoveDuplicate = function() { var arr = new Array(); for (i = 0; i < this.elements.length; i++) { var flag = true; for(var j=0;j

' }) /* POPOVER NO CONFLICT * =================== */ $.fn.popover.noConflict = function () { $.fn.popover = old return this } }(window.jQuery); ================================================ FILE: clover/clover-admin/src/main/webapp/js/bootstrap-tooltip.js ================================================ /* =========================================================== * bootstrap-tooltip.js v2.3.2 * http://twbs.github.com/bootstrap/javascript.html#tooltips * Inspired by the original jQuery.tipsy by Jason Frame * =========================================================== * Copyright 2013 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ========================================================== */ !function ($) { "use strict"; // jshint ;_; /* TOOLTIP PUBLIC CLASS DEFINITION * =============================== */ var Tooltip = function (element, options) { this.init('tooltip', element, options) } Tooltip.prototype = { constructor: Tooltip , init: function (type, element, options) { var eventIn , eventOut , triggers , trigger , i this.type = type this.$element = $(element) this.options = this.getOptions(options) this.enabled = true triggers = this.options.trigger.split(' ') for (i = triggers.length; i--;) { trigger = triggers[i] if (trigger == 'click') { this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) } else if (trigger != 'manual') { eventIn = trigger == 'hover' ? 'mouseenter' : 'focus' eventOut = trigger == 'hover' ? 'mouseleave' : 'blur' this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) } } this.options.selector ? (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : this.fixTitle() } , getOptions: function (options) { options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options) if (options.delay && typeof options.delay == 'number') { options.delay = { show: options.delay , hide: options.delay } } return options } , enter: function (e) { var defaults = $.fn[this.type].defaults , options = {} , self this._options && $.each(this._options, function (key, value) { if (defaults[key] != value) options[key] = value }, this) self = $(e.currentTarget)[this.type](options).data(this.type) if (!self.options.delay || !self.options.delay.show) return self.show() clearTimeout(this.timeout) self.hoverState = 'in' this.timeout = setTimeout(function() { if (self.hoverState == 'in') self.show() }, self.options.delay.show) } , leave: function (e) { var self = $(e.currentTarget)[this.type](this._options).data(this.type) if (this.timeout) clearTimeout(this.timeout) if (!self.options.delay || !self.options.delay.hide) return self.hide() self.hoverState = 'out' this.timeout = setTimeout(function() { if (self.hoverState == 'out') self.hide() }, self.options.delay.hide) } , show: function () { var $tip , pos , actualWidth , actualHeight , placement , tp , e = $.Event('show') if (this.hasContent() && this.enabled) { this.$element.trigger(e) if (e.isDefaultPrevented()) return $tip = this.tip() this.setContent() if (this.options.animation) { $tip.addClass('fade') } placement = typeof this.options.placement == 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement $tip .detach() .css({ top: 0, left: 0, display: 'block' }) this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) pos = this.getPosition() actualWidth = $tip[0].offsetWidth actualHeight = $tip[0].offsetHeight switch (placement) { case 'bottom': tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} break case 'top': tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} break case 'left': tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} break case 'right': tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} break } this.applyPlacement(tp, placement) this.$element.trigger('shown') } } , applyPlacement: function(offset, placement){ var $tip = this.tip() , width = $tip[0].offsetWidth , height = $tip[0].offsetHeight , actualWidth , actualHeight , delta , replace $tip .offset(offset) .addClass(placement) .addClass('in') actualWidth = $tip[0].offsetWidth actualHeight = $tip[0].offsetHeight if (placement == 'top' && actualHeight != height) { offset.top = offset.top + height - actualHeight replace = true } if (placement == 'bottom' || placement == 'top') { delta = 0 if (offset.left < 0){ delta = offset.left * -2 offset.left = 0 $tip.offset(offset) actualWidth = $tip[0].offsetWidth actualHeight = $tip[0].offsetHeight } this.replaceArrow(delta - width + actualWidth, actualWidth, 'left') } else { this.replaceArrow(actualHeight - height, actualHeight, 'top') } if (replace) $tip.offset(offset) } , replaceArrow: function(delta, dimension, position){ this .arrow() .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '') } , setContent: function () { var $tip = this.tip() , title = this.getTitle() $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) $tip.removeClass('fade in top bottom left right') } , hide: function () { var that = this , $tip = this.tip() , e = $.Event('hide') this.$element.trigger(e) if (e.isDefaultPrevented()) return $tip.removeClass('in') function removeWithAnimation() { var timeout = setTimeout(function () { $tip.off($.support.transition.end).detach() }, 500) $tip.one($.support.transition.end, function () { clearTimeout(timeout) $tip.detach() }) } $.support.transition && this.$tip.hasClass('fade') ? removeWithAnimation() : $tip.detach() this.$element.trigger('hidden') return this } , fixTitle: function () { var $e = this.$element if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') } } , hasContent: function () { return this.getTitle() } , getPosition: function () { var el = this.$element[0] return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : { width: el.offsetWidth , height: el.offsetHeight }, this.$element.offset()) } , getTitle: function () { var title , $e = this.$element , o = this.options title = $e.attr('data-original-title') || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) return title } , tip: function () { return this.$tip = this.$tip || $(this.options.template) } , arrow: function(){ return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow") } , validate: function () { if (!this.$element[0].parentNode) { this.hide() this.$element = null this.options = null } } , enable: function () { this.enabled = true } , disable: function () { this.enabled = false } , toggleEnabled: function () { this.enabled = !this.enabled } , toggle: function (e) { var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this self.tip().hasClass('in') ? self.hide() : self.show() } , destroy: function () { this.hide().$element.off('.' + this.type).removeData(this.type) } } /* TOOLTIP PLUGIN DEFINITION * ========================= */ var old = $.fn.tooltip $.fn.tooltip = function ( option ) { return this.each(function () { var $this = $(this) , data = $this.data('tooltip') , options = typeof option == 'object' && option if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) if (typeof option == 'string') data[option]() }) } $.fn.tooltip.Constructor = Tooltip $.fn.tooltip.defaults = { animation: true , placement: 'top' , selector: false , template: '
' , trigger: 'hover focus' , title: '' , delay: 0 , html: false , container: false } /* TOOLTIP NO CONFLICT * =================== */ $.fn.tooltip.noConflict = function () { $.fn.tooltip = old return this } }(window.jQuery); ================================================ FILE: clover/clover-admin/src/main/webapp/js/exporting.js ================================================ /* Highcharts JS v3.0.1 (2013-04-09) Exporting module (c) 2010-2013 Torstein Hønsi License: www.highcharts.com/license */ (function(e){var y=e.Chart,v=e.addEvent,B=e.removeEvent,m=e.createElement,j=e.discardElement,t=e.css,k=e.merge,r=e.each,p=e.extend,C=Math.max,i=document,z=window,D=e.isTouchDevice,E=e.Renderer.prototype.symbols,s=e.getOptions(),w;p(s.lang,{printChart:"Print chart",downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",contextButtonTitle:"Chart context menu"});s.navigation={menuStyle:{border:"1px solid #A0A0A0", background:"#FFFFFF",padding:"5px 0"},menuItemStyle:{padding:"0 10px",background:"none",color:"#303030",fontSize:D?"14px":"11px"},menuItemHoverStyle:{background:"#4572A5",color:"#FFFFFF"},buttonOptions:{symbolFill:"#E0E0E0",symbolSize:14,symbolStroke:"#666",symbolStrokeWidth:3,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,theme:{fill:"white",stroke:"none"},verticalAlign:"top",width:24}};s.exporting={type:"image/png",url:"http://export.highcharts.com/",buttons:{contextButton:{symbol:"menu", _titleKey:"contextButtonTitle",menuItems:[{textKey:"printChart",onclick:function(){this.print()}},{separator:!0},{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]}}};e.post=function(a,b){var c,d;d=m("form",{method:"post",action:a,enctype:"multipart/form-data"}, {display:"none"},i.body);for(c in b)m("input",{type:"hidden",name:c,value:b[c]},null,d);d.submit();j(d)};p(y.prototype,{getSVG:function(a){var b=this,c,d,x,g,f=k(b.options,a);if(!i.createElementNS)i.createElementNS=function(a,b){return i.createElement(b)};a=m("div",null,{position:"absolute",top:"-9999em",width:b.chartWidth+"px",height:b.chartHeight+"px"},i.body);d=b.renderTo.style.width;g=b.renderTo.style.height;d=f.exporting.sourceWidth||f.chart.width||/px$/.test(d)&&parseInt(d,10)||600;g=f.exporting.sourceHeight|| f.chart.height||/px$/.test(g)&&parseInt(g,10)||400;p(f.chart,{animation:!1,renderTo:a,forExport:!0,width:d,height:g});f.exporting.enabled=!1;f.chart.plotBackgroundImage=null;f.series=[];r(b.series,function(a){x=k(a.options,{animation:!1,showCheckbox:!1,visible:a.visible});x.isInternal||f.series.push(x)});c=new e.Chart(f,b.callback);r(["xAxis","yAxis"],function(a){r(b[a],function(b,d){var f=c[a][d],e=b.getExtremes(),g=e.userMin,e=e.userMax;(g!==void 0||e!==void 0)&&f.setExtremes(g,e,!0,!1)})});d=c.container.innerHTML; f=null;c.destroy();j(a);d=d.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\([^#]+#/g,"url(#").replace(/.*?$/,"").replace(/ /g," ").replace(/­/g,"­").replace(//g, 'xlink:href="$1"/>').replace(/id=([^" >]+)/g,'id="$1"').replace(/class=([^" ]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/style="([^"]+)"/g,function(a){return a.toLowerCase()});d=d.replace(/(url\(#highcharts-[0-9]+)"/g,"$1").replace(/"/g,"'");d.match(/ xmlns="/g).length===2&&(d=d.replace(/xmlns="[^"]+"/,""));return d},exportChart:function(a,b){var a=a||{},c=this.options.exporting,c=this.getSVG(k({chart:{borderRadius:0}},c,b,{exporting:{sourceWidth:a.sourceWidth|| c.sourceWidth,sourceHeight:a.sourceHeight||c.sourceHeight}})),a=k(this.options.exporting,a);e.post(a.url,{filename:a.filename||"chart",type:a.type,width:a.width||0,scale:a.scale||2,svg:c})},print:function(){var a=this,b=a.container,c=[],d=b.parentNode,e=i.body,g=e.childNodes;if(!a.isPrinting)a.isPrinting=!0,r(g,function(a,b){if(a.nodeType===1)c[b]=a.style.display,a.style.display="none"}),e.appendChild(b),z.focus(),z.print(),setTimeout(function(){d.appendChild(b);r(g,function(a,b){if(a.nodeType=== 1)a.style.display=c[b]});a.isPrinting=!1},1E3)},contextMenu:function(a,b,c,d,e,g,f){var h=this,q=h.options.navigation,n=q.menuItemStyle,o=h.chartWidth,i=h.chartHeight,A="cache-"+a,l=h[A],k=C(e,g),u,j,s;if(!l)h[A]=l=m("div",{className:"highcharts-"+a},{position:"absolute",zIndex:1E3,padding:k+"px"},h.container),u=m("div",null,p({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},q.menuStyle),l),j=function(){t(l,{display:"none"});f&&f.setState(0)},v(l, "mouseleave",function(){s=setTimeout(j,500)}),v(l,"mouseenter",function(){clearTimeout(s)}),r(b,function(a){if(a){var b=a.separator?m("hr",null,null,u):m("div",{onmouseover:function(){t(this,q.menuItemHoverStyle)},onmouseout:function(){t(this,n)},onclick:function(){j();a.onclick.apply(h,arguments)},innerHTML:a.text||h.options.lang[a.textKey]},p({cursor:"pointer"},n),u);h.exportDivElements.push(b)}}),h.exportDivElements.push(u,l),h.exportMenuWidth=l.offsetWidth,h.exportMenuHeight=l.offsetHeight;a= {display:"block"};c+h.exportMenuWidth>o?a.right=o-c-e-k+"px":a.left=c-k+"px";d+g+h.exportMenuHeight>i?a.bottom=i-d-k+"px":a.top=d+g-k+"px";t(l,a)},addButton:function(a){var b=this,c=b.renderer,a=k(b.options.navigation.buttonOptions,a),d=a.onclick,i=a.menuItems,g,f,h={stroke:a.symbolStroke,fill:a.symbolFill},q=a.symbolSize||12;if(!b.btnCount)b.btnCount=0;b.btnCount++;if(!b.exportDivElements)b.exportDivElements=[],b.exportSVGElements=[];if(a.enabled!==!1){var n=a.theme,o=n.states,m=o&&o.hover,o=o&& o.select,j;delete n.states;d?j=function(){d.apply(b,arguments)}:i&&(j=function(){b.contextMenu("contextmenu",i,f.translateX,f.translateY,f.width,f.height,f);f.setState(2)});a.text&&a.symbol?n.paddingLeft=e.pick(n.paddingLeft,25):a.text||p(n,{width:a.width,height:a.height,padding:0});f=c.button(a.text,0,0,j,n,m,o).attr({title:b.options.lang[a._titleKey],"stroke-linecap":"round"});a.symbol&&(g=c.symbol(a.symbol,a.symbolX-q/2,a.symbolY-q/2,q,q).attr(p(h,{"stroke-width":a.symbolStrokeWidth||1,zIndex:1})).add(f)); f.add().align(p(a,{width:f.width,x:e.pick(a.x,w)}),!0,"spacingBox");w+=(f.width+a.buttonSpacing)*(a.align==="right"?-1:1);b.exportSVGElements.push(f,g)}},destroyExport:function(a){var a=a.target,b,c;for(b=0;b3?c.length%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+Q(a-c).toFixed(f).slice(2):"")}function ua(a,b){return Array((b||2)+1-String(a).length).join(0)+a}function Ea(a,b){for(var c="{",d=!1,e,f,g,h,i,j=[];(c=a.indexOf(c))!==-1;){e=a.slice(0,c);if(d){f=e.split(":");g=f.shift().split(".");i=g.length;e=b;for(h=0;h< i;h++)e=e[g[h]];if(f.length)f=f.join(":"),g=/\.([0-9])/,h=N.lang,i=void 0,/f$/.test(f)?(i=(i=f.match(g))?i[1]:-1,e=Na(e,i,h.decimalPoint,f.indexOf(",")>-1?h.thousandsSep:"")):e=Ua(f,e)}j.push(e);a=a.slice(c+1);c=(d=!d)?"}":"{"}j.push(a);return j.join("")}function ib(a,b,c,d){var e,c=o(c,1);e=a/c;b||(b=[1,2,2.5,5,10],d&&d.allowDecimals===!1&&(c===1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d=E[jb]&& (i.setMilliseconds(0),i.setSeconds(j>=E[Va]?0:k*T(i.getSeconds()/k)));if(j>=E[Va])i[Bb](j>=E[Oa]?0:k*T(i[kb]()/k));if(j>=E[Oa])i[Cb](j>=E[oa]?0:k*T(i[lb]()/k));if(j>=E[oa])i[mb](j>=E[Pa]?1:k*T(i[Qa]()/k));j>=E[Pa]&&(i[Db](j>=E[va]?0:k*T(i[Xa]()/k)),h=i[Ya]());j>=E[va]&&(h-=h%k,i[Eb](h));if(j===E[Wa])i[mb](i[Qa]()-i[nb]()+o(d,1));b=1;h=i[Ya]();for(var d=i.getTime(),m=i[Xa](),l=i[Qa](),i=g?0:(864E5+i.getTimezoneOffset()*6E4)%864E5;dc&&(c=a[b]);return c}function Ga(a, b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),delete a[c]}function Ra(a){$a||($a=U(wa));a&&$a.appendChild(a);$a.innerHTML=""}function qa(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;else O.console&&console.log(c)}function ia(a){return parseFloat(a.toPrecision(14))}function Ha(a,b){xa=o(a,b.animation)}function Hb(){var a=N.global.useUTC,b=a?"getUTC":"get",c=a?"setUTC":"set";Za=a?Date.UTC:function(a,b,c,g,h,i){return(new Date(a,b,o(c,1),o(g,0),o(h, 0),o(i,0))).getTime()};kb=b+"Minutes";lb=b+"Hours";nb=b+"Day";Qa=b+"Date";Xa=b+"Month";Ya=b+"FullYear";Bb=c+"Minutes";Cb=c+"Hours";mb=c+"Date";Db=c+"Month";Eb=c+"FullYear"}function ra(){}function Ia(a,b,c,d){this.axis=a;this.pos=b;this.type=c||"";this.isNew=!0;!c&&!d&&this.addLabel()}function ob(a,b){this.axis=a;if(b)this.options=b,this.id=b.id}function Ib(a,b,c,d,e,f){var g=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=b;this.x=d;this.stack=e;this.percent=f==="percent";this.alignOptions= {align:b.align||(g?c?"left":"right":"center"),verticalAlign:b.verticalAlign||(g?"middle":c?"bottom":"top"),y:o(b.y,g?4:c?14:-6),x:o(b.x,g?c?-6:6:0)};this.textAlign=b.textAlign||(g?c?"right":"left":"center")}function ab(){this.init.apply(this,arguments)}function pb(){this.init.apply(this,arguments)}function qb(a,b){this.init(a,b)}function rb(a,b){this.init(a,b)}function sb(){this.init.apply(this,arguments)}var x,z=document,O=window,I=Math,t=I.round,T=I.floor,ja=I.ceil,q=I.max,K=I.min,Q=I.abs,Y=I.cos, ca=I.sin,Ja=I.PI,bb=Ja*2/360,ya=navigator.userAgent,Jb=O.opera,Da=/msie/i.test(ya)&&!Jb,cb=z.documentMode===8,db=/AppleWebKit/.test(ya),eb=/Firefox/.test(ya),Kb=/(Mobile|Android|Windows Phone)/.test(ya),sa="http://www.w3.org/2000/svg",Z=!!z.createElementNS&&!!z.createElementNS(sa,"svg").createSVGRect,Rb=eb&&parseInt(ya.split("Firefox/")[1],10)<4,$=!Z&&!Da&&!!z.createElement("canvas").getContext,Sa,fb=z.documentElement.ontouchstart!==x,Lb={},tb=0,$a,N,Ua,xa,ub,E,ta=function(){},za=[],wa="div",S="none", Mb="rgba(192,192,192,"+(Z?1.0E-4:0.002)+")",zb="millisecond",jb="second",Va="minute",Oa="hour",oa="day",Wa="week",Pa="month",va="year",Nb="stroke-width",Za,kb,lb,nb,Qa,Xa,Ya,Bb,Cb,mb,Db,Eb,aa={};O.Highcharts=O.Highcharts?qa(16,!0):{};Ua=function(a,b,c){if(!r(b)||isNaN(b))return"Invalid date";var a=o(a,"%Y-%m-%d %H:%M:%S"),d=new Date(b),e,f=d[lb](),g=d[nb](),h=d[Qa](),i=d[Xa](),j=d[Ya](),k=N.lang,m=k.weekdays,d=v({a:m[g].substr(0,3),A:m[g],d:ua(h),e:h,b:k.shortMonths[i],B:k.months[i],m:ua(i+1),y:j.toString().substr(2, 2),Y:j,H:ua(f),I:ua(f%12||12),l:f%12||12,M:ua(d[kb]()),p:f<12?"AM":"PM",P:f<12?"am":"pm",S:ua(d.getSeconds()),L:ua(t(b%1E3),3)},Highcharts.dateFormats);for(e in d)for(;a.indexOf("%"+e)!==-1;)a=a.replace("%"+e,typeof d[e]==="function"?d[e](b):d[e]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a};Fb.prototype={wrapColor:function(a){if(this.color>=a)this.color=0},wrapSymbol:function(a){if(this.symbol>=a)this.symbol=0}};E=function(){for(var a=0,b=arguments,c=b.length,d={};a-1,f=e?7:3,g,b=b.split(" "),c=[].concat(c),h,i,j=function(a){for(g=a.length;g--;)a[g]==="M"&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&&(j(b),j(c));a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6));if(d<=c.length/f)for(;d--;)c=[].concat(c).splice(0,f).concat(c);a.shift=0;if(b.length)for(a=c.length;b.length{point.key}
', pointFormat:'{series.name}: {point.y}
',shadow:!0,snap:Kb?25:10,style:{color:"#333333",cursor:"default",fontSize:"12px",padding:"8px",whiteSpace:"nowrap"}},credits:{enabled:!0,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"9px"}}};var X=N.plotOptions,W=X.line;Hb();var ma=function(a){var b=[],c,d;(function(a){a&&a.stops?d=Ka(a.stops, function(a){return ma(a[1])}):(c=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(a))?b=[u(c[1]),u(c[2]),u(c[3]),parseFloat(c[4],10)]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(a))?b=[u(c[1],16),u(c[2],16),u(c[3],16),1]:(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(a))&&(b=[u(c[1]),u(c[2]),u(c[3]),1])})(a);return{get:function(c){var f;d?(f=y(a),f.stops=[].concat(f.stops),n(d,function(a,b){f.stops[b]=[f.stops[b][0], a.get(c)]})):f=b&&!isNaN(b[0])?c==="rgb"?"rgb("+b[0]+","+b[1]+","+b[2]+")":c==="a"?b[3]:"rgba("+b.join(",")+")":a;return f},brighten:function(a){if(d)n(d,function(b){b.brighten(a)});else if(Ca(a)&&a!==0){var c;for(c=0;c<3;c++)b[c]+=u(a*255),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},rgba:b,setOpacity:function(a){b[3]=a;return this}}};ra.prototype={init:function(a,b){this.element=b==="span"?U(b):z.createElementNS(sa,b);this.renderer=a;this.attrSetters={}},opacity:1,animate:function(a,b,c){b= o(b,xa,!0);Ta(this);if(b){b=y(b);if(c)b.complete=c;vb(this,a,b)}else this.attr(a),c&&c()},attr:function(a,b){var c,d,e,f,g=this.element,h=g.nodeName.toLowerCase(),i=this.renderer,j,k=this.attrSetters,m=this.shadows,l,p,s=this;fa(a)&&r(b)&&(c=a,a={},a[c]=b);if(fa(a))c=a,h==="circle"?c={x:"cx",y:"cy"}[c]||c:c==="strokeWidth"&&(c="stroke-width"),s=A(g,c)||this[c]||0,c!=="d"&&c!=="visibility"&&(s=parseFloat(s));else{for(c in a)if(j=!1,d=a[c],e=k[c]&&k[c].call(this,d,c),e!==!1){e!==x&&(d=e);if(c==="d")d&& d.join&&(d=d.join(" ")),/(NaN| {2}|^$)/.test(d)&&(d="M 0 0");else if(c==="x"&&h==="text")for(e=0;el&&/[ \-]/.test(b.textContent||b.innerText))L(b,{width:l+"px",display:"block",whiteSpace:"normal"}),k=l;l=a.fontMetrics(b.style.fontSize).b;B=s<0&&-k;w=p<0&&-m;wb=s*p<0;B+=p*l*(wb?1-h:h);w-=s*l*(j?wb?h:1-h:1);i&&(B-=k*h*(s<0?-1:1),j&&(w-=m*h*(p<0?-1:1)),L(b,{textAlign:g}));this.xCorr=B;this.yCorr=w}L(b,{left:e+B+"px",top:f+w+"px"});if(db)m=b.offsetHeight;this.cTT=G}}else this.alignOnAdd=!0},updateTransform:function(){var a=this.translateX|| 0,b=this.translateY||0,c=this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation,g=[];e&&(a+=this.attr("width"),b+=this.attr("height"));(a||b)&&g.push("translate("+a+","+b+")");e?g.push("rotate(90) scale(-1,1)"):f&&g.push("rotate("+f+" "+(this.x||0)+" "+(this.y||0)+")");(r(c)||r(d))&&g.push("scale("+o(c,1)+" "+o(d,1)+")");g.length&&A(this.element,"transform",g.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){var d,e,f,g,h={};e=this.renderer; f=e.alignedObjects;if(a){if(this.alignOptions=a,this.alignByTranslate=b,!c||fa(c))this.alignTo=d=c||"renderer",ga(f,this),f.push(this),c=null}else a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo;c=o(c,e[d],e);d=a.align;e=a.verticalAlign;f=(c.x||0)+(a.x||0);g=(c.y||0)+(a.y||0);if(d==="right"||d==="center")f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?"translateX":"x"]=t(f);if(e==="bottom"||e==="middle")g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?"translateY":"y"]=t(g); this[this.placed?"animate":"attr"](h);this.placed=!0;this.alignAttr=h;return this},getBBox:function(){var a=this.bBox,b=this.renderer,c,d=this.rotation;c=this.element;var e=this.styles,f=d*bb;if(!a){if(c.namespaceURI===sa||b.forExport){try{a=c.getBBox?v({},c.getBBox()):{width:c.offsetWidth,height:c.offsetHeight}}catch(g){}if(!a||a.width<0)a={width:0,height:0}}else a=this.htmlGetBBox();if(b.isSVG){b=a.width;c=a.height;if(Da&&e&&e.fontSize==="11px"&&c.toPrecision(3)==="22.7")a.height=c=14;if(d)a.width= Q(c*ca(f))+Q(b*Y(f)),a.height=Q(c*Y(f))+Q(b*ca(f))}this.bBox=a}return a},show:function(){return this.attr({visibility:"visible"})},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||150,complete:function(){b.hide()}})},add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=d.childNodes,f=this.element,g=A(f,"zIndex"),h;if(a)this.parentGroup=a;this.parentInverted=a&&a.inverted;this.textStr!==void 0&&b.buildText(this);if(g)c.handleZ= !0,g=u(g);if(c.handleZ)for(c=0;cg||!r(g)&&r(b))){d.insertBefore(f,a);h=!0;break}h||d.appendChild(f);this.added=!0;D(this,"add");return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||{},c=a.shadows,d,e;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point=null;Ta(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(e=0;e/g,'').replace(/<(i|em)>/g,'').replace(//g,"").split(//g),f=b.childNodes,g=/style="([^"]+)"/,h=/href="([^"]+)"/,i=A(b,"x"),j=a.styles,k=j&&j.width&&u(j.width),m=j&&j.lineHeight,l=f.length;l--;)b.removeChild(f[l]);k&&!a.added&&this.box.appendChild(b);e[e.length-1]===""&&e.pop();n(e,function(e,f){var l,o=0,e=e.replace(//g,"|||");l=e.split("|||");n(l,function(e){if(e!==""||l.length===1){var p={},n=z.createElementNS(sa,"tspan"),q;g.test(e)&&(q= e.match(g)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),A(n,"style",q));h.test(e)&&!d&&(A(n,"onclick",'location.href="'+e.match(h)[1]+'"'),L(n,{cursor:"pointer"}));e=(e.replace(/<(.|\n)*?>/g,"")||" ").replace(/</g,"<").replace(/>/g,">");n.appendChild(z.createTextNode(e));o?p.dx=0:p.x=i;A(n,p);!o&&f&&(!Z&&d&&L(n,{display:"block"}),A(n,"dy",m||c.fontMetrics(/px$/.test(n.style.fontSize)?n.style.fontSize:j.fontSize).h,db&&n.offsetHeight));b.appendChild(n);o++;if(k)for(var e=e.replace(/([^\^])-/g, "$1- ").split(" "),r,t=[];e.length||t.length;)delete a.bBox,r=a.getBBox().width,p=r>k,!p||e.length===1?(e=t,t=[],e.length&&(n=z.createElementNS(sa,"tspan"),A(n,{dy:m||16,x:i}),q&&A(n,"style",q),b.appendChild(n),r>k&&(k=r))):(n.removeChild(n.firstChild),t.unshift(e.pop())),e.length&&n.appendChild(z.createTextNode(e.join(" ").replace(/- /g,"-")))}})})},button:function(a,b,c,d,e,f,g){var h=this.label(a,b,c,null,null,null,null,null,"button"),i=0,j,k,m,l,p,a={x1:0,y1:0,x2:0,y2:1},e=y({"stroke-width":1, stroke:"#CCCCCC",fill:{linearGradient:a,stops:[[0,"#FEFEFE"],[1,"#F6F6F6"]]},r:2,padding:5,style:{color:"black"}},e);m=e.style;delete e.style;f=y(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#FFF"],[1,"#ACF"]]}},f);l=f.style;delete f.style;g=y(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#9BD"],[1,"#CDF"]]}},g);p=g.style;delete g.style;J(h.element,"mouseenter",function(){h.attr(f).css(l)});J(h.element,"mouseleave",function(){j=[e,f,g][i];k=[m,l,p][i];h.attr(j).css(k)});h.setState=function(a){(i= a)?a===2&&h.attr(g).css(p):h.attr(e).css(m)};return h.on("click",function(){d.call(h)}).attr(e).css(v({cursor:"default"},m))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=t(a[1])-b%2/2);a[2]===a[5]&&(a[2]=a[5]=t(a[2])+b%2/2);return a},path:function(a){var b={fill:S};Ba(a)?b.d=a:V(a)&&v(b,a);return this.createElement("path").attr(b)},circle:function(a,b,c){a=V(a)?a:{x:a,y:b,r:c};return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(V(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end, a=a.x;return this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0})},rect:function(a,b,c,d,e,f){e=V(a)?a.r:e;e=this.createElement("rect").attr({rx:e,ry:e,fill:S});return e.attr(V(a)?a:e.crisp(f,a,b,q(c,0),q(d,0)))},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[o(c,!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return r(a)?b.attr({"class":"highcharts-"+a}):b},image:function(a, b,c,d,e){var f={preserveAspectRatio:S};arguments.length>1&&v(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e,f){var g,h=this.symbols[a],h=h&&h(t(b),t(c),d,e,f),i=/^url\((.*?)\)$/,j,k;if(h)g=this.path(h),v(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&v(g,f);else if(i.test(a))k=function(a,b){a.element&&(a.attr({width:b[0], height:b[1]}),a.alignByTranslate||a.translate(t((d-b[0])/2),t((e-b[1])/2)))},j=a.match(i)[1],a=Lb[j],g=this.image(j).attr({x:b,y:c}),g.isImg=!0,a?k(g,a):(g.attr({width:0,height:0}),U("img",{onload:function(){k(g,Lb[j]=[this.width,this.height])},src:j}));return g},symbols:{circle:function(a,b,c,d){var e=0.166*c;return["M",a+c/2,b,"C",a+c+e,b,a+c+e,b+d,a+c/2,b+d,"C",a-e,b+d,a-e,b,a+c/2,b,"Z"]},square:function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M", a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d/2,a+c/2,b+d,a,b+d/2,"Z"]},arc:function(a,b,c,d,e){var f=e.start,c=e.r||c||d,g=e.end-0.001,d=e.innerR,h=e.open,i=Y(f),j=ca(f),k=Y(g),g=ca(g),e=e.end-f');if(b)c=e||b==="span"||b==="img"?c.join(""):a.prepVML(c),this.element=U(c);this.renderer=a;this.attrSetters={}},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();D(this,"add");return this},updateTransform:ra.prototype.htmlUpdateTransform,attr:function(a,b){var c, d,e,f=this.element||{},g=f.style,h=f.nodeName,i=this.renderer,j=this.symbolName,k,m=this.shadows,l,p=this.attrSetters,s=this;fa(a)&&r(b)&&(c=a,a={},a[c]=b);if(fa(a))c=a,s=c==="strokeWidth"||c==="stroke-width"?this.strokeweight:this[c];else for(c in a)if(d=a[c],l=!1,e=p[c]&&p[c].call(this,d,c),e!==!1&&d!==null){e!==x&&(d=e);if(j&&/^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(c))k||(this.symbolAttr(a),k=!0),l=!0;else if(c==="d"){d=d||[];this.d=d.join(" ");e=d.length;l=[];for(var o;e--;)if(Ca(d[e]))l[e]= t(d[e]*10)-5;else if(d[e]==="Z")l[e]="x";else if(l[e]=d[e],d.isArc&&(d[e]==="wa"||d[e]==="at"))o=d[e]==="wa"?1:-1,l[e+5]===l[e+7]&&(l[e+7]-=o),l[e+6]===l[e+8]&&(l[e+8]-=o);d=l.join(" ")||"x";f.path=d;if(m)for(e=m.length;e--;)m[e].path=m[e].cutOff?this.cutOffPath(d,m[e].cutOff):d;l=!0}else if(c==="visibility"){if(m)for(e=m.length;e--;)m[e].style[c]=d;h==="DIV"&&(d=d==="hidden"?"-999em":0,cb||(g[c]=d?"visible":"hidden"),c="top");g[c]=d;l=!0}else if(c==="zIndex")d&&(g[c]=d),l=!0;else if(la(c,["x","y", "width","height"])!==-1)this[c]=d,c==="x"||c==="y"?c={x:"left",y:"top"}[c]:d=q(0,d),this.updateClipping?(this[c]=d,this.updateClipping()):g[c]=d,l=!0;else if(c==="class"&&h==="DIV")f.className=d;else if(c==="stroke")d=i.color(d,f,c),c="strokecolor";else if(c==="stroke-width"||c==="strokeWidth")f.stroked=d?!0:!1,c="strokeweight",this[c]=d,Ca(d)&&(d+="px");else if(c==="dashstyle")(f.getElementsByTagName("stroke")[0]||U(i.prepVML([""]),null,null,f))[c]=d||"solid",this.dashstyle=d,l=!0;else if(c=== "fill")if(h==="SPAN")g.color=d;else{if(h!=="IMG")f.filled=d!==S?!0:!1,d=i.color(d,f,c,this),c="fillcolor"}else if(c==="opacity")l=!0;else if(h==="shape"&&c==="rotation")this[c]=d,f.style.left=-t(ca(d*bb)+1)+"px",f.style.top=t(Y(d*bb))+"px";else if(c==="translateX"||c==="translateY"||c==="rotation")this[c]=d,this.updateTransform(),l=!0;else if(c==="text")this.bBox=null,f.innerHTML=d,l=!0;l||(cb?f[c]=d:A(f,c,d))}return s},clip:function(a){var b=this,c;a?(c=a.members,ga(c,b),c.push(b),b.destroyClip= function(){ga(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:cb?"inherit":"rect(auto)"});return b.css(a)},css:ra.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Ra(a)},destroy:function(){this.destroyClip&&this.destroyClip();return ra.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+a]=function(){var a=O.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){var c,a=a.split(/[ ,]/);c=a.length;if(c===9||c===11)a[c-4]=a[c-2]=u(a[c-2])-10*b; return a.join(" ")},shadow:function(a,b,c){var d=[],e,f=this.element,g=this.renderer,h,i=f.style,j,k=f.path,m,l,p,s;k&&typeof k.value!=="string"&&(k="x");l=k;if(a){p=o(a.width,3);s=(a.opacity||0.15)/p;for(e=1;e<=3;e++){m=p*2+1-2*e;c&&(l=this.cutOffPath(k.value,m+0.5));j=[''];h=U(g.prepVML(j),null,{left:u(i.left)+o(a.offsetX,1),top:u(i.top)+o(a.offsetY,1)});if(c)h.cutOff=m+1;j=[''];U(g.prepVML(j),null,null,h);b?b.element.appendChild(h):f.parentNode.insertBefore(h,f);d.push(h)}this.shadows=d}return this}};F=ea(ra,F);var na={Element:F,isIE8:ya.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d,e;this.alignedObjects=[];d=this.createElement(wa);e=d.element;e.style.position="relative";a.appendChild(d.element);this.isVML=!0;this.box=e;this.boxWrapper=d;this.setSize(b,c,!1);if(!z.namespaces.hcv)z.namespaces.add("hcv","urn:schemas-microsoft-com:vml"), z.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "},isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=V(a);return v(e,{members:[],left:f?a.x:a,top:f?a.y:b,width:f?a.width:c,height:f?a.height:d,getCSS:function(a){var b=a.element,c=b.nodeName,a=a.inverted,d=this.top-(c==="shape"?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:"rect("+t(a?e:d)+ "px,"+t(a?f:b)+"px,"+t(a?b:f)+"px,"+t(a?d:e)+"px)"};!a&&cb&&c==="DIV"&&v(d,{width:b+"px",height:f+"px"});return d},updateClipping:function(){n(e.members,function(a){a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var e=this,f,g=/^rgba/,h,i,j=S;a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern");if(i){var k,m,l=a.linearGradient||a.radialGradient,p,s,o,B,w,q="",a=a.stops,r,t=[],x=function(){h=['']; U(e.prepVML(h),null,null,b)};p=a[0];r=a[a.length-1];p[0]>0&&a.unshift([0,p[1]]);r[0]<1&&a.push([1,r[1]]);n(a,function(a,b){g.test(a[1])?(f=ma(a[1]),k=f.get("rgb"),m=f.get("a")):(k=a[1],m=1);t.push(a[0]*100+"% "+k);b?(o=m,B=k):(s=m,w=k)});if(c==="fill")if(i==="gradient")c=l.x1||l[0]||0,a=l.y1||l[1]||0,p=l.x2||l[2]||0,l=l.y2||l[3]||0,q='angle="'+(90-I.atan((l-a)/(p-c))*180/Ja)+'"',x();else{var j=l.r,v=j*2,P=j*2,H=l.cx,C=l.cy,y=b.radialReference,u,j=function(){y&&(u=d.getBBox(),H+=(y[0]-u.x)/u.width- 0.5,C+=(y[1]-u.y)/u.height-0.5,v*=y[2]/u.width,P*=y[2]/u.height);q='src="'+N.global.VMLRadialGradientURL+'" size="'+v+","+P+'" origin="0.5,0.5" position="'+H+","+C+'" color2="'+w+'" ';x()};d.added?j():J(d,"add",j);j=B}else j=k}else if(g.test(a)&&b.tagName!=="IMG")f=ma(a),h=["<",c,' opacity="',f.get("a"),'"/>'],U(this.prepVML(h),null,null,b),j=f.get("rgb");else{j=b.getElementsByTagName(c);if(j.length)j[0].opacity=1,j[0].type="solid";j=a}return j},prepVML:function(a){var b=this.isIE8,a=a.join("");b? (a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')):a=a.replace("<","1&&f.attr({x:b,y:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){if(V(a))b=a.y,c=a.width,d=a.height,f=a.strokeWidth,a=a.x;var g=this.symbol("rect");g.r=e;return g.attr(g.crisp(f,a,b,q(c,0),q(d,0)))},invertChild:function(a,b){var c=b.style;L(a,{flip:"x", left:u(c.width)-1,top:u(c.height)-1,rotation:-90})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||d,c=e.innerR,d=Y(f),i=ca(f),j=Y(g),k=ca(g);if(g-f===0)return["x"];f=["wa",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*j,b+h*k];e.open&&!c&&f.push("e","M",a,b);f.push("at",a-c,b-c,a+c,b+c,a+c*j,b+c*k,a+c*d,b+c*i,"x","e");f.isArc=!0;return f},circle:function(a,b,c,d){return["wa",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,"e"]},rect:function(a,b,c,d,e){var f=a+c,g=b+d,h;!r(e)||!e.r?f=Aa.prototype.symbols.square.apply(0, arguments):(h=K(e.r,c,d),f=["M",a+h,b,"L",f-h,b,"wa",f-2*h,b,f,b+2*h,f-h,b,f,b+h,"L",f,g-h,"wa",f-2*h,g-2*h,f,g,f,g-h,f-h,g,"L",a+h,g,"wa",a,g-2*h,a+2*h,g,a+h,g,a,g-h,"L",a,b+h,"wa",a,b,a+2*h,b+2*h,a,b+h,a+h,b,"x","e"]);return f}}};Highcharts.VMLRenderer=F=function(){this.init.apply(this,arguments)};F.prototype=y(Aa.prototype,na);Sa=F}var Qb;if($)Highcharts.CanVGRenderer=F=function(){sa="http://www.w3.org/1999/xhtml"},F.prototype.symbols={},Qb=function(){function a(){var a=b.length,d;for(d=0;dj&&(c=!1)):h+k>l&&(h=l-k,d&& h+m0&&b.height>0){f=y({align:c&&k&&"center",x:c?!k&&4:10,verticalAlign:!c&&k&&"middle",y:c?k?16:10:k?6:-4,rotation:c&&!k&&90},f);if(!g)a.label=g=t.text(f.text,0,0).attr({align:f.textAlign||f.align,rotation:f.rotation,zIndex:w}).css(f.style).add();b=[s[1],s[4], o(s[6],s[1])];s=[s[2],s[5],o(s[7],s[2])];c=Fa(b);k=Fa(s);g.align(f,!1,{x:c,y:k,width:pa(b)-c,height:pa(s)-k});g.show()}else g&&g.hide();return a},destroy:function(){ga(this.axis.plotLinesAndBands,this);Ga(this,this.axis)}};Ib.prototype={destroy:function(){Ga(this,this.axis)},setTotal:function(a){this.cum=this.total=a},render:function(a){var b=this.options,c=b.formatter.call(this);this.label?this.label.attr({text:c,visibility:"hidden"}):this.label=this.axis.chart.renderer.text(c,0,0,b.useHTML).css(b.style).attr({align:this.textAlign, rotation:b.rotation,visibility:"hidden"}).add(a)},setOffset:function(a,b){var c=this.axis,d=c.chart,e=d.inverted,f=this.isNegative,g=c.translate(this.percent?100:this.total,0,0,0,1),c=c.translate(0),c=Q(g-c),h=d.xAxis[0].translate(this.x)+a,i=d.plotHeight,f={x:e?f?g:g-c:h,y:e?i-h-b:f?i-g-c:i-g,width:e?c:b,height:e?b:c};if(e=this.label)e.align(this.alignOptions,null,f),f=e.alignAttr,e.attr({visibility:this.options.crop===!1||d.isInsidePlot(f.x,f.y)?Z?"inherit":"visible":"hidden"})}};ab.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L", second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,gridLineColor:"#C0C0C0",labels:M,lineColor:"#C0D0E0",lineWidth:1,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#4d759e", fontWeight:"bold"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0,gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{align:"right",x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return this.total},style:M.style}},defaultLeftAxisOptions:{labels:{align:"right",x:-8,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{align:"left",x:8,y:null},title:{rotation:90}}, defaultBottomAxisOptions:{labels:{align:"center",x:0,y:14},title:{rotation:0}},defaultTopAxisOptions:{labels:{align:"center",x:0,y:-5},title:{rotation:0}},init:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c;this.xOrY=(this.isXAxis=c)?"x":"y";this.opposite=b.opposite;this.side=this.horiz?this.opposite?0:2:this.opposite?1:3;this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.staggerLines=this.horiz&&d.labels.staggerLines;this.userOptions= b;this.minPixelPadding=0;this.chart=a;this.reversed=d.reversed;this.zoomEnabled=d.zoomEnabled!==!1;this.categories=d.categories||e==="category";this.isLog=e==="logarithmic";this.isDatetimeAxis=e==="datetime";this.isLinked=r(d.linkedTo);this.tickmarkOffset=this.categories&&d.tickmarkPlacement==="between"?0.5:0;this.ticks={};this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;this.offset=d.offset||0; this.stacks={};this._stacksTouched=0;this.min=this.max=null;var f,d=this.options.events;la(this,a.axes)===-1&&(a.axes.push(this),a[c?"xAxis":"yAxis"].push(this));this.series=this.series||[];if(a.inverted&&c&&this.reversed===x)this.reversed=!0;this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in d)J(this,f,d[f]);if(this.isLog)this.val2lin=ka,this.lin2val=da},setOptions:function(a){this.options=y(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions, this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],y(N[this.isXAxis?"xAxis":"yAxis"],a))},update:function(a,b){var c=this.chart,a=c.options[this.xOrY+"Axis"][this.options.index]=y(this.userOptions,a);this.destroy();this._addedPlotLB=!1;this.init(c,a);c.isDirtyBox=!0;o(b,!0)&&c.redraw()},remove:function(a){var b=this.chart,c=this.xOrY+"Axis";n(this.series,function(a){a.remove(!1)});ga(b.axes,this);ga(b[c],this);b.options[c].splice(this.options.index, 1);this.destroy();b.isDirtyBox=!0;o(a,!0)&&b.redraw()},defaultLabelFormatter:function(){var a=this.axis,b=this.value,c=a.categories,d=this.dateTimeLabelFormat,e=N.lang.numericSymbols,f=e&&e.length,g,h=a.options.labels.format,a=a.isLog?b:a.tickInterval;if(h)g=Ea(h,this);else if(c)g=b;else if(d)g=Ua(d,b);else if(f&&a>=1E3)for(;f--&&g===x;)c=Math.pow(1E3,f+1),a>=c&&e[f]!==null&&(g=Na(b/c,-1)+e[f]);g===x&&(g=b>=1E3?Na(b,0):Na(b,-1));return g},getSeriesExtremes:function(){var a=this,b=a.chart,c=a.stacks, d=[],e=[],f=a._stacksTouched+=1,g,h;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=null;n(a.series,function(g){if(g.visible||!b.options.chart.ignoreHiddenSeries){var j=g.options,k,m,l,p,s,n,B,w,G,t=j.threshold,v,u=[],y=0;a.hasVisibleSeries=!0;if(a.isLog&&t<=0)t=j.threshold=null;if(a.isXAxis){if(j=g.xData,j.length)a.dataMin=K(o(a.dataMin,j[0]),Fa(j)),a.dataMax=q(o(a.dataMax,j[0]),pa(j))}else{var P,H,C,A=g.cropped,z=g.xAxis.getExtremes(),E=!!g.modifyValue;k=j.stacking;a.usePercentage=k==="percent";if(k)s= j.stack,p=g.type+o(s,""),n="-"+p,g.stackKey=p,m=d[p]||[],d[p]=m,l=e[n]||[],e[n]=l;if(a.usePercentage)a.dataMin=0,a.dataMax=99;j=g.processedXData;B=g.processedYData;v=B.length;for(h=0;h0))if(E&&(G=g.modifyValue(G)),g.getExtremesFromAll||A||(j[h+1]||w)>= z.min&&(j[h-1]||w)<=z.max)if(w=G.length)for(;w--;)G[w]!==null&&(u[y++]=G[w]);else u[y++]=G}if(!a.usePercentage&&u.length)g.dataMin=k=Fa(u),g.dataMax=g=pa(u),a.dataMin=K(o(a.dataMin,k),k),a.dataMax=q(o(a.dataMax,g),g);if(r(t))if(a.dataMin>=t)a.dataMin=t,a.ignoreMinPadding=!0;else if(a.dataMaxf+this.width)l=!0}else if(c=f,i=m-this.right,hg+this.height)l=!0;return l&&!d?null:e.renderer.crispLine(["M",c,h,"L",i,j],b||0)},getPlotBandPath:function(a,b){var c=this.getPlotLinePath(b),d=this.getPlotLinePath(a);d&&c?d.push(c[4],c[5],c[1],c[2]): d=null;return d},getLinearTickPositions:function(a,b,c){for(var d,b=ia(T(b/a)*a),c=ia(ja(c/a)*a),e=[];b<=c;){e.push(b);b=ia(b+a);if(b===d)break;d=b}return e},getLogTickPositions:function(a,b,c,d){var e=this.options,f=this.len,g=[];if(!d)this._minorAutoInterval=null;if(a>=0.5)a=t(a),g=this.getLinearTickPositions(a,b,c);else if(a>=0.08)for(var f=T(b),h,i,j,k,m,e=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];fb&&(!d||k<=c)&&g.push(k), k>c&&(m=!0),k=j}else if(b=da(b),c=da(c),a=e[d?"minorTickInterval":"tickInterval"],a=o(a==="auto"?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=ib(a,null,I.pow(10,T(I.log(a)/I.LN10))),g=Ka(this.getLinearTickPositions(a,b,c),ka),!d)this._minorAutoInterval=a/5;if(!d)this.tickInterval=a;return g},getMinorTickPositions:function(){var a=this.options,b=this.tickPositions,c=this.minorTickInterval,d=[],e;if(this.isLog){e=b.length;for(a=1;a=this.minRange,f,g,h,i,j;if(this.isXAxis&&this.minRange===x&&!this.isLog)r(a.min)||r(a.max)?this.minRange=null:(n(this.series,function(a){i= a.xData;for(g=j=a.xIncrement?1:i.length-1;g>0;g--)if(h=i[g]-i[g-1],f===x||hb&&(g=0);c=q(c,g);e=q(e,h?0:g/2);f=q(f,h==="on"?0:g);!a.noSharedTooltip&&r(m)&&(d=r(d)?K(d,m):m)}),g=this.ordinalSlope?this.ordinalSlope/d:1,this.minPointOffset=e*=g,this.pointRangePadding=f*=g,this.pointRange=K(c,b),this.closestPointRange=d;if(a)this.oldTransA=h;this.translationSlope=this.transA=h=this.len/(b+f||1);this.transB=this.horiz?this.left:this.bottom;this.minPixelPadding=h*e},setTickPositions:function(a){var b= this,c=b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=b.options.tickPositioner,j=d.maxPadding,k=d.minPadding,m=d.tickInterval,l=d.minTickInterval,p=d.tickPixelInterval,s=b.categories;h?(b.linkedParent=c[g?"xAxis":"yAxis"][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=o(c.min,c.dataMin),b.max=o(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&qa(11,1)):(b.min=o(b.userMin,d.min,b.dataMin),b.max=o(b.userMax,d.max,b.dataMax));if(e)!a&&K(b.min,o(b.dataMin,b.min))<= 0&&qa(10,1),b.min=ia(ka(b.min)),b.max=ia(ka(b.max));if(b.range&&(b.userMin=b.min=q(b.min,b.max-b.range),b.userMax=b.max,a))b.range=null;b.beforePadding&&b.beforePadding();b.adjustForMinRange();if(!s&&!b.usePercentage&&!h&&r(b.min)&&r(b.max)&&(c=b.max-b.min)){if(!r(d.min)&&!r(b.userMin)&&k&&(b.dataMin<0||!b.ignoreMinPadding))b.min-=c*k;if(!r(d.max)&&!r(b.userMax)&&j&&(b.dataMax>0||!b.ignoreMaxPadding))b.max+=c*j}b.tickInterval=b.min===b.max||b.min===void 0||b.max===void 0?1:h&&!m&&p===b.linkedParent.options.tickPixelInterval? b.linkedParent.tickInterval:o(m,s?1:(b.max-b.min)*p/(b.len||1));g&&!a&&n(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();if(b.postProcessTickInterval)b.tickInterval=b.postProcessTickInterval(b.tickInterval);if(!m&&b.tickIntervale&&i.shift(),d.endOnTick? b.max=f:b.max+h(b[d]||0)&&this.options.alignTicks!==!1)b[d]=c.length;a.maxTicks=b},adjustTickAmount:function(){var a=this._maxTicksKey,b=this.tickPositions,c=this.chart.maxTicks;if(c&&c[a]&&!this.isDatetimeAxis&&!this.categories&&!this.isLinked&&this.options.alignTicks!== !1){var d=this.tickAmount,e=b.length;this.tickAmount=a=c[a];if(e=this.dataMax&&(b=x));this.displayBtn=a!==x||b!==x;this.setExtremes(a,b,!1,x,{trigger:"zoom"});return!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=b.offsetRight||0,e=this.horiz,f,g;this.left=g=o(b.left,a.plotLeft+c);this.top=f=o(b.top,a.plotTop);this.width=c=o(b.width,a.plotWidth-c+d);this.height=b=o(b.height,a.plotHeight);this.bottom=a.chartHeight-b-f;this.right=a.chartWidth-c-g; this.len=q(e?c:b,0);this.pos=e?g:f},getExtremes:function(){var a=this.isLog;return{min:a?ia(da(this.min)):this.min,max:a?ia(da(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?da(this.min):this.min,b=b?da(this.max):this.max;c>a||a===null?a=c:b=a.min&&b<=a.max)j[b]||(j[b]=new Ia(a,b)),w&&j[b].isNew&&j[b].render(c,!0),j[b].render(c,!1,1)}),s&&a.min===0&&(j[-1]||(j[-1]=new Ia(a,-1,null,!0)),j[-1].render(-1))),p&&n(g,function(b,c){if(c%2===0&&b1||Q(b-f.y)>1))clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32)},hide:function(){var a=this,b;if(!this.isHidden)b= this.chart.hoverPoints,this.hideTimer=setTimeout(function(){a.label.fadeOut();a.isHidden=!0},o(this.options.hideDelay,500)),b&&n(b,function(a){a.setState()}),this.chart.hoverPoints=null},hideCrosshairs:function(){n(this.crosshairs,function(a){a&&a.hide()})},getAnchor:function(a,b){var c,d=this.chart,e=d.inverted,f=d.plotTop,g=0,h=0,i,a=ha(a);c=a[0].tooltipPos;this.followPointer&&b&&(b.chartX===x&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]);c||(n(a,function(a){i=a.series.yAxis;g+= a.plotX;h+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&i?i.top-f:0)}),g/=a.length,h/=a.length,c=[e?d.plotWidth-h:g,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-g:h]);return Ka(c,t)},getPosition:function(a,b,c){var d=this.chart,e=d.plotLeft,f=d.plotTop,g=d.plotWidth,h=d.plotHeight,i=o(this.options.distance,12),j=c.plotX,c=c.plotY,d=j+e+(d.inverted?i:-a-i),k=c-b+f+15,m;d<7&&(d=e+q(j,0)+i);d+a>e+g&&(d-=d+a-(e+g),k=c-b+f-i,m=!0);k=k&&c<=k+b&&(k=c+f+i));k+b>f+h&&(k= q(f,f+h-b-i));return{x:d,y:k}},defaultFormatter:function(a){var b=this.points||ha(this),c=b[0].series,d;d=[c.tooltipHeaderFormatter(b[0])];n(b,function(a){c=a.series;d.push(c.tooltipFormatter&&c.tooltipFormatter(a)||a.point.tooltipFormatter(c.tooltipOptions.pointFormat))});d.push(a.options.footerFormat||"");return d.join("")},refresh:function(a,b){var c=this.chart,d=this.label,e=this.options,f,g,h,i={},j,k=[];j=e.formatter||this.defaultFormatter;var i=c.hoverPoints,m,l=e.crosshairs;h=this.shared; clearTimeout(this.hideTimer);this.followPointer=ha(a)[0].series.tooltipOptions.followPointer;g=this.getAnchor(a,b);f=g[0];g=g[1];h&&(!a.series||!a.series.noSharedTooltip)?(c.hoverPoints=a,i&&n(i,function(a){a.setState()}),n(a,function(a){a.setState("hover");k.push(a.getLabelConfig())}),i={x:a[0].category,y:a[0].y},i.points=k,a=a[0]):i=a.getLabelConfig();j=j.call(i,this);i=a.series;h=h||!i.isCartesian||i.tooltipOutsidePlot||c.isInsidePlot(f,g);j===!1||!h?this.hide():(this.isHidden&&(Ta(d),d.attr("opacity", 1).show()),d.attr({text:j}),m=e.borderColor||a.color||i.color||"#606060",d.attr({stroke:m}),this.updatePosition({plotX:f,plotY:g}),this.isHidden=!1);if(l){l=ha(l);for(d=l.length;d--;)if(e=a.series[d?"yAxis":"xAxis"],l[d]&&e)if(h=d?o(a.stackY,a.y):a.x,e.isLog&&(h=ka(h)),e=e.getPlotLinePath(h,1),this.crosshairs[d])this.crosshairs[d].attr({d:e,visibility:"visible"});else{h={"stroke-width":l[d].width||1,stroke:l[d].color||"#C0C0C0",zIndex:l[d].zIndex||2};if(l[d].dashStyle)h.dashstyle=l[d].dashStyle;this.crosshairs[d]= c.renderer.path(e).attr(h).add()}}D(c,"tooltipRefresh",{text:j,x:f+c.plotLeft,y:g+c.plotTop,borderColor:m})},updatePosition:function(a){var b=this.chart,c=this.label,c=(this.options.positioner||this.getPosition).call(this,c.width,c.height,a);this.move(t(c.x),t(c.y),a.plotX+b.plotLeft,a.plotY+b.plotTop)}};qb.prototype={init:function(a,b){var c=$?"":b.chart.zoomType,d=a.inverted,e;this.options=b;this.chart=a;this.zoomX=e=/x/.test(c);this.zoomY=c=/y/.test(c);this.zoomHor=e&&!d||c&&d;this.zoomVert=c&& !d||e&&d;this.pinchDown=[];this.lastValidTouch={};if(b.tooltip.enabled)a.tooltip=new pb(a,b.tooltip);this.setDOMEvents()},normalize:function(a){var b,c,d,a=a||O.event;if(!a.target)a.target=a.srcElement;a=Pb(a);d=a.touches?a.touches.item(0):a;this.chartPosition=b=Tb(this.chart.container);d.pageX===x?(c=a.x,b=a.y):(c=d.pageX-b.left,b=d.pageY-b.top);return v(a,{chartX:t(c),chartY:t(b)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};n(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c, value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},getIndex:function(a){var b=this.chart;return b.inverted?b.plotHeight+b.plotTop-a.chartY:a.chartX-b.plotLeft},runPointActions:function(a){var b=this.chart,c=b.series,d=b.tooltip,e,f=b.hoverPoint,g=b.hoverSeries,h,i,j=b.chartWidth,k=this.getIndex(a);if(d&&this.options.tooltip.shared&&(!g||!g.noSharedTooltip)){e=[];h=c.length;for(i=0;ij&&e.splice(h,1);if(e.length&&e[0].clientX!==this.hoverX)d.refresh(e,a),this.hoverX=e[0].clientX}if(g&&g.tracker){if((b=g.tooltipPoints[k])&&b!==f)b.onMouseOver(a)}else d&&d.followPointer&&!d.isHidden&&(a=d.getAnchor([{}],a),d.updatePosition({plotX:a[0],plotY:a[1]}))},reset:function(a){var b=this.chart,c=b.hoverSeries,d=b.hoverPoint,e=b.tooltip,b=e&&e.shared?b.hoverPoints:d;(a=a&&e&&b)&& ha(b)[0].plotX===x&&(a=!1);if(a)e.refresh(b);else{if(d)d.onMouseOut();if(c)c.onMouseOut();e&&(e.hide(),e.hideCrosshairs());this.hoverX=null}},scaleGroups:function(a,b){var c=this.chart;n(c.series,function(d){d.xAxis.zoomEnabled&&(d.group.attr(a),d.markerGroup&&(d.markerGroup.attr(a),d.markerGroup.clip(b?c.clipRect:null)),d.dataLabelsGroup&&d.dataLabelsGroup.attr(a))});c.clipRect.attr(b||c.clipBox)},pinchTranslateDirection:function(a,b,c,d,e,f,g){var h=this.chart,i=a?"x":"y",j=a?"X":"Y",k="chart"+ j,m=a?"width":"height",l=h["plot"+(a?"Left":"Top")],p,s,o=1,n=h.inverted,w=h.bounds[a?"h":"v"],q=b.length===1,t=b[0][k],r=c[0][k],v=!q&&b[1][k],u=!q&&c[1][k],x,c=function(){!q&&Q(t-v)>20&&(o=Q(r-u)/Q(t-v));s=(l-r)/o+t;p=h["plot"+(a?"Width":"Height")]/o};c();b=s;bw.max&&(b=w.max-p,x=!0);x?(r-=0.8*(r-g[i][0]),q||(u-=0.8*(u-g[i][1])),c()):g[i]=[r,u];n||(f[i]=s-l,f[m]=p);f=n?1/o:o;e[m]=p;e[i]=b;d[n?a?"scaleY":"scaleX":"scale"+j]=o;d["translate"+j]=f*l+(r-f*t)},pinch:function(a){var b= this,c=b.chart,d=b.pinchDown,e=c.tooltip.options.followTouchMove,f=a.touches,g=f.length,h=b.lastValidTouch,i=b.zoomHor||b.pinchHor,j=b.zoomVert||b.pinchVert,k=i||j,m=b.selectionMarker,l={},p={};a.type==="touchstart"&&e&&(b.inClass(a.target,"highcharts-tracker")?(!c.runTrackerClick||g>1)&&a.preventDefault():(!c.runChartClick||g>1)&&a.preventDefault());Ka(f,function(a){return b.normalize(a)});if(a.type==="touchstart")n(f,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),h.x=[d[0].chartX,d[1]&& d[1].chartX],h.y=[d[0].chartY,d[1]&&d[1].chartY],n(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?"h":"v"],d=a.minPixelPadding,e=a.toPixels(a.dataMin),f=a.toPixels(a.dataMax),g=K(e,f),e=q(e,f);b.min=K(a.pos,g-d);b.max=q(a.pos+a.len,e+d)}});else if(d.length){if(!m)b.selectionMarker=m=v({destroy:ta},c.plotBox);i&&b.pinchTranslateDirection(!0,d,f,l,m,p,h);j&&b.pinchTranslateDirection(!1,d,f,l,m,p,h);b.hasPinched=k;b.scaleGroups(l,p);!k&&e&&g===1&&this.runPointActions(b.normalize(a))}},dragStart:function(a){var b= this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,a=a.chartY,e=this.zoomHor,f=this.zoomVert,g=b.plotLeft,h=b.plotTop,i=b.plotWidth,j=b.plotHeight,k,m=this.mouseDownX,l=this.mouseDownY;dg+i&&(d=g+i);ah+j&&(a=h+j);this.hasDragged=Math.sqrt(Math.pow(m-d,2)+Math.pow(l-a,2));if(this.hasDragged>10){k=b.isInsidePlot(m-g,l-h);if(b.hasCartesianSeries&&(this.zoomX|| this.zoomY)&&k&&!this.selectionMarker)this.selectionMarker=b.renderer.rect(g,h,e?1:i,f?1:j,0).attr({fill:c.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add();this.selectionMarker&&e&&(e=d-m,this.selectionMarker.attr({width:Q(e),x:(e>0?0:e)+m}));this.selectionMarker&&f&&(e=a-l,this.selectionMarker.attr({height:Q(e),y:(e>0?0:e)+l}));k&&!this.selectionMarker&&c.panning&&b.pan(d)}},drop:function(a){var b=this.chart,c=this.hasPinched;if(this.selectionMarker){var d={xAxis:[],yAxis:[],originalEvent:a.originalEvent|| a},e=this.selectionMarker,f=e.x,g=e.y,h;if(this.hasDragged||c)n(b.axes,function(a){if(a.zoomEnabled){var b=a.horiz,c=a.minPixelPadding,m=a.toValue((b?f:g)+c),b=a.toValue((b?f+e.width:g+e.height)-c);!isNaN(m)&&!isNaN(b)&&(d[a.xOrY+"Axis"].push({axis:a,min:K(m,b),max:q(m,b)}),h=!0)}}),h&&D(b,"selection",d,function(a){b.zoom(v(a,c?{animation:!1}:null))});this.selectionMarker=this.selectionMarker.destroy();c&&this.scaleGroups({translateX:b.plotLeft,translateY:b.plotTop,scaleX:1,scaleY:1})}if(b)L(b.container, {cursor:b._cursor}),b.cancelClick=this.hasDragged,b.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[]},onContainerMouseDown:function(a){a=this.normalize(a);a.preventDefault&&a.preventDefault();this.dragStart(a)},onDocumentMouseUp:function(a){this.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,d=b.hoverSeries,a=Pb(a);c&&d&&d.isCartesian&&!b.isInsidePlot(a.pageX-c.left-b.plotLeft,a.pageY-c.top-b.plotTop)&&this.reset()},onContainerMouseLeave:function(){this.reset(); this.chartPosition=null},onContainerMouseMove:function(a){var b=this.chart,a=this.normalize(a);a.returnValue=!1;b.mouseIsDown==="mousedown"&&this.drag(a);b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=A(a,"class"))if(c.indexOf(b)!==-1)return!0;else if(c.indexOf("highcharts-container")!==-1)return!1;a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries;if(b&&!b.options.stickyTracking&&!this.inClass(a.toElement|| a.relatedTarget,"highcharts-tooltip"))b.onMouseOut()},onContainerClick:function(a){var b=this.chart,c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,f=b.inverted,g,h,i,a=this.normalize(a);a.cancelBubble=!0;if(!b.cancelClick)c&&this.inClass(a.target,"highcharts-tracker")?(g=this.chartPosition,h=c.plotX,i=c.plotY,v(c,{pageX:g.left+d+(f?b.plotWidth-i:h),pageY:g.top+e+(f?b.plotHeight-h:i)}),D(c.series,"click",v(a,{point:c})),c.firePointEvent("click",a)):(v(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY- e)&&D(b,"click",a))},onContainerTouchStart:function(a){var b=this.chart;a.touches.length===1?(a=this.normalize(a),b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&(this.runPointActions(a),this.pinch(a))):a.touches.length===2&&this.pinch(a)},onContainerTouchMove:function(a){(a.touches.length===1||a.touches.length===2)&&this.pinch(a)},onDocumentTouchEnd:function(a){this.drop(a)},setDOMEvents:function(){var a=this,b=a.chart.container,c;this._events=c=[[b,"onmousedown","onContainerMouseDown"], [b,"onmousemove","onContainerMouseMove"],[b,"onclick","onContainerClick"],[b,"mouseleave","onContainerMouseLeave"],[z,"mousemove","onDocumentMouseMove"],[z,"mouseup","onDocumentMouseUp"]];fb&&c.push([b,"ontouchstart","onContainerTouchStart"],[b,"ontouchmove","onContainerTouchMove"],[z,"touchend","onDocumentTouchEnd"]);n(c,function(b){a["_"+b[2]]=function(c){a[b[2]](c)};b[1].indexOf("on")===0?b[0][b[1]]=a["_"+b[2]]:J(b[0],b[1],a["_"+b[2]])})},destroy:function(){var a=this;n(a._events,function(b){b[1].indexOf("on")=== 0?b[0][b[1]]=null:ba(b[0],b[1],a["_"+b[2]])});delete a._events;clearInterval(a.tooltipTimeout)}};rb.prototype={init:function(a,b){var c=this,d=b.itemStyle,e=o(b.padding,8),f=b.itemMarginTop||0;this.options=b;if(b.enabled)c.baseline=u(d.fontSize)+3+f,c.itemStyle=d,c.itemHiddenStyle=y(d,b.itemHiddenStyle),c.itemMarginTop=f,c.padding=e,c.initialItemX=e,c.initialItemY=e-5,c.maxItemWidth=0,c.chart=a,c.itemHeight=0,c.lastLineHeight=0,c.render(),J(c.chart,"endResize",function(){c.positionCheckboxes()})}, colorizeItem:function(a,b){var c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,c=b?c.itemStyle.color:g,h=b?a.color:g,g=a.options&&a.options.marker,i={stroke:h,fill:h},j;d&&d.css({fill:c,color:c});e&&e.attr({stroke:h});if(f){if(g)for(j in g=a.convertAttribs(g),g)d=g[j],d!==x&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;a.legendGroup&&a.legendGroup.translate(b?e:this.legendWidth- e-2*c-4,d);if(f)f.x=e,f.y=d},destroyItem:function(a){var b=a.checkbox;n(["legendItem","legendLine","legendSymbol","legendGroup"],function(b){a[b]&&a[b].destroy()});b&&Ra(a.checkbox)},destroy:function(){var a=this.group,b=this.box;if(b)this.box=b.destroy();if(a)this.group=a.destroy()},positionCheckboxes:function(a){var b=this.group.alignAttr,c,d=this.clipHeight||this.legendHeight;if(b)c=b.translateY,n(this.allItems,function(e){var f=e.checkbox,g;f&&(g=c+f.y+(a||0)+3,L(f,{left:b.translateX+e.legendItemWidth+ f.x-20+"px",top:g+"px",display:g>c-6&&g(l||c.chartWidth-2*k-o))b.itemX=o,b.itemY+=s+b.lastLineHeight+p,b.lastLineHeight=0;b.maxItemWidth=q(b.maxItemWidth,e);b.lastItemY=s+b.itemY+p;b.lastLineHeight=q(g,b.lastLineHeight);a._legendItemPos=[b.itemX,b.itemY];f?b.itemX+=e:(b.itemY+=s+g+p,b.lastLineHeight=g);b.offsetWidth=l||q(f?b.itemX-o:e,b.offsetWidth)},render:function(){var a=this,b=a.chart,c=b.renderer, d=a.group,e,f,g,h,i=a.box,j=a.options,k=a.padding,m=j.borderWidth,l=j.backgroundColor;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;if(!d)a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup),a.clipRect=c.clipRect(0,0,9999,b.chartHeight),a.contentGroup.clip(a.clipRect);a.renderTitle();e=[];n(b.series,function(a){var b=a.options;b.showInLegend&&!r(b.linkedTo)&&(e=e.concat(a.legendItems||(b.legendType=== "point"?a.data:a)))});Gb(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});j.reversed&&e.reverse();a.allItems=e;a.display=f=!!e.length;n(e,function(b){a.renderItem(b)});g=j.width||a.offsetWidth;h=a.lastItemY+a.lastLineHeight+a.titleHeight;h=a.handleOverflow(h);if(m||l){g+=k;h+=k;if(i){if(g>0&&h>0)i[i.isNew?"attr":"animate"](i.crisp(null,null,null,g,h)),i.isNew=!1}else a.box=i=c.rect(0,0,g,h,j.borderRadius,m||0).attr({stroke:j.borderColor,"stroke-width":m|| 0,fill:l||S}).add(d).shadow(j.shadow),i.isNew=!0;i[f?"show":"hide"]()}a.legendWidth=g;a.legendHeight=h;n(e,function(b){a.positionItem(b)});f&&d.align(v({width:g,height:h},j),!0,"spacingBox");b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+(e.verticalAlign==="top"?-f:f)-this.padding,g=e.maxHeight,h=this.clipRect,i=e.navigation,j=o(i.animation,!0),k=i.arrowSize||12,m=this.nav;e.layout==="horizontal"&& (f/=2);g&&(f=K(f,g));if(a>f&&!e.useHTML){this.clipHeight=c=f-20-this.titleHeight;this.pageCount=ja(a/c);this.currentPage=o(this.currentPage,1);this.fullHeight=a;h.attr({height:c});if(!m)this.nav=m=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,k,k).on("click",function(){b.scroll(-1,j)}).add(m),this.pager=d.text("",15,10).css(i.style).add(m),this.down=d.symbol("triangle-down",0,0,k,k).on("click",function(){b.scroll(1,j)}).add(m);b.scroll(0);a=f}else if(m)h.attr({height:c.chartHeight}), m.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0;return a},scroll:function(a,b){var c=this.pageCount,d=this.currentPage+a,e=this.clipHeight,f=this.options.navigation,g=f.activeColor,h=f.inactiveColor,f=this.pager,i=this.padding;d>c&&(d=c);if(d>0)b!==x&&Ha(b,this.chart),this.nav.attr({translateX:i,translateY:e+7+this.titleHeight,visibility:"visible"}),this.up.attr({fill:d===1?h:g}).css({cursor:d===1?"default":"pointer"}),f.attr({text:d+"/"+this.pageCount}),this.down.attr({x:18+this.pager.getBBox().width, fill:d===c?h:g}).css({cursor:d===c?"default":"pointer"}),e=-K(e*(d-1),this.fullHeight-e+i)+1,this.scrollGroup.animate({translateY:e}),f.attr({text:d+"/"+c}),this.currentPage=d,this.positionCheckboxes(e)}};sb.prototype={init:function(a,b){var c,d=a.series;a.series=null;c=y(N,a);c.series=a.series=d;var d=c.chart,e=d.margin,e=V(e)?e:[e,e,e,e];this.optionsMarginTop=o(d.marginTop,e[0]);this.optionsMarginRight=o(d.marginRight,e[1]);this.optionsMarginBottom=o(d.marginBottom,e[2]);this.optionsMarginLeft= o(d.marginLeft,e[3]);this.runChartClick=(e=d.events)&&!!e.click;this.bounds={h:{},v:{}};this.callback=b;this.isResizing=0;this.options=c;this.axes=[];this.series=[];this.hasCartesianSeries=d.showAxes;var f=this,g;f.index=za.length;za.push(f);d.reflow!==!1&&J(f,"load",function(){f.initReflow()});if(e)for(g in e)J(f,g,e[g]);f.xAxis=[];f.yAxis=[];f.animation=$?!1:o(d.animation,!0);f.pointCount=0;f.counters=new Fb;f.firstRender()},initSeries:function(a){var b=this.options.chart;(b=aa[a.type||b.type|| b.defaultSeriesType])||qa(17,!0);b=new b;b.init(this,a);return b},addSeries:function(a,b,c){var d,e=this;a&&(b=o(b,!0),D(e,"addSeries",{options:a},function(){d=e.initSeries(a);e.isDirtyLegend=!0;b&&e.redraw(c)}));return d},addAxis:function(a,b,c,d){var b=b?"xAxis":"yAxis",e=this.options;new ab(this,y(a,{index:this[b].length}));e[b]=ha(e[b]||{});e[b].push(a);o(c,!0)&&this.redraw(d)},isInsidePlot:function(a,b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},adjustTickAmounts:function(){this.options.chart.alignTicks!== !1&&n(this.axes,function(a){a.adjustTickAmount()});this.maxTicks=null},redraw:function(a){var b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,g,h=this.isDirtyBox,i=c.length,j=i,k=this.renderer,m=k.isHidden(),l=[];Ha(a,this);for(m&&this.cloneRenderTo();j--;)if(a=c[j],a.isDirty&&a.options.stacking){g=!0;break}if(g)for(j=i;j--;)if(a=c[j],a.options.stacking)a.isDirty=!0;n(c,function(a){a.isDirty&&a.options.legendType==="point"&&(f=!0)});if(f&&e.options.enabled)e.render(),this.isDirtyLegend= !1;if(this.hasCartesianSeries){if(!this.isResizing)this.maxTicks=null,n(b,function(a){a.setScale()});this.adjustTickAmounts();this.getMargins();n(b,function(a){if(a.isDirtyExtremes)a.isDirtyExtremes=!1,l.push(function(){D(a,"afterSetExtremes",a.getExtremes())});if(a.isDirty||h||g)a.redraw(),h=!0})}h&&this.drawChartBox();n(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()});d&&d.reset&&d.reset(!0);k.draw();D(this,"redraw");m&&this.cloneRenderTo(!0);n(l,function(a){a.call()})}, showLoading:function(a){var b=this.options,c=this.loadingDiv,d=b.loading;if(!c)this.loadingDiv=c=U(wa,{className:"highcharts-loading"},v(d.style,{zIndex:10,display:S}),this.container),this.loadingSpan=U("span",null,d.labelStyle,c);this.loadingSpan.innerHTML=a||b.lang.loading;if(!this.loadingShown)L(c,{opacity:0,display:"",left:this.plotLeft+"px",top:this.plotTop+"px",width:this.plotWidth+"px",height:this.plotHeight+"px"}),vb(c,{opacity:d.style.opacity},{duration:d.showDuration||0}),this.loadingShown= !0},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&vb(b,{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){L(b,{display:S})}});this.loadingShown=!1},get:function(a){var b=this.axes,c=this.series,d,e;for(d=0;dK(e.dataMin,e.min)&&c< q(e.dataMax,e.max)&&b.setExtremes(f,c,!0,!1,{trigger:"pan"});this.mouseDownX=a;L(this.container,{cursor:"move"})},setTitle:function(a,b){var f;var c=this,d=c.options,e;e=d.title=y(d.title,a);f=d.subtitle=y(d.subtitle,b),d=f;n([["title",a,e],["subtitle",b,d]],function(a){var b=a[0],d=c[b],e=a[1],a=a[2];d&&e&&(c[b]=d=d.destroy());a&&a.text&&!d&&(c[b]=c.renderer.text(a.text,0,0,a.useHTML).attr({align:a.align,"class":"highcharts-"+b,zIndex:a.zIndex||4}).css(a.style).add().align(a,!1,"spacingBox"))})}, getChartSize:function(){var a=this.options.chart,b=this.renderToClone||this.renderTo;this.containerWidth=gb(b,"width");this.containerHeight=gb(b,"height");this.chartWidth=q(0,a.width||this.containerWidth||600);this.chartHeight=q(0,o(a.height,this.containerHeight>19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Ra(b),delete this.renderToClone):(c&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0), L(b,{position:"absolute",top:"-9999px",display:"block"}),z.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,b=this.options.chart,c,d,e;this.renderTo=a=b.renderTo;e="highcharts-"+tb++;if(fa(a))this.renderTo=a=z.getElementById(a);a||qa(13,!0);c=u(A(a,"data-highcharts-chart"));!isNaN(c)&&za[c]&&za[c].destroy();A(a,"data-highcharts-chart",this.index);a.innerHTML="";a.offsetWidth||this.cloneRenderTo();this.getChartSize();c=this.chartWidth;d=this.chartHeight;this.container=a=U(wa, {className:"highcharts-container"+(b.className?" "+b.className:""),id:e},v({position:"relative",overflow:"hidden",width:c+"px",height:d+"px",textAlign:"left",lineHeight:"normal",zIndex:0},b.style),this.renderToClone||a);this._cursor=a.style.cursor;this.renderer=b.forExport?new Aa(a,c,d,!0):new Sa(a,c,d);$&&this.renderer.create(this,a,c,d)},getMargins:function(){var a=this.options.chart,b=a.spacingTop,c=a.spacingRight,d=a.spacingBottom,a=a.spacingLeft,e,f=this.legend,g=this.optionsMarginTop,h=this.optionsMarginLeft, i=this.optionsMarginRight,j=this.optionsMarginBottom,k=this.options.title,m=this.options.subtitle,l=this.options.legend,p=o(l.margin,10),s=l.x,t=l.y,B=l.align,w=l.verticalAlign;this.resetMargins();e=this.axisOffset;if((this.title||this.subtitle)&&!r(this.optionsMarginTop))if(m=q(this.title&&!k.floating&&!k.verticalAlign&&k.y||0,this.subtitle&&!m.floating&&!m.verticalAlign&&m.y||0))this.plotTop=q(this.plotTop,m+o(k.margin,15)+b);if(f.display&&!l.floating)if(B==="right"){if(!r(i))this.marginRight=q(this.marginRight, f.legendWidth-s+p+c)}else if(B==="left"){if(!r(h))this.plotLeft=q(this.plotLeft,f.legendWidth+s+p+a)}else if(w==="top"){if(!r(g))this.plotTop=q(this.plotTop,f.legendHeight+t+p+b)}else if(w==="bottom"&&!r(j))this.marginBottom=q(this.marginBottom,f.legendHeight-t+p+d);this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin);this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);this.hasCartesianSeries&&n(this.axes,function(a){a.getOffset()});r(h)||(this.plotLeft+=e[3]);r(g)||(this.plotTop+= e[0]);r(j)||(this.marginBottom+=e[2]);r(i)||(this.marginRight+=e[1]);this.setChartSize()},initReflow:function(){function a(a){var g=c.width||gb(d,"width"),h=c.height||gb(d,"height"),a=a?a.target:O;if(!b.hasUserSize&&g&&h&&(a===O||a===z)){if(g!==b.containerWidth||h!==b.containerHeight)clearTimeout(e),b.reflowTimeout=e=setTimeout(function(){if(b.container)b.setSize(g,h,!1),b.hasUserSize=null},100);b.containerWidth=g;b.containerHeight=h}}var b=this,c=b.options.chart,d=b.renderTo,e;J(O,"resize",a);J(b, "destroy",function(){ba(O,"resize",a)})},setSize:function(a,b,c){var d=this,e,f,g;d.isResizing+=1;g=function(){d&&D(d,"endResize",null,function(){d.isResizing-=1})};Ha(c,d);d.oldChartHeight=d.chartHeight;d.oldChartWidth=d.chartWidth;if(r(a))d.chartWidth=e=q(0,t(a)),d.hasUserSize=!!e;if(r(b))d.chartHeight=f=q(0,t(b));L(d.container,{width:e+"px",height:f+"px"});d.setChartSize(!0);d.renderer.setSize(e,f,c);d.maxTicks=null;n(d.axes,function(a){a.isDirty=!0;a.setScale()});n(d.series,function(a){a.isDirty= !0});d.isDirtyLegend=!0;d.isDirtyBox=!0;d.getMargins();d.redraw(c);d.oldChartHeight=null;D(d,"resize");xa===!1?g():setTimeout(g,xa&&xa.duration||500)},setChartSize:function(a){var b=this.inverted,c=this.renderer,d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=f.spacingTop,h=f.spacingRight,i=f.spacingBottom,j=f.spacingLeft,k=this.clipOffset,m,l,p,o;this.plotLeft=m=t(this.plotLeft);this.plotTop=l=t(this.plotTop);this.plotWidth=p=q(0,t(d-m-this.marginRight));this.plotHeight=o=q(0,t(e-l-this.marginBottom)); this.plotSizeX=b?o:p;this.plotSizeY=b?p:o;this.plotBorderWidth=b=f.plotBorderWidth||0;this.spacingBox=c.spacingBox={x:j,y:g,width:d-j-h,height:e-g-i};this.plotBox=c.plotBox={x:m,y:l,width:p,height:o};c=ja(q(b,k[3])/2);d=ja(q(b,k[0])/2);this.clipBox={x:c,y:d,width:T(this.plotSizeX-q(b,k[1])/2-c),height:T(this.plotSizeY-q(b,k[2])/2-d)};a||n(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this.options.chart,b=a.spacingRight,c=a.spacingBottom,d=a.spacingLeft; this.plotTop=o(this.optionsMarginTop,a.spacingTop);this.marginRight=o(this.optionsMarginRight,b);this.marginBottom=o(this.optionsMarginBottom,c);this.plotLeft=o(this.optionsMarginLeft,d);this.axisOffset=[0,0,0,0];this.clipOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,m=a.plotBackgroundImage, l=a.plotBorderWidth||0,p,o=this.plotLeft,n=this.plotTop,t=this.plotWidth,q=this.plotHeight,r=this.plotBox,v=this.clipRect,u=this.clipBox;p=i+(a.shadow?8:0);if(i||j)if(e)e.animate(e.crisp(null,null,null,c-p,d-p));else{e={fill:j||S};if(i)e.stroke=a.borderColor,e["stroke-width"]=i;this.chartBackground=b.rect(p/2,p/2,c-p,d-p,a.borderRadius,i).attr(e).add().shadow(a.shadow)}if(k)f?f.animate(r):this.plotBackground=b.rect(o,n,t,q,0).attr({fill:k}).add().shadow(a.plotShadow);if(m)h?h.animate(r):this.plotBGImage= b.image(m,o,n,t,q).add();v?v.animate({width:u.width,height:u.height}):this.clipRect=b.clipRect(u);if(l)g?g.animate(g.crisp(null,o,n,t,q)):this.plotBorder=b.rect(o,n,t,q,0,l).attr({stroke:a.plotBorderColor,"stroke-width":l,zIndex:1}).add();this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart,c,d=a.options.series,e,f;n(["inverted","angular","polar"],function(g){c=aa[b.type||b.defaultSeriesType];f=a[g]||b[g]||c&&c.prototype[g];for(e=d&&d.length;!f&&e--;)(c=aa[d[e].type])&&c.prototype[g]&& (f=!0);a[g]=f})},render:function(){var a=this,b=a.axes,c=a.renderer,d=a.options,e=d.labels,f=d.credits,g;a.setTitle();a.legend=new rb(a,d.legend);n(b,function(a){a.setScale()});a.getMargins();a.maxTicks=null;n(b,function(a){a.setTickPositions(!0);a.setMaxTicks()});a.adjustTickAmounts();a.getMargins();a.drawChartBox();a.hasCartesianSeries&&n(b,function(a){a.render()});if(!a.seriesGroup)a.seriesGroup=c.g("series-group").attr({zIndex:3}).add();n(a.series,function(a){a.translate();a.setTooltipPoints(); a.render()});e.items&&n(e.items,function(b){var d=v(e.style,b.style),f=u(d.left)+a.plotLeft,g=u(d.top)+a.plotTop+12;delete d.left;delete d.top;c.text(b.html,f,g).attr({zIndex:2}).css(d).add()});if(f.enabled&&!a.credits)g=f.href,a.credits=c.text(f.text,0,0).on("click",function(){if(g)location.href=g}).attr({align:f.position.align,zIndex:8}).css(f.style).add().align(f.position);a.hasRendered=!0},destroy:function(){var a=this,b=a.axes,c=a.series,d=a.container,e,f=d&&d.parentNode;D(a,"destroy");za[a.index]= x;a.renderTo.removeAttribute("data-highcharts-chart");ba(a);for(e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();n("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())});if(d)d.innerHTML="",ba(d),f&&Ra(d);for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!Z&&O==O.top&&z.readyState!== "complete"||$&&!O.canvg?($?Qb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):z.attachEvent("onreadystatechange",function(){z.detachEvent("onreadystatechange",a.firstRender);z.readyState==="complete"&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;if(a.isReadyToRender())a.getContainer(),D(a,"init"),a.resetMargins(),a.setChartSize(),a.propFromSeries(),a.getAxes(),n(b.series||[],function(b){a.initSeries(b)}),D(a,"beforeRender"),a.pointer=new qb(a, b),a.render(),a.renderer.draw(),c&&c.apply(a,[a]),n(a.callbacks,function(b){b.apply(a,[a])}),a.cloneRenderTo(!0),D(a,"load")}};sb.prototype.callbacks=[];var Ma=function(){};Ma.prototype={init:function(a,b,c){this.series=a;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=this.color||b[a.colorCounter++],a.colorCounter===b.length))a.colorCounter=0;a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d= c.pointValKey,a=Ma.prototype.optionsToObject.call(this,a);v(this,a);this.options=this.options?v(this.options,a):a;if(d)this.y=this[d];if(this.x===x&&c)this.x=b===x?c.autoIncrement():b;return this},optionsToObject:function(a){var b,c=this.series,d=c.pointArrayMap||["y"],e=d.length,f=0,g=0;if(typeof a==="number"||a===null)b={y:a};else if(Ba(a)){b={};if(a.length>e){c=typeof a[0];if(c==="string")b.name=a[0];else if(c==="number")b.x=a[0];f++}for(;ga+1&&b.push(d.slice(a+1,g)),a=g):g===e-1&&b.push(d.slice(a+1,g+1))});this.segments=b},setOptions:function(a){var b=this.chart.options,c=b.plotOptions,d=c[this.type];this.userOptions=a;a=y(d,c.series,a);this.tooltipOptions=y(b.tooltip,a.tooltip);d.marker===null&&delete a.marker; return a},getColor:function(){var a=this.options,b=this.userOptions,c=this.chart.options.colors,d=this.chart.counters,e;e=a.color||X[this.type].color;if(!e&&!a.colorByPoint)r(b._colorIndex)?a=b._colorIndex:(b._colorIndex=d.color,a=d.color++),e=c[a];this.color=e;d.wrapColor(c.length)},getSymbol:function(){var a=this.userOptions,b=this.options.marker,c=this.chart,d=c.options.symbols,c=c.counters;this.symbol=b.symbol;if(!this.symbol)r(a._symbolIndex)?a=a._symbolIndex:(a._symbolIndex=c.symbol,a=c.symbol++), this.symbol=d[a];if(/^url/.test(this.symbol))b.radius=0;c.wrapSymbol(d.length)},drawLegendSymbol:function(a){var b=this.options,c=b.marker,d=a.options.symbolWidth,e=this.chart.renderer,f=this.legendGroup,a=a.baseline,g;if(b.lineWidth){g={"stroke-width":b.lineWidth};if(b.dashStyle)g.dashstyle=b.dashStyle;this.legendLine=e.path(["M",0,a-4,"L",d,a-4]).attr(g).add(f)}if(c&&c.enabled)b=c.radius,this.legendSymbol=e.symbol(this.symbol,d/2-b,a-4-b,2*b,2*b).add(f)},addPoint:function(a,b,c,d){var e=this.options, f=this.data,g=this.graph,h=this.area,i=this.chart,j=this.xData,k=this.yData,m=this.zData,l=this.names,p=g&&g.shift||0,n=e.data;Ha(d,i);if(g&&c)g.shift=p+1;if(h){if(c)h.shift=p+1;h.isArea=!0}b=o(b,!0);d={series:this};this.pointClass.prototype.applyOptions.apply(d,[a]);j.push(d.x);k.push(this.toYData?this.toYData(d):d.y);m.push(d.z);if(l)l[d.x]=d.name;n.push(a);e.legendType==="point"&&this.generatePoints();c&&(f[0]&&f[0].remove?f[0].remove(!1):(f.shift(),j.shift(),k.shift(),m.shift(),n.shift()));this.getAttribs(); this.isDirtyData=this.isDirty=!0;b&&i.redraw()},setData:function(a,b){var c=this.points,d=this.options,e=this.chart,f=null,g=this.xAxis,h=g&&g.categories&&!g.categories.length?[]:null,i;this.xIncrement=null;this.pointRange=g&&g.categories?1:d.pointRange;this.colorCounter=0;var j=[],k=[],m=[],l=a?a.length:[],p=(i=this.pointArrayMap)&&i.length,n=!!this.toYData;if(l>(d.turboThreshold||1E3)){for(i=0;f===null&&i1&&j[1]k||this.forceCrop))if(a=i.getExtremes(),i=a.min,k=a.max,b[d-1]k)b=[],c=[];else if(b[0]k){for(a=0;a=i){e=q(0,a-1);break}for(;ak){f=a+1;break}b=b.slice(e,f);c=c.slice(e,f);g=!0}for(a=b.length-1;a>0;a--)if(d=b[a]-b[a-1],d>0&&(h===x||d=0&&c<=d;)h[c++]=f}this.tooltipPoints=h}},tooltipHeaderFormatter:function(a){var b=this.tooltipOptions,c=b.xDateFormat,d=this.xAxis,e=d&&d.options.type==="datetime",f=b.headerFormat,g;if(e&&!c)for(g in E)if(E[g]>=d.closestPointRange){c= b.dateTimeLabelFormats[g];break}e&&c&&Ca(a.key)&&(f=f.replace("{point.key}","{point.key:"+c+"}"));return Ea(f,{point:a,series:this})},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&D(this,"mouseOver");this.setState("hover");a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;if(d)d.onMouseOut();this&&a.events.mouseOut&&D(this,"mouseOut");c&&!a.stickyTracking&&(!c.shared||this.noSharedTooltip)&& c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this,c=b.chart,d=c.renderer,e;e=b.options.animation;var f=c.clipBox,g=c.inverted,h;if(e&&!V(e))e=X[b.type].animation;h="_sharedClip"+e.duration+e.easing;if(a)a=c[h],e=c[h+"m"],a||(c[h]=a=d.clipRect(v(f,{width:0})),c[h+"m"]=e=d.clipRect(-99,g?-c.plotLeft:-c.plotTop,99,g?c.chartWidth:c.chartHeight)),b.group.clip(a),b.markerGroup.clip(e),b.sharedClipKey=h;else{if(a=c[h])a.animate({width:c.plotSizeX},e),c[h+"m"].animate({width:c.plotSizeX+ 99},e);b.animate=null;b.animationTimeout=setTimeout(function(){b.afterAnimate()},e.duration)}},afterAnimate:function(){var a=this.chart,b=this.sharedClipKey,c=this.group;c&&this.options.clip!==!1&&(c.clip(a.clipRect),this.markerGroup.clip());setTimeout(function(){b&&a[b]&&(a[b]=a[b].destroy(),a[b+"m"]=a[b+"m"].destroy())},100)},drawPoints:function(){var a,b=this.points,c=this.chart,d,e,f,g,h,i,j,k,m=this.options.marker,l,n=this.markerGroup;if(m.enabled||this._hasPointMarkers)for(f=b.length;f--;)if(g= b[f],d=g.plotX,e=g.plotY,k=g.graphic,i=g.marker||{},a=m.enabled&&i.enabled===x||i.enabled,l=c.isInsidePlot(d,e,c.inverted),a&&e!==x&&!isNaN(e)&&g.y!==null)if(a=g.pointAttr[g.selected?"select":""],h=a.r,i=o(i.symbol,this.symbol),j=i.indexOf("url")===0,k)k.attr({visibility:l?Z?"inherit":"visible":"hidden"}).animate(v({x:d-h,y:e-h},k.symbolName?{width:2*h,height:2*h}:{}));else{if(l&&(h>0||j))g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h).attr(a).add(n)}else if(k)g.graphic=k.destroy()},convertAttribs:function(a, b,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=o(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var a=this,b=a.options,c=X[a.type].marker?b.marker:b,d=c.states,e=d.hover,f,g=a.color,h={stroke:g,fill:g},i=a.points||[],j=[],k,m=a.pointAttrToOptions,l=b.negativeColor,p;b.marker?(e.radius=e.radius||c.radius+2,e.lineWidth=e.lineWidth||c.lineWidth+1):e.color=e.color||ma(e.color||g).brighten(e.brightness).get();j[""]=a.convertAttribs(c,h);n(["hover", "select"],function(b){j[b]=a.convertAttribs(d[b],j[""])});a.pointAttr=j;for(g=i.length;g--;){h=i[g];if((c=h.options&&h.options.marker||h.options)&&c.enabled===!1)c.radius=0;if(h.negative&&l)h.color=h.fillColor=l;f=b.colorByPoint||h.color;if(h.options)for(p in m)r(c[m[p]])&&(f=!0);if(f){c=c||{};k=[];d=c.states||{};f=d.hover=d.hover||{};if(!b.marker)f.color=ma(f.color||h.color).brighten(f.brightness||e.brightness).get();k[""]=a.convertAttribs(v({color:h.color},c),j[""]);k.hover=a.convertAttribs(d.hover, j.hover,k[""]);k.select=a.convertAttribs(d.select,j.select,k[""]);if(h.negative&&b.marker)k[""].fill=k.hover.fill=k.select.fill=a.convertAttribs({fillColor:l}).fill}else k=j;h.pointAttr=k}},update:function(a,b){var c=this.chart,d=this.type,a=y(this.userOptions,{animation:!1,index:this.index,pointStart:this.xData[0]},a);this.remove(!1);v(this,aa[a.type||d].prototype);this.init(c,a);o(b,!0)&&c.redraw(!1)},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\/533/.test(ya),d,e,f=a.data||[],g,h,i;D(a, "destroy");ba(a);n(["xAxis","yAxis"],function(b){if(i=a[b])ga(i.series,a),i.isDirty=i.forceRedraw=!0});a.legendItem&&a.chart.legend.destroyItem(a);for(e=f.length;e--;)(g=f[e])&&g.destroy&&g.destroy();a.points=null;clearTimeout(a.animationTimeout);n("area,graph,dataLabelsGroup,group,markerGroup,tracker,graphNeg,areaNeg,posClip,negClip".split(","),function(b){a[b]&&(d=c&&b==="group"?"hide":"destroy",a[b][d]())});if(b.hoverSeries===a)b.hoverSeries=null;ga(b.series,a);for(h in a)delete a[h]},drawDataLabels:function(){var a= this,b=a.options.dataLabels,c=a.points,d,e,f,g;if(b.enabled||a._hasPointLabels)a.dlProcessOptions&&a.dlProcessOptions(b),g=a.plotGroup("dataLabelsGroup","data-labels",a.visible?"visible":"hidden",b.zIndex||6),e=b,n(c,function(c){var i,j=c.dataLabel,k,m,l=c.connector,n=!0;d=c.options&&c.options.dataLabels;i=e.enabled||d&&d.enabled;if(j&&!i)c.dataLabel=j.destroy();else if(i){i=b.rotation;b=y(e,d);k=c.getLabelConfig();f=b.format?Ea(b.format,k):b.formatter.call(k,b);b.style.color=o(b.color,b.style.color, a.color,"black");if(j)if(r(f))j.attr({text:f}),n=!1;else{if(c.dataLabel=j=j.destroy(),l)c.connector=l.destroy()}else if(r(f)){j={fill:b.backgroundColor,stroke:b.borderColor,"stroke-width":b.borderWidth,r:b.borderRadius||0,rotation:i,padding:b.padding,zIndex:1};for(m in j)j[m]===x&&delete j[m];j=c.dataLabel=a.chart.renderer[i?"text":"label"](f,0,-999,null,null,null,b.useHTML).attr(j).css(b.style).add(g).shadow(b.shadow)}j&&a.alignDataLabel(c,j,b,null,n)}})},alignDataLabel:function(a,b,c,d,e){var f= this.chart,g=f.inverted,h=o(a.plotX,-999),a=o(a.plotY,-999),i=b.getBBox(),d=v({x:g?f.plotWidth-a:h,y:t(g?f.plotHeight-h:a),width:0,height:0},d);v(c,{width:i.width,height:i.height});c.rotation?(d={align:c.align,x:d.x+c.x+d.width/2,y:d.y+c.y+d.height/2},b[e?"attr":"animate"](d)):b.align(c,null,d);b.attr({visibility:c.crop===!1||f.isInsidePlot(h,a,g)?f.renderer.isSVG?"inherit":"visible":"hidden"})},getSegmentPath:function(a){var b=this,c=[],d=b.options.step;n(a,function(e,f){var g=e.plotX,h=e.plotY, i;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?"L":"M"),d&&f&&(i=a[f-1],d==="right"?c.push(i.plotX,h):d==="center"?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))});return c},getGraphPath:function(){var a=this,b=[],c,d=[];n(a.segments,function(e){c=a.getSegmentPath(e);e.length>1?b=b.concat(c):d.push(e[0])});a.singlePoints=d;return a.graphPath=b},drawGraph:function(){var a=this,b=this.options,c=[["graph",b.lineColor||this.color]],d=b.lineWidth, e=b.dashStyle,f=this.getGraphPath(),g=b.negativeColor;g&&c.push(["graphNeg",g]);n(c,function(c,g){var j=c[0],k=a[j];if(k)Ta(k),k.animate({d:f});else if(d&&f.length){k={stroke:c[1],"stroke-width":d,zIndex:1};if(e)k.dashstyle=e;a[j]=a.chart.renderer.path(f).attr(k).add(a.group).shadow(!g&&b.shadow)}})},clipNeg:function(){var a=this.options,b=this.chart,c=b.renderer,d=a.negativeColor,e,f=this.posClip,g=this.negClip;e=b.chartWidth;var h=b.chartHeight,i=q(e,h);if(d&&this.graph)d=ja(this.yAxis.len-this.yAxis.translate(a.threshold|| 0)),a={x:0,y:0,width:i,height:d},i={x:0,y:d,width:i,height:i-d},b.inverted&&c.isVML&&(a={x:b.plotWidth-d-b.plotLeft,y:0,width:e,height:h},i={x:d+b.plotLeft-e,y:0,width:b.plotLeft+d,height:e}),this.yAxis.reversed?(b=i,e=a):(b=a,e=i),f?(f.animate(b),g.animate(e)):(this.posClip=f=c.clipRect(b),this.graph.clip(f),this.negClip=g=c.clipRect(e),this.graphNeg.clip(g),this.area&&(this.area.clip(f),this.areaNeg.clip(g)))},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};n(["group", "markerGroup"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;J(c,"resize",a);J(b,"destroy",function(){ba(c,"resize",a)});a();b.invertGroups=a},plotGroup:function(a,b,c,d,e){var f=this[a],g=!f,h=this.chart,i=this.xAxis,j=this.yAxis;g&&(this[a]=f=h.renderer.g(b).attr({visibility:c,zIndex:d||0.1}).add(e));f[g?"attr":"animate"]({translateX:i?i.left:h.plotLeft,translateY:j?j.top:h.plotTop,scaleX:1,scaleY:1});return f},render:function(){var a=this.chart,b,c=this.options,d=c.animation&& !!this.animate&&a.renderer.isSVG,e=this.visible?"visible":"hidden",f=c.zIndex,g=this.hasRendered,h=a.seriesGroup;b=this.plotGroup("group","series",e,f,h);this.markerGroup=this.plotGroup("markerGroup","markers",e,f,h);d&&this.animate(!0);this.getAttribs();b.inverted=a.inverted;this.drawGraph&&(this.drawGraph(),this.clipNeg());this.drawDataLabels();this.drawPoints();this.options.enableMouseTracking!==!1&&this.drawTracker();a.inverted&&this.invertGroups();c.clip!==!1&&!this.sharedClipKey&&!g&&b.clip(a.clipRect); d?this.animate():g||this.afterAnimate();this.isDirty=this.isDirtyData=!1;this.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:o(d&&d.left,a.plotLeft),translateY:o(e&&e.top,a.plotTop)}));this.translate();this.setTooltipPoints(!0);this.render();b&&D(this,"updatedData")},setState:function(a){var b=this.options,c=this.graph,d=this.graphNeg,e=b.states,b=b.lineWidth, a=a||"";if(this.state!==a)this.state=a,e[a]&&e[a].enabled===!1||(a&&(b=e[a].lineWidth||b+1),c&&!c.dashstyle&&(a={"stroke-width":b},c.attr(a),d&&d.attr(a)))},setVisible:function(a,b){var c=this,d=c.chart,e=c.legendItem,f,g=d.options.chart.ignoreHiddenSeries,h=c.visible;f=(c.visible=a=c.userOptions.visible=a===x?!h:a)?"show":"hide";n(["group","dataLabelsGroup","markerGroup","tracker"],function(a){if(c[a])c[a][f]()});if(d.hoverSeries===c)c.onMouseOut();e&&d.legend.colorizeItem(c,a);c.isDirty=!0;c.options.stacking&& n(d.series,function(a){if(a.options.stacking&&a.visible)a.isDirty=!0});n(c.linkedSeries,function(b){b.setVisible(a,!1)});if(g)d.isDirtyBox=!0;b!==!1&&d.redraw();D(c,f)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=a===x?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;D(this,a?"select":"unselect")},drawTracker:function(){var a=this,b=a.options,c=b.trackByArea,d=[].concat(c?a.areaPath:a.graphPath),e=d.length,f=a.chart,g=f.pointer, h=f.renderer,i=f.options.tooltip.snap,j=a.tracker,k=b.cursor,k=k&&{cursor:k},m=a.singlePoints,l,n=function(){if(f.hoverSeries!==a)a.onMouseOver()};if(e&&!c)for(l=e+1;l--;)d[l]==="M"&&d.splice(l+1,0,d[l+1]-i,d[l+2],"L"),(l&&d[l]==="M"||l===e)&&d.splice(l,0,"L",d[l-2]+i,d[l-1]);for(l=0;l=0;d--)da&&i>e?(i=q(a,e),k=2*e-i):ig&&k>e?(k=q(g,e),i=2*e-k):kh?n-h:g-(f.translate(c.y,0,1,0,1)<=g?h:0));c.barX=s;c.pointWidth=i;c.shapeType="rect";c.shapeArgs=c=b.renderer.Element.prototype.crisp.call(0,e,s,t,j,l);e%2&&(c.y-=1,c.height+=1)})},getSymbol:ta,drawLegendSymbol:M.prototype.drawLegendSymbol, drawGraph:ta,drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d;n(a.points,function(e){var f=e.plotY,g=e.graphic;if(f!==x&&!isNaN(f)&&e.y!==null)d=e.shapeArgs,g?(Ta(g),g.animate(y(d))):e.graphic=c[e.shapeType](d).attr(e.pointAttr[e.selected?"select":""]).add(a.group).shadow(b.shadow,null,b.stacking&&!b.borderRadius);else if(g)e.graphic=g.destroy()})},drawTracker:function(){var a=this,b=a.chart.pointer,c=a.options.cursor,d=c&&{cursor:c},e=function(b){var c=b.target,d;for(a.onMouseOver();c&& !d;)d=c.point,c=c.parentNode;if(d!==x)d.onMouseOver(b)};n(a.points,function(a){if(a.graphic)a.graphic.element.point=a;if(a.dataLabel)a.dataLabel.element.point=a});a._hasTracking?a._hasTracking=!0:n(a.trackerGroups,function(c){if(a[c]&&(a[c].addClass("highcharts-tracker").on("mouseover",e).on("mouseout",function(a){b.onTrackerMouseOut(a)}).css(d),fb))a[c].on("touchstart",e)})},alignDataLabel:function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=a.dlBox||a.shapeArgs,i=a.below||a.plotY>o(this.translatedThreshold, f.plotSizeY),j=o(c.inside,!!this.options.stacking);if(h&&(d=y(h),g&&(d={x:f.plotWidth-d.y-d.height,y:f.plotHeight-d.x-d.width,width:d.height,height:d.width}),!j))g?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0);c.align=o(c.align,!g||j?"center":i?"right":"left");c.verticalAlign=o(c.verticalAlign,g||j?"middle":i?"top":"bottom");R.prototype.alignDataLabel.call(this,a,b,c,d,e)},animate:function(a){var b=this.yAxis,c=this.options,d=this.chart.inverted,e={};if(Z)a?(e.scaleY=0.001,a=K(b.pos+ b.len,q(b.pos,b.toPixels(c.threshold))),d?e.translateX=a-b.len:e.translateY=a,this.group.attr(e)):(e.scaleY=1,e[d?"translateX":"translateY"]=b.pos,this.group.animate(e,this.options.animation),this.animate=null)},remove:function(){var a=this,b=a.chart;b.hasRendered&&n(b.series,function(b){if(b.type===a.type)b.isDirty=!0});R.prototype.remove.apply(a,arguments)}});aa.column=F;X.bar=y(X.column);na=ea(F,{type:"bar",inverted:!0});aa.bar=na;X.scatter=y(W,{lineWidth:0,tooltip:{headerFormat:'{series.name}
', pointFormat:"x: {point.x}
y: {point.y}
",followPointer:!0},stickyTracking:!1});na=ea(R,{type:"scatter",sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["markerGroup"],drawTracker:F.prototype.drawTracker,setTooltipPoints:ta});aa.scatter=na;X.pie=y(W,{borderColor:"#FFFFFF",borderWidth:1,center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name}},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null, showInLegend:!1,slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}});W={type:"pie",isCartesian:!1,pointClass:ea(Ma,{init:function(){Ma.prototype.init.apply(this,arguments);var a=this,b;if(a.y<0)a.y=null;v(a,{visible:a.visible!==!1,name:o(a.name,"Slice")});b=function(){a.slice()};J(a,"select",b);J(a,"unselect",b);return a},setVisible:function(a){var b=this,c=b.series,d=c.chart,e;b.visible=b.options.visible=a=a===x?!b.visible:a;c.options.data[la(b, c.data)]=b.options;e=a?"show":"hide";n(["graphic","dataLabel","connector","shadowGroup"],function(a){if(b[a])b[a][e]()});b.legendItem&&d.legend.colorizeItem(b,a);if(!c.isDirty&&c.options.ignoreHiddenPoint)c.isDirty=!0,d.redraw()},slice:function(a,b,c){var d=this.series;Ha(c,d.chart);o(b,!0);this.sliced=this.options.sliced=a=r(a)?a:!this.sliced;d.options.data[la(this,d.data)]=this.options;a=a?this.slicedTranslation:{translateX:0,translateY:0};this.graphic.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)}}), requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},getColor:ta,animate:function(a){var b=this,c=b.points,d=b.startAngleRad;if(!a)n(c,function(a){var c=a.graphic,a=a.shapeArgs;c&&(c.attr({r:b.center[3]/2,start:d,end:d}),c.animate({r:a.r,start:a.start,end:a.end},b.options.animation))}),b.animate=null},setData:function(a,b){R.prototype.setData.call(this,a,!1);this.processData();this.generatePoints(); o(b,!0)&&this.chart.redraw()},getCenter:function(){var a=this.options,b=this.chart,c=2*(a.slicedOffset||0),d,e=b.plotWidth-2*c,f=b.plotHeight-2*c,b=a.center,a=[o(b[0],"50%"),o(b[1],"50%"),a.size||"100%",a.innerSize||0],g=K(e,f),h;return Ka(a,function(a,b){h=/%$/.test(a);d=b<2||b===2&&h;return(h?[e,f,g,g][b]*u(a)/100:a)+(d?c:0)})},translate:function(a){this.generatePoints();var b=0,c=0,d=this.options,e=d.slicedOffset,f=e+d.borderWidth,g,h,i,j=this.startAngleRad=Ja/180*((d.startAngle||0)%360-90),k= this.points,m=2*Ja,l=d.dataLabels.distance,n=d.ignoreHiddenPoint,o,q=k.length,r;if(!a)this.center=a=this.getCenter();this.getX=function(b,c){i=I.asin((b-a[1])/(a[2]/2+l));return a[0]+(c?-1:1)*Y(i)*(a[2]/2+l)};for(o=0;o0.75*m&&(i-=2*Ja);r.slicedTranslation={translateX:t(Y(i)* e),translateY:t(ca(i)*e)};g=Y(i)*a[2]/2;h=ca(i)*a[2]/2;r.tooltipPos=[a[0]+g*0.7,a[1]+h*0.7];r.half=i0,v,w,u,x,y=[[],[]],A,z,E,H,C,D=[0,0,0,0],K=function(a,b){return b.y-a.y},M=function(a,b){a.sort(function(a,c){return a.angle!==void 0&&(c.angle-a.angle)*b})};if(e.enabled||a._hasPointLabels){R.prototype.drawDataLabels.apply(a);n(b,function(a){a.dataLabel&&y[a.half].push(a)});for(H=0;!x&&b[H];)x=b[H]&&b[H].dataLabel&&(b[H].dataLabel.getBBox().height||21),H++;for(H=2;H--;){var b=[],L=[],I=y[H],J=I.length,F;M(I,H- 0.5);if(m>0){for(C=s-p-m;C<=s+p+m;C+=x)b.push(C);w=b.length;if(J>w){c=[].concat(I);c.sort(K);for(C=J;C--;)c[C].rank=C;for(C=J;C--;)I[C].rank>=w&&I.splice(C,1);J=I.length}for(C=0;C0){if(w=L.pop(), F=w.i,z=w.y,c>z&&b[F+1]!==null||ch-f&&(D[1]=q(t(A+w-h+f),D[1])),z-x/2<0?D[0]=q(t(-z+x/2),D[0]):z+x/2>d&&(D[2]=q(t(z+x/2-d),D[2]))}}if(pa(D)===0||this.verifyDataLabelOverflow(D))this.placeDataLabels(),r&&g&&n(this.points,function(b){i= b.connector;u=b.labelPos;if((v=b.dataLabel)&&v._pos)A=v.connX,z=v.connY,j=k?["M",A+(u[6]==="left"?5:-5),z,"C",A,z,2*u[2]-u[4],2*u[3]-u[5],u[2],u[3],"L",u[4],u[5]]:["M",A+(u[6]==="left"?5:-5),z,"L",u[2],u[3],"L",u[4],u[5]],i?(i.animate({d:j}),i.attr("visibility",E)):b.connector=i=a.chart.renderer.path(j).attr({"stroke-width":g,stroke:e.connectorColor||b.color||"#606060",visibility:E}).add(a.group);else if(i)b.connector=i.destroy()})}},verifyDataLabelOverflow:function(a){var b=this.center,c=this.options, d=c.center,e=c=c.minSize||80,f;d[0]!==null?e=q(b[2]-q(a[1],a[3]),c):(e=q(b[2]-a[1]-a[3],c),b[0]+=(a[3]-a[1])/2);d[1]!==null?e=q(K(e,b[2]-q(a[0],a[2])),c):(e=q(K(e,b[2]-a[0]-a[2]),c),b[1]+=(a[0]-a[2])/2);e",d.insertBefore(c.lastChild,d.firstChild)}function i(){var a=l.elements;return typeof a=="string"?a.split(" "):a}function j(a){var b={},c=a.createElement,f=a.createDocumentFragment,g=f();a.createElement=function(a){l.shivMethods||c(a);var f;return b[a]?f=b[a].cloneNode():e.test(a)?f=(b[a]=c(a)).cloneNode():f=c(a),f.canHaveChildren&&!d.test(a)?g.appendChild(f):f},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+i().join().replace(/\w+/g,function(a){return b[a]=c(a),g.createElement(a),'c("'+a+'")'})+");return n}")(l,g)}function k(a){var b;return a.documentShived?a:(l.shivCSS&&!f&&(b=!!h(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),g||(b=!j(a)),b&&(a.documentShived=b),a)}function p(a){var b,c=a.getElementsByTagName("*"),d=c.length,e=RegExp("^(?:"+i().join("|")+")$","i"),f=[];while(d--)b=c[d],e.test(b.nodeName)&&f.push(b.applyElement(q(b)));return f}function q(a){var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(n+":"+a.nodeName);while(d--)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function r(a){var b,c=a.split("{"),d=c.length,e=RegExp("(^|[\\s,>+~])("+i().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),f="$1"+n+"\\:$2";while(d--)b=c[d]=c[d].split("}"),b[b.length-1]=b[b.length-1].replace(e,f),c[d]=b.join("}");return c.join("{")}function s(a){var b=a.length;while(b--)a[b].removeNode()}function t(a){var b,c,d=a.namespaces,e=a.parentWindow;return!o||a.printShived?a:(typeof d[n]=="undefined"&&d.add(n),e.attachEvent("onbeforeprint",function(){var d,e,f,g=a.styleSheets,i=[],j=g.length,k=Array(j);while(j--)k[j]=g[j];while(f=k.pop())if(!f.disabled&&m.test(f.media)){for(d=f.imports,j=0,e=d.length;j",f="hidden"in c,f&&typeof injectElementWithStyles=="function"&&injectElementWithStyles("#modernizr{}",function(b){b.hidden=!0,f=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).display=="none"}),g=c.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var l={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:k};a.html5=l,k(b);var m=/^$|\b(?:all|print)\b/,n="html5shiv",o=!g&&function(){var c=b.documentElement;return typeof b.namespaces!="undefined"&&typeof b.parentWindow!="undefined"&&typeof c.applyElement!="undefined"&&typeof c.removeNode!="undefined"&&typeof a.attachEvent!="undefined"}();l.type+=" print",l.shivPrint=t,t(b)})(this,document) ================================================ FILE: clover/clover-admin/src/main/webapp/js/jquery.validate.js ================================================ /* * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ * http://docs.jquery.com/Plugins/Validation * * Copyright (c) 2006 - 2008 Jörn Zaefferer * * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $ * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html */ /** * @fileoverview jQuery validation 基于jQuery的验证插件 * @author Toolman * @version 1.7 */ (function($) { $.extend($.fn, { // http://docs.jquery.com/Plugins/Validation/validate validate: function( options ) { // if nothing is selected, return nothing; can't chain anyway if (!this.length) { options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" ); return; } // check if a validator for this form was already created var validator = $.data(this[0], 'validator'); if ( validator ) { return validator; } validator = new $.validator( options, this[0] ); $.data(this[0], 'validator', validator); if ( validator.settings.onsubmit ) { // allow suppresing validation by adding a cancel class to the submit button this.find("input, button").filter(".cancel").click(function() { validator.cancelSubmit = true; }); // when a submitHandler is used, capture the submitting button if (validator.settings.submitHandler) { this.find("input, button").filter(":submit").click(function() { validator.submitButton = this; }); } // validate the form on submit this.submit( function( event ) { if ( validator.settings.debug ) // prevent form submit to be able to see console output event.preventDefault(); function handle() { if ( validator.settings.submitHandler ) { if (validator.submitButton) { // insert a hidden input as a replacement for the missing submit button var hidden = $("").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); } validator.settings.submitHandler.call( validator, validator.currentForm ); if (validator.submitButton) { // and clean up afterwards; thanks to no-block-scope, hidden can be referenced hidden.remove(); } return false; } return true; } // prevent submit for invalid forms or custom submit handlers if ( validator.cancelSubmit ) { validator.cancelSubmit = false; return handle(); } if ( validator.form() ) { if ( validator.pendingRequest ) { validator.formSubmitted = true; return false; } return handle(); } else { validator.focusInvalid(); return false; } }); } return validator; }, // http://docs.jquery.com/Plugins/Validation/valid valid: function() { if ( $(this[0]).is('form')) { return this.validate().form(); } else { var valid = true; var validator = $(this[0].form).validate(); this.each(function() { valid &= validator.element(this); }); return valid; } }, // attributes: space seperated list of attributes to retrieve and remove removeAttrs: function(attributes) { var result = {}, $element = this; $.each(attributes.split(/\s/), function(index, value) { result[value] = $element.attr(value); $element.removeAttr(value); }); return result; }, // http://docs.jquery.com/Plugins/Validation/rules rules: function(command, argument) { var element = this[0]; if (command) { var settings = $.data(element.form, 'validator').settings; var staticRules = settings.rules; var existingRules = $.validator.staticRules(element); switch(command) { case "add": $.extend(existingRules, $.validator.normalizeRule(argument)); staticRules[element.name] = existingRules; if (argument.messages) settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); break; case "remove": if (!argument) { delete staticRules[element.name]; return existingRules; } var filtered = {}; $.each(argument.split(/\s/), function(index, method) { filtered[method] = existingRules[method]; delete existingRules[method]; }); return filtered; } } var data = $.validator.normalizeRules( $.extend( {}, $.validator.metadataRules(element), $.validator.classRules(element), $.validator.attributeRules(element), $.validator.staticRules(element) ), element); // make sure required is at front if (data.required) { var param = data.required; delete data.required; data = $.extend({required: param}, data); } return data; } }); // Custom selectors $.extend($.expr[":"], { // http://docs.jquery.com/Plugins/Validation/blank blank: function(a) {return !$.trim("" + a.value);}, // http://docs.jquery.com/Plugins/Validation/filled filled: function(a) {return !!$.trim("" + a.value);}, // http://docs.jquery.com/Plugins/Validation/unchecked unchecked: function(a) {return !a.checked;} }); // constructor for validator $.validator = function( options, form ) { this.settings = $.extend( true, {}, $.validator.defaults, options ); this.currentForm = form; this.init(); }; $.validator.format = function(source, params) { if ( arguments.length == 1 ) return function() { var args = $.makeArray(arguments); args.unshift(source); return $.validator.format.apply( this, args ); }; if ( arguments.length > 2 && params.constructor != Array ) { params = $.makeArray(arguments).slice(1); } if ( params.constructor != Array ) { params = [ params ]; } $.each(params, function(i, n) { source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); }); return source; }; $.extend($.validator, { defaults: { messages: {}, groups: {}, rules: {}, errorClass: "error", validClass: "valid", errorElement: "label", focusInvalid: true, errorContainer: $( [] ), errorLabelContainer: $( [] ), onsubmit: true, ignore: [], ignoreTitle: false, onfocusin: function(element) { this.lastActive = element; // hide error label and remove error class on focus if enabled if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); this.errorsFor(element).hide(); } }, onfocusout: function(element) { if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { this.element(element); } }, onkeyup: function(element) { if ( element.name in this.submitted || element == this.lastElement ) { this.element(element); } }, onclick: function(element) { // click on selects, radiobuttons and checkboxes if ( element.name in this.submitted ) this.element(element); // or option elements, check parent select in that case else if (element.parentNode.name in this.submitted) this.element(element.parentNode); }, highlight: function( element, errorClass, validClass ) { $(element).addClass(errorClass).removeClass(validClass); }, unhighlight: function( element, errorClass, validClass ) { $(element).removeClass(errorClass).addClass(validClass); } }, // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults setDefaults: function(settings) { $.extend( $.validator.defaults, settings ); }, messages: { required: "This field is required.", remote: "Please fix this field.", email: "Please enter a valid email address.", url: "Please enter a valid URL.", date: "Please enter a valid date.", dateISO: "Please enter a valid date (ISO).", number: "Please enter a valid number.", digits: "Please enter only digits.", creditcard: "Please enter a valid credit card number.", equalTo: "Please enter the same value again.", accept: "Please enter a value with a valid extension.", maxlength: $.validator.format("Please enter no more than {0} characters."), minlength: $.validator.format("Please enter at least {0} characters."), rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), range: $.validator.format("Please enter a value between {0} and {1}."), max: $.validator.format("Please enter a value less than or equal to {0}."), min: $.validator.format("Please enter a value greater than or equal to {0}.") }, autoCreateRanges: false, prototype: { init: function() { this.labelContainer = $(this.settings.errorLabelContainer); this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); this.submitted = {}; this.valueCache = {}; this.pendingRequest = 0; this.pending = {}; this.invalid = {}; this.reset(); var groups = (this.groups = {}); $.each(this.settings.groups, function(key, value) { $.each(value.split(/\s/), function(index, name) { groups[name] = key; }); }); var rules = this.settings.rules; $.each(rules, function(key, value) { rules[key] = $.validator.normalizeRule(value); }); function delegate(event) { var validator = $.data(this[0].form, "validator"), eventType = "on" + event.type.replace(/^validate/, ""); validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] ); } $(this.currentForm) .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate) .validateDelegate(":radio, :checkbox, select, option", "click", delegate); if (this.settings.invalidHandler) $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); }, // http://docs.jquery.com/Plugins/Validation/Validator/form form: function() { this.checkForm(); $.extend(this.submitted, this.errorMap); this.invalid = $.extend({}, this.errorMap); if (!this.valid()) $(this.currentForm).triggerHandler("invalid-form", [this]); this.showErrors(); return this.valid(); }, checkForm: function() { this.prepareForm(); for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { this.check( elements[i] ); } return this.valid(); }, // http://docs.jquery.com/Plugins/Validation/Validator/element element: function( element ) { element = this.clean( element ); this.lastElement = element; this.prepareElement( element ); this.currentElements = $(element); var result = this.check( element ); if ( result ) { delete this.invalid[element.name]; } else { this.invalid[element.name] = true; } if ( !this.numberOfInvalids() ) { // Hide error containers on last error this.toHide = this.toHide.add( this.containers ); } this.showErrors(); return result; }, // http://docs.jquery.com/Plugins/Validation/Validator/showErrors showErrors: function(errors) { if(errors) { // add items to error list and map $.extend( this.errorMap, errors ); this.errorList = []; for ( var name in errors ) { this.errorList.push({ message: errors[name], element: this.findByName(name)[0] }); } // remove items from success list this.successList = $.grep( this.successList, function(element) { return !(element.name in errors); }); } this.settings.showErrors ? this.settings.showErrors.call( this, this.errorMap, this.errorList ) : this.defaultShowErrors(); }, // http://docs.jquery.com/Plugins/Validation/Validator/resetForm resetForm: function() { if ( $.fn.resetForm ) $( this.currentForm ).resetForm(); this.submitted = {}; this.prepareForm(); this.hideErrors(); this.elements().removeClass( this.settings.errorClass ); }, numberOfInvalids: function() { return this.objectLength(this.invalid); }, objectLength: function( obj ) { var count = 0; for ( var i in obj ) count++; return count; }, hideErrors: function() { this.addWrapper( this.toHide ).hide(); }, valid: function() { return this.size() == 0; }, size: function() { return this.errorList.length; }, focusInvalid: function() { if( this.settings.focusInvalid ) { try { $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) .filter(":visible") .focus() // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find .trigger("focusin"); } catch(e) { // ignore IE throwing errors when focusing hidden elements } } }, findLastActive: function() { var lastActive = this.lastActive; return lastActive && $.grep(this.errorList, function(n) { return n.element.name == lastActive.name; }).length == 1 && lastActive; }, elements: function() { var validator = this, rulesCache = {}; // select all valid inputs inside the form (no submit or reset buttons) // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved return $([]).add(this.currentForm.elements) .filter(":input") .not(":submit, :reset, :image, [disabled]") .not( this.settings.ignore ) .filter(function() { !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); // select only the first element for each name, and only those with rules specified if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) return false; rulesCache[this.name] = true; return true; }); }, clean: function( selector ) { return $( selector )[0]; }, errors: function() { return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext ); }, reset: function() { this.successList = []; this.errorList = []; this.errorMap = {}; this.toShow = $([]); this.toHide = $([]); this.currentElements = $([]); }, prepareForm: function() { this.reset(); this.toHide = this.errors().add( this.containers ); }, prepareElement: function( element ) { this.reset(); this.toHide = this.errorsFor(element); }, check: function( element ) { element = this.clean( element ); // if radio/checkbox, validate first element in group instead if (this.checkable(element)) { element = this.findByName( element.name )[0]; } var rules = $(element).rules(); var dependencyMismatch = false; for( method in rules ) { var rule = { method: method, parameters: rules[method] }; try { var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters ); // if a method indicates that the field is optional and therefore valid, // don't mark it as valid when there are no other rules if ( result == "dependency-mismatch" ) { dependencyMismatch = true; continue; } dependencyMismatch = false; if ( result == "pending" ) { this.toHide = this.toHide.not( this.errorsFor(element) ); return; } if( !result ) { this.formatAndAdd( element, rule ); return false; } } catch(e) { this.settings.debug && window.console && console.log("exception occured when checking element " + element.id + ", check the '" + rule.method + "' method", e); throw e; } } if (dependencyMismatch) return; if ( this.objectLength(rules) ) this.successList.push(element); return true; }, // return the custom message for the given element and validation method // specified in the element's "messages" metadata customMetaMessage: function(element, method) { if (!$.metadata) return; var meta = this.settings.meta ? $(element).metadata()[this.settings.meta] : $(element).metadata(); return meta && meta.messages && meta.messages[method]; }, // return the custom message for the given element name and validation method customMessage: function( name, method ) { var m = this.settings.messages[name]; return m && (m.constructor == String ? m : m[method]); }, // return the first defined argument, allowing empty strings findDefined: function() { for(var i = 0; i < arguments.length; i++) { if (arguments[i] !== undefined) return arguments[i]; } return undefined; }, defaultMessage: function( element, method) { return this.findDefined( this.customMessage( element.name, method ), this.customMetaMessage( element, method ), // title is never undefined, so handle empty string as undefined !this.settings.ignoreTitle && element.title || undefined, $.validator.messages[method], "Warning: No message defined for " + element.name + "" ); }, formatAndAdd: function( element, rule ) { var message = this.defaultMessage( element, rule.method ), theregex = /\$?\{(\d+)\}/g; if ( typeof message == "function" ) { message = message.call(this, rule.parameters, element); } else if (theregex.test(message)) { message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters); } this.errorList.push({ message: message, element: element }); this.errorMap[element.name] = message; this.submitted[element.name] = message; }, addWrapper: function(toToggle) { if ( this.settings.wrapper ) toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); return toToggle; }, defaultShowErrors: function() { for ( var i = 0; this.errorList[i]; i++ ) { var error = this.errorList[i]; this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); this.showLabel( error.element, error.message ); } if( this.errorList.length ) { this.toShow = this.toShow.add( this.containers ); } if (this.settings.success) { for ( var i = 0; this.successList[i]; i++ ) { this.showLabel( this.successList[i] ); } } if (this.settings.unhighlight) { for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) { this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); } } this.toHide = this.toHide.not( this.toShow ); this.hideErrors(); this.addWrapper( this.toShow ).show(); }, validElements: function() { return this.currentElements.not(this.invalidElements()); }, invalidElements: function() { return $(this.errorList).map(function() { return this.element; }); }, showLabel: function(element, message) { var label = this.errorsFor( element ); if ( label.length ) { // refresh error/success class label.removeClass().addClass( this.settings.errorClass ); // check if we have a generated label, replace the message then label.attr("generated") && label.html(message); } else { // create label label = $("<" + this.settings.errorElement + "/>") .attr({"for": this.idOrName(element), generated: true}) .addClass(this.settings.errorClass) .html(message || ""); if ( this.settings.wrapper ) { // make sure the element is visible, even in IE // actually showing the wrapped element is handled elsewhere label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); } if ( !this.labelContainer.append(label).length ) this.settings.errorPlacement ? this.settings.errorPlacement(label, $(element) ) : label.insertAfter(element); } if ( !message && this.settings.success ) { label.text(""); typeof this.settings.success == "string" ? label.addClass( this.settings.success ) : this.settings.success( label ); } this.toShow = this.toShow.add(label); }, errorsFor: function(element) { var name = this.idOrName(element); return this.errors().filter(function() { return $(this).attr('for') == name; }); }, idOrName: function(element) { return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); }, checkable: function( element ) { return /radio|checkbox/i.test(element.type); }, findByName: function( name ) { // select by name and filter by form for performance over form.find("[name=...]") var form = this.currentForm; return $(document.getElementsByName(name)).map(function(index, element) { return element.form == form && element.name == name && element || null; }); }, getLength: function(value, element) { switch( element.nodeName.toLowerCase() ) { case 'select': return $("option:selected", element).length; case 'input': if( this.checkable( element) ) return this.findByName(element.name).filter(':checked').length; } return value.length; }, depend: function(param, element) { return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true; }, dependTypes: { "boolean": function(param, element) { return param; }, "string": function(param, element) { return !!$(param, element.form).length; }, "function": function(param, element) { return param(element); } }, optional: function(element) { return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch"; }, startRequest: function(element) { if (!this.pending[element.name]) { this.pendingRequest++; this.pending[element.name] = true; } }, stopRequest: function(element, valid) { this.pendingRequest--; // sometimes synchronization fails, make sure pendingRequest is never < 0 if (this.pendingRequest < 0) this.pendingRequest = 0; delete this.pending[element.name]; if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) { $(this.currentForm).submit(); this.formSubmitted = false; } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) { $(this.currentForm).triggerHandler("invalid-form", [this]); this.formSubmitted = false; } }, previousValue: function(element) { return $.data(element, "previousValue") || $.data(element, "previousValue", { old: null, valid: true, message: this.defaultMessage( element, "remote" ) }); } }, classRuleSettings: { required: {required: true}, email: {email: true}, url: {url: true}, date: {date: true}, dateISO: {dateISO: true}, dateDE: {dateDE: true}, number: {number: true}, numberDE: {numberDE: true}, digits: {digits: true}, creditcard: {creditcard: true} }, addClassRules: function(className, rules) { className.constructor == String ? this.classRuleSettings[className] = rules : $.extend(this.classRuleSettings, className); }, classRules: function(element) { var rules = {}; var classes = $(element).attr('class'); classes && $.each(classes.split(' '), function() { if (this in $.validator.classRuleSettings) { $.extend(rules, $.validator.classRuleSettings[this]); } }); return rules; }, attributeRules: function(element) { var rules = {}; var $element = $(element); for (method in $.validator.methods) { var value = $element.attr(method); if (value) { rules[method] = value; } } // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { delete rules.maxlength; } return rules; }, metadataRules: function(element) { if (!$.metadata) return {}; var meta = $.data(element.form, 'validator').settings.meta; return meta ? $(element).metadata()[meta] : $(element).metadata(); }, staticRules: function(element) { var rules = {}; var validator = $.data(element.form, 'validator'); if (validator.settings.rules) { rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; } return rules; }, normalizeRules: function(rules, element) { // handle dependency check $.each(rules, function(prop, val) { // ignore rule when param is explicitly false, eg. required:false if (val === false) { delete rules[prop]; return; } if (val.param || val.depends) { var keepRule = true; switch (typeof val.depends) { case "string": keepRule = !!$(val.depends, element.form).length; break; case "function": keepRule = val.depends.call(element, element); break; } if (keepRule) { rules[prop] = val.param !== undefined ? val.param : true; } else { delete rules[prop]; } } }); // evaluate parameters $.each(rules, function(rule, parameter) { rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; }); // clean number parameters $.each(['minlength', 'maxlength', 'min', 'max'], function() { if (rules[this]) { rules[this] = Number(rules[this]); } }); $.each(['rangelength', 'range'], function() { if (rules[this]) { rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; } }); if ($.validator.autoCreateRanges) { // auto-create ranges if (rules.min && rules.max) { rules.range = [rules.min, rules.max]; delete rules.min; delete rules.max; } if (rules.minlength && rules.maxlength) { rules.rangelength = [rules.minlength, rules.maxlength]; delete rules.minlength; delete rules.maxlength; } } // To support custom messages in metadata ignore rule methods titled "messages" if (rules.messages) { delete rules.messages; } return rules; }, // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} normalizeRule: function(data) { if( typeof data == "string" ) { var transformed = {}; $.each(data.split(/\s/), function() { transformed[this] = true; }); data = transformed; } return data; }, // http://docs.jquery.com/Plugins/Validation/Validator/addMethod addMethod: function(name, method, message) { $.validator.methods[name] = method; $.validator.messages[name] = message != undefined ? message : $.validator.messages[name]; if (method.length < 3) { $.validator.addClassRules(name, $.validator.normalizeRule(name)); } }, methods: { // http://docs.jquery.com/Plugins/Validation/Methods/required required: function(value, element, param) { // check if dependency is met if ( !this.depend(param, element) ) return "dependency-mismatch"; switch( element.nodeName.toLowerCase() ) { case 'select': // could be an array for select-multiple or a string, both are fine this way var val = $(element).val(); return val && val.length > 0; case 'input': if ( this.checkable(element) ) return this.getLength(value, element) > 0; default: return $.trim(value).length > 0; } }, // http://docs.jquery.com/Plugins/Validation/Methods/remote remote: function(value, element, param) { if ( this.optional(element) ) return "dependency-mismatch"; var previous = this.previousValue(element); if (!this.settings.messages[element.name] ) this.settings.messages[element.name] = {}; previous.originalMessage = this.settings.messages[element.name].remote; this.settings.messages[element.name].remote = previous.message; param = typeof param == "string" && {url:param} || param; if ( previous.old !== value ) { previous.old = value; var validator = this; this.startRequest(element); var data = {}; data[element.name] = value; $.ajax($.extend(true, { url: param, mode: "abort", port: "validate" + element.name, dataType: "json", data: data, success: function(response) { validator.settings.messages[element.name].remote = previous.originalMessage; var valid = response === true; if ( valid ) { var submitted = validator.formSubmitted; validator.prepareElement(element); validator.formSubmitted = submitted; validator.successList.push(element); validator.showErrors(); } else { var errors = {}; var message = (previous.message = response || validator.defaultMessage( element, "remote" )); errors[element.name] = $.isFunction(message) ? message(value) : message; validator.showErrors(errors); } previous.valid = valid; validator.stopRequest(element, valid); } }, param)); return "pending"; } else if( this.pending[element.name] ) { return "pending"; } return previous.valid; }, // http://docs.jquery.com/Plugins/Validation/Methods/minlength minlength: function(value, element, param) { return this.optional(element) || this.getLength($.trim(value), element) >= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/maxlength maxlength: function(value, element, param) { return this.optional(element) || this.getLength($.trim(value), element) <= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/rangelength rangelength: function(value, element, param) { var length = this.getLength($.trim(value), element); return this.optional(element) || ( length >= param[0] && length <= param[1] ); }, // http://docs.jquery.com/Plugins/Validation/Methods/min min: function( value, element, param ) { return this.optional(element) || value >= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/max max: function( value, element, param ) { return this.optional(element) || value <= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/range range: function( value, element, param ) { return this.optional(element) || ( value >= param[0] && value <= param[1] ); }, // http://docs.jquery.com/Plugins/Validation/Methods/email email: function(value, element) { // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/url url: function(value, element) { // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/date date: function(value, element) { return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); }, // http://docs.jquery.com/Plugins/Validation/Methods/dateISO dateISO: function(value, element) { return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/number number: function(value, element) { return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/digits digits: function(value, element) { return this.optional(element) || /^\d+$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/creditcard // based on http://en.wikipedia.org/wiki/Luhn creditcard: function(value, element) { if ( this.optional(element) ) return "dependency-mismatch"; // accept only digits and dashes if (/[^0-9-]+/.test(value)) return false; var nCheck = 0, nDigit = 0, bEven = false; value = value.replace(/\D/g, ""); for (var n = value.length - 1; n >= 0; n--) { var cDigit = value.charAt(n); var nDigit = parseInt(cDigit, 10); if (bEven) { if ((nDigit *= 2) > 9) nDigit -= 9; } nCheck += nDigit; bEven = !bEven; } return (nCheck % 10) == 0; }, // http://docs.jquery.com/Plugins/Validation/Methods/accept accept: function(value, element, param) { param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif"; return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); }, // http://docs.jquery.com/Plugins/Validation/Methods/equalTo equalTo: function(value, element, param) { // bind to the blur event of the target in order to revalidate whenever the target field is updated // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { $(element).valid(); }); return value == target.val(); } } }); // deprecated, use $.validator.format instead $.format = $.validator.format; })(jQuery); // ajax mode: abort // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() ;(function($) { var ajax = $.ajax; var pendingRequests = {}; $.ajax = function(settings) { // create settings for compatibility with ajaxSetup settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings)); var port = settings.port; if (settings.mode == "abort") { if ( pendingRequests[port] ) { pendingRequests[port].abort(); } return (pendingRequests[port] = ajax.apply(this, arguments)); } return ajax.apply(this, arguments); }; })(jQuery); // provides cross-browser focusin and focusout events // IE has native support, in other browsers, use event caputuring (neither bubbles) // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target ;(function($) { // only implement if not provided by jQuery core (since 1.4) // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) { $.each({ focus: 'focusin', blur: 'focusout' }, function( original, fix ){ $.event.special[fix] = { setup:function() { this.addEventListener( original, handler, true ); }, teardown:function() { this.removeEventListener( original, handler, true ); }, handler: function(e) { arguments[0] = $.event.fix(e); arguments[0].type = fix; return $.event.handle.apply(this, arguments); } }; function handler(e) { e = $.event.fix(e); e.type = fix; return $.event.handle.call(this, e); } }); }; $.extend($.fn, { validateDelegate: function(delegate, type, handler) { return this.bind(type, function(event) { var target = $(event.target); if (target.is(delegate)) { return handler.apply(target, arguments); } }); } }); })(jQuery); // 字符验证 jQuery.validator.addMethod("stringCheck", function(value, element) { return this.optional(element) || /^[\u0391-\uFFE5\w]+$/.test(value); }, "只能包括中文字、英文字母、数字和下划线"); jQuery.validator.addMethod("noAndLetter", function(value, element) { return this.optional(element) || /^[A-Za-z0-9]+$/.test(value); }, "只能包括中文字、英文字母、数字和下划线"); // 中文字两个字节 jQuery.validator.addMethod("byteRangeLength", function(value, element, param) { var length = value.length; for(var i = 0; i < value.length; i++){ if(value.charCodeAt(i) > 127){ length++; } } return this.optional(element) || ( length >= param[0] && length <= param[1] ); }, "请确保输入的值在3-15个字节之间(一个中文字算2个字节)"); // dateSet日期验证2012-12-12 jQuery.validator.addMethod("dateSet", function(value, element) { var dS =/^((?!0000)[0-9]{4}-((0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])|(0[13-9]|1[0-2])-(29|30)|(0[13578]|1[02])-31)|([0-9]{2}(0[48]|[2468][048]|[13579][26])|(0[48]|[2468][048]|[13579][26])00)-02-29)$/; return this.optional(element) || (dS.test(value)); }, "XXX"); // 身份证号码验证 jQuery.validator.addMethod("isIdCardNo", function(value, element) { return this.optional(element) || idCardNoUtil.checkIdCardNo(value); }, "请正确输入您的身份证号码"); //护照编号验证 jQuery.validator.addMethod("passport", function(value, element) { return this.optional(element) || checknumber(value); }, "请正确输入您的护照编号"); // 手机号码验证 jQuery.validator.addMethod("isMobile", function(value, element) { var length = value.length; var mobile = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/; return this.optional(element) || (length == 11 && mobile.test(value)); }, "请正确填写您的手机号码"); // 电话号码验证 jQuery.validator.addMethod("isTel", function(value, element) { var tel = /^(0[0-9]{2,3}\-)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$/; //电话号码格式010-12345678-123(4) return this.optional(element) || (tel.test(value)); }, "请正确填写您的电话号码"); // 联系电话(手机/电话皆可)验证 jQuery.validator.addMethod("isPhone", function(value,element) { var length = value.length; var mobile = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/; var tel = /^(0[0-9]{2,3}\-)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$/; return this.optional(element) || (tel.test(value) || mobile.test(value)); }, "请正确填写您的联系电话"); // 邮政编码验证 jQuery.validator.addMethod("isZipCode", function(value, element) { var tel = /^[0-9]{6}$/; return this.optional(element) || (tel.test(value)); }, "请正确填写您的邮政编码"); jQuery.validator.addMethod("compareDateTo", function(value, element, param) { var startDate = jQuery(param).val(); if(!value) return true; if(startDate&&value){ var arr1 = /^(\d\d\d\d)-(\d\d)-(\d\d)$/g.exec(startDate); var arr2 = /^(\d\d\d\d)-(\d\d)-(\d\d)$/g.exec(value); var date1 = new Date(Date.parse(arr1[2]+"/"+arr1[3]+"/"+arr1[1])); var date2 = new Date(Date.parse(arr2[2]+"/"+arr2[3]+"/"+arr2[1])); } return startDate&&value&&date1 < date2; },"开始日期必须小于结束日期"); /*身份证验证开始*/ var idCardNoUtil = { provinceAndCitys: {11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江", 31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北",43:"湖南",44:"广东", 45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃",63:"青海",64:"宁夏", 65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"}, powers: ["7","9","10","5","8","4","2","1","6","3","7","9","10","5","8","4","2"], parityBit: ["1","0","X","9","8","7","6","5","4","3","2"], genders: {male:"男",female:"女"}, checkAddressCode: function(addressCode){ var check = /^[1-9]\d{5}$/.test(addressCode); if(!check) return false; if(idCardNoUtil.provinceAndCitys[parseInt(addressCode.substring(0,2))]){ return true; }else{ return false; } }, checkBirthDayCode: function(birDayCode){ var check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode); if(!check) return false; var yyyy = parseInt(birDayCode.substring(0,4),10); var mm = parseInt(birDayCode.substring(4,6),10); var dd = parseInt(birDayCode.substring(6),10); var xdata = new Date(yyyy,mm-1,dd); if(xdata > new Date()){ return false;//生日不能大于当前日期 }else if ( ( xdata.getFullYear() == yyyy ) && ( xdata.getMonth () == mm - 1 ) && ( xdata.getDate() == dd ) ){ return true; }else{ return false; } }, getParityBit: function(idCardNo){ var id17 = idCardNo.substring(0,17); var power = 0; for(var i=0;i<17;i++){ power += parseInt(id17.charAt(i),10) * parseInt(idCardNoUtil.powers[i]); } var mod = power % 11; return idCardNoUtil.parityBit[mod]; }, checkParityBit: function(idCardNo){ var parityBit = idCardNo.charAt(17).toUpperCase(); if(idCardNoUtil.getParityBit(idCardNo) == parityBit){ return true; }else{ return false; } }, checkIdCardNo: function(idCardNo){ //15位和18位身份证号码的基本校验 var check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo); if(!check) return false; //判断长度为15位或18位 if(idCardNo.length==15){ return idCardNoUtil.check15IdCardNo(idCardNo); }else if(idCardNo.length==18){ return idCardNoUtil.check18IdCardNo(idCardNo); }else{ return false; } }, //校验15位的身份证号码 check15IdCardNo: function(idCardNo){ //15位身份证号码的基本校验 var check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo); if(!check) return false; //校验地址码 var addressCode = idCardNo.substring(0,6); check = idCardNoUtil.checkAddressCode(addressCode); if(!check) return false; var birDayCode = '19' + idCardNo.substring(6,12); //校验日期码 return idCardNoUtil.checkBirthDayCode(birDayCode); }, //校验18位的身份证号码 check18IdCardNo: function(idCardNo){ //18位身份证号码的基本格式校验 var check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo); if(!check) return false; //校验地址码 var addressCode = idCardNo.substring(0,6); check = idCardNoUtil.checkAddressCode(addressCode); if(!check) return false; //校验日期码 var birDayCode = idCardNo.substring(6,14); check = idCardNoUtil.checkBirthDayCode(birDayCode); if(!check) return false; //验证校检码 return idCardNoUtil.checkParityBit(idCardNo); }, formateDateCN: function(day){ var yyyy =day.substring(0,4); var mm = day.substring(4,6); var dd = day.substring(6); return yyyy + '-' + mm +'-' + dd; }, //获取信息 getIdCardInfo: function(idCardNo){ var idCardInfo = { gender:"", //性别 birthday:"" // 出生日期(yyyy-mm-dd) }; if(idCardNo.length==15){ var aday = '19' + idCardNo.substring(6,12); idCardInfo.birthday=idCardNoUtil.formateDateCN(aday); if(parseInt(idCardNo.charAt(14))%2==0){ idCardInfo.gender=idCardNoUtil.genders.female; }else{ idCardInfo.gender=idCardNoUtil.genders.male; } }else if(idCardNo.length==18){ var aday = idCardNo.substring(6,14); idCardInfo.birthday=idCardNoUtil.formateDateCN(aday); if(parseInt(idCardNo.charAt(16))%2==0){ idCardInfo.gender=idCardNoUtil.genders.female; }else{ idCardInfo.gender=idCardNoUtil.genders.male; } } return idCardInfo; }, getId15:function(idCardNo){ if(idCardNo.length==15){ return idCardNo; }else if(idCardNo.length==18){ return idCardNo.substring(0,6) + idCardNo.substring(8,17); }else{ return null; } }, getId18: function(idCardNo){ if(idCardNo.length==15){ var id17 = idCardNo.substring(0,6) + '19' + idCardNo.substring(6); var parityBit = idCardNoUtil.getParityBit(id17); return id17 + parityBit; }else if(idCardNo.length==18){ return idCardNo; }else{ return null; } } }; //验证护照是否正确 function checknumber(number){ var str=number; //在JavaScript中,正则表达式只能使用"/"开头和结束,不能使用双引号 var Expression=/(P\d{7})|(G\d{8})/; var objExp=new RegExp(Expression); console.log(1); if(objExp.test(str)==true){ return true; }else{ return false; } }; /*身份证验证结束*/ ================================================ FILE: clover/clover-admin/src/main/webapp/js/ui.datepicker-zh-CN.js ================================================ /* Chinese initialisation for the jQuery UI date picker plugin. */ /* Written by Cloudream (cloudream@gmail.com). */ jQuery(function($){ $.datepicker.regional['zh-CN'] = { closeText: '关闭', prevText: '<上月', nextText: '下月>', currentText: '今天', monthNames: ['一月','二月','三月','四月','五月','六月', '七月','八月','九月','十月','十一月','十二月'], monthNamesShort: ['一','二','三','四','五','六', '七','八','九','十','十一','十二'], dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'], dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'], dayNamesMin: ['日','一','二','三','四','五','六'], dateFormat: 'yy-mm-dd', firstDay: 1, isRTL: false}; $.datepicker.setDefaults($.datepicker.regional['zh-CN']); }); ================================================ FILE: clover/clover-admin/src/main/webapp/js/ui.datepicker.js ================================================ /* * jQuery UI Datepicker 1.7 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Datepicker * * Depends: * ui.core.js */ (function($) { // hide the namespace $.extend($.ui, { datepicker: { version: "1.7" } }); var PROP_NAME = 'datepicker'; /* Date picker manager. Use the singleton instance of this class, $.datepicker, to interact with the date picker. Settings for (groups of) date pickers are maintained in an instance object, allowing multiple different settings on the same page. */ function Datepicker() { this.debug = false; // Change this to true to start debugging this._curInst = null; // The current instance in use this._keyEvent = false; // If the last event was a key event this._disabledInputs = []; // List of date picker inputs that have been disabled this._datepickerShowing = false; // True if the popup picker is showing , false if not this._inDialog = false; // True if showing within a "dialog", false if not this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class this._appendClass = 'ui-datepicker-append'; // The name of the append marker class this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class this.regional = []; // Available regional settings, indexed by language code this.regional[''] = { // Default regional settings closeText: 'Done', // Display text for close link prevText: 'Prev', // Display text for previous month link nextText: 'Next', // Display text for next month link currentText: 'Today', // Display text for current month link monthNames: ['January','February','March','April','May','June', 'July','August','September','October','November','December'], // Names of months for drop-down and formatting monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday dateFormat: 'mm/dd/yy', // See format options on parseDate firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... isRTL: false // True if right-to-left language, false if left-to-right }; this._defaults = { // Global defaults for all the date picker instances showOn: 'focus', // 'focus' for popup on focus, // 'button' for trigger button, or 'both' for either showAnim: 'show', // Name of jQuery animation for popup showOptions: {}, // Options for enhanced animations defaultDate: null, // Used when field is blank: actual date, // +/-number for offset from today, null for today appendText: '', // Display text following the input box, e.g. showing the format buttonText: '...', // Text for trigger button buttonImage: '', // URL for trigger button image buttonImageOnly: false, // True if the image appears alone, false if it appears on a button hideIfNoPrevNext: false, // True to hide next/previous month links // if not applicable, false to just disable them navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links gotoCurrent: false, // True if today link goes back to current selection instead changeMonth: false, // True if month can be selected directly, false if only prev/next changeYear: false, // True if year can be selected directly, false if only prev/next showMonthAfterYear: false, // True if the year select precedes month, false for month then year yearRange: '-10:+10', // Range of years to display in drop-down, // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn) showOtherMonths: false, // True to show dates in other months, false to leave blank calculateWeek: this.iso8601Week, // How to calculate the week of the year, // takes a Date and returns the number of the week for it shortYearCutoff: '+10', // Short year values < this are in the current century, // > this are in the previous century, // string value starting with '+' for current year + value minDate: null, // The earliest selectable date, or null for no limit maxDate: null, // The latest selectable date, or null for no limit duration: 'normal', // Duration of display/closure beforeShowDay: null, // Function that takes a date and returns an array with // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', // [2] = cell title (optional), e.g. $.datepicker.noWeekends beforeShow: null, // Function that takes an input field and // returns a set of custom settings for the date picker onSelect: null, // Define a callback function when a date is selected onChangeMonthYear: null, // Define a callback function when the month or year is changed onClose: null, // Define a callback function when the datepicker is closed numberOfMonths: 1, // Number of months to show at a time showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) stepMonths: 1, // Number of months to step back/forward stepBigMonths: 12, // Number of months to step back/forward for the big links altField: '', // Selector for an alternate field to store selected dates into altFormat: '', // The date format to use for the alternate field constrainInput: true, // The input is constrained by the current date format showButtonPanel: false // True to show button panel, false to not show it }; $.extend(this._defaults, this.regional['']); this.dpDiv = $('
'); } $.extend(Datepicker.prototype, { /* Class name added to elements to indicate already configured with a date picker. */ markerClassName: 'hasDatepicker', /* Debug logging (if enabled). */ log: function () { if (this.debug) console.log.apply('', arguments); }, /* Override the default settings for all instances of the date picker. @param settings object - the new settings to use as defaults (anonymous object) @return the manager object */ setDefaults: function(settings) { extendRemove(this._defaults, settings || {}); return this; }, /* Attach the date picker to a jQuery selection. @param target element - the target input field or division or span @param settings object - the new settings to use for this date picker instance (anonymous) */ _attachDatepicker: function(target, settings) { // check for settings on the control itself - in namespace 'date:' var inlineSettings = null; for (var attrName in this._defaults) { var attrValue = target.getAttribute('date:' + attrName); if (attrValue) { inlineSettings = inlineSettings || {}; try { inlineSettings[attrName] = eval(attrValue); } catch (err) { inlineSettings[attrName] = attrValue; } } } var nodeName = target.nodeName.toLowerCase(); var inline = (nodeName == 'div' || nodeName == 'span'); if (!target.id) target.id = 'dp' + (++this.uuid); var inst = this._newInst($(target), inline); inst.settings = $.extend({}, settings || {}, inlineSettings || {}); if (nodeName == 'input') { this._connectDatepicker(target, inst); } else if (inline) { this._inlineDatepicker(target, inst); } }, /* Create a new instance object. */ _newInst: function(target, inline) { var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars return {id: id, input: target, // associated target selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection drawMonth: 0, drawYear: 0, // month being drawn inline: inline, // is datepicker inline or not dpDiv: (!inline ? this.dpDiv : // presentation div $('
'))}; }, /* Attach the date picker to an input field. */ _connectDatepicker: function(target, inst) { var input = $(target); if (input.hasClass(this.markerClassName)) return; var appendText = this._get(inst, 'appendText'); var isRTL = this._get(inst, 'isRTL'); if (appendText) input[isRTL ? 'before' : 'after']('' + appendText + ''); var showOn = this._get(inst, 'showOn'); if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field input.focus(this._showDatepicker); if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked var buttonText = this._get(inst, 'buttonText'); var buttonImage = this._get(inst, 'buttonImage'); var trigger = $(this._get(inst, 'buttonImageOnly') ? $('').addClass(this._triggerClass). attr({ src: buttonImage, alt: buttonText, title: buttonText }) : $('').addClass(this._triggerClass). html(buttonImage == '' ? buttonText : $('').attr( { src:buttonImage, alt:buttonText, title:buttonText }))); input[isRTL ? 'before' : 'after'](trigger); trigger.click(function() { if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target) $.datepicker._hideDatepicker(); else $.datepicker._showDatepicker(target); return false; }); } input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress). bind("setData.datepicker", function(event, key, value) { inst.settings[key] = value; }).bind("getData.datepicker", function(event, key) { return this._get(inst, key); }); $.data(target, PROP_NAME, inst); }, /* Attach an inline date picker to a div. */ _inlineDatepicker: function(target, inst) { var divSpan = $(target); if (divSpan.hasClass(this.markerClassName)) return; divSpan.addClass(this.markerClassName).append(inst.dpDiv). bind("setData.datepicker", function(event, key, value){ inst.settings[key] = value; }).bind("getData.datepicker", function(event, key){ return this._get(inst, key); }); $.data(target, PROP_NAME, inst); this._setDate(inst, this._getDefaultDate(inst)); this._updateDatepicker(inst); this._updateAlternate(inst); }, /* Pop-up the date picker in a "dialog" box. @param input element - ignored @param dateText string - the initial date to display (in the current format) @param onSelect function - the function(dateText) to call when a date is selected @param settings object - update the dialog date picker instance's settings (anonymous object) @param pos int[2] - coordinates for the dialog's position within the screen or event - with x/y coordinates or leave empty for default (screen centre) @return the manager object */ _dialogDatepicker: function(input, dateText, onSelect, settings, pos) { var inst = this._dialogInst; // internal instance if (!inst) { var id = 'dp' + (++this.uuid); this._dialogInput = $(''); this._dialogInput.keydown(this._doKeyDown); $('body').append(this._dialogInput); inst = this._dialogInst = this._newInst(this._dialogInput, false); inst.settings = {}; $.data(this._dialogInput[0], PROP_NAME, inst); } extendRemove(inst.settings, settings || {}); this._dialogInput.val(dateText); this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); if (!this._pos) { var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; var scrollY = document.documentElement.scrollTop || document.body.scrollTop; this._pos = // should use actual width/height below [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; } // move input on screen for focus, but hidden behind dialog this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px'); inst.settings.onSelect = onSelect; this._inDialog = true; this.dpDiv.addClass(this._dialogClass); this._showDatepicker(this._dialogInput[0]); if ($.blockUI) $.blockUI(this.dpDiv); $.data(this._dialogInput[0], PROP_NAME, inst); return this; }, /* Detach a datepicker from its control. @param target element - the target input field or division or span */ _destroyDatepicker: function(target) { var $target = $(target); if (!$target.hasClass(this.markerClassName)) { return; } var nodeName = target.nodeName.toLowerCase(); $.removeData(target, PROP_NAME); if (nodeName == 'input') { $target.siblings('.' + this._appendClass).remove().end(). siblings('.' + this._triggerClass).remove().end(). removeClass(this.markerClassName). unbind('focus', this._showDatepicker). unbind('keydown', this._doKeyDown). unbind('keypress', this._doKeyPress); } else if (nodeName == 'div' || nodeName == 'span') $target.removeClass(this.markerClassName).empty(); }, /* Enable the date picker to a jQuery selection. @param target element - the target input field or division or span */ _enableDatepicker: function(target) { var $target = $(target); if (!$target.hasClass(this.markerClassName)) { return; } var nodeName = target.nodeName.toLowerCase(); if (nodeName == 'input') { target.disabled = false; $target.siblings('button.' + this._triggerClass). each(function() { this.disabled = false; }).end(). siblings('img.' + this._triggerClass). css({opacity: '1.0', cursor: ''}); } else if (nodeName == 'div' || nodeName == 'span') { var inline = $target.children('.' + this._inlineClass); inline.children().removeClass('ui-state-disabled'); } this._disabledInputs = $.map(this._disabledInputs, function(value) { return (value == target ? null : value); }); // delete entry }, /* Disable the date picker to a jQuery selection. @param target element - the target input field or division or span */ _disableDatepicker: function(target) { var $target = $(target); if (!$target.hasClass(this.markerClassName)) { return; } var nodeName = target.nodeName.toLowerCase(); if (nodeName == 'input') { target.disabled = true; $target.siblings('button.' + this._triggerClass). each(function() { this.disabled = true; }).end(). siblings('img.' + this._triggerClass). css({opacity: '0.5', cursor: 'default'}); } else if (nodeName == 'div' || nodeName == 'span') { var inline = $target.children('.' + this._inlineClass); inline.children().addClass('ui-state-disabled'); } this._disabledInputs = $.map(this._disabledInputs, function(value) { return (value == target ? null : value); }); // delete entry this._disabledInputs[this._disabledInputs.length] = target; }, /* Is the first field in a jQuery collection disabled as a datepicker? @param target element - the target input field or division or span @return boolean - true if disabled, false if enabled */ _isDisabledDatepicker: function(target) { if (!target) { return false; } for (var i = 0; i < this._disabledInputs.length; i++) { if (this._disabledInputs[i] == target) return true; } return false; }, /* Retrieve the instance data for the target control. @param target element - the target input field or division or span @return object - the associated instance data @throws error if a jQuery problem getting data */ _getInst: function(target) { try { return $.data(target, PROP_NAME); } catch (err) { throw 'Missing instance data for this datepicker'; } }, /* Update the settings for a date picker attached to an input field or division. @param target element - the target input field or division or span @param name object - the new settings to update or string - the name of the setting to change or @param value any - the new value for the setting (omit if above is an object) */ _optionDatepicker: function(target, name, value) { var settings = name || {}; if (typeof name == 'string') { settings = {}; settings[name] = value; } var inst = this._getInst(target); if (inst) { if (this._curInst == inst) { this._hideDatepicker(null); } extendRemove(inst.settings, settings); var date = new Date(); extendRemove(inst, {rangeStart: null, // start of range endDay: null, endMonth: null, endYear: null, // end of range selectedDay: date.getDate(), selectedMonth: date.getMonth(), selectedYear: date.getFullYear(), // starting point currentDay: date.getDate(), currentMonth: date.getMonth(), currentYear: date.getFullYear(), // current selection drawMonth: date.getMonth(), drawYear: date.getFullYear()}); // month being drawn this._updateDatepicker(inst); } }, // change method deprecated _changeDatepicker: function(target, name, value) { this._optionDatepicker(target, name, value); }, /* Redraw the date picker attached to an input field or division. @param target element - the target input field or division or span */ _refreshDatepicker: function(target) { var inst = this._getInst(target); if (inst) { this._updateDatepicker(inst); } }, /* Set the dates for a jQuery selection. @param target element - the target input field or division or span @param date Date - the new date @param endDate Date - the new end date for a range (optional) */ _setDateDatepicker: function(target, date, endDate) { var inst = this._getInst(target); if (inst) { this._setDate(inst, date, endDate); this._updateDatepicker(inst); this._updateAlternate(inst); } }, /* Get the date(s) for the first entry in a jQuery selection. @param target element - the target input field or division or span @return Date - the current date or Date[2] - the current dates for a range */ _getDateDatepicker: function(target) { var inst = this._getInst(target); if (inst && !inst.inline) this._setDateFromField(inst); return (inst ? this._getDate(inst) : null); }, /* Handle keystrokes. */ _doKeyDown: function(event) { var inst = $.datepicker._getInst(event.target); var handled = true; var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); inst._keyEvent = true; if ($.datepicker._datepickerShowing) switch (event.keyCode) { case 9: $.datepicker._hideDatepicker(null, ''); break; // hide on tab out case 13: var sel = $('td.' + $.datepicker._dayOverClass + ', td.' + $.datepicker._currentClass, inst.dpDiv); if (sel[0]) $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); else $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration')); return false; // don't submit the form break; // select the value on enter case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration')); break; // hide on escape case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? -$.datepicker._get(inst, 'stepBigMonths') : -$.datepicker._get(inst, 'stepMonths')), 'M'); break; // previous month/year on page up/+ ctrl case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? +$.datepicker._get(inst, 'stepBigMonths') : +$.datepicker._get(inst, 'stepMonths')), 'M'); break; // next month/year on page down/+ ctrl case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); handled = event.ctrlKey || event.metaKey; break; // clear on ctrl or command +end case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); handled = event.ctrlKey || event.metaKey; break; // current on ctrl or command +home case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); handled = event.ctrlKey || event.metaKey; // -1 day on ctrl or command +left if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? -$.datepicker._get(inst, 'stepBigMonths') : -$.datepicker._get(inst, 'stepMonths')), 'M'); // next month/year on alt +left on Mac break; case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); handled = event.ctrlKey || event.metaKey; break; // -1 week on ctrl or command +up case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); handled = event.ctrlKey || event.metaKey; // +1 day on ctrl or command +right if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? +$.datepicker._get(inst, 'stepBigMonths') : +$.datepicker._get(inst, 'stepMonths')), 'M'); // next month/year on alt +right break; case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); handled = event.ctrlKey || event.metaKey; break; // +1 week on ctrl or command +down default: handled = false; } else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home $.datepicker._showDatepicker(this); else { handled = false; } if (handled) { event.preventDefault(); event.stopPropagation(); } }, /* Filter entered characters - based on date format. */ _doKeyPress: function(event) { var inst = $.datepicker._getInst(event.target); if ($.datepicker._get(inst, 'constrainInput')) { var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); } }, /* Pop-up the date picker for a given input field. @param input element - the input field attached to the date picker or event - if triggered by focus */ _showDatepicker: function(input) { input = input.target || input; if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger input = $('input', input.parentNode)[0]; if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here return; var inst = $.datepicker._getInst(input); var beforeShow = $.datepicker._get(inst, 'beforeShow'); extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {})); $.datepicker._hideDatepicker(null, ''); $.datepicker._lastInput = input; $.datepicker._setDateFromField(inst); if ($.datepicker._inDialog) // hide cursor input.value = ''; if (!$.datepicker._pos) { // position below input $.datepicker._pos = $.datepicker._findPos(input); $.datepicker._pos[1] += input.offsetHeight; // add the height } var isFixed = false; $(input).parents().each(function() { isFixed |= $(this).css('position') == 'fixed'; return !isFixed; }); if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled $.datepicker._pos[0] -= document.documentElement.scrollLeft; $.datepicker._pos[1] -= document.documentElement.scrollTop; } var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; $.datepicker._pos = null; inst.rangeStart = null; // determine sizing offscreen inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); $.datepicker._updateDatepicker(inst); // fix width for dynamic number of date pickers // and adjust position before showing offset = $.datepicker._checkOffset(inst, offset, isFixed); inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', left: offset.left + 'px', top: offset.top + 'px'}); if (!inst.inline) { var showAnim = $.datepicker._get(inst, 'showAnim') || 'show'; var duration = $.datepicker._get(inst, 'duration'); var postProcess = function() { $.datepicker._datepickerShowing = true; if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4, height: inst.dpDiv.height() + 4}); }; if ($.effects && $.effects[showAnim]) inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); else inst.dpDiv[showAnim](duration, postProcess); if (duration == '') postProcess(); if (inst.input[0].type != 'hidden') inst.input[0].focus(); $.datepicker._curInst = inst; } }, /* Generate the date picker content. */ _updateDatepicker: function(inst) { var dims = {width: inst.dpDiv.width() + 4, height: inst.dpDiv.height() + 4}; var self = this; inst.dpDiv.empty().append(this._generateHTML(inst)) .find('iframe.ui-datepicker-cover'). css({width: dims.width, height: dims.height}) .end() .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a') .bind('mouseout', function(){ $(this).removeClass('ui-state-hover'); if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover'); if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover'); }) .bind('mouseover', function(){ if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) { $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); $(this).addClass('ui-state-hover'); if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover'); if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover'); } }) .end() .find('.' + this._dayOverClass + ' a') .trigger('mouseover') .end(); var numMonths = this._getNumberOfMonths(inst); var cols = numMonths[1]; var width = 17; if (cols > 1) { inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); } else { inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); } inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + 'Class']('ui-datepicker-multi'); inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + 'Class']('ui-datepicker-rtl'); if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst) $(inst.input[0]).focus(); }, /* Check positioning to remain on screen. */ _checkOffset: function(inst, offset, isFixed) { var dpWidth = inst.dpDiv.outerWidth(); var dpHeight = inst.dpDiv.outerHeight(); var inputWidth = inst.input ? inst.input.outerWidth() : 0; var inputHeight = inst.input ? inst.input.outerHeight() : 0; var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft(); var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop(); offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; // now check if datepicker is showing outside window viewport - move to a better place if so. offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0; offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0; return offset; }, /* Find an object's position on the screen. */ _findPos: function(obj) { while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) { obj = obj.nextSibling; } var position = $(obj).offset(); return [position.left, position.top]; }, /* Hide the date picker from view. @param input element - the input field attached to the date picker @param duration string - the duration over which to close the date picker */ _hideDatepicker: function(input, duration) { var inst = this._curInst; if (!inst || (input && inst != $.data(input, PROP_NAME))) return; if (inst.stayOpen) this._selectDate('#' + inst.id, this._formatDate(inst, inst.currentDay, inst.currentMonth, inst.currentYear)); inst.stayOpen = false; if (this._datepickerShowing) { duration = (duration != null ? duration : this._get(inst, 'duration')); var showAnim = this._get(inst, 'showAnim'); var postProcess = function() { $.datepicker._tidyDialog(inst); }; if (duration != '' && $.effects && $.effects[showAnim]) inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); else inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' : (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess); if (duration == '') this._tidyDialog(inst); var onClose = this._get(inst, 'onClose'); if (onClose) onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback this._datepickerShowing = false; this._lastInput = null; if (this._inDialog) { this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); if ($.blockUI) { $.unblockUI(); $('body').append(this.dpDiv); } } this._inDialog = false; } this._curInst = null; }, /* Tidy up after a dialog display. */ _tidyDialog: function(inst) { inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); }, /* Close date picker if clicked elsewhere. */ _checkExternalClick: function(event) { if (!$.datepicker._curInst) return; var $target = $(event.target); if (($target.parents('#' + $.datepicker._mainDivId).length == 0) && !$target.hasClass($.datepicker.markerClassName) && !$target.hasClass($.datepicker._triggerClass) && $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI)) $.datepicker._hideDatepicker(null, ''); }, /* Adjust one of the date sub-fields. */ _adjustDate: function(id, offset, period) { var target = $(id); var inst = this._getInst(target[0]); if (this._isDisabledDatepicker(target[0])) { return; } this._adjustInstDate(inst, offset + (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning period); this._updateDatepicker(inst); }, /* Action for current link. */ _gotoToday: function(id) { var target = $(id); var inst = this._getInst(target[0]); if (this._get(inst, 'gotoCurrent') && inst.currentDay) { inst.selectedDay = inst.currentDay; inst.drawMonth = inst.selectedMonth = inst.currentMonth; inst.drawYear = inst.selectedYear = inst.currentYear; } else { var date = new Date(); inst.selectedDay = date.getDate(); inst.drawMonth = inst.selectedMonth = date.getMonth(); inst.drawYear = inst.selectedYear = date.getFullYear(); } this._notifyChange(inst); this._adjustDate(target); }, /* Action for selecting a new month/year. */ _selectMonthYear: function(id, select, period) { var target = $(id); var inst = this._getInst(target[0]); inst._selectingMonthYear = false; inst['selected' + (period == 'M' ? 'Month' : 'Year')] = inst['draw' + (period == 'M' ? 'Month' : 'Year')] = parseInt(select.options[select.selectedIndex].value,10); this._notifyChange(inst); this._adjustDate(target); }, /* Restore input focus after not changing month/year. */ _clickMonthYear: function(id) { var target = $(id); var inst = this._getInst(target[0]); if (inst.input && inst._selectingMonthYear && !$.browser.msie) inst.input[0].focus(); inst._selectingMonthYear = !inst._selectingMonthYear; }, /* Action for selecting a day. */ _selectDay: function(id, month, year, td) { var target = $(id); if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { return; } var inst = this._getInst(target[0]); inst.selectedDay = inst.currentDay = $('a', td).html(); inst.selectedMonth = inst.currentMonth = month; inst.selectedYear = inst.currentYear = year; if (inst.stayOpen) { inst.endDay = inst.endMonth = inst.endYear = null; } this._selectDate(id, this._formatDate(inst, inst.currentDay, inst.currentMonth, inst.currentYear)); if (inst.stayOpen) { inst.rangeStart = this._daylightSavingAdjust( new Date(inst.currentYear, inst.currentMonth, inst.currentDay)); this._updateDatepicker(inst); } }, /* Erase the input field and hide the date picker. */ _clearDate: function(id) { var target = $(id); var inst = this._getInst(target[0]); inst.stayOpen = false; inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null; this._selectDate(target, ''); }, /* Update the input field with the selected date. */ _selectDate: function(id, dateStr) { var target = $(id); var inst = this._getInst(target[0]); dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); if (inst.input) inst.input.val(dateStr); this._updateAlternate(inst); var onSelect = this._get(inst, 'onSelect'); if (onSelect) onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback else if (inst.input) inst.input.trigger('change'); // fire the change event if (inst.inline) this._updateDatepicker(inst); else if (!inst.stayOpen) { this._hideDatepicker(null, this._get(inst, 'duration')); this._lastInput = inst.input[0]; if (typeof(inst.input[0]) != 'object') inst.input[0].focus(); // restore focus this._lastInput = null; } }, /* Update any alternate field to synchronise with the main field. */ _updateAlternate: function(inst) { var altField = this._get(inst, 'altField'); if (altField) { // update alternate field too var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); var date = this._getDate(inst); dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); $(altField).each(function() { $(this).val(dateStr); }); } }, /* Set as beforeShowDay function to prevent selection of weekends. @param date Date - the date to customise @return [boolean, string] - is this date selectable?, what is its CSS class? */ noWeekends: function(date) { var day = date.getDay(); return [(day > 0 && day < 6), '']; }, /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. @param date Date - the date to get the week for @return number - the number of the week within the year that contains this date */ iso8601Week: function(date) { var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7 firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year return $.datepicker.iso8601Week(checkDate); } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7; if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary return 1; } } return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date }, /* Parse a string value into a date object. See formatDate below for the possible formats. @param format string - the expected format of the date @param value string - the date in the above format @param settings Object - attributes include: shortYearCutoff number - the cutoff year for determining the century (optional) dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) dayNames string[7] - names of the days from Sunday (optional) monthNamesShort string[12] - abbreviated names of the months (optional) monthNames string[12] - names of the months (optional) @return Date - the extracted date value or null if value is blank */ parseDate: function (format, value, settings) { if (format == null || value == null) throw 'Invalid arguments'; value = (typeof value == 'object' ? value.toString() : value + ''); if (value == '') return null; var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; var year = -1; var month = -1; var day = -1; var doy = -1; var literal = false; // Check whether a format character is doubled var lookAhead = function(match) { var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); if (matches) iFormat++; return matches; }; // Extract a number from the string value var getNumber = function(match) { lookAhead(match); var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2))); var size = origSize; var num = 0; while (size > 0 && iValue < value.length && value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') { num = num * 10 + parseInt(value.charAt(iValue++),10); size--; } if (size == origSize) throw 'Missing number at position ' + iValue; return num; }; // Extract a name from the string value and convert to an index var getName = function(match, shortNames, longNames) { var names = (lookAhead(match) ? longNames : shortNames); var size = 0; for (var j = 0; j < names.length; j++) size = Math.max(size, names[j].length); var name = ''; var iInit = iValue; while (size > 0 && iValue < value.length) { name += value.charAt(iValue++); for (var i = 0; i < names.length; i++) if (name == names[i]) return i + 1; size--; } throw 'Unknown name at position ' + iInit; }; // Confirm that a literal character matches the string value var checkLiteral = function() { if (value.charAt(iValue) != format.charAt(iFormat)) throw 'Unexpected literal at position ' + iValue; iValue++; }; var iValue = 0; for (var iFormat = 0; iFormat < format.length; iFormat++) { if (literal) if (format.charAt(iFormat) == "'" && !lookAhead("'")) literal = false; else checkLiteral(); else switch (format.charAt(iFormat)) { case 'd': day = getNumber('d'); break; case 'D': getName('D', dayNamesShort, dayNames); break; case 'o': doy = getNumber('o'); break; case 'm': month = getNumber('m'); break; case 'M': month = getName('M', monthNamesShort, monthNames); break; case 'y': year = getNumber('y'); break; case '@': var date = new Date(getNumber('@')); year = date.getFullYear(); month = date.getMonth() + 1; day = date.getDate(); break; case "'": if (lookAhead("'")) checkLiteral(); else literal = true; break; default: checkLiteral(); } } if (year == -1) year = new Date().getFullYear(); else if (year < 100) year += new Date().getFullYear() - new Date().getFullYear() % 100 + (year <= shortYearCutoff ? 0 : -100); if (doy > -1) { month = 1; day = doy; do { var dim = this._getDaysInMonth(year, month - 1); if (day <= dim) break; month++; day -= dim; } while (true); } var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) throw 'Invalid date'; // E.g. 31/02/* return date; }, /* Standard date formats. */ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) COOKIE: 'D, dd M yy', ISO_8601: 'yy-mm-dd', RFC_822: 'D, d M y', RFC_850: 'DD, dd-M-y', RFC_1036: 'D, d M y', RFC_1123: 'D, d M yy', RFC_2822: 'D, d M yy', RSS: 'D, d M y', // RFC 822 TIMESTAMP: '@', W3C: 'yy-mm-dd', // ISO 8601 /* Format a date object into a string value. The format can be combinations of the following: d - day of month (no leading zero) dd - day of month (two digit) o - day of year (no leading zeros) oo - day of year (three digit) D - day name short DD - day name long m - month of year (no leading zero) mm - month of year (two digit) M - month name short MM - month name long y - year (two digit) yy - year (four digit) @ - Unix timestamp (ms since 01/01/1970) '...' - literal text '' - single quote @param format string - the desired format of the date @param date Date - the date value to format @param settings Object - attributes include: dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) dayNames string[7] - names of the days from Sunday (optional) monthNamesShort string[12] - abbreviated names of the months (optional) monthNames string[12] - names of the months (optional) @return string - the date in the above format */ formatDate: function (format, date, settings) { if (!date) return ''; var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; // Check whether a format character is doubled var lookAhead = function(match) { var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); if (matches) iFormat++; return matches; }; // Format a number, with leading zero if necessary var formatNumber = function(match, value, len) { var num = '' + value; if (lookAhead(match)) while (num.length < len) num = '0' + num; return num; }; // Format a name, short or long as requested var formatName = function(match, value, shortNames, longNames) { return (lookAhead(match) ? longNames[value] : shortNames[value]); }; var output = ''; var literal = false; if (date) for (var iFormat = 0; iFormat < format.length; iFormat++) { if (literal) if (format.charAt(iFormat) == "'" && !lookAhead("'")) literal = false; else output += format.charAt(iFormat); else switch (format.charAt(iFormat)) { case 'd': output += formatNumber('d', date.getDate(), 2); break; case 'D': output += formatName('D', date.getDay(), dayNamesShort, dayNames); break; case 'o': var doy = date.getDate(); for (var m = date.getMonth() - 1; m >= 0; m--) doy += this._getDaysInMonth(date.getFullYear(), m); output += formatNumber('o', doy, 3); break; case 'm': output += formatNumber('m', date.getMonth() + 1, 2); break; case 'M': output += formatName('M', date.getMonth(), monthNamesShort, monthNames); break; case 'y': output += (lookAhead('y') ? date.getFullYear() : (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); break; case '@': output += date.getTime(); break; case "'": if (lookAhead("'")) output += "'"; else literal = true; break; default: output += format.charAt(iFormat); } } return output; }, /* Extract all possible characters from the date format. */ _possibleChars: function (format) { var chars = ''; var literal = false; for (var iFormat = 0; iFormat < format.length; iFormat++) if (literal) if (format.charAt(iFormat) == "'" && !lookAhead("'")) literal = false; else chars += format.charAt(iFormat); else switch (format.charAt(iFormat)) { case 'd': case 'm': case 'y': case '@': chars += '0123456789'; break; case 'D': case 'M': return null; // Accept anything case "'": if (lookAhead("'")) chars += "'"; else literal = true; break; default: chars += format.charAt(iFormat); } return chars; }, /* Get a setting value, defaulting if necessary. */ _get: function(inst, name) { return inst.settings[name] !== undefined ? inst.settings[name] : this._defaults[name]; }, /* Parse existing date and initialise date picker. */ _setDateFromField: function(inst) { var dateFormat = this._get(inst, 'dateFormat'); var dates = inst.input ? inst.input.val() : null; inst.endDay = inst.endMonth = inst.endYear = null; var date = defaultDate = this._getDefaultDate(inst); var settings = this._getFormatConfig(inst); try { date = this.parseDate(dateFormat, dates, settings) || defaultDate; } catch (event) { this.log(event); date = defaultDate; } inst.selectedDay = date.getDate(); inst.drawMonth = inst.selectedMonth = date.getMonth(); inst.drawYear = inst.selectedYear = date.getFullYear(); inst.currentDay = (dates ? date.getDate() : 0); inst.currentMonth = (dates ? date.getMonth() : 0); inst.currentYear = (dates ? date.getFullYear() : 0); this._adjustInstDate(inst); }, /* Retrieve the default date shown on opening. */ _getDefaultDate: function(inst) { var date = this._determineDate(this._get(inst, 'defaultDate'), new Date()); var minDate = this._getMinMaxDate(inst, 'min', true); var maxDate = this._getMinMaxDate(inst, 'max'); date = (minDate && date < minDate ? minDate : date); date = (maxDate && date > maxDate ? maxDate : date); return date; }, /* A date may be specified as an exact value or a relative one. */ _determineDate: function(date, defaultDate) { var offsetNumeric = function(offset) { var date = new Date(); date.setDate(date.getDate() + offset); return date; }; var offsetString = function(offset, getDaysInMonth) { var date = new Date(); var year = date.getFullYear(); var month = date.getMonth(); var day = date.getDate(); var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; var matches = pattern.exec(offset); while (matches) { switch (matches[2] || 'd') { case 'd' : case 'D' : day += parseInt(matches[1],10); break; case 'w' : case 'W' : day += parseInt(matches[1],10) * 7; break; case 'm' : case 'M' : month += parseInt(matches[1],10); day = Math.min(day, getDaysInMonth(year, month)); break; case 'y': case 'Y' : year += parseInt(matches[1],10); day = Math.min(day, getDaysInMonth(year, month)); break; } matches = pattern.exec(offset); } return new Date(year, month, day); }; date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) : (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date))); date = (date && date.toString() == 'Invalid Date' ? defaultDate : date); if (date) { date.setHours(0); date.setMinutes(0); date.setSeconds(0); date.setMilliseconds(0); } return this._daylightSavingAdjust(date); }, /* Handle switch to/from daylight saving. Hours may be non-zero on daylight saving cut-over: > 12 when midnight changeover, but then cannot generate midnight datetime, so jump to 1AM, otherwise reset. @param date (Date) the date to check @return (Date) the corrected date */ _daylightSavingAdjust: function(date) { if (!date) return null; date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); return date; }, /* Set the date(s) directly. */ _setDate: function(inst, date, endDate) { var clear = !(date); var origMonth = inst.selectedMonth; var origYear = inst.selectedYear; date = this._determineDate(date, new Date()); inst.selectedDay = inst.currentDay = date.getDate(); inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth(); inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear(); if (origMonth != inst.selectedMonth || origYear != inst.selectedYear) this._notifyChange(inst); this._adjustInstDate(inst); if (inst.input) { inst.input.val(clear ? '' : this._formatDate(inst)); } }, /* Retrieve the date(s) directly. */ _getDate: function(inst) { var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : this._daylightSavingAdjust(new Date( inst.currentYear, inst.currentMonth, inst.currentDay))); return startDate; }, /* Generate the HTML for the current state of the date picker. */ _generateHTML: function(inst) { var today = new Date(); today = this._daylightSavingAdjust( new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time var isRTL = this._get(inst, 'isRTL'); var showButtonPanel = this._get(inst, 'showButtonPanel'); var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); var numMonths = this._getNumberOfMonths(inst); var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); var stepMonths = this._get(inst, 'stepMonths'); var stepBigMonths = this._get(inst, 'stepBigMonths'); var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); var minDate = this._getMinMaxDate(inst, 'min', true); var maxDate = this._getMinMaxDate(inst, 'max'); var drawMonth = inst.drawMonth - showCurrentAtPos; var drawYear = inst.drawYear; if (drawMonth < 0) { drawMonth += 12; drawYear--; } if (maxDate) { var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate())); maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { drawMonth--; if (drawMonth < 0) { drawMonth = 11; drawYear--; } } } inst.drawMonth = drawMonth; inst.drawYear = drawYear; var prevText = this._get(inst, 'prevText'); prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), this._getFormatConfig(inst))); var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? '
' + prevText + '' : (hideIfNoPrevNext ? '' : '' + prevText + '')); var nextText = this._get(inst, 'nextText'); nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), this._getFormatConfig(inst))); var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? '' + nextText + '' : (hideIfNoPrevNext ? '' : '' + nextText + '')); var currentText = this._get(inst, 'currentText'); var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); currentText = (!navigationAsDateFormat ? currentText : this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); var controls = (!inst.inline ? '' : ''); var buttonPanel = (showButtonPanel) ? '
' + (isRTL ? controls : '') + (this._isInRange(inst, gotoDate) ? '' : '') + (isRTL ? '' : controls) + '
' : ''; var firstDay = parseInt(this._get(inst, 'firstDay'),10); firstDay = (isNaN(firstDay) ? 0 : firstDay); var dayNames = this._get(inst, 'dayNames'); var dayNamesShort = this._get(inst, 'dayNamesShort'); var dayNamesMin = this._get(inst, 'dayNamesMin'); var monthNames = this._get(inst, 'monthNames'); var monthNamesShort = this._get(inst, 'monthNamesShort'); var beforeShowDay = this._get(inst, 'beforeShowDay'); var showOtherMonths = this._get(inst, 'showOtherMonths'); var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; var endDate = inst.endDay ? this._daylightSavingAdjust( new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate; var defaultDate = this._getDefaultDate(inst); var html = ''; for (var row = 0; row < numMonths[0]; row++) { var group = ''; for (var col = 0; col < numMonths[1]; col++) { var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); var cornerClass = ' ui-corner-all'; var calender = ''; if (isMultiMonth) { calender += '
'; } calender += '
' + (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers '
' + ''; var thead = ''; for (var dow = 0; dow < 7; dow++) { // days of the week var day = (dow + firstDay) % 7; thead += '= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' + '' + dayNamesMin[day] + ''; } calender += thead + ''; var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows calender += ''; var tbody = ''; for (var dow = 0; dow < 7; dow++) { // create date picker days var daySettings = (beforeShowDay ? beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); var otherMonth = (printDate.getMonth() != drawMonth); var unselectable = otherMonth || !daySettings[0] || (minDate && printDate < minDate) || (maxDate && printDate > maxDate); tbody += ''; // display for this month printDate.setDate(printDate.getDate() + 1); printDate = this._daylightSavingAdjust(printDate); } calender += tbody + ''; } drawMonth++; if (drawMonth > 11) { drawMonth = 0; drawYear++; } calender += '
' + // actions (otherMonth ? (showOtherMonths ? printDate.getDate() : ' ') : // display for other months (unselectable ? '' + printDate.getDate() + '' : '' + printDate.getDate() + '')) + '
' + (isMultiMonth ? '
' + ((numMonths[0] > 0 && col == numMonths[1]-1) ? '
' : '') : ''); group += calender; } html += group; } html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ? '' : ''); inst._keyEvent = false; return html; }, /* Generate the month and year header. */ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, selectedDate, secondary, monthNames, monthNamesShort) { minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate); var changeMonth = this._get(inst, 'changeMonth'); var changeYear = this._get(inst, 'changeYear'); var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); var html = '
'; var monthHtml = ''; // month selection if (secondary || !changeMonth) monthHtml += '' + monthNames[drawMonth] + ' '; else { var inMinYear = (minDate && minDate.getFullYear() == drawYear); var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); monthHtml += ''; } if (!showMonthAfterYear) html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? ' ' : ''); // year selection if (secondary || !changeYear) html += '' + drawYear + ''; else { // determine range of years to display var years = this._get(inst, 'yearRange').split(':'); var year = 0; var endYear = 0; if (years.length != 2) { year = drawYear - 10; endYear = drawYear + 10; } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') { year = drawYear + parseInt(years[0], 10); endYear = drawYear + parseInt(years[1], 10); } else { year = parseInt(years[0], 10); endYear = parseInt(years[1], 10); } year = (minDate ? Math.max(year, minDate.getFullYear()) : year); endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); html += ''; } if (showMonthAfterYear) html += (secondary || changeMonth || changeYear ? ' ' : '') + monthHtml; html += '
'; // Close datepicker_header return html; }, /* Adjust one of the date sub-fields. */ _adjustInstDate: function(inst, offset, period) { var year = inst.drawYear + (period == 'Y' ? offset : 0); var month = inst.drawMonth + (period == 'M' ? offset : 0); var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period == 'D' ? offset : 0); var date = this._daylightSavingAdjust(new Date(year, month, day)); // ensure it is within the bounds set var minDate = this._getMinMaxDate(inst, 'min', true); var maxDate = this._getMinMaxDate(inst, 'max'); date = (minDate && date < minDate ? minDate : date); date = (maxDate && date > maxDate ? maxDate : date); inst.selectedDay = date.getDate(); inst.drawMonth = inst.selectedMonth = date.getMonth(); inst.drawYear = inst.selectedYear = date.getFullYear(); if (period == 'M' || period == 'Y') this._notifyChange(inst); }, /* Notify change of month/year. */ _notifyChange: function(inst) { var onChange = this._get(inst, 'onChangeMonthYear'); if (onChange) onChange.apply((inst.input ? inst.input[0] : null), [inst.selectedYear, inst.selectedMonth + 1, inst]); }, /* Determine the number of months to show. */ _getNumberOfMonths: function(inst) { var numMonths = this._get(inst, 'numberOfMonths'); return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); }, /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */ _getMinMaxDate: function(inst, minMax, checkRange) { var date = this._determineDate(this._get(inst, minMax + 'Date'), null); return (!checkRange || !inst.rangeStart ? date : (!date || inst.rangeStart > date ? inst.rangeStart : date)); }, /* Find the number of days in a given month. */ _getDaysInMonth: function(year, month) { return 32 - new Date(year, month, 32).getDate(); }, /* Find the day of the week of the first of a month. */ _getFirstDayOfMonth: function(year, month) { return new Date(year, month, 1).getDay(); }, /* Determines if we should allow a "next/prev" month display change. */ _canAdjustMonth: function(inst, offset, curYear, curMonth) { var numMonths = this._getNumberOfMonths(inst); var date = this._daylightSavingAdjust(new Date( curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1)); if (offset < 0) date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); return this._isInRange(inst, date); }, /* Is the given date in the accepted range? */ _isInRange: function(inst, date) { // during range selection, use minimum of selected date and range start var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust( new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay))); newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate); var minDate = newMinDate || this._getMinMaxDate(inst, 'min'); var maxDate = this._getMinMaxDate(inst, 'max'); return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate)); }, /* Provide the configuration settings for formatting/parsing. */ _getFormatConfig: function(inst) { var shortYearCutoff = this._get(inst, 'shortYearCutoff'); shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); return {shortYearCutoff: shortYearCutoff, dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; }, /* Format the given date for display. */ _formatDate: function(inst, day, month, year) { if (!day) { inst.currentDay = inst.selectedDay; inst.currentMonth = inst.selectedMonth; inst.currentYear = inst.selectedYear; } var date = (day ? (typeof day == 'object' ? day : this._daylightSavingAdjust(new Date(year, month, day))) : this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); } }); /* jQuery extend now ignores nulls! */ function extendRemove(target, props) { $.extend(target, props); for (var name in props) if (props[name] == null || props[name] == undefined) target[name] = props[name]; return target; }; /* Determine whether an object is an array. */ function isArray(a) { return (a && (($.browser.safari && typeof a == 'object' && a.length) || (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); }; /* Invoke the datepicker functionality. @param options string - a command, optionally followed by additional parameters or Object - settings for attaching new datepicker functionality @return jQuery object */ $.fn.datepicker = function(options){ /* Initialise the date picker. */ if (!$.datepicker.initialized) { $(document).mousedown($.datepicker._checkExternalClick). find('body').append($.datepicker.dpDiv); $.datepicker.initialized = true; } var otherArgs = Array.prototype.slice.call(arguments, 1); if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate')) return $.datepicker['_' + options + 'Datepicker']. apply($.datepicker, [this[0]].concat(otherArgs)); return this.each(function() { typeof options == 'string' ? $.datepicker['_' + options + 'Datepicker']. apply($.datepicker, [this].concat(otherArgs)) : $.datepicker._attachDatepicker(this, options); }); }; $.datepicker = new Datepicker(); // singleton instance $.datepicker.initialized = false; $.datepicker.uuid = new Date().getTime(); $.datepicker.version = "1.7"; // Workaround for #4055 // Add another global to avoid noConflict issues with inline event handlers window.DP_jQuery = $; })(jQuery); ================================================ FILE: clover/clover-admin/src/main/webapp/logList.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@page import="com.gome.clover.common.mongodb.DBTableInfo" %> <%@ page import="com.gome.clover.common.mongodb.MongoDBUtil" %> <%@ page import="com.gome.clover.common.tools.StringUtil" %> <%@ page import="com.mongodb.BasicDBObject" %> <%@ page import="com.mongodb.DBCursor" %> <%@ page import="com.mongodb.DBObject" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; String qSystemId = request.getParameter("qSystemId"); String qJobKey = request.getParameter("qJobKey"); String qIp = request.getParameter("qIp"); String qExecMethod = request.getParameter("qExecMethod"); DBObject condition = new BasicDBObject(); if (!StringUtil.isEmpty(qSystemId)) condition.put(DBTableInfo.COL_SYSTEM_ID, qSystemId); if (!StringUtil.isEmpty(qJobKey)) condition.put(DBTableInfo.COL_JOB_KEY, qJobKey); if (!StringUtil.isEmpty(qIp)) condition.put(DBTableInfo.COL_IP, qIp); if (!StringUtil.isEmpty(qExecMethod)) condition.put(DBTableInfo.COL_EXEC_METHOD, qExecMethod); DBCursor dbCursor; if(StringUtil.isEmpty(qSystemId) && StringUtil.isEmpty(qJobKey) && StringUtil.isEmpty(qIp) && StringUtil.isEmpty(qExecMethod)){ dbCursor = null; }else { dbCursor = MongoDBUtil.INSTANCE.findByCondition(condition,DBTableInfo.TBL_CLOVER_LOG); } %>
System Id: "> ip: "> Job Key: "> Exec Method: ">
<% if(null!=dbCursor && dbCursor.size()>0){ int index =0; while (dbCursor.hasNext()) { DBObject tempDBObject = dbCursor.next(); System.err.println("index:"+(index++)+" tempDBObject "+tempDBObject); %> <% } }else { %> <% } %>
SystemId ip JobKey ExecMethod ExecResult ExecTime ts 操作
<%=tempDBObject.get(DBTableInfo.COL_SYSTEM_ID)%> <%=tempDBObject.get(DBTableInfo.COL_IP)%> <%=tempDBObject.get(DBTableInfo.COL_JOB_KEY)%> <%=(tempDBObject.get(DBTableInfo.COL_EXEC_METHOD)).toString().substring(0, 50)%> <%=(tempDBObject.get(DBTableInfo.COL_EXEC_RESULT)).toString().substring(0,50)%> <%=tempDBObject.get(DBTableInfo.COL_EXEC_TIME)%> <%=tempDBObject.get(DBTableInfo.COL_TS)%> 查看
暂无相关记录
================================================ FILE: clover/clover-admin/src/main/webapp/login.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
员工登录页面
*员工账号: " class="span2" />
*密码:  
================================================ FILE: clover/clover-admin/src/main/webapp/monitorList.jsp ================================================ <%@ page import="com.gome.clover.common.tools.CommonConstants" %> <%@ page import="com.gome.clover.common.tools.IpUtil" %> <%@ page import="com.gome.clover.common.tools.PropertiesUtil" %> <%@ page import="com.gome.clover.common.tools.StringUtil" %> <%@ page import="com.gome.clover.common.zk.ZKManager" %> <%@ page import="com.mongodb.BasicDBObject" %> <%@ page import="com.mongodb.util.JSON" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; ZKManager zkManager = new ZKManager(PropertiesUtil.loadProperties()); String serverDataStr = zkManager.getData(CommonConstants.ZK_ROOT_PATH + "/monitor/server/"+ IpUtil.getLocalIP()); String cloverServerStatus = "0"; String cloverServerTS = ""; String serverHeartBeatStatus = "0"; String serverHeartBeatTS = ""; String monitorHeartBeatStatus = "0"; String monitorHeartBeatTS = ""; if(!StringUtil.isEmpty(serverDataStr)){ BasicDBObject serverData = (BasicDBObject) JSON.parse(serverDataStr); if(serverData.containsField("cloverServerStatus")){ cloverServerStatus = (String) serverData.get("cloverServerStatus"); } if(serverData.containsField("cloverServerTS")){ cloverServerTS = (String) serverData.get("cloverServerTS"); } if(serverData.containsField("serverHeartBeatStatus")){ serverHeartBeatStatus = (String) serverData.get("serverHeartBeatStatus"); } if(serverData.containsField("serverHeartBeatTS")){ serverHeartBeatTS = (String) serverData.get("serverHeartBeatTS"); } if(serverData.containsField("monitorHeartBeatStatus")){ monitorHeartBeatStatus = (String) serverData.get("monitorHeartBeatStatus"); } if(serverData.containsField("monitorHeartBeatTS")){ monitorHeartBeatTS = (String) serverData.get("monitorHeartBeatTS"); } } zkManager.close(); %>
Service Name Service Status ts comment 操作
Clover Server <% if("0".equals(cloverServerStatus)){ %> 未启动 <% } else if("1".equals(cloverServerStatus)){ %> 已启动 <% }else { %> 未启动 <% } %> <%=cloverServerTS%> 启动 Clover Server <% if("0".equals(cloverServerStatus)){ %> 启动 <% } else if("1".equals(cloverServerStatus)){ %> 停止 <% }else { %> 启动 <% } %>
Server Heart Beat <% if("0".equals(serverHeartBeatStatus)){ %> 未启动 <% } else if("1".equals(serverHeartBeatStatus)){ %> 已启动 <% }else { %> 未启动 <% } %> <%=serverHeartBeatTS%> 启动 Server Heart Beat,每隔指定(默认:2分钟)时间发送内存、cpu、活跃线程数等信息到ZK <% if("0".equals(serverHeartBeatStatus)){ %> 启动 <% } else if("1".equals(serverHeartBeatStatus)){ %> 停止 <% }else { %> 启动 <% } %>
Monitor Heart Beat <% if("0".equals(monitorHeartBeatStatus)){ %> 未启动 <% } else if("1".equals(monitorHeartBeatStatus)){ %> 已启动 <% }else { %> 未启动 <% } %> <%=monitorHeartBeatTS%> 启动 Monitor Heart Beat,监控所有server节点,当server中一台不可用, 将会把不可用server中的所有job信息转移到另一台可用server中;当所有server不可用,那就报警通知相关server负责人 <% if("0".equals(monitorHeartBeatStatus)){ %> 启动 <% } else if("1".equals(monitorHeartBeatStatus)){ %> 停止 <% }else { %> 启动 <% } %>
================================================ FILE: clover/clover-admin/src/main/webapp/register.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%-- --%>
员工注册页面
*员工账号:
*员工名:
*密码:  
*性别:
*手机号码:
*邮箱:
身份证号码:
生日: '})" readonly class="span2" />
*地址:
*邮编:
================================================ FILE: clover/clover-admin/src/main/webapp/zkList.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ page import="com.gome.clover.common.tools.CommonConstants" %> <%@ page import="com.gome.clover.common.tools.StringUtil" %> <%@ page import="com.gome.clover.common.zk.ZKUtil" %> <%@ page import="com.mongodb.BasicDBObject" %> <%@ page import="org.apache.curator.framework.CuratorFramework" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path; String qDest = request.getParameter("qDest"); String qHostName = request.getParameter("qHostName"); String qIp = request.getParameter("qIp"); String qJobClass = request.getParameter("qJobClass"); String qPort = request.getParameter("qPort"); CuratorFramework curatorFramework = ZKUtil.create(); if (!curatorFramework.isStarted()) curatorFramework.start(); String serverPathStr = CommonConstants.ZK_ROOT_PATH + "/" + CommonConstants.MODULE_TYPE_SERVER; String clientPathStr = CommonConstants.ZK_ROOT_PATH + "/" + CommonConstants.MODULE_TYPE_CLIENT; List serverNodeList = null; List clientNodeList = null; if ("1".equals(qDest)) { serverNodeList = ZKUtil.getChilds(curatorFramework, serverPathStr); } else if ("2".equals(qDest)) { clientNodeList = ZKUtil.getChilds(curatorFramework, clientPathStr); } else { serverNodeList = ZKUtil.getChilds(curatorFramework, serverPathStr); clientNodeList = ZKUtil.getChilds(curatorFramework, clientPathStr); } List filterServerDataList = null; if (null != serverNodeList && serverNodeList.size() > 0) { filterServerDataList = new ArrayList(); for (int i = 0; (serverNodeList != null) && (i < serverNodeList.size()); i++) { String id = (String) serverNodeList.get(i); String c = ZKUtil.getData(curatorFramework, serverPathStr + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) com.mongodb.util.JSON.parse(c); String tempId = (String) record.get("id"); String tempPort = (String) record.get("port"); String tempIp = (String) record.get("ip"); if (!StringUtil.isEmpty(qHostName) && !StringUtil.isEmpty(qIp) && !StringUtil.isEmpty(qPort)) { if (tempId.contains(qHostName) && tempIp.equals(qIp) && tempPort.equals(qPort)) { filterServerDataList.add(record); } } else if (!StringUtil.isEmpty(qHostName) && !StringUtil.isEmpty(qIp) && StringUtil.isEmpty(qPort)) { if (tempId.contains(qHostName) && tempIp.equals(qIp)) { filterServerDataList.add(record); } } else if (!StringUtil.isEmpty(qHostName) && StringUtil.isEmpty(qIp) && StringUtil.isEmpty(qPort)) { if (tempId.contains(qHostName)) { filterServerDataList.add(record); } } else { filterServerDataList.add(record); } } } List filterClientDataList = null; if (null != clientNodeList && clientNodeList.size() > 0) { filterClientDataList = new ArrayList(); for (int i = 0; (clientNodeList != null) && (i < clientNodeList.size()); i++) { String id = (String) clientNodeList.get(i); String c = ZKUtil.getData(curatorFramework, clientPathStr + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) com.mongodb.util.JSON.parse(c); String tempId = (String) record.get("id"); String tempPort = (String) record.get("port"); String tempIp = (String) record.get("ip"); List jobClassList = (List) record.get("jobClass"); if (!StringUtil.isEmpty(qHostName) && !StringUtil.isEmpty(tempIp) && !StringUtil.isEmpty(tempPort) && (null != jobClassList && jobClassList.size() > 0)) { if (tempId.contains(qHostName) && tempIp.equals(qIp) && tempPort.equals(qPort) && jobClassList.contains(qJobClass)) { filterClientDataList.add(record); } } else if (!StringUtil.isEmpty(tempId) && !StringUtil.isEmpty(tempIp)&& !StringUtil.isEmpty(tempPort) && (null == jobClassList || jobClassList.size() == 0)) { if (tempId.contains(qHostName) && tempIp.equals(qIp) && tempPort.equals(qPort)) { filterClientDataList.add(record); } } else if (!StringUtil.isEmpty(tempId) && StringUtil.isEmpty(tempIp) && StringUtil.isEmpty(tempPort) && (null == jobClassList || jobClassList.size() == 0)) { if (tempId.contains(qHostName) && tempIp.equals(qIp)) { filterClientDataList.add(record); } } else if (!StringUtil.isEmpty(tempId) && StringUtil.isEmpty(tempIp) && StringUtil.isEmpty(tempPort) && (null == jobClassList || jobClassList.size() == 0)) { if (tempId.contains(qHostName)) { filterClientDataList.add(record); } } else { filterClientDataList.add(record); } } } curatorFramework.close(); %>
Host Name: "/> ip: "/> Job Class: "/> port: "/>
<%-- 启动zeromq--%>
<%-- --%> <% if (null != filterServerDataList && filterServerDataList.size() > 0) { for (BasicDBObject tempServerData : filterServerDataList) { %> <%-- --%> <% } } else { %> <% } %>
Server Name ip port ts Mem Ratio Cpu Ratio Total Thread操作
<%=(String) tempServerData.get("id")%> <%=tempServerData.get("ip")%> <%=tempServerData.get("port")%> <%=tempServerData.get("ts")%> <%=tempServerData.get("memRatio")%> <%=tempServerData.get("cpuRatio")%> <%=tempServerData.get("totalThread")%> 更新 删除
暂无相关记录
<%-- --%> <% if (null != filterClientDataList && filterClientDataList.size() > 0) { for (BasicDBObject tempClientData : filterClientDataList) { %> <%-- --%> <% } } else { %> <% } %>
Client Name Job Class ip port ts Mem Ratio Cpu Ratio Total Thread操作
<%=(String) tempClientData.get("id")%> <%=(tempClientData.get("jobClass")).toString().substring(0, 80)%> <%=(String) tempClientData.get("ip")%> <%=(String) tempClientData.get("port")%> <%=(String) tempClientData.get("ts")%> <%= tempClientData.get("memRatio")%> <%= tempClientData.get("cpuRatio")%> <%= tempClientData.get("totalThread")%> 更新 删除
暂无相关记录
================================================ FILE: clover/clover-admin/src/test/java/TestAnnotationWithSpring.java ================================================ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/30 * Time: 19:58 */ @ContextConfiguration({"classpath:spring/spring-config.xml"}) @RunWith(SpringJUnit4ClassRunner.class) public class TestAnnotationWithSpring { @Test public void testInit(){ System.err.println("testInit"); } } ================================================ FILE: clover/clover-client/pom.xml ================================================ 4.0.0 com.gome clover 1.0 com.gome clover-client ${clover.version} jar clover-client-${clover.version} src/main/resources true com.gome clover-core ${clover.version} org.quartz-scheduler quartz 2.2.1 org.mongodb mongo-java-driver 2.11.3 com.alibaba fastjson 1.1.31 org.zeromq jeromq 0.3.4 javax.mail mail 1.5.0-b01 org.apache.curator curator-framework 2.7.0 org.springframework spring-context 3.2.4.RELEASE org.springframework spring-webmvc 3.2.4.RELEASE org.xerial.snappy snappy-java 1.1.1.6 org.apache.zookeeper zookeeper 3.4.5 commons commons-lang3 3.1 org.apache.commons com.springsource.org.apache.commons.codec 1.6.0 javax.servlet servlet-api 2.4 provided ================================================ FILE: clover/clover-client/src/main/java/com/gome/bg/clover/client/job/LocalJob.java ================================================ package com.gome.bg.clover.client.job; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Local Job * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/2 * Time: 10:33 */ public abstract class LocalJob implements Job { private static final Logger logger = LoggerFactory.getLogger(LocalJob.class); @Override public void execute(JobExecutionContext context) throws JobExecutionException { try { executeJob(context); MongoDBUtil.updateOrDeleteDB(context); } catch (Exception e) { logger.error("LocalJob-->>execute(" + JSON.toJSONString(context) + ") error", e); String execMethod = "LocalJob-->>execute(" + JSON.toJSONString(context) + ")"; String execResult = "LocalJob-->>execute(" + JSON.toJSONString(context) + ") error," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } public abstract void executeJob(JobExecutionContext context); } ================================================ FILE: clover/clover-client/src/main/java/com/gome/bg/clover/client/job/RemoteJob.java ================================================ package com.gome.bg.clover.client.job; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Remote Job * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/2 * Time: 10:33 */ public abstract class RemoteJob implements Job { private static final Logger logger = LoggerFactory.getLogger(RemoteJob.class); @Override public void execute(JobExecutionContext context) throws JobExecutionException { try { executeJob(context); } catch (Exception e) { logger.error("RemoteJob-->>execute(" + JSON.toJSONString(context) + ") error", e); String execMethod = "RemoteJob-->>execute(" + JSON.toJSONString(context) + ")"; String execResult = "RemoteJob-->>execute(" + JSON.toJSONString(context) + ") error," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } public abstract void executeJob(JobExecutionContext context); } ================================================ FILE: clover/clover-client/src/main/java/com/gome/bg/clover/client/job/SimpleJob.java ================================================ package com.gome.bg.clover.client.job; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Simple Job * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/2 * Time: 10:33 */ public abstract class SimpleJob implements Job { private static final Logger logger = LoggerFactory.getLogger(SimpleJob.class); @Override public void execute(JobExecutionContext context) throws JobExecutionException { try { executeJob(context); MongoDBUtil.updateOrDeleteDB(context); } catch (Exception e) { logger.error("SimpleJob-->>execute(" + JSON.toJSONString(context) + ") error", e); String execMethod = "SimpleJob-->>execute(" + JSON.toJSONString(context) + ")"; String execResult = "SimpleJob-->>execute(" + JSON.toJSONString(context) + ") error," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } public abstract void executeJob(JobExecutionContext context); } ================================================ FILE: clover/clover-client/src/main/java/com/gome/bg/clover/client/job/TransactionJob.java ================================================ package com.gome.bg.clover.client.job; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Transaction Job * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/2 * Time: 10:33 */ public abstract class TransactionJob implements Job { private static final Logger logger = LoggerFactory.getLogger(TransactionJob.class); @Override public void execute(JobExecutionContext context) throws JobExecutionException { try { executeJob(context); } catch (Exception e) { logger.error("TransactionJob-->>execute(" + JSON.toJSONString(context) + ") error", e); String execMethod = "TransactionJob-->>execute(" + JSON.toJSONString(context) + ")"; String execResult = "TransactionJob-->>execute(" + JSON.toJSONString(context) + ") error," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } public abstract void executeJob(JobExecutionContext context); } ================================================ FILE: clover/clover-client/src/main/java/com/gome/bg/clover/client/module/SchedulerClientInitial.java ================================================ package com.gome.bg.clover.client.module; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.ConfigUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.core.module.ModuleSchedulerClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Scheduler 客户端 初始化 Servlet * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ @Component("SchedulerClientInitial") public class SchedulerClientInitial extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(SchedulerClientInitial.class); public static String token = ConfigUtil.getInstance("job.properties").getValue("token"); public static String systemId = ConfigUtil.getInstance("job.properties").getValue("systemId"); public static String jobClassStr = ConfigUtil.getInstance("job.properties").getValue("jobClassStr"); public static String isRegisterToZK = ConfigUtil.getInstance("job.properties").getValue("isRegisterToZK"); public static String isStartupNetty = ConfigUtil.getInstance("job.properties").getValue("isStartupNetty"); @Override public void init(ServletConfig config) throws ServletException { super.init(); logger.error("token>>"+token+"*****systemId>>"+systemId+"*****jobClassStr>>"+jobClassStr+"*****isRegisterToZK>>"+isRegisterToZK+"*****isStartupNetty>>"+isStartupNetty); // String token = config.getInitParameter("token"); String token = this.token; if (!StringUtil.isEmpty(token)) { //String systemId = config.getInitParameter("systemId"); String systemId = this.systemId; if(StringUtil.isEmpty(systemId)) throw new RuntimeException("SchedulerClientInitial-->>init(config) systemId null "); List jobClassList = null; //String jobClassStr = config.getInitParameter("jobClassStr"); String jobClassStr = this.jobClassStr; boolean isRegisterToZK = true; //默认是启动的 //String isRegisterToZKStr = config.getInitParameter("isRegisterToZK"); String isRegisterToZKStr = this.isRegisterToZK; if(!StringUtil.isEmpty(isRegisterToZKStr)){ isRegisterToZK = Boolean.valueOf(isRegisterToZKStr); } //String isStartupNetty = config.getInitParameter("isStartupNetty"); String isStartupNetty = this.isStartupNetty; boolean isStartupNe = true; //默认是启动的 if(!StringUtil.isEmpty(isStartupNetty)){ isStartupNe = Boolean.valueOf(isStartupNetty); } if(!StringUtil.isEmpty(jobClassStr)){ String jobClassStrs[] = jobClassStr.split(","); jobClassList = new ArrayList(); for(String tempJobClass : jobClassStrs){ if(!StringUtil.isEmpty(tempJobClass)){ jobClassList.add(tempJobClass) ; } } } //String port = config.getInitParameter("port"); ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); client.startup(jobClassList, isRegisterToZK, isStartupNe, String.valueOf(CommonConstants.NETTY_SERVER_PORT),systemId,token); }else { throw new RuntimeException("SchedulerClientInitial-->>init(config) token null "); } logger.info("SchedulerClientInitial-->>init(config)......"); } public void init(List jobClassList, boolean isRegisterToZK, boolean isStartupMQ,String port,String systemId,String token) throws ServletException { try { ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); client.startup(jobClassList,isRegisterToZK,isStartupMQ,port,systemId,token); } catch (Exception e) { String execMethod = "SchedulerClientInitial-->>init("+ JSON.toJSONString(jobClassList)+")"; String execResult = "SchedulerClientInitial-->>init("+JSON.toJSONString(jobClassList)+") error ,"+e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } logger.info("SchedulerClientInitial-->>init("+JSON.toJSONString(jobClassList)+")......"); } /** * @see HttpServlet#HttpServlet() */ public SchedulerClientInitial() { super(); } } ================================================ FILE: clover/clover-common/pom.xml ================================================ 4.0.0 com.gome clover 1.0 com.gome clover-common ${clover.version} jar clover-common-${clover.version} src/main/resources true ================================================ FILE: clover/clover-core/pom.xml ================================================ 4.0.0 com.gome clover 1.0 clover-core ${clover.version} jar clover-core-${clover.version} src/main/resources true org.quartz-scheduler quartz org.mongodb mongo-java-driver com.alibaba fastjson javax.servlet servlet-api org.apache.httpcomponents com.springsource.org.apache.httpcomponents.httpclient org.apache.httpcomponents com.springsource.org.apache.httpcomponents.httpcore io.netty netty-all com.alibaba.rocketmq rocketmq-client org.apache.commons com.springsource.org.apache.commons.codec org.zeromq jeromq javax.mail mail redis.clients jedis com.sun tools org.apache.curator curator-framework org.springframework spring-context com.typesafe.akka akka-actor com.typesafe.akka akka-zeromq_2.10 org.xerial.snappy snappy-java commons commons-lang3 ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/annotation/CloverConfigBeanDefinitionParser.java ================================================ package com.gome.clover.common.annotation; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.core.module.ModuleSchedulerClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Clover Config Bean Definition Parser * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/3 * Time: 17:53 */ public class CloverConfigBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { private static final Logger logger = LoggerFactory.getLogger(CloverConfigBeanDefinitionParser.class); private static final String CLOVERJOB_ANNOTATION = "CLOVERJOB_ANNOTATION"; private static final String CLOVER_CONFIG_INIT = "CLOVER_CONFIG_INIT"; private volatile boolean init = false; @Override protected Class getBeanClass(Element element) { return CloverConfigInit.class; } @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, parserContext, builder); if (init) { throw new RuntimeException("一个应用中只允许配置一个"); } builder.setInitMethodName("init"); builder.setDestroyMethodName("destroy"); builder.addPropertyValue("element", element); doParseJobConfig(element); if (!parserContext.getRegistry().containsBeanDefinition(CLOVERJOB_ANNOTATION)) { RootBeanDefinition annotation = new RootBeanDefinition(CloverJobAnnotationBean.class); parserContext.getRegistry().registerBeanDefinition(CLOVERJOB_ANNOTATION, annotation); } init = true; } private void doParseJobConfig(Element element) { //解析 spring clover config:config标签配置元素 开始 String token = element.getAttribute("token"); if (!StringUtil.isEmpty(token) && CommonConstants.token.equals(token)) { String systemId = element.getAttribute("systemId"); if(StringUtil.isEmpty(systemId)) throw new RuntimeException("CloverConfigBeanDefinitionParser-->>doParseJobConfig(element) systemId null "); String port = element.getAttribute("port"); boolean isStartupNetty = Boolean.valueOf(element.getAttribute("isStartupNetty")); boolean isRegisterToZK = Boolean.valueOf(element.getAttribute("isRegisterToZK")); String jobClassName = element.getAttribute("jobClassName"); if (StringUtil.isEmpty(jobClassName)) { logger.error("CloverConfigBeanDefinitionParser-->>doParseJobConfig(element) jobClassName can not null "); throw new RuntimeException("CloverConfigBeanDefinitionParser-->>doParseJobConfig(element) jobClassName can not null "); } else { List jobClassList = new ArrayList(); if (!StringUtil.isEmpty(jobClassName) && !jobClassName.contains(",")) { String jobClassNames[] = jobClassName.split(","); for (String jobClassNameStr : jobClassNames) { if (!StringUtil.isEmpty(jobClassNameStr)) { jobClassList.add(jobClassNameStr.trim()); } } } else if (!StringUtil.isEmpty(jobClassName) && jobClassName.contains(",")) { logger.error("CloverConfigBeanDefinitionParser-->>doParseJobConfig(element) jobClassName can not include chinese comma"); throw new RuntimeException("CloverConfigBeanDefinitionParser-->>doParseJobConfig(element) jobClassName can not include chinese comma"); } ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); client.startup(jobClassList, isRegisterToZK, isStartupNetty, port,systemId,token); } } else if (!StringUtil.isEmpty(token) && !CommonConstants.token.equals(token)) { throw new RuntimeException("CloverConfigBeanDefinitionParser-->>doParseJobConfig() token wrong "); } else if (StringUtil.isEmpty(token)) { throw new RuntimeException("CloverConfigBeanDefinitionParser-->>doParseJobConfig() token null "); } //解析 spring cloverjob:config标签配置元素 结束 } @Override protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException { return CLOVER_CONFIG_INIT; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/annotation/CloverConfigInit.java ================================================ package com.gome.clover.common.annotation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/10 * Time: 17:32 */ public class CloverConfigInit { private static final Logger logger = LoggerFactory.getLogger(CloverConfigInit.class); private Element element; @PostConstruct public void init() { System.err.println("CloverConfigInit--->>>init()....."); } @PreDestroy public void destroy() { } public void setElement(Element element) { this.element = element; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/annotation/CloverJobAnnotation.java ================================================ package com.gome.clover.common.annotation; import com.gome.clover.core.job.ClientJob; import org.quartz.JobKey; import java.lang.annotation.*; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Clover Job Annotation * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 15:09 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface CloverJobAnnotation { /** * job 所属组 * @return */ String jobGroup() default JobKey.DEFAULT_GROUP; /** * job 名称 * @return */ String jobName() default ""; /** * job类型 LOCAL,REMOTE * @return */ ClientJob.JobType jobType() default ClientJob.JobType.LOCAL; /** * job 执行类型 ADD,UPDATE,DELETE * @return */ ClientJob.ExecuteType executeType() default ClientJob.ExecuteType.ADD; /** * job 执行策略 HASH,SYSTEM_CAPACITY * @return */ ClientJob.JobStrategy jobStrategy() default ClientJob.JobStrategy.HASH; /** * job 执行时间 * @return */ String startTime() default ""; /** * job cron执行表达式 * @return */ String cronExpression() default ""; /** * 指定客户端IP地址 * @return */ String fixedClientIps() default ""; /** * 指定服务端IP地址 * @return */ String fixedServerIps() default ""; } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/annotation/CloverJobAnnotationBean.java ================================================ package com.gome.clover.common.annotation; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; import org.quartz.Job; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.stereotype.Component; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Clover Job Annotation Bean * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 15:09 */ @Component public class CloverJobAnnotationBean implements BeanPostProcessor, ApplicationContextAware { private static final Logger logger = LoggerFactory.getLogger(CloverJobAnnotationBean.class); private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { parseBean(bean); return bean; } private void parseBean(Object bean) { CloverJobAnnotation annotation = AnnotationUtils.findAnnotation(bean.getClass(), CloverJobAnnotation.class); if (null != annotation) { String jobGroup = annotation.jobGroup(); String jobName = annotation.jobName(); if (StringUtil.isEmpty(jobName)) throw new RuntimeException("CloverJobAnnotationBean-->>postProcessAfterInitialization jobName is null"); ClientJob.JobType jobType = annotation.jobType(); if (StringUtil.isEmpty(jobType.name())) jobType = ClientJob.JobType.LOCAL; ClientJob.ExecuteType executeType = annotation.executeType(); if (StringUtil.isEmpty(executeType.name())) executeType = ClientJob.ExecuteType.ADD; ClientJob.JobStrategy jobStrategy = annotation.jobStrategy(); if (StringUtil.isEmpty(jobStrategy.name())) jobStrategy = ClientJob.JobStrategy.HASH; /** * startTime & cronExpression都不为空,那么优先是startTime生效 */ String startTime = annotation.startTime(); String cronExpression = annotation.cronExpression(); ClientJob clientJob; if (!StringUtil.isEmpty(startTime) && !StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(jobGroup, jobName, (Class) bean.getClass(), jobType, executeType, jobStrategy, DateUtil.formatWithDefaultPattern(startTime)); } else if (!StringUtil.isEmpty(startTime) && StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(jobGroup, jobName, (Class) bean.getClass(), jobType, executeType, jobStrategy, DateUtil.formatWithDefaultPattern(startTime)); } else if (StringUtil.isEmpty(startTime) && !StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndCronExpression(jobGroup, jobName, (Class) bean.getClass(), jobType, executeType, jobStrategy, cronExpression); } else { throw new RuntimeException("CloverJobAnnotationBean-->>postProcessAfterInitialization startTime & cronExpression can not null at the same time"); } String fixedClientIps = annotation.fixedClientIps(); if (!StringUtil.isEmpty(fixedClientIps) && !fixedClientIps.contains(",")) { clientJob.setFixedClientIps(fixedClientIps.split(",")); } else if (!StringUtil.isEmpty(fixedClientIps) && fixedClientIps.contains(",")) { logger.error("CloverJobAnnotationBean-->>fixedClientIps can not include chinese comma"); throw new RuntimeException("CloverJobAnnotationBean-->>fixedClientIps can not include chinese comma"); } String fixedServerIps = annotation.fixedServerIps(); if (!StringUtil.isEmpty(fixedServerIps) && !fixedServerIps.contains(",")) { clientJob.setFixedServerIps(fixedServerIps.split(",")); } else if (!StringUtil.isEmpty(fixedServerIps) && fixedServerIps.contains(",")) { logger.error("CloverJobAnnotationBean-->>fixedServerIps can not include chinese comma"); throw new RuntimeException("CloverJobAnnotationBean-->>fixedServerIps can not include chinese comma"); } ModuleSchedulerClient.getInstance().handlerJob(clientJob); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/annotation/CloverJobBeanDefinitionParser.java ================================================ package com.gome.clover.common.annotation; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; import org.quartz.Job; import org.quartz.JobKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Clover Job Bean Definition Parser * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/3 * Time: 17:53 */ public class CloverJobBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { private static final Logger logger = LoggerFactory.getLogger(CloverJobBeanDefinitionParser.class); private static final String CLOVER_JOB_ANNOTATION = "CLOVER_JOB_ANNOTATION"; @Override protected Class getBeanClass(Element element) { try { return Class.forName(element.getAttribute("id")); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, parserContext, builder); doParseElement(element); if (!parserContext.getRegistry().containsBeanDefinition(CLOVER_JOB_ANNOTATION)) { RootBeanDefinition annotation = new RootBeanDefinition(CloverJobAnnotationBean.class); parserContext.getRegistry().registerBeanDefinition(CLOVER_JOB_ANNOTATION, annotation); } } /** * 解析 spring cloverjob:job标签配置元素,并创建ClientJob(代码一大坨 一大坨的 都不忍直视了) * * @param element */ private void doParseElement(Element element) { //解析 spring cloverjob:config标签配置元素 开始 String id = element.getAttribute("id"); String jobGroup = element.getAttribute("jobGroup"); if (StringUtil.isEmpty(jobGroup)) jobGroup = JobKey.DEFAULT_GROUP; String jobName = element.getAttribute("jobName"); if (StringUtil.isEmpty(jobName)) jobName = id; String jobType = element.getAttribute("jobType"); if (StringUtil.isEmpty(jobType)) { jobType = ClientJob.JobType.LOCAL.name(); } else if (!jobType.equalsIgnoreCase(ClientJob.JobType.LOCAL.name()) && !jobType.equalsIgnoreCase(ClientJob.JobType.REMOTE.name())) { logger.error("CloverJobBeanDefinitionParser-->>doParseElement() jobType must be LOCAL or REMOTE "); throw new RuntimeException("CloverJobBeanDefinitionParser-->>doParse() jobType must be LOCAL or REMOTE "); } String executeType = element.getAttribute("executeType"); if (StringUtil.isEmpty(executeType)) { executeType = ClientJob.ExecuteType.ADD.name(); } else if (!executeType.equalsIgnoreCase(ClientJob.ExecuteType.ADD.name()) && !executeType.equalsIgnoreCase(ClientJob.ExecuteType.UPDATE.name()) && !executeType.equalsIgnoreCase(ClientJob.ExecuteType.DELETE.name())) { logger.error("CloverJobBeanDefinitionParser-->>doParseElement() executeType must be ADD or UPDATE or DELETE "); throw new RuntimeException("CloverJobBeanDefinitionParser-->>doParse() executeType must be ADD or UPDATE or DELETE "); } String jobStrategy = element.getAttribute("jobStrategy"); if (StringUtil.isEmpty(jobStrategy)) { jobStrategy = ClientJob.JobStrategy.HASH.name(); } else if (!jobStrategy.equalsIgnoreCase(ClientJob.JobStrategy.HASH.name()) && !jobStrategy.equalsIgnoreCase(ClientJob.JobStrategy.SYSTEM_CAPACITY.name())) { logger.error("CloverJobBeanDefinitionParser-->>doParseElement() jobStrategy must be HASH or SYSTEM_CAPACITY "); throw new RuntimeException("CloverJobBeanDefinitionParser-->>doParse() jobStrategy must be HASH or SYSTEM_CAPACITY "); } String startTime = element.getAttribute("startTime"); String cronExpression = element.getAttribute("cronExpression"); //解析 spring cloverjob:config标签配置元素 结束 //创建ClientJob 开始 ClientJob clientJob; if (!StringUtil.isEmpty(startTime) && !StringUtil.isEmpty(cronExpression)) { try { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(jobGroup, jobName,(Class) Class.forName(id), ClientJob.JobType.valueOf(jobType), ClientJob.ExecuteType.valueOf(executeType), ClientJob.JobStrategy.valueOf(jobStrategy), DateUtil.formatWithDefaultPattern(startTime)); } catch (ClassNotFoundException e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverJobBeanDefinitionParser-->>doParseElement() error," + e.getMessage()); throw new RuntimeException(e); } } else if (!StringUtil.isEmpty(startTime) && StringUtil.isEmpty(cronExpression)) { try { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(jobGroup, jobName,(Class) Class.forName(id), ClientJob.JobType.valueOf(jobType), ClientJob.ExecuteType.valueOf(executeType), ClientJob.JobStrategy.valueOf(jobStrategy), DateUtil.formatWithDefaultPattern(startTime)); } catch (ClassNotFoundException e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverJobBeanDefinitionParser-->>doParseElement() error," + e.getMessage()); throw new RuntimeException(e); } } else if (StringUtil.isEmpty(startTime) && !StringUtil.isEmpty(cronExpression)) { try { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndCronExpression(jobGroup, jobName,(Class) Class.forName(id), ClientJob.JobType.valueOf(jobType), ClientJob.ExecuteType.valueOf(executeType), ClientJob.JobStrategy.valueOf(jobStrategy), cronExpression); } catch (ClassNotFoundException e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("CloverJobBeanDefinitionParser-->>doParseElement() error," + e.getMessage()); throw new RuntimeException(e); } } else { logger.error("CloverJobBeanDefinitionParser-->>postProcessAfterInitialization startTime & cronExpression can not null at the same time"); throw new RuntimeException("CloverJobBeanDefinitionParser-->>postProcessAfterInitialization startTime & cronExpression can not null at the same time"); } String fixedClientIpsStr = element.getAttribute("fixedClientIps"); if (!StringUtil.isEmpty(fixedClientIpsStr) && !fixedClientIpsStr.contains(",")) { clientJob.setFixedClientIps(fixedClientIpsStr.split(",")); } else if (!StringUtil.isEmpty(fixedClientIpsStr) && fixedClientIpsStr.contains(",")) { logger.error("CloverJobBeanDefinitionParser-->>fixedClientIps can not include chinese comma"); throw new RuntimeException("CloverJobBeanDefinitionParser-->>fixedClientIps can not include chinese comma"); } String fixedServerIpsStr = element.getAttribute("fixedServerIps"); if (!StringUtil.isEmpty(fixedServerIpsStr) && !fixedClientIpsStr.contains(",")) { clientJob.setFixedClientIps(fixedServerIpsStr.split(",")); } else if (!StringUtil.isEmpty(fixedServerIpsStr) && fixedServerIpsStr.contains(",")) { logger.error("CloverJobBeanDefinitionParser-->>fixedServerIps can not include chinese comma"); throw new RuntimeException("CloverJobBeanDefinitionParser-->>fixedServerIps can not include chinese comma"); } //创建ClientJob 结束 ModuleSchedulerClient.getInstance().handlerJob(clientJob); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/annotation/CloverJobNamespaceHandler.java ================================================ package com.gome.clover.common.annotation; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/3 * Time: 17:50 */ public class CloverJobNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("config", new CloverConfigBeanDefinitionParser()); registerBeanDefinitionParser("job", new CloverJobBeanDefinitionParser()); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/cache/LRUCache.java ================================================ package com.gome.clover.common.cache; import java.util.Hashtable; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/22 * Time: 17:25 */ public class LRUCache { private int cacheSize; private Hashtable nodes;//缓存容器 private int currentSize; private Entry first;//链表头 private Entry last;//链表尾 public LRUCache(int i) { currentSize = 0; cacheSize = i; nodes = new Hashtable(i);//缓存容器 } /** * 获取缓存中对象,并把它放在最前面 */ public Entry get(Object key) { Entry node = nodes.get(key); if (node != null) { moveToHead(node); return node; } else { return null; } } /** * 添加 entry到hashtable, 并把entry */ public void put(Object key, Object value) { //先查看hashtable是否存在该entry, 如果存在,则只更新其value Entry node = nodes.get(key); if (node == null) { //缓存容器是否已经超过大小. if (currentSize >= cacheSize) { nodes.remove(last.key); removeLast(); } else { currentSize++; } node = new Entry(); } node.value = value; //将最新使用的节点放到链表头,表示最新使用的. moveToHead(node); nodes.put(key, node); } /** * 将entry删除, 注意:删除操作只有在cache满了才会被执行 */ public void remove(Object key) { Entry node = nodes.get(key); //在链表中删除 if (node != null) { if (node.prev != null) { node.prev.next = node.next; } if (node.next != null) { node.next.prev = node.prev; } if (last == node) last = node.prev; if (first == node) first = node.next; } //在hashtable中删除 nodes.remove(key); } /** * 删除链表尾部节点,即使用最后 使用的entry */ private void removeLast() { //链表尾不为空,则将链表尾指向null. 删除连表尾(删除最少使用的缓存对象) if (last != null) { if (last.prev != null) last.prev.next = null; else first = null; last = last.prev; } } /** * 移动到链表头,表示这个节点是最新使用过的 */ private void moveToHead(Entry node) { if (node == first) return; if (node.prev != null) node.prev.next = node.next; if (node.next != null) node.next.prev = node.prev; if (last == node) last = node.prev; if (first != null) { node.next = first; first.prev = node; } first = node; node.prev = null; if (last == null) last = first; } /* * 清空缓存 */ public void clear() { first = null; last = null; currentSize = 0; } } class Entry { Entry prev;//前一节点 Entry next;//后一节点 Object value;//值 Object key;//键 } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/cache/LRUCache2.java ================================================ package com.gome.clover.common.cache; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/22 * Time: 17:31 */ public class LRUCache2 { private static final float hashTableLoadFactor = 0.75f; private LinkedHashMap map; private int cacheSize; /** * Creates a new LRU cache. * @param cacheSize the maximum number of entries that will be kept in this cache. */ public LRUCache2 (int cacheSize) { this.cacheSize = cacheSize; int hashTableCapacity = (int)Math.ceil(cacheSize / hashTableLoadFactor) + 1; map = new LinkedHashMap(hashTableCapacity, hashTableLoadFactor, true) { // (an anonymous inner class) private static final long serialVersionUID = 1; @Override protected boolean removeEldestEntry (Map.Entry eldest) { return size() > LRUCache2.this.cacheSize; }}; } /** * Retrieves an entry from the cache. * The retrieved entry becomes the MRU (most recently used) entry. * @param key the key whose associated value is to be returned. * @return the value associated to this key, or null if no value with this key exists in the cache. */ public synchronized V get (K key) { return map.get(key); } /** * Adds an entry to this cache. * The new entry becomes the MRU (most recently used) entry. * If an entry with the specified key already exists in the cache, it is replaced by the new entry. * If the cache is full, the LRU (least recently used) entry is removed from the cache. * @param key the key with which the specified value is to be associated. * @param value a value to be associated with the specified key. */ public synchronized void put (K key, V value) { map.put (key, value); } /** * Clears the cache. */ public synchronized void clear() { map.clear(); } /** * Returns the number of used entries in the cache. * @return the number of entries currently in the cache. */ public synchronized int usedEntries() { return map.size(); } /** * Returns a Collection that contains a copy of all cache entries. * @return a Collection with a copy of the cache content. */ public synchronized Collection> getAll() { return new ArrayList>(map.entrySet()); } } // end class LRUCache ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/compile/CreateAndCompileClassFile.java ================================================ package com.gome.clover.common.compile; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover Create And Compile Class File * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/26 * Time: 19:31 */ public class CreateAndCompileClassFile { public static Class compileAndLoading(String classPath, String className){ String packageStr = className.substring(0,className.lastIndexOf(".")); String clazzName = className.substring(className.lastIndexOf(".")+1); String separator = File.separator; File file = new File(classPath+separator+clazzName+".java"); PrintWriter out; try { out = new PrintWriter(new FileOutputStream(file)); StringBuilder sb = new StringBuilder(); sb.append("package ").append(packageStr).append(" ; ").append("public class ").append(clazzName) .append("{}"); out.println(sb.toString()); //关闭文件流 out.flush(); out.close(); com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main(); String[] args = new String[] {"-d",System.getProperty("user.dir"),clazzName+".java"}; int status = javac.compile(args); if(0==status){ /* return new DynamicClassLoader(DynamicClassLoader.class.getClassLoader()) .loadClass(classPath, className + ".class");*/ } } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } public static void main(String args[]){ CreateAndCompileClassFile.compileAndLoading(System.getProperty("user.dir"),"com.gome.sb.SB"); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/compile/DynamicClassLoader.java ================================================ package com.gome.clover.common.compile; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/26 * Time: 20:24 */ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; public class DynamicClassLoader extends ClassLoader { public DynamicClassLoader(ClassLoader parent) { super(parent); } @SuppressWarnings("unchecked") public Class loadClass(String classPath, String className) throws ClassNotFoundException { try { String url = classPathParser(classPath) + classNameParser(className); System.out.println(url); URL myUrl = new URL(url); URLConnection connection = myUrl.openConnection(); InputStream input = connection.getInputStream(); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int data = input.read(); while (data != -1) { buffer.write(data); data = input.read(); } input.close(); byte[] classData = buffer.toByteArray(); return defineClass(noSuffix(className), classData, 0, classData.length); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private String pathParser(String path) { return path.replaceAll("\\\\", "/"); } private String classPathParser(String path) { String classPath = pathParser(path); if (!classPath.startsWith("file:")) { classPath = "file:" + classPath; } if (!classPath.endsWith("/")) { classPath = classPath + "/"; } return classPath; } private String classNameParser(String className) { return className.substring(0, className.lastIndexOf(".")).replaceAll( "\\.", "/") + className.substring(className.lastIndexOf(".")); } private String noSuffix(String className) { return className.substring(0, className.lastIndexOf(".")); } public static void main(String[] arguments) throws Exception { String classPath = "D:\\Java\\apache-tomcat-6.0.18\\bin\\"; String className = "com.gome.clover.core.job.client.WYMyJob1.class"; Object object = new DynamicClassLoader(DynamicClassLoader.class.getClassLoader()) .loadClass(classPath, className).newInstance(); System.err.println(object); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/compile/MyClassLoader.java ================================================ package com.gome.clover.common.compile; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.core.job.ClientJob; import org.apache.commons.codec.binary.Base64; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Hashtable; /** * 自定义类加载器 */ public class MyClassLoader extends ClassLoader { private static String myClasspath; private static ArrayList loadClassList = new ArrayList(); private static Hashtable loadClassHashTable = new Hashtable(); public MyClassLoader() { super(null); // 指定父类加载器为 null } /** * 构造自定义的加载器 参数1:路径名 */ public MyClassLoader(String MyClasspath) { super(null); // 指定父类加载器为 null if (!MyClasspath.endsWith("\\")) { MyClasspath = MyClasspath + "\\"; } this.myClasspath = MyClasspath; } /** * 设置加载路径 参数1:路径名 */ public void SetMyClasspath(String myClasspath) { if (!myClasspath.endsWith("\\")) { myClasspath = myClasspath + "\\"; } this.myClasspath = myClasspath; } /** * 查找类并加载 参数1:文件名 被 loadClass() 调用 */ public Class findClass(String name) { byte[] classData = null; try { classData = loadClassData(name); } catch (IOException e) { e.printStackTrace(); } Class c = defineClass(name, classData, 0, classData.length); loadClassHashTable.put(name, c); System.out.println("加载" + name + "类成功。"); return c; } /** * 读取文件字节码 参数1:文件名 被 findClass() 调用 */ private byte[] loadClassData(String name) throws IOException { String classname = name.replace('.', File.separatorChar) + ".class"; System.out.println(classname); if (!(classname == null || classname == "")) { FileInputStream inFile = new FileInputStream(myClasspath +File.separatorChar+classname); byte[] classData = new byte[inFile.available()]; inFile.read(classData); inFile.close(); return classData; } System.out.println("读取字节码失败。"); return null; } /** * 加载类 参数1:字节码数组 参数2:类名 */ public Class loadClass(byte[] classData, String className) throws ClassNotFoundException { Class c = defineClass(className, classData, 0, classData.length); loadClassHashTable.put(className, c); System.out.println("加载" + className + "类成功。"); return c; } /** * 加载类 参数1:类名 */ public Class loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } /** * 加载类 参数1:类名 参数2:是否分析这个类 */ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { byte[] classData = null; Class temp = null; // 如是系统类直接装载并记录后返回 if (name.startsWith("java.")) { temp = findSystemClass(name); // 调用父类方法 loadClassHashTable.put(name, temp); System.out.println("loadClass: SystemLoading " + name); return temp; } try { temp = findLoadedClass(name);// here need try again it is how to work if (temp != null) { System.out.println(name + " have loaded"); return (temp); } try { temp = findClass(name); } catch (Exception fnfe) { } if (temp == null) { temp = findSystemClass(name); } if (resolve && (temp != null)) { resolveClass(temp); } return temp; } catch (Exception e) { throw new ClassNotFoundException(e.toString()); } } public static void main(String[] args) { System.out.println(); String classPath = System.getProperty("user.dir"); MyClassLoader cl = new MyClassLoader(classPath); try { // 从tools.jar包中加载ContentSigner类 //cl.loadClass("ContentSigner", "tools"); String className = "com.gome.clover.job.MyJobWithSimpleJob"; CreateAndCompileClassFile.compileAndLoading(classPath,className); Class cls=cl.loadClass(className); Object obj = cls.newInstance(); String msg = "rO0ABXNyACJjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuQ2xpZW50Sm9iDQZqULjOYzACAApaABJpc1JlY292ZXJKb2JGcm9tREJMAAtleGVjdXRlVHlwZXQAMExjb20vZ29tZS9jbG92ZXIvY29yZS9qb2IvQ2xpZW50Sm9iJEV4ZWN1dGVUeXBlO1sADmZpeGVkQ2xpZW50SXBzdAATW0xqYXZhL2xhbmcvU3RyaW5nO1sADmZpeGVkU2VydmVySXBzcQB+AAJMAAJpcHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wACGpvYkNsYXNzdAARTGphdmEvbGFuZy9DbGFzcztMAAxqb2JDbGFzc05hbWVxAH4AA0wACWpvYkRldGFpbHQAFkxvcmcvcXVhcnR6L0pvYkRldGFpbDtMAAdqb2JUeXBldAAsTGNvbS9nb21lL2Nsb3Zlci9jb3JlL2pvYi9DbGllbnRKb2IkSm9iVHlwZTtMAAd0cmlnZ2VydAAUTG9yZy9xdWFydHovVHJpZ2dlcjt4cAF+cgAuY29tLmdvbWUuY2xvdmVyLmNvcmUuam9iLkNsaWVudEpvYiRFeGVjdXRlVHlwZQAAAAAAAAAAEgAAeHIADmphdmEubGFuZy5FbnVtAAAAAAAAAAASAAB4cHQAA0FERHBwdAANMTAuMTQ0LjMzLjIxMnZyACZjb20uZ29tZS5jbG92ZXIuam9iLk15Sm9iV2l0aFNpbXBsZUpvYgAAAAAAAAAAAAAAeHB0ACZjb20uZ29tZS5jbG92ZXIuam9iLk15Sm9iV2l0aFNpbXBsZUpvYnNyAB1vcmcucXVhcnR6LmltcGwuSm9iRGV0YWlsSW1wbKvDyuwBWlSvAgAHWgAKZHVyYWJpbGl0eVoADXNob3VsZFJlY292ZXJMAAtkZXNjcmlwdGlvbnEAfgADTAAFZ3JvdXBxAH4AA0wACGpvYkNsYXNzcQB+AARMAApqb2JEYXRhTWFwdAAXTG9yZy9xdWFydHovSm9iRGF0YU1hcDtMAARuYW1lcQB+AAN4cAAAcHQAB3d5R3JvdXBxAH4AD3B0AAV3eUpvYn5yACpjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuQ2xpZW50Sm9iJEpvYlR5cGUAAAAAAAAAABIAAHhxAH4ACnQABUxPQ0FMc3IAKm9yZy5xdWFydHouaW1wbC50cmlnZ2Vycy5TaW1wbGVUcmlnZ2VySW1wbMwnIeqkAm6jAgAIWgAIY29tcGxldGVJAAtyZXBlYXRDb3VudEoADnJlcGVhdEludGVydmFsSQAOdGltZXNUcmlnZ2VyZWRMAAdlbmRUaW1ldAAQTGphdmEvdXRpbC9EYXRlO0wADG5leHRGaXJlVGltZXEAfgAaTAAQcHJldmlvdXNGaXJlVGltZXEAfgAaTAAJc3RhcnRUaW1lcQB+ABp4cgAob3JnLnF1YXJ0ei5pbXBsLnRyaWdnZXJzLkFic3RyYWN0VHJpZ2dlcsnRVzsN4PXuAgALSQASbWlzZmlyZUluc3RydWN0aW9uSQAIcHJpb3JpdHlaAAp2b2xhdGlsaXR5TAAMY2FsZW5kYXJOYW1lcQB+AANMAAtkZXNjcmlwdGlvbnEAfgADTAAOZmlyZUluc3RhbmNlSWRxAH4AA0wABWdyb3VwcQB+AANMAApqb2JEYXRhTWFwcQB+ABJMAAhqb2JHcm91cHEAfgADTAAHam9iTmFtZXEAfgADTAAEbmFtZXEAfgADeHAAAAAAAAAABQBwcHBxAH4AFHBxAH4AFHEAfgAVcQB+ABUAAAAAAAAAAAAAAAAAAAAAAHBzcgAOamF2YS51dGlsLkRhdGVoaoEBS1l0GQMAAHhwdwgAAAFKPIEUYHhwcQB+AB4="; ClientJob serverJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64(msg)); /* Method m = obj.getClass().getMethod("sayHello", new Class[]{}); Object v=m.invoke(obj, new Object[]{});*/ System.err.println(obj); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/compress/CompressUtil.java ================================================ package com.gome.clover.common.compress; import org.xerial.snappy.Snappy; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Compress Util * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/4 * Time: 22:36 */ public class CompressUtil { public static byte[] compress(byte[] orig) { try { return Snappy.compress(orig); } catch (Exception e) { } return orig; } public static byte[] uncompress(byte[] compressed) { try { return Snappy.uncompress(compressed); } catch (Exception e) { } return compressed; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/encryption/DesUtil.java ================================================ package com.gome.clover.common.encryption; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec; /** * 模块描述:des加密工具 * User: wangyue-ds6 * Date: 2014/7/29 * Time: 10:16 */ public class DesUtil { /** * 加密、解密key. */ private static final String PASSWORD_CRYPT_KEY = "gomedscn"; /** * 加密算法 */ private final static String ALGORITHM = "DES/CBC/PKCS5Padding"; /** * 对数据进行DES加密. * @param data 待进行DES加密的数据 * @param cryptKey 待进行DES加密的key * @return 返回经过DES加密后的数据 * @throws Exception */ public final static String decrypt(String data,String cryptKey) throws Exception { return new String(decrypt(hex2byte(data.getBytes()),cryptKey.getBytes())); } /** * 对用DES加密过的数据进行解密. * * @param data DES加密数据 * @param cryptKey DES加密key * @return 返回解密后的数据 * @throws Exception */ public final static String encrypt(String data,String cryptKey) throws Exception { return byte2hex(encrypt(data.getBytes(), PASSWORD_CRYPT_KEY .getBytes())); } /** * 用指定的key对数据进行DES加密. * * @param data 待加密的数据 * @param key DES加密的key * @return 返回DES加密后的数据 * @throws Exception */ private static byte[] encrypt(byte[] data, byte[] key) throws Exception { // 从原始密匙数据创建DESKeySpec对象 DESKeySpec dks = new DESKeySpec(key); // 创建一个密匙工厂,然后用它把DESKeySpec转换成 // 一个SecretKey对象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey securekey = keyFactory.generateSecret(dks); //向量 IvParameterSpec iv = new IvParameterSpec(key); // Cipher对象实际完成加密操作 Cipher cipher = Cipher.getInstance(ALGORITHM); // 用密匙初始化Cipher对象 cipher.init(Cipher.ENCRYPT_MODE, securekey, iv); // 现在,获取数据并加密 // 正式执行加密操作 return cipher.doFinal(data); } /** * 用指定的key对数据进行DES解密. * * @param data 待解密的数据 * @param key DES解密的key * @return 返回DES解密后的数据 * @throws Exception */ private static byte[] decrypt(byte[] data, byte[] key) throws Exception { // 从原始密匙数据创建一个DESKeySpec对象 DESKeySpec dks = new DESKeySpec(key); // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成 // 一个SecretKey对象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey securekey = keyFactory.generateSecret(dks); //向量 IvParameterSpec iv = new IvParameterSpec(key); // Cipher对象实际完成解密操作 Cipher cipher = Cipher.getInstance(ALGORITHM); // 用密匙初始化Cipher对象 cipher.init(Cipher.DECRYPT_MODE, securekey, iv); // 现在,获取数据并解密 // 正式执行解密操作 return cipher.doFinal(data); } public static byte[] hex2byte(byte[] b) { if ((b.length % 2) != 0) throw new IllegalArgumentException("长度不是偶数"); byte[] b2 = new byte[b.length / 2]; for (int n = 0; n < b.length; n += 2) { String item = new String(b, n, 2); b2[n / 2] = (byte) Integer.parseInt(item, 16); } return b2; } public static String byte2hex(byte[] b) { String hs = ""; String stmp = ""; for (int n = 0; n < b.length; n++) { stmp = (Integer.toHexString(b[n] & 0XFF)); if (stmp.length() == 1) hs = hs + "0" + stmp; else hs = hs + stmp; } return hs.toUpperCase(); } public static void main(String args[]) { try { System.out.println(DesUtil.encrypt("admin", "gomedscn")); System.out.println(DesUtil.decrypt("25E9C7A91E66A5AA44573C1590847862", "gomedscn")); } catch (Exception e) { e.printStackTrace(); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/encryption/MD5Util.java ================================================ package com.gome.clover.common.encryption; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; /** * 采用MD5加密解密 * @author wangyue-ds6 tfq * @datetime 2011-10-13 */ public class MD5Util { public static final String ENCODE = "UTF-8"; //UTF-8 /*** * MD5加码 生成32位md5码 */ public static String encryptMD5(String inStr){ MessageDigest md5 = null; try{ md5 = MessageDigest.getInstance("MD5"); }catch (Exception e){ System.out.println(e.toString()); e.printStackTrace(); return ""; } char[] charArray = inStr.toCharArray(); byte[] byteArray = new byte[charArray.length]; for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; byte[] md5Bytes = md5.digest(byteArray); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++){ int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } /*** * MD5加码 生成32位md5码 */ public static String encryptMD5WithKey(String encryptStr,String encryptKey){ byte k_ipa[] = new byte[64]; byte k_opal[] = new byte[64]; byte strBytes[]; byte value[]; try { strBytes = encryptStr.getBytes(ENCODE); value = encryptKey.getBytes(ENCODE); } catch(UnsupportedEncodingException e) { strBytes = encryptStr.getBytes(); value = encryptKey.getBytes(); } Arrays.fill(k_ipa, strBytes.length, 64, (byte) 54); Arrays.fill(k_opal, strBytes.length, 64, (byte)92); for(int i = 0; i < strBytes.length; i++) { k_ipa[i] = (byte)(strBytes[i] ^ 0x36); k_opal[i] = (byte)(strBytes[i] ^ 0x5c); } MessageDigest md; try { md = MessageDigest.getInstance("MD5"); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); return null; } md.update(k_ipa); md.update(value); byte dg[] = md.digest(); md.reset(); md.update(k_opal); md.update(dg, 0, 16); dg = md.digest(); return toHex(dg); } /** * 加密解密算法 执行一次加密,两次解密 */ public static String convertMD5(String inStr){ char[] a = inStr.toCharArray(); for (int i = 0; i < a.length; i++){ a[i] = (char) (a[i] ^ 't'); } String s = new String(a); return s; } public static String toHex(byte input[]) { if(input == null) return null; StringBuffer output = new StringBuffer(input.length * 2); for(int i = 0; i < input.length; i++) { int current = input[i] & 0xff; if(current < 16) output.append("0"); output.append(Integer.toString(current, 16)); } return output.toString(); } // 测试主函数 public static void main(String args[]) { /* String s = new String("wangyue-ds6"); System.out.println("原始:" + s); System.out.println("MD5后:" + encryptMD5(s)); //System.out.println("加密的:" + convertMD5(s)); System.out.println("解密的:" + convertMD5(convertMD5(s))); */ String key ="clover"; String s = new String("clover"); System.out.println("原始:" + s); System.out.println("MD5后:" + encryptMD5WithKey(s,key)); System.out.println("解密的:" + convertMD5(convertMD5(s))); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/exception/AppException.java ================================================ package com.gome.clover.common.exception; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc: App Exception * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class AppException extends RuntimeException{ private static final long serialVersionUID = 1L; public AppException() { super(); } public AppException(String message) { super(message); } public AppException(String message, Throwable cause) { super(message, cause); } public AppException(Throwable cause) { super(cause); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/file/ConfigFile.java ================================================ package com.gome.clover.common.file; import com.gome.clover.common.tools.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Node; import java.util.ResourceBundle; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 15:09 */ public class ConfigFile { protected static Logger logger = LoggerFactory.getLogger(ConfigFile.class); private ResourceBundle rb = null; private static ConfigFile commonConfig = null; private static ConfigFile mongoDBConfig = null; private static ConfigFile zkConfig = null; private static ConfigFile redisConfig = null; static { logger.info("load mongoDBConfig properities & zkConfig & url & redisConfig properities."); commonConfig = new ConfigFile(ResourceBundle.getBundle("commonConfig")); mongoDBConfig = new ConfigFile(ResourceBundle.getBundle("mongoDBConfig")); zkConfig = new ConfigFile(ResourceBundle.getBundle("zkConfig")); redisConfig = new ConfigFile(ResourceBundle.getBundle("redisConfig")); } public ConfigFile(ResourceBundle rb) { this.rb = rb; } public static ConfigFile commonConfig() { return commonConfig; } public static ConfigFile mongoDBConfig() { return mongoDBConfig; } public static ConfigFile zkConfig() {return zkConfig;} public static ConfigFile redisConfig() {return redisConfig;} public String getItem(String item,String defaultValue) { String value = null; if (this.rb != null) { try { value = this.rb.getString(item.trim()); value = value.trim(); } catch (Exception e) { value = defaultValue; } } if (StringUtil.isEmpty(value)) { value = defaultValue; } return value; } public int getIntItem(String item, String defaultValue) { int i = 0; String value = getItem(item,defaultValue); try { i = Integer.parseInt(value); } catch (NumberFormatException e) { logger.info(e.getMessage()); } return i; } public long getLongItem(String item, String defaultValue) { long i = 0; String value = getItem(item,defaultValue); try { i = Long.valueOf(value); } catch (NumberFormatException e) { logger.info(e.getMessage()); } return i; } public double getDoubleItem(String item, String defaultValue) { double i = 0; String value = getItem(item,defaultValue); try { i = Double.valueOf(value); } catch (NumberFormatException e) { logger.info(e.getMessage()); } return i; } public boolean getBooleanItem(String item, boolean defaultValue) { boolean b = false; String value = getItem(item, new Boolean(defaultValue).toString()); if ((value != null) && (value.equalsIgnoreCase("true"))) { b = true; } return b; } protected String getNodeValue(Node _node) { if (_node == null) { return null; } Node _firstChild = _node.getFirstChild(); if (_firstChild == null) { return null; } String _text = _firstChild.getNodeValue(); if (_text != null) { _text = _text.trim(); } return _text; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/hash/HashTimes.java ================================================ package com.gome.clover.common.hash; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 14:00 */ public class HashTimes { public static int use33(String key) { int hashCode = 0; int i = 0; int len = key.length(); for (; i < len; i++) { hashCode = hashCode * 33 + key.codePointAt(i) & 0x7FFFFFFF; } return hashCode; } public static int use37(String key) { return 0; } public static void main(String[] args) { for (int i = 0; i < 100; i++) System.out.println(i + "=" + use33(String.valueOf(i)) % 5); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/mongodb/BuildMongoDBData.java ================================================ package com.gome.clover.common.mongodb; import com.alibaba.fastjson.JSON; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ServerJob; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import org.apache.commons.codec.binary.Base64; import sun.net.util.IPAddressUtil; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/27 * Time: 20:17 */ public class BuildMongoDBData { public static BasicDBObject getInsertJobBasicDBObject(ClientJob clientJob) { BasicDBObject document = new BasicDBObject(); document.put(DBTableInfo.COL_JOB_KEY, clientJob.getJobDetail().getKey().toString()); document.put(DBTableInfo.COL_JOB_TYPE, clientJob.getJobType().name()); document.put(DBTableInfo.COL_EXECUTE_TYPE, clientJob.getExecuteType().name()); document.put(DBTableInfo.COL_JOB_STRATEGY, clientJob.getJobStrategy().name()); document.put(DBTableInfo.COL_START_TIME, null != clientJob.getStartTime()?clientJob.getStartTime():""); document.put(DBTableInfo.COL_CRON_EXPRESSION, null != clientJob.getCronExpression()?clientJob.getCronExpression():""); document.put(DBTableInfo.COL_JOB_INFO, Base64.encodeBase64String(ClassUtil.ObjectToBytes(clientJob))); document.put(DBTableInfo.COL_CLIENT_IP, null != clientJob.getClientIp()?clientJob.getClientIp() : ""); if(clientJob.getJobType() == ClientJob.JobType.REMOTE) document.put(DBTableInfo.COL_SERVER_IP, null != clientJob.getServerIp()?clientJob.getServerIp() : IpUtil.getLocalIP()); document.put(DBTableInfo.COL_FIXED_CLIENT_IPS, null != clientJob.getFixedClientIps() ? JSON.toJSONString(clientJob.getFixedClientIps()) : ""); document.put(DBTableInfo.COL_FIXED_SERVER_IPS, null != clientJob.getFixedServerIps() ? JSON.toJSONString(clientJob.getFixedServerIps()) : ""); document.put(DBTableInfo.COL_EXECUTE_START_TIME,""); document.put(DBTableInfo.COL_EXECUTE_END_TIME, ""); document.put(DBTableInfo.COL_TIMES,0); document.put(DBTableInfo.COL_FAIL_TIMES,0); document.put(DBTableInfo.COL_STATUS, CommonConstants.JOB_STATUS_1); document.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); return document; } public static BasicDBObject getDeleteJobBasicDBObject(ClientJob clientJob) { BasicDBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_JOB_KEY, clientJob.getJobDetail().getKey().toString()); condition.put(DBTableInfo.COL_JOB_TYPE,clientJob.getJobType().name()); return condition; } public static BasicDBObject getInsertLogBasicDBObject(String jobKey, String execMethod, String execResult) { BasicDBObject basicDBObject = new BasicDBObject(); basicDBObject.put(DBTableInfo.COL_SYSTEM_ID, CommonConstants.SYSTEM_ID_CLOVER); basicDBObject.put(DBTableInfo.COL_IP, IpUtil.getLocalIP()); basicDBObject.put(DBTableInfo.COL_JOB_KEY, jobKey); basicDBObject.put(DBTableInfo.COL_EXEC_METHOD, execMethod); basicDBObject.put(DBTableInfo.COL_EXEC_RESULT, execResult); basicDBObject.put(DBTableInfo.COL_EXEC_TIME, DateUtil.currentDateTime()); basicDBObject.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); return basicDBObject; } public static void saveTempJobData2DB(ServerJob serverJob) { DBObject queryCondition = new BasicDBObject(); queryCondition.put(DBTableInfo.COL_JOB_KEY, serverJob.getJobDetail().getKey().toString()); queryCondition.put(DBTableInfo.COL_CLIENT_IP, serverJob.getClientIp()); DBObject retObj = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB).findOne(queryCondition); if (null == retObj) { BasicDBObject document = BuildMongoDBData.getInsertJobBasicDBObject(serverJob); MongoDBUtil.INSTANCE.insertOrUpdate(document, DBTableInfo.TBL_CLOVER_JOB_TEMP); } } public static DBObject getDBObjectFromClientJob(ClientJob clientJob){ DBObject dbObject = new BasicDBObject(); dbObject.put(DBTableInfo.COL_JOB_KEY, clientJob.getJobDetail().getKey().toString()); dbObject.put(DBTableInfo.COL_JOB_TYPE, clientJob.getJobType().name()); return dbObject; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/mongodb/DBTableInfo.java ================================================ package com.gome.clover.common.mongodb; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:DB Table Info * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class DBTableInfo { /*表中公用列字段 开始*/ /** * 表 clover_job */ public static final String TBL_CLOVER_JOB = "clover_job"; /** * 表 clover_job_temp */ public static final String TBL_CLOVER_JOB_TEMP = "clover_job_temp"; /** * 表 clover_contact */ public static final String TBL_CLOVER_CONTACT = "clover_contact"; /** * 表 clover_log */ public static final String TBL_CLOVER_LOG = "clover_log"; /** * 表 clover_config */ public static final String TBL_CLOVER_CONFIG = "clover_config"; /** * DB 列 ID */ public static final String COL_ID= "_id"; /** * DB 列 jobKey */ public static final String COL_JOB_KEY = "jobKey"; /** * DB 列 client ip */ public static final String COL_CLIENT_IP= "clientIp"; /** * DB 列 server ip */ public static final String COL_SERVER_IP= "serverIp"; /** * DB 列 ts */ public static final String COL_TS = "ts"; /*表中公用列字段 结束*/ /*job表列字段 开始*/ /** * DB 列 jobType */ public static final String COL_JOB_TYPE = "jobType"; /** * DB 列 executeType */ public static final String COL_EXECUTE_TYPE = "executeType"; /** * DB 列 jobStrategy */ public static final String COL_JOB_STRATEGY = "jobStrategy"; /** * DB 列 job 执行时间 */ public static final String COL_START_TIME = "startTime"; /** * DB 列 job cron执行表达式 */ public static final String COL_CRON_EXPRESSION = "cronExpression"; /** * DB 列 jobInfo */ public static final String COL_JOB_INFO = "jobInfo"; /** * DB 列 fixedClientIps */ public static final String COL_FIXED_CLIENT_IPS = "fixedClientIps"; /** * DB 列 fixedServerIps */ public static final String COL_FIXED_SERVER_IPS = "fixedServerIps"; /** * DB 列 execute start time */ public static final String COL_EXECUTE_START_TIME = "executeStartTime"; /** * DB 列 execute end time */ public static final String COL_EXECUTE_END_TIME = "executeEndTime"; /** * DB 列 times */ public static final String COL_TIMES = "times"; /** * DB 列 failTimes */ public static final String COL_FAIL_TIMES = "failTimes"; /** * DB 列 status */ public static final String COL_STATUS = "status"; /*job表列字段 结束*/ /*contact表列字段 开始*/ /** * DB 列 contacter */ public static final String COL_CONTACTER = "contacter"; /** * DB 列 email */ public static final String COL_EMAIL = "email"; /** * DB 列 mobile */ public static final String COL_MOBILE = "mobile"; /*contact表列字段 结束*/ /*log表列字段 开始*/ /** * DB 列 systemId */ public static final String COL_SYSTEM_ID = "systemId"; /** * DB 列 ip */ public static final String COL_IP = "ip"; /** * DB 列 execMethod */ public static final String COL_EXEC_METHOD = "execMethod"; /** * DB 列 execResult */ public static final String COL_EXEC_RESULT = "execResult"; /** * DB 列 execTime */ public static final String COL_EXEC_TIME = "execTime"; /*log表列字段 结束*/ /*config表列字段 开始*/ /** * DB 列 key */ public static final String COL_CONFIG_KEY = "key"; /** * DB 列 value */ public static final String COL_CONFIG_VALUE = "value"; /** * DB 列 type */ public static final String COL_CONFIG_TYPE = "type"; /*config表列字段 结束*/ } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/mongodb/MongoDBUtil.java ================================================ package com.gome.clover.common.mongodb; import com.alibaba.fastjson.JSON; import com.gome.clover.common.tools.*; import com.mongodb.*; import org.quartz.JobExecutionContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Properties; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:MongoDB 工具类 * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum MongoDBUtil { INSTANCE; private static final Logger logger = LoggerFactory.getLogger(MongoDBUtil.class); private static DB db = null; private static void getDB() { Properties properties = PropertiesUtil.loadProperties("mongoDBConfig.properties"); try { List serverAddressArrayList = new ArrayList(); List credentialsList = new ArrayList(); String mongoAddressStr = (String) properties.get("mongoAddress"); if (!StringUtil.isEmpty(mongoAddressStr)) { String[] ipStr = mongoAddressStr.split(","); for (String ip : ipStr) { String[] addressStr = ip.split(":"); ServerAddress address = new ServerAddress(addressStr[0], Integer.parseInt(addressStr[1])); serverAddressArrayList.add(address);//地址 MongoCredential credential = MongoCredential.createMongoCRCredential( (String) properties.get("userName"), (String) properties.get("dbName"), ((String) properties.get("password")).toCharArray()); credentialsList.add(credential);//用户名和密码 } MongoClientOptions.Builder builder = new MongoClientOptions.Builder(); builder.connectionsPerHost(Integer.parseInt((String) properties.get("connectionsPerHost"))); builder.socketTimeout(Integer.parseInt((String) properties.get("socketTimeout"))); builder.maxWaitTime(Integer.parseInt((String) properties.get("maxWaitTime"))); builder.connectTimeout(Integer.parseInt((String) properties.get("connectTimeout"))); builder.socketKeepAlive(Boolean.valueOf((String) properties.get("socketKeepAlive"))); builder.autoConnectRetry(Boolean.valueOf((String) properties.get("autoConnectRetry"))); builder.threadsAllowedToBlockForConnectionMultiplier(Integer.parseInt((String) properties.get("threadsAllowedToBlockForConnectionMultiplier"))); MongoClient client = new MongoClient(serverAddressArrayList, credentialsList, builder.build()); client.setReadPreference(ReadPreference.secondaryPreferred()); client.setWriteConcern(new WriteConcern(1, 10000, false, false)); db = client.getDB((String) properties.get("dbName")); } } catch (UnknownHostException e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("MongoDBUtil-->>getDB() error", e); } } public static DBCollection getCollection(String collectionName) { try { if (db == null) { getDB(); } return db.getCollection(collectionName); } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("MongoDBUtil-->>getCollection(collectionName:" + collectionName + ") error", e); } return null; } public static DBObject findOneByCondition(DBObject condition, String collectionName) { DBCollection dbCollection = getCollection(collectionName); return dbCollection.findOne(condition); } public static DBCursor findByCondition(DBObject condition, String collectionName) { DBCollection dbCollection = getCollection(collectionName); return dbCollection.find(condition); } public static boolean insert(BasicDBObject basicDBObject, String collectionName) { DBCollection dbCollection = getCollection(collectionName); WriteResult writeResult = dbCollection.insert(basicDBObject); return writeResult.getN() > 0; } public static boolean insertOrUpdate(BasicDBObject basicDBObject, String collectionName) { logger.error("MongoDBUtil -> insertOrUpdate >>>"); DBCollection dbCollection = getCollection(collectionName); DBObject queryCondition = new BasicDBObject(); queryCondition.put(DBTableInfo.COL_JOB_KEY, basicDBObject.get(DBTableInfo.COL_JOB_KEY)); queryCondition.put(DBTableInfo.COL_JOB_TYPE, basicDBObject.get(DBTableInfo.COL_JOB_TYPE)); DBObject retObj = dbCollection.findOne(queryCondition); boolean flag; if (null != retObj) { //只更新时间戳TS和状态 BasicDBObject updateCondition = new BasicDBObject(); if (null != retObj.get(DBTableInfo.COL_STATUS) && !retObj.get(DBTableInfo.COL_STATUS).equals(CommonConstants.JOB_STATUS_2)) { updateCondition.put(DBTableInfo.COL_STATUS, CommonConstants.JOB_STATUS_2); } if (null != basicDBObject.get(DBTableInfo.COL_JOB_INFO) && !retObj.get(DBTableInfo.COL_JOB_INFO).equals(basicDBObject.get(DBTableInfo.COL_JOB_INFO))) { updateCondition.put(DBTableInfo.COL_JOB_INFO, basicDBObject.get(DBTableInfo.COL_JOB_INFO)); } if (null != basicDBObject.get(DBTableInfo.COL_CLIENT_IP) && !retObj.get(DBTableInfo.COL_CLIENT_IP).equals(basicDBObject.get(DBTableInfo.COL_CLIENT_IP))) { updateCondition.put(DBTableInfo.COL_CLIENT_IP, basicDBObject.get(DBTableInfo.COL_CLIENT_IP)); } if (null != basicDBObject.get(DBTableInfo.COL_SERVER_IP) && !retObj.get(DBTableInfo.COL_SERVER_IP).equals(basicDBObject.get(DBTableInfo.COL_SERVER_IP))) { updateCondition.put(DBTableInfo.COL_SERVER_IP, basicDBObject.get(DBTableInfo.COL_SERVER_IP)); } if (null != basicDBObject.get(DBTableInfo.COL_START_TIME) && !retObj.get(DBTableInfo.COL_START_TIME).equals(basicDBObject.get(DBTableInfo.COL_START_TIME))) { updateCondition.put(DBTableInfo.COL_START_TIME, basicDBObject.get(DBTableInfo.COL_START_TIME)); } if (null != basicDBObject.get(DBTableInfo.COL_START_TIME) && !retObj.get(DBTableInfo.COL_START_TIME).equals(basicDBObject.get(DBTableInfo.COL_START_TIME))) { updateCondition.put(DBTableInfo.COL_START_TIME, basicDBObject.get(DBTableInfo.COL_START_TIME)); } if (null != basicDBObject.get(DBTableInfo.COL_CRON_EXPRESSION) && !retObj.get(DBTableInfo.COL_CRON_EXPRESSION).equals(basicDBObject.get(DBTableInfo.COL_CRON_EXPRESSION))) { updateCondition.put(DBTableInfo.COL_CRON_EXPRESSION, basicDBObject.get(DBTableInfo.COL_CRON_EXPRESSION)); } if (null != basicDBObject.get(DBTableInfo.COL_FIXED_CLIENT_IPS) && !retObj.get(DBTableInfo.COL_FIXED_CLIENT_IPS).equals(basicDBObject.get(DBTableInfo.COL_FIXED_CLIENT_IPS))) { updateCondition.put(DBTableInfo.COL_FIXED_CLIENT_IPS, basicDBObject.get(DBTableInfo.COL_FIXED_CLIENT_IPS)); } if (null != basicDBObject.get(DBTableInfo.COL_FIXED_SERVER_IPS) && !retObj.get(DBTableInfo.COL_FIXED_SERVER_IPS).equals(basicDBObject.get(DBTableInfo.COL_FIXED_SERVER_IPS))) { updateCondition.put(DBTableInfo.COL_FIXED_SERVER_IPS, basicDBObject.get(DBTableInfo.COL_FIXED_SERVER_IPS)); } updateCondition.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); flag = dbCollection.update(new BasicDBObject(DBTableInfo.COL_ID, retObj.get(DBTableInfo.COL_ID)), new BasicDBObject("$set", updateCondition), true, false).getN() > 0; } else { dbCollection.insert(basicDBObject); flag = true; } return flag; } public static boolean update(BasicDBObject basicDBObject, String collectionName) { DBCollection dbCollection = getCollection(collectionName); DBObject queryCondition = new BasicDBObject(); queryCondition.put(DBTableInfo.COL_JOB_KEY, basicDBObject.get(DBTableInfo.COL_JOB_KEY)); queryCondition.put(DBTableInfo.COL_JOB_TYPE, basicDBObject.get(DBTableInfo.COL_JOB_TYPE)); DBObject retObj = dbCollection.findOne(queryCondition); boolean flag = false; if (null != retObj) { //只更新时间戳TS和状态 BasicDBObject updateCondition = new BasicDBObject(); if (null != retObj.get(DBTableInfo.COL_STATUS) && !retObj.get(DBTableInfo.COL_STATUS).equals(CommonConstants.JOB_STATUS_2)) { updateCondition.put(DBTableInfo.COL_STATUS, CommonConstants.JOB_STATUS_2); } if (null != basicDBObject.get(DBTableInfo.COL_EXECUTE_TYPE) && !retObj.get(DBTableInfo.COL_EXECUTE_TYPE).equals(basicDBObject.get(DBTableInfo.COL_EXECUTE_TYPE))) { updateCondition.put(DBTableInfo.COL_EXECUTE_TYPE, basicDBObject.get(DBTableInfo.COL_EXECUTE_TYPE)); } if (null != basicDBObject.get(DBTableInfo.COL_JOB_STRATEGY) && !retObj.get(DBTableInfo.COL_JOB_STRATEGY).equals(basicDBObject.get(DBTableInfo.COL_JOB_STRATEGY))) { updateCondition.put(DBTableInfo.COL_JOB_STRATEGY, basicDBObject.get(DBTableInfo.COL_JOB_STRATEGY)); } if (null != basicDBObject.get(DBTableInfo.COL_JOB_INFO) && !retObj.get(DBTableInfo.COL_JOB_INFO).equals(basicDBObject.get(DBTableInfo.COL_JOB_INFO))) { updateCondition.put(DBTableInfo.COL_JOB_INFO, basicDBObject.get(DBTableInfo.COL_JOB_INFO)); } if (null != basicDBObject.get(DBTableInfo.COL_CLIENT_IP) && !retObj.get(DBTableInfo.COL_CLIENT_IP).equals(basicDBObject.get(DBTableInfo.COL_CLIENT_IP))) { updateCondition.put(DBTableInfo.COL_CLIENT_IP, basicDBObject.get(DBTableInfo.COL_CLIENT_IP)); } if (null != basicDBObject.get(DBTableInfo.COL_SERVER_IP) && !retObj.get(DBTableInfo.COL_SERVER_IP).equals(basicDBObject.get(DBTableInfo.COL_SERVER_IP))) { updateCondition.put(DBTableInfo.COL_SERVER_IP, basicDBObject.get(DBTableInfo.COL_SERVER_IP)); } if (null != basicDBObject.get(DBTableInfo.COL_START_TIME) && !retObj.get(DBTableInfo.COL_START_TIME).equals(basicDBObject.get(DBTableInfo.COL_START_TIME))) { updateCondition.put(DBTableInfo.COL_START_TIME, basicDBObject.get(DBTableInfo.COL_START_TIME)); } if (null != basicDBObject.get(DBTableInfo.COL_START_TIME) && !retObj.get(DBTableInfo.COL_START_TIME).equals(basicDBObject.get(DBTableInfo.COL_START_TIME))) { updateCondition.put(DBTableInfo.COL_START_TIME, basicDBObject.get(DBTableInfo.COL_START_TIME)); } if (null != basicDBObject.get(DBTableInfo.COL_CRON_EXPRESSION) && !retObj.get(DBTableInfo.COL_CRON_EXPRESSION).equals(basicDBObject.get(DBTableInfo.COL_CRON_EXPRESSION))) { updateCondition.put(DBTableInfo.COL_CRON_EXPRESSION, basicDBObject.get(DBTableInfo.COL_CRON_EXPRESSION)); } if (null != basicDBObject.get(DBTableInfo.COL_FIXED_CLIENT_IPS) && !retObj.get(DBTableInfo.COL_FIXED_CLIENT_IPS).equals(basicDBObject.get(DBTableInfo.COL_FIXED_CLIENT_IPS))) { updateCondition.put(DBTableInfo.COL_FIXED_CLIENT_IPS, basicDBObject.get(DBTableInfo.COL_FIXED_CLIENT_IPS)); } if (null != basicDBObject.get(DBTableInfo.COL_FIXED_SERVER_IPS) && !retObj.get(DBTableInfo.COL_FIXED_SERVER_IPS).equals(basicDBObject.get(DBTableInfo.COL_FIXED_SERVER_IPS))) { updateCondition.put(DBTableInfo.COL_FIXED_SERVER_IPS, basicDBObject.get(DBTableInfo.COL_FIXED_SERVER_IPS)); } updateCondition.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); flag = dbCollection.update(new BasicDBObject(DBTableInfo.COL_ID, retObj.get(DBTableInfo.COL_ID)), new BasicDBObject("$set", updateCondition), true, false).getN() > 0; } return flag; } public static boolean delete(BasicDBObject condition, String collectionName) { DBCollection dbCollection = getCollection(collectionName); WriteResult writeResult = dbCollection.remove(condition); return writeResult.getN() > 0; } public static boolean update(BasicDBObject queryCondition, BasicDBObject updateCondition, String collectionName) { try { DBCollection dbCollection = getCollection(collectionName); dbCollection.update(queryCondition, new BasicDBObject("$set", updateCondition),true,true); return true; } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("MongoDBUtil-->>findAndModify(" + JSON.toJSONString(queryCondition) + "," + JSON.toJSONString(updateCondition) + ")", e); return false; } } public static void updateOrDeleteDB(JobExecutionContext context) { BasicDBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_JOB_KEY, context.getJobDetail().getKey().toString()); condition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_LOCAL); condition.put(DBTableInfo.COL_CLIENT_IP, IpUtil.getLocalIP()); DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject retObj = dbCollection.findOne(condition); boolean flag; if (context.getNextFireTime() != null) { if (null != retObj) { //只更新时间戳TS和状态 BasicDBObject updateCondition = new BasicDBObject(); if (!retObj.get(DBTableInfo.COL_STATUS).equals(CommonConstants.JOB_STATUS_2)) { updateCondition.put(DBTableInfo.COL_STATUS, CommonConstants.JOB_STATUS_2); } updateCondition.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); flag = dbCollection.update(new BasicDBObject(DBTableInfo.COL_ID, retObj.get(DBTableInfo.COL_ID)), new BasicDBObject("$set", updateCondition), true, false).getN() > 0; if (!flag) { logger.error("MongoDBUtil-->>updateOrDeleteDB(" + JSON.toJSONString(context) + ") error"); } } return; } if (null == context.getNextFireTime()) { if (null != retObj) { BasicDBObject deleteCondition = new BasicDBObject(); deleteCondition.put(DBTableInfo.COL_JOB_KEY, context.getJobDetail().getKey().toString()); deleteCondition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_LOCAL); deleteCondition.put(DBTableInfo.COL_CLIENT_IP, IpUtil.getLocalIP()); dbCollection.remove(deleteCondition); } } } /** * 更新job 开始执行时间和结束执行时间 * * @param context * @param updateType 1:update executeStartTime;2: update executeEndTime */ public static void updateJobTime(JobExecutionContext context, int updateType) { BasicDBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_JOB_KEY, context.getJobDetail().getKey().toString()); condition.put(DBTableInfo.COL_CLIENT_IP, IpUtil.getLocalIP()); DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject retObj = dbCollection.findOne(condition); boolean flag; if (null != retObj) { if (1 == updateType) { BasicDBObject updateCondition = new BasicDBObject(); updateCondition.put(DBTableInfo.COL_EXECUTE_START_TIME, DateUtil.currentDateTime()); updateCondition.put(DBTableInfo.COL_EXECUTE_END_TIME, ""); flag = dbCollection.update(new BasicDBObject(DBTableInfo.COL_ID, retObj.get(DBTableInfo.COL_ID)), new BasicDBObject("$set", updateCondition), true, false).getN() > 0; if (!flag) { logger.error("MongoDBUtil-->>updateJobTime(" + JSON.toJSONString(context) + "," + updateType + ") error"); } } else if (2 == updateType) { BasicDBObject updateCondition = new BasicDBObject(); updateCondition.put(DBTableInfo.COL_EXECUTE_END_TIME, DateUtil.currentDateTime()); updateCondition.put(DBTableInfo.COL_TIMES, (Long.parseLong(String.valueOf(retObj.get(DBTableInfo.COL_TIMES))) + 1)); flag = dbCollection.update(new BasicDBObject(DBTableInfo.COL_ID, retObj.get(DBTableInfo.COL_ID)), new BasicDBObject("$set", updateCondition), true, false).getN() > 0; if (!flag) { logger.error("MongoDBUtil-->>updateJobTime(" + JSON.toJSONString(context) + "," + updateType + ") error"); } } } } public static boolean isEnabledDB(){ DBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_CONFIG_KEY,CommonConstants.DISABLED_DB); condition.put(DBTableInfo.COL_CONFIG_TYPE,CommonConstants.TYPE_DB); DBObject result = MongoDBUtil.INSTANCE.findOneByCondition(condition,DBTableInfo.TBL_CLOVER_CONFIG); if(null!=result && result.containsField(DBTableInfo.COL_CONFIG_VALUE) && !Boolean.valueOf((String) result.get(DBTableInfo.COL_CONFIG_VALUE))){ return false; } else { return true; } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/netty/client/ObjectReqClient.java ================================================ package com.gome.clover.common.netty.client; import com.alibaba.fastjson.JSON; import com.gome.clover.common.compress.CompressUtil; import com.gome.clover.common.zeromq.ZeroMQEntity; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.http.*; import java.net.URI; import java.util.logging.Logger; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.slf4j.LoggerFactory; /** * 时间服务 客户端 * @author linyoufa * */ public class ObjectReqClient { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ObjectReqClient.class); public void connect(int port ,String host, final ZeroMQEntity entity) throws Exception { EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer() { /** @Override public void initChannel(SocketChannel ch) throws Exception { // 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码 ch.pipeline().addLast(new HttpResponseDecoder()); // 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码 ch.pipeline().addLast(new HttpRequestEncoder()); ch.pipeline().addLast(new SubReqClientHandel(entity)); } **/ @Override protected void initChannel(SocketChannel ch) throws Exception { /** ch.pipeline().addLast(new ObjectDecoder(1024*1024*1024*2-1, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader()))); ch.pipeline().addLast(new ObjectEncoder()); ch.pipeline().addLast(new SubReqClientHandel(entity)); **/ ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("frameDecoder",new LengthFieldBasedFrameDecoder(1024*1024*1024*2-1, 0,4, 0, 4)); pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); pipeline.addLast("decoder",new ObjectDecoder(1024*1024*1024*2-1, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader()))); pipeline.addLast("encoder",new ObjectEncoder()); pipeline.addLast("handler", new SubReqClientHandel()); }; }); try { byte[] entityBytes = CompressUtil.compress(JSON.toJSONString(entity).getBytes()); Channel channel = b.connect(host, port).sync().channel(); channel.writeAndFlush(entityBytes).sync(); logger.info("连接向Server("+host+":"+port+")写数据完成,数据包大小:"+entityBytes.length ); }catch (Exception e){ logger.error(String.format("连接Server失败", host, port), e); } /** // Start the client. ChannelFuture f = b.connect(host, port).sync(); URI uri = new URI("http://"+host+":"+port); String msg = "Are you ok?"; DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toASCIIString(), Unpooled.wrappedBuffer(msg.getBytes("UTF-8"))); // 构建http请求 request.headers().set(HttpHeaders.Names.HOST, host); request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, request.content().readableBytes()); // 发送http请求 f.channel().write(request); f.channel().flush(); f.channel().closeFuture().sync(); **/ } finally { workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { ObjectReqClient client = new ObjectReqClient(); //client.connect("127.0.0.1", 8844); } /** public static void main(String[] args) throws Exception { int defualtPort=8080; if(args!=null && args.length>0){ defualtPort=Integer.valueOf(args[0]); } //new ObjectReqClient().connect(defualtPort,"127.0.0.1"); } public void connect(int port,String host ,final ZeroMQEntity entity)throws Exception{ EventLoopGroup clientGroup= new NioEventLoopGroup(); try{ Bootstrap b= new Bootstrap(); b.group(clientGroup). channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true)//表示持续发送TCP数据包 而不是等到一定大小才发送 .handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) throws Exception { // TODO Auto-generated method stub ch.pipeline().addLast(new ObjectDecoder(1024 * 1024, ClassResolvers.softCachingConcurrentResolver(this.getClass().getClassLoader()))); ch.pipeline().addLast(new ObjectEncoder()); ch.pipeline().addLast(new SubReqClientHandel(entity)); } }); // 等待完成 连接 ChannelFuture f=b.connect(host,port).sync(); //等待 客户端 链路关闭 f.channel().closeFuture().sync(); }finally{ clientGroup.shutdownGracefully(); } } **/ } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/netty/client/SubReqClientHandel.java ================================================ package com.gome.clover.common.netty.client; import com.alibaba.fastjson.JSON; import com.gome.clover.common.compress.CompressUtil; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.common.zeromq.ZeroMQEntity; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ServerJob; import com.gome.clover.core.module.ModuleSchedulerClient; import io.netty.channel.*; import org.apache.commons.codec.binary.Base64; import org.quartz.TriggerBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SubReqClientHandel extends SimpleChannelInboundHandler { private static final Logger logger = LoggerFactory.getLogger(SubReqClientHandel.class); private ZeroMQEntity entity; public SubReqClientHandel(ZeroMQEntity entity){ this.entity=entity; } public SubReqClientHandel(){ } /** @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub logger.error("ChannelHandlerContext.channelActive().write() >>>>>>>ctx.channel().config():"+ctx.channel().config()); ctx.write(CompressUtil.compress( JSON.toJSONString(entity).getBytes())); ctx.flush(); logger.error("ChannelHandlerContext.channelActive().write()"); } **/ @Override public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { logger.info("******Client接收到Server回调数据成功******"); String result = new String(CompressUtil.uncompress((byte[])msg)); ZeroMQEntity entity = JSON.parseObject(result, ZeroMQEntity.class); if (entity!=null){ ServerJob serverJob = (ServerJob) ClassUtil.BytesToObject(Base64.decodeBase64(entity.getJobInfo())); ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String) serverJob.getJobDetail().getJobDataMap().get(CommonConstants.CLIENT_JOB_INFO))); resetClientJobTriggerAndJobType(clientJob); client.handlerJob(clientJob); logger.info("client接收到服务器返回的消息:" + msg); }else { logger.error("client accept Server resp Error!"); } ctx.close(); } private void resetClientJobTriggerAndJobType(ClientJob clientJob) { clientJob.setTrigger(TriggerBuilder.newTrigger().startNow().withIdentity(clientJob.getTrigger().getKey()).build()); clientJob.setJobType(ClientJob.JobType.REMOTE); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/netty/protol/SubScribeResp.java ================================================ package com.gome.clover.common.netty.protol; import java.io.Serializable; /** * * 功能描述:应答对象 * @author linyoufa * 2014-12-23 */ public class SubScribeResp implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String subReqId; private String respCode; private String desc; public SubScribeResp(String subRespId,String userName,String address){ this.subReqId=subRespId; this.respCode="0"; this.desc="Netty book order succesd name:"+userName +" address"+address; } public String getSubReqId() { return subReqId; } public void setSubReqId(String subReqId) { this.subReqId = subReqId; } public String getRespCode() { return respCode; } public void setRespCode(String respCode) { this.respCode = respCode; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } @Override public String toString() { return "SubScribeResp [desc=" + desc + ", respCode=" + respCode + ", subReqId=" + subReqId + "]"; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/netty/protol/SubscribeReq.java ================================================ package com.gome.clover.common.netty.protol; import java.io.Serializable; /** * * 功能描述:请求对象 * @author linyoufa * 2014-12-23 */ public class SubscribeReq implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private String subReqId; private String userName; private String porductName; private String phoneNumber; private String address; public SubscribeReq(String subReqId){ this.subReqId=subReqId; this.phoneNumber="15210130485"; this.porductName="Nett权威指南"; this.userName="linyoufa"; this.address="北京市朝阳区晓云路26号鹏润大厦21层"; } @Override public String toString() { return "SubscribeReq [phoneNumber=" + phoneNumber + ", porductName=" + porductName + ", subReqId=" + subReqId + ", userName=" + userName + "]"; } public String getSubReqId() { return subReqId; } public void setSubReqId(String subReqId) { this.subReqId = subReqId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPorductName() { return porductName; } public void setPorductName(String porductName) { this.porductName = porductName; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/netty/server/ObjectRespServer.java ================================================ package com.gome.clover.common.netty.server; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; public class ObjectRespServer { public void bind(int port)throws Exception{ //配置服务端的NIo 线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try{ ServerBootstrap b= new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .option(ChannelOption.TCP_NODELAY, true) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ObjectDecoder(1024*1024*1024*2,ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader()))); ch.pipeline().addLast(new ObjectEncoder()); ch.pipeline().addLast(new SubReqServerHandel()); }; }); //绑定 端口 同步等待成功 ChannelFuture future=b.bind(port).sync(); //等待服务器监听 关闭 future.channel().closeFuture().sync(); }finally{ //优雅的退出 释放线程资源 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public void start(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { /** // server端发送的是httpResponse,所以要使用HttpResponseEncoder进行编码 ch.pipeline().addLast(new ObjectEncoder()); // server端接收到的是httpRequest,所以要使用HttpRequestDecoder进行解码 ch.pipeline().addLast(new ObjectDecoder(1024*1024*1024*2-1, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader()))); ch.pipeline().addLast(new SubReqServerHandel()); **/ ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024*1024*1024*2-1, 0, 4, 0, 4)); pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); pipeline.addLast("decoder", new ObjectDecoder(1024 * 1024 * 1024 * 2 - 1, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader()))); pipeline.addLast("encoder", new ObjectEncoder()); pipeline.addLast(new SubReqServerHandel()); } }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(port).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub int defualtPort=8080; if(args!=null && args.length>0){ defualtPort=Integer.valueOf(args[0]); } new ObjectRespServer().bind(defualtPort); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/netty/server/SubReqServerHandel.java ================================================ package com.gome.clover.common.netty.server; import com.alibaba.fastjson.JSON; import com.gome.clover.common.compress.CompressUtil; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.netty.client.ObjectReqClient; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.common.zeromq.ZeroMQEntity; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.job.ServerJob; import com.gome.clover.core.module.ModuleSchedulerClient; import com.gome.clover.core.module.ModuleSchedulerServer; import com.gome.clover.core.scheduler.MyScheduler; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.sun.org.apache.xpath.internal.operations.Bool; import io.netty.channel.*; import org.apache.commons.codec.binary.Base64; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.quartz.JobBuilder.*; import static org.quartz.TriggerBuilder.*; import static org.quartz.SimpleScheduleBuilder.*; public class SubReqServerHandel extends SimpleChannelInboundHandler { private static final Logger logger = LoggerFactory.getLogger(SubReqServerHandel.class); @Override public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { String msg1 = new String(CompressUtil.uncompress((byte[])msg)); ZeroMQEntity entity = JSON.parseObject(msg1, ZeroMQEntity.class); if(entity != null){ logger.info("Server接收到Client数据成功,开始处理....."); this.serverHandelJob(entity,ctx); //ctx.writeAndFlush(CompressUtil.compress(entity.getMsg().getBytes())); } //super.channelRead(ctx, msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub cause.printStackTrace(); ctx.close(); } public void serverHandelJob(ZeroMQEntity zeroMQEntity,ChannelHandlerContext ctx) throws SchedulerException, ClassNotFoundException { logger.error("SubReqServerHandel: MODULE_TYPE >>>"+zeroMQEntity.getDestServer()); try { if (CommonConstants.MODULE_TYPE_SERVER.equals(zeroMQEntity.getDestServer())) { System.err.println("--------------MODULE_TYPE_SERVER--------------"); ServerJob serverJob = (ServerJob) ClassUtil.BytesToObject(Base64.decodeBase64(zeroMQEntity.getJobInfo())); ModuleSchedulerServer server = ModuleSchedulerServer.getInstance(); server.handlerJob(serverJob); } else if (CommonConstants.MODULE_TYPE_CLIENT.equals(zeroMQEntity.getDestServer())) { System.err.println("--------------MODULE_TYPE_CLIENT--------------"); ServerJob serverJob = (ServerJob) ClassUtil.BytesToObject(Base64.decodeBase64(zeroMQEntity.getJobInfo())); ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); /** ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String) serverJob.getJobDetail().getJobDataMap().get(CommonConstants.CLIENT_JOB_INFO))); resetClientJobTriggerAndJobType(clientJob); client.handlerJob(clientJob); **/ zeroMQEntity.setMsg(CommonConstants.SUCCESS); zeroMQEntity.setJobInfo(Base64.encodeBase64String(ClassUtil.ObjectToBytes(serverJob))); //new ObjectReqClient().connect(CommonConstants.NETTY_SERVER_PORT,zeroMQEntity.getDestIp(), zeroMQEntity);// 只传类路径给client端 ctx.writeAndFlush(CompressUtil.compress(ClassUtil.ObjectToBytes(zeroMQEntity))); } else if (CommonConstants.MODULE_TYPE_SERVER_WITH_ADMIN.equals(zeroMQEntity.getDestServer())) { String mqMsg = zeroMQEntity.getMsg(); if (!StringUtil.isEmpty(mqMsg)) { System.err.println("--------------MODULE_TYPE_SERVER_WITH_ADMIN--------------"); BasicDBObject basicDBObject = (BasicDBObject) com.mongodb.util.JSON.parse(mqMsg); String jobGroup = (String) basicDBObject.get("jobGroup"); String jobName = (String) basicDBObject.get("jobName"); Scheduler scheduler = new StdSchedulerFactory().getScheduler(); JobKey jobKey = new JobKey(jobName, jobGroup); if (scheduler.checkExists(jobKey)) { scheduler.deleteJob(jobKey); } } } else if (CommonConstants.MODULE_TYPE_CLIENT_WITH_ADMIN.equals(zeroMQEntity.getDestServer())) { String mqMsg = zeroMQEntity.getMsg(); if (!StringUtil.isEmpty(mqMsg)) { System.err.println("--------------MODULE_TYPE_CLIENT_WITH_ADMIN--------------"); BasicDBObject basicDBObject = (BasicDBObject) com.mongodb.util.JSON.parse(mqMsg); String jobGroup = (String) basicDBObject.get("jobGroup"); String jobName = (String) basicDBObject.get("jobName"); String jobClassName = (String) basicDBObject.get("jobClassName"); Class jobClass = (Class) Class.forName(jobClassName); ClientJob.JobType jobType = ClientJob.JobType.valueOf((String) basicDBObject.get("jobType")); ClientJob.ExecuteType executeType = ClientJob.ExecuteType.valueOf((String) basicDBObject.get("executeType")); ClientJob.JobStrategy jobStrategy = ClientJob.JobStrategy.valueOf((String) basicDBObject.get("jobStrategy")); String startTime = (String) basicDBObject.get("startTime"); String cronExpression = (String) basicDBObject.get("cronExpression"); ClientJob clientJob = null; if (!StringUtil.isEmpty(startTime) && !StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(jobGroup, jobName, jobClass, jobType, executeType, jobStrategy, DateUtil.formatWithDefaultPattern(startTime)); } else if (!StringUtil.isEmpty(startTime) && StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(jobGroup, jobName, jobClass, jobType, executeType, jobStrategy, DateUtil.formatWithDefaultPattern(startTime)); } else if (StringUtil.isEmpty(startTime) && !StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndCronExpression(jobGroup, jobName, jobClass, jobType, executeType, jobStrategy, cronExpression); } if (null != clientJob) { String fixedClientIps = (String) basicDBObject.get("fixedClientIps"); if (!StringUtil.isEmpty(fixedClientIps)) clientJob.setFixedClientIps(fixedClientIps.split(",")); String fixedServerIps = (String) basicDBObject.get("fixedServerIps"); if (!StringUtil.isEmpty(fixedServerIps)) clientJob.setFixedServerIps(fixedServerIps.split(",")); ModuleSchedulerClient.getInstance().handlerJob(clientJob); } } } else if (CommonConstants.MODULE_TYPE_SERVER_WITH_MONITOR.equals(zeroMQEntity.getDestServer())) { String mqMsg = zeroMQEntity.getMsg(); if (!StringUtil.isEmpty(mqMsg)) { System.err.println("--------------MODULE_TYPE_SERVER_WITH_MONITOR--------------"); BasicDBObject basicDBObject = (BasicDBObject) com.mongodb.util.JSON.parse(mqMsg); String action = (String) basicDBObject.get("action"); String ip = (String) basicDBObject.get("ip"); if (!StringUtil.isEmpty(action) && !StringUtil.isEmpty(ip)) { if ("reloadDB".equals(action)) {//恢复数据 DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_SERVER_IP, ip); condition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_REMOTE); DBCursor cursorDocMap = dbCollection.find(condition); while (cursorDocMap.hasNext()) { ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String) cursorDocMap.next() .get(DBTableInfo.COL_JOB_INFO))); MyScheduler scheduler = MyScheduler.INSTANCE; scheduler.start(); scheduler.add(clientJob); } } } } } zeroMQEntity.setMsg(CommonConstants.SUCCESS); }catch (Exception e){ zeroMQEntity.setMsg(CommonConstants.ERROR_CODE); logger.info("Server回调Client异常",e); } } private void resetClientJobTriggerAndJobType(ClientJob clientJob) { clientJob.setTrigger(TriggerBuilder.newTrigger().startNow().withIdentity(clientJob.getTrigger().getKey()).build()); clientJob.setJobType(ClientJob.JobType.REMOTE); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/rocketmq/ConsumerUtil.java ================================================ package com.gome.clover.common.rocketmq; import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.common.message.MessageExt; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.common.tools.ProgressUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.module.ModuleSchedulerClient; import com.gome.clover.core.module.ModuleSchedulerServer; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Consumer Util * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ConsumerUtil { private static final Logger logger = LoggerFactory.getLogger(ConsumerUtil.class); /** public static void startup(String namesrvAddr, String topic, String subExpression) throws MQClientException { DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer-clover-group"); consumer.setInstanceName("ConsumerInstance_" + ProgressUtil.getPid()); consumer.setNamesrvAddr(namesrvAddr); consumer.subscribe(topic, subExpression); consumer.registerMessageListener(new MessageListenerConcurrently() { @Override public consumeMessage(List msgs, ConsumeConcurrentlyContext context) { System.out.println("consumeMessage"); MessageExt msg = msgs.get(0); if (null == msg) return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; if (CommonConstants.MODULE_TYPE_SERVER.equals(msg.getKeys())) { if(msg.getTags() != null && msg.getTags().equals(IpUtil.getLocalIP().replace(".", "-"))){ System.err.println("MODULE_TYPE_SERVER--------------"); ClientJob clientJob = null; try { clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64(new String(msg.getBody(), "ISO-8859-1"))); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } System.err.println("clientJob"+clientJob.getTrigger()); ModuleSchedulerServer server = ModuleSchedulerServer.getInstance(); //server.handlerJob(clientJob); } } else if (CommonConstants.MODULE_TYPE_CLIENT.equals(msg.getKeys())) { if (msg.getTags() != null && msg.getTags().equals(IpUtil.getLocalIP().replace(".", "-"))) { System.err.println("MODULE_TYPE_CLIENT--------------"); ClientJob clientJob = null; try { clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64(new String(msg.getBody(), "ISO-8859-1"))); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } System.err.println("clientJob" + clientJob.getTrigger()); ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); client.handlerJob(clientJob); } } return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } }); consumer.start(); System.out.println("Consumer Started."); } public static void main(String args[]) { try { ConsumerUtil.startup("10.58.50.204:9876;10.58.50.205:9876", CommonConstants.TOPIC_CLOVER_SERVER, IpUtil.getLocalIP().replace(".", "-")); } catch (Exception e) { } } **/ } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/rocketmq/ProducerUtil.java ================================================ package com.gome.clover.common.rocketmq; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.producer.DefaultMQProducer; import com.alibaba.rocketmq.client.producer.SendResult; import com.alibaba.rocketmq.common.message.Message; import com.alibaba.rocketmq.remoting.exception.RemotingException; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.common.tools.ProgressUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Producer Util * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ProducerUtil { private static final Logger logger = LoggerFactory.getLogger(ProducerUtil.class); private static DefaultMQProducer producer; static { producer = new DefaultMQProducer("producer-clover-group"); producer.setNamesrvAddr("10.58.50.204:9876;10.58.50.205:9876"); producer.setInstanceName("ProducerInstance_" + ProgressUtil.getPid()); try { producer.start(); } catch (MQClientException e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("ProducerUtil-->>producer.start() error",e); } } public static SendResult send(Message msg) throws InterruptedException, RemotingException, MQClientException, MQBrokerException { return producer.send(msg); } public static void shutdown(){ producer.shutdown(); } public static void main(String args[]){ try{ Message msg = new Message(); msg.setTopic(CommonConstants.TOPIC_CLOVER_SERVER); String ip = IpUtil.getLocalIP(); msg.setTags(IpUtil.getLocalIP().replace(".","-")); msg.setKeys(CommonConstants.MODULE_TYPE_CLIENT); msg.setBody("sb".getBytes()); System.err.println("SendResult"+ProducerUtil.send(msg)); shutdown(); }catch (Exception e){ } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/rpc/HttpRequestEntity.java ================================================ package com.gome.clover.common.rpc; import java.io.Serializable; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:MQ Entity * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class HttpRequestEntity implements Serializable { } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/rpc/HttpRequestHandler.java ================================================ package com.gome.clover.common.rpc; import com.gome.clover.common.tools.StringUtil; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.*; import org.jboss.netty.handler.codec.http.*; import org.jboss.netty.util.CharsetUtil; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Http Request Handler * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class HttpRequestHandler extends SimpleChannelUpstreamHandler { private static final String RESPONSE_TEMPLATE = "{success:%d, m:'%s'}"; private static final String PATTERN = "([^?|!]*)(.*)"; private String decodeUri(String uri) { try { return URLDecoder.decode(uri, "UTF-8"); } catch (UnsupportedEncodingException e) { try { return URLDecoder.decode(uri, "ISO-8859-1"); } catch (UnsupportedEncodingException e1) { } } return uri; } private static String getParameterFromUri(String startPrefix, String uri) { Pattern pattern = Pattern.compile(startPrefix + "([^?|!]*)(.*)", 2); Matcher matcher = pattern.matcher(uri); if (!matcher.find()) { return null; } return matcher.group(1); } public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { HttpRequest request = (HttpRequest)e.getMessage(); String uri = decodeUri(request.getUri()); QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri()); Map params = queryStringDecoder.getParameters(); String msg; if (uri.startsWith("/push/")) { msg = getParameterValue("msg", params); if(StringUtil.isEmpty(msg)) return; System.err.println("msg:"+msg); writeResponse(e, HttpResponseStatus.OK, String.format("{success:%d, msg:'%s'}", new Object[] { Integer.valueOf(1), Long.valueOf(1)}),request); } else { } } private String getParameterValue(String parameterName, Map> params) { List values = (List)params.get(parameterName); String parameterValue = null; if ((values != null) && (!values.isEmpty())) { parameterValue = (String)values.get(0); } return parameterValue; } private void writeResponse(MessageEvent e, HttpResponseStatus httpResponseStatus, String bufString, HttpRequest request) { HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, httpResponseStatus); response.setContent(ChannelBuffers.copiedBuffer(bufString, CharsetUtil.UTF_8)); response.setHeader("Content-Type", "application/json; charset=UTF-8"); ChannelFuture future = e.getChannel().write(response); future.addListener(ChannelFutureListener.CLOSE); } public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { e.getCause().printStackTrace(); e.getChannel().close(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/rpc/HttpResponseEntity.java ================================================ package com.gome.clover.common.rpc; import java.io.Serializable; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:HttpResponseEntity * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class HttpResponseEntity implements Serializable { /** * 0:失败,1:成功 */ private int success; /** * 错误消息/消息内容 */ private String msg; /** * 消息的目的地 */ private String dest; public HttpResponseEntity() { } public HttpResponseEntity(String msg, String dest) { this.msg = msg; this.dest = dest; } public int getSuccess() { return success; } public void setSuccess(int success) { this.success = success; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String getDest() { return dest; } public void setDest(String dest) { this.dest = dest; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/rpc/QueueDaemon.java ================================================ package com.gome.clover.common.rpc; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.codec.http.HttpRequestDecoder; import org.jboss.netty.handler.codec.http.HttpResponseEncoder; import java.net.InetSocketAddress; import java.util.concurrent.Executors; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Queue Daemon * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class QueueDaemon { private int port; public QueueDaemon(int port) { this.port = port; } public void start() { ServerBootstrap bootstrap = new ServerBootstrap( new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("decoder", new HttpRequestDecoder()); pipeline.addLast("encoder", new HttpResponseEncoder()); pipeline.addLast("handler", new HttpRequestHandler()); return pipeline; } }); bootstrap.setOption("child.tcpNoDelay", Boolean.valueOf(true)); bootstrap.setOption("child.keepAlive", Boolean.valueOf(true)); bootstrap.setOption("child.reuseAddress", Boolean.valueOf(true)); bootstrap.setOption("child.connectTimeoutMillis", Integer.valueOf(100)); bootstrap.bind(new InetSocketAddress(this.port)); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/rpc/QueueServer.java ================================================ package com.gome.clover.common.rpc; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Queue Server * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum QueueServer { INSTANCE; private static final Logger logger = LoggerFactory.getLogger(QueueServer.class); public boolean startup(){ int port = 50470; try { QueueDaemon queueDaemon = new QueueDaemon(port); queueDaemon.start(); return true; }catch (Exception e){ if(logger.isDebugEnabled())e.printStackTrace(); logger.error("QueueServer-->>startup()",e); } finally { logger.info("QueueServer start with port "+port+" start now ~"); } return false; } public boolean startup(int port){ try { QueueDaemon queueDaemon = new QueueDaemon(port); queueDaemon.start(); return true; }catch (Exception e){ if(logger.isDebugEnabled())e.printStackTrace(); logger.error("QueueServer-->>startup("+port+")",e); } finally { logger.info("QueueServer start with port "+port+" start now ~"); } return false; } public static void main(String[] args) { int port = 50470; QueueDaemon queueDaemon = new QueueDaemon(port); logger.info("QueueServer start with port "+port+" start now ~"); System.err.println("QueueServer start with port \"+port+\" start now ~"); queueDaemon.start(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/systeminfo/IMonitorService.java ================================================ package com.gome.clover.common.systeminfo; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/25 * Time: 15:18 */ public interface IMonitorService { public MonitorInfoBean getMonitorInfoBean() throws Exception; } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/systeminfo/MonitorInfoBean.java ================================================ package com.gome.clover.common.systeminfo; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/25 * Time: 15:18 */ public class MonitorInfoBean { /** 可使用内存. */ private long totalMemory; /** 剩余内存. */ private long freeMemory; /** 最大可使用内存. */ private long maxMemory; /** 操作系统. */ private String osName; /** 总的物理内存. */ private long totalMemorySize; /** 剩余的物理内存. */ private long freePhysicalMemorySize; /** 已使用的物理内存. */ private long usedMemory; /** 线程总数. */ private int totalThread; /** cpu使用率. */ private double cpuRatio; public long getFreeMemory() { return freeMemory; } public void setFreeMemory(long freeMemory) { this.freeMemory = freeMemory; } public long getFreePhysicalMemorySize() { return freePhysicalMemorySize; } public void setFreePhysicalMemorySize(long freePhysicalMemorySize) { this.freePhysicalMemorySize = freePhysicalMemorySize; } public long getMaxMemory() { return maxMemory; } public void setMaxMemory(long maxMemory) { this.maxMemory = maxMemory; } public String getOsName() { return osName; } public void setOsName(String osName) { this.osName = osName; } public long getTotalMemory() { return totalMemory; } public void setTotalMemory(long totalMemory) { this.totalMemory = totalMemory; } public long getTotalMemorySize() { return totalMemorySize; } public void setTotalMemorySize(long totalMemorySize) { this.totalMemorySize = totalMemorySize; } public int getTotalThread() { return totalThread; } public void setTotalThread(int totalThread) { this.totalThread = totalThread; } public long getUsedMemory() { return usedMemory; } public void setUsedMemory(long usedMemory) { this.usedMemory = usedMemory; } public double getCpuRatio() { return cpuRatio; } public void setCpuRatio(double cpuRatio) { this.cpuRatio = cpuRatio; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/systeminfo/MonitorServiceImpl.java ================================================ package com.gome.clover.common.systeminfo; import com.sun.management.OperatingSystemMXBean; import sun.management.ManagementFactory; import java.io.*; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/25 * Time: 15:21 */ public class MonitorServiceImpl implements IMonitorService { private static final int CPUTIME = 30; private static final int PERCENT = 100; private static final int FAULTLENGTH = 10; /** * 获得当前的监控对象. * @return 返回构造好的监控对象 * @throws Exception * @author GuoHuang */ public MonitorInfoBean getMonitorInfoBean() throws Exception { int kb = 1024; // 可使用内存 long totalMemory = Runtime.getRuntime().totalMemory() / kb; // 剩余内存 long freeMemory = Runtime.getRuntime().freeMemory() / kb; // 最大可使用内存 long maxMemory = Runtime.getRuntime().maxMemory() / kb; OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory .getOperatingSystemMXBean(); // 操作系统 String osName = System.getProperty("os.name"); // 总的物理内存 long totalMemorySize = osmxb.getTotalPhysicalMemorySize() / kb; // 剩余的物理内存 long freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize() / kb; // 已使用的物理内存 long usedMemory = (osmxb.getTotalPhysicalMemorySize() - osmxb .getFreePhysicalMemorySize()) / kb; // 获得线程总数 ThreadGroup parentThread; for (parentThread = Thread.currentThread().getThreadGroup(); parentThread .getParent() != null; parentThread = parentThread.getParent()); int totalThread = parentThread.activeCount(); double cpuRatio = 0; if (osName.toLowerCase().startsWith("windows")) { cpuRatio = this.getCpuRatioForWindows(); } else { cpuRatio = this.getCpuRateForLinux(); } // 构造返回对象 MonitorInfoBean infoBean = new MonitorInfoBean(); infoBean.setFreeMemory(freeMemory); infoBean.setFreePhysicalMemorySize(freePhysicalMemorySize); infoBean.setMaxMemory(maxMemory); infoBean.setOsName(osName); infoBean.setTotalMemory(totalMemory); infoBean.setTotalMemorySize(totalMemorySize); infoBean.setTotalThread(totalThread); infoBean.setUsedMemory(usedMemory); infoBean.setCpuRatio(cpuRatio); return infoBean; } private static double getCpuRateForLinux(){ double cpuUsage = 0; Process pro1,pro2; Runtime r = Runtime.getRuntime(); try { String command = "cat /proc/stat"; //第一次采集CPU时间 long startTime = System.currentTimeMillis(); pro1 = r.exec(command); BufferedReader in1 = new BufferedReader(new InputStreamReader(pro1.getInputStream())); String line; long idleCpuTime1 = 0, totalCpuTime1 = 0; //分别为系统启动后空闲的CPU时间和总的CPU时间 while((line=in1.readLine()) != null){ if(line.startsWith("cpu")){ line = line.trim(); //log.info(line); String[] temp = line.split("\\s+"); idleCpuTime1 = Long.parseLong(temp[4]); for(String s : temp){ if(!s.equals("cpu")){ totalCpuTime1 += Long.parseLong(s); } } // log.info("IdleCpuTime: " + idleCpuTime1 + ", " + "TotalCpuTime" + totalCpuTime1); break; } } in1.close(); pro1.destroy(); try { Thread.sleep(100); } catch (InterruptedException e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); //log.error("CpuUsage休眠时发生InterruptedException. " + e.getMessage()); //log.error(sw.toString()); } //第二次采集CPU时间 long endTime = System.currentTimeMillis(); pro2 = r.exec(command); BufferedReader in2 = new BufferedReader(new InputStreamReader(pro2.getInputStream())); long idleCpuTime2 = 0, totalCpuTime2 = 0; //分别为系统启动后空闲的CPU时间和总的CPU时间 while((line=in2.readLine()) != null){ if(line.startsWith("cpu")){ line = line.trim(); //log.info(line); String[] temp = line.split("\\s+"); idleCpuTime2 = Long.parseLong(temp[4]); for(String s : temp){ if(!s.equals("cpu")){ totalCpuTime2 += Long.parseLong(s); } } //log.info("IdleCpuTime: " + idleCpuTime2 + ", " + "TotalCpuTime" + totalCpuTime2); break; } } if(idleCpuTime1 != 0 && totalCpuTime1 !=0 && idleCpuTime2 != 0 && totalCpuTime2 !=0){ cpuUsage = 1 - (float)(idleCpuTime2 - idleCpuTime1)/(float)(totalCpuTime2 - totalCpuTime1); //log.info("本节点CPU使用率为: " + cpuUsage); } in2.close(); pro2.destroy(); } catch (IOException e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); //log.error("CpuUsage发生InstantiationException. " + e.getMessage()); //log.error(sw.toString()); } return cpuUsage; } /** * 获得CPU使用率. * @return 返回cpu使用率 * @author GuoHuang */ private double getCpuRatioForWindows() { try { String procCmd = System.getenv("windir") + "\\system32\\wbem\\wmic.exe process get Caption,CommandLine," + "KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount"; // 取进程信息 long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd)); Thread.sleep(CPUTIME); long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd)); if (c0 != null && c1 != null) { long idletime = c1[0] - c0[0]; long busytime = c1[1] - c0[1]; return Double.valueOf( PERCENT * (busytime) / (busytime + idletime)) .doubleValue(); } else { return 0.0; } } catch (Exception ex) { ex.printStackTrace(); return 0.0; } } /** * 读取CPU信息. * @param proc * @return * @author GuoHuang */ private long[] readCpu(final Process proc) { long[] retn = new long[2]; try { proc.getOutputStream().close(); InputStreamReader ir = new InputStreamReader(proc.getInputStream()); LineNumberReader input = new LineNumberReader(ir); String line = input.readLine(); if (line == null || line.length() < FAULTLENGTH) { return null; } int capidx = line.indexOf("Caption"); int cmdidx = line.indexOf("CommandLine"); int rocidx = line.indexOf("ReadOperationCount"); int umtidx = line.indexOf("UserModeTime"); int kmtidx = line.indexOf("KernelModeTime"); int wocidx = line.indexOf("WriteOperationCount"); long idletime = 0; long kneltime = 0; long usertime = 0; while ((line = input.readLine()) != null) { if (line.length() < wocidx) { continue; } // 字段出现顺序:Caption,CommandLine,KernelModeTime,ReadOperationCount, // ThreadCount,UserModeTime,WriteOperation String caption = Bytes.substring(line, capidx, cmdidx - 1) .trim(); String cmd = Bytes.substring(line, cmdidx, kmtidx - 1).trim(); if (cmd.indexOf("wmic.exe") >= 0) { continue; } // log.info("line="+line); if (caption.equals("System Idle Process") || caption.equals("System")) { idletime += Long.valueOf( Bytes.substring(line, kmtidx, rocidx - 1).trim()) .longValue(); idletime += Long.valueOf( Bytes.substring(line, umtidx, wocidx - 1).trim()) .longValue(); continue; } kneltime += Long.valueOf( Bytes.substring(line, kmtidx, rocidx - 1).trim()) .longValue(); usertime += Long.valueOf( Bytes.substring(line, umtidx, wocidx - 1).trim()) .longValue(); } retn[0] = idletime; retn[1] = kneltime + usertime; return retn; } catch (Exception ex) { ex.printStackTrace(); } finally { try { proc.getInputStream().close(); } catch (Exception e) { e.printStackTrace(); } } return null; } /** 测试方法. * @param args * @throws Exception * @author GuoHuang */ public static void main(String[] args) throws Exception { IMonitorService service = new MonitorServiceImpl(); MonitorInfoBean monitorInfo = service.getMonitorInfoBean(); System.out.println("cpu占有率=" + monitorInfo.getCpuRatio()); System.out.println("可使用内存=" + monitorInfo.getTotalMemory()); System.out.println("剩余内存=" + monitorInfo.getFreeMemory()); System.out.println("最大可使用内存=" + monitorInfo.getMaxMemory()); System.out.println("操作系统=" + monitorInfo.getOsName()); System.out.println("总的物理内存=" + monitorInfo.getTotalMemorySize() + "kb"); System.out.println("剩余的物理内存=" + monitorInfo.getFreeMemory() + "kb"); System.out.println("已使用的物理内存=" + monitorInfo.getUsedMemory() + "kb"); System.out.println("线程总数=" + monitorInfo.getTotalThread() + "kb"); } } class Bytes { public static String substring(String src, int start_idx, int end_idx){ byte[] b = src.getBytes(); String tgt = ""; for(int i=start_idx; i <= end_idx; i++){ tgt +=(char)b[i]; } return tgt; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/systeminfo/SystemInfoUtil.java ================================================ package com.gome.clover.common.systeminfo; import com.sun.management.OperatingSystemMXBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sun.management.ManagementFactory; import java.io.*; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/25 * Time: 16:29 */ public class SystemInfoUtil { private final static Logger logger = LoggerFactory.getLogger(SystemInfoUtil.class); private static final OperatingSystemMXBean osmxb = (OperatingSystemMXBean) java.lang.management.ManagementFactory.getOperatingSystemMXBean(); private static final int KB = 1024; private static final int FAULTLENGTH = 10; private static final int CPUTIME = 30; public static double getMemRatio(){ long totalMemorySize = osmxb.getTotalPhysicalMemorySize()/KB;// 总的物理内存 long usedMemory = (osmxb.getTotalPhysicalMemorySize() - osmxb.getFreePhysicalMemorySize()) / KB; // 已使用的物理内存 return ((usedMemory*1.0/totalMemorySize)); } public static int getTotalThread(){ // 获得线程总数 ThreadGroup parentThread; for (parentThread = Thread.currentThread().getThreadGroup(); parentThread .getParent() != null; parentThread = parentThread.getParent()); return parentThread.activeCount(); } public static double getCpuRatio(){ double cpuRatio; // 操作系统 String osName = System.getProperty("os.name"); if (osName.toLowerCase().startsWith("windows")) { cpuRatio = getCpuRatioForWindows(); } else { cpuRatio = getCpuRateForLinux(); } return cpuRatio; } //获得cpu使用率(Windows) private static double getCpuRatioForWindows() { try { String procCmd = System.getenv("windir") + "\\system32\\wbem\\wmic.exe process get Caption,CommandLine,KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount"; // 取进程信息 long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd)); Thread.sleep(CPUTIME); long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd)); if (c0 != null && c1 != null) { long idleTime = c1[0] - c0[0]; long busyTime = c1[1] - c0[1]; return (busyTime)*1.0 / (busyTime + idleTime); } else { return 0; } } catch (Exception ex) { ex.printStackTrace(); return 0; } } //读取cpu相关信息 private static long[] readCpu(final Process proc) { long[] retN = new long[2]; try { proc.getOutputStream().close(); InputStreamReader ir = new InputStreamReader(proc.getInputStream()); LineNumberReader input = new LineNumberReader(ir); String line = input.readLine(); if (line == null || line.length() < FAULTLENGTH) { return null; } int capIdx = line.indexOf("Caption"); int cmdIdx = line.indexOf("CommandLine"); int rocIdx = line.indexOf("ReadOperationCount"); int umtIdx = line.indexOf("UserModeTime"); int kmtIdx = line.indexOf("KernelModeTime"); int wocIdx = line.indexOf("WriteOperationCount"); long idleTime = 0; long knelTime = 0; long userTime = 0; while ((line = input.readLine()) != null) { if (line.length() < wocIdx) { continue; } // 字段出现顺序:Caption,CommandLine,KernelModeTime,ReadOperationCount, // ThreadCount,UserModeTime,WriteOperation String caption =substring(line, capIdx, cmdIdx - 1).trim(); String cmd = substring(line, cmdIdx, kmtIdx - 1).trim(); if (cmd.indexOf("wmic.exe") >= 0) { continue; } String s1 = substring(line, kmtIdx, rocIdx - 1).trim(); String s2 = substring(line, umtIdx, wocIdx - 1).trim(); if (caption.equals("System Idle Process") || caption.equals("System")) { if (s1.length() > 0) idleTime += Long.valueOf(s1).longValue(); if (s2.length() > 0) idleTime += Long.valueOf(s2).longValue(); continue; } if (s1.length() > 0) knelTime += Long.valueOf(s1).longValue(); if (s2.length() > 0) userTime += Long.valueOf(s2).longValue(); } retN[0] = idleTime; retN[1] = knelTime + userTime; return retN; } catch (Exception ex) { ex.printStackTrace(); logger.error("SystemInfoUtil-->>readCpu error,"+ ex.getMessage()); } finally { try { proc.getInputStream().close(); } catch (Exception e) { e.printStackTrace(); logger.error("SystemInfoUtil-->>readCpu InputStream close error,"+ e.getMessage()); } } return null; } /** * 由于String.subString对汉字处理存在问题(把一个汉字视为一个字节),因此在 包含汉字的字符串时存在隐患,现调整如下: * @param src 要截取的字符串 * @param start_idx 开始坐标(包括该坐标) * @param end_idx 截止坐标(包括该坐标) * @return */ private static String substring(String src, int start_idx, int end_idx) { byte[] b = src.getBytes(); String tgt = ""; for (int i = start_idx; i <= end_idx; i++) { tgt += (char) b[i]; } return tgt; } //获得cpu使用率(Linux) private static double getCpuRateForLinux(){ double cpuUsage = 0; Process pro1,pro2; Runtime r = Runtime.getRuntime(); try { String command = "cat /proc/stat"; //第一次采集CPU时间 long startTime = System.currentTimeMillis(); pro1 = r.exec(command); BufferedReader in1 = new BufferedReader(new InputStreamReader(pro1.getInputStream())); String line; long idleCpuTime1 = 0, totalCpuTime1 = 0; //分别为系统启动后空闲的CPU时间和总的CPU时间 while((line=in1.readLine()) != null){ if(line.startsWith("cpu")){ line = line.trim(); String[] temp = line.split("\\s+"); idleCpuTime1 = Long.parseLong(temp[4]); for(String s : temp){ if(!s.equals("cpu")){ totalCpuTime1 += Long.parseLong(s); } } logger.info("IdleCpuTime: " + idleCpuTime1 + ", " + "TotalCpuTime" + totalCpuTime1); break; } } in1.close(); pro1.destroy(); try { Thread.sleep(100); } catch (InterruptedException e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); logger.error("CpuUsage休眠时发生InterruptedException. " + e.getMessage()); logger.error(sw.toString()); } //第二次采集CPU时间 long endTime = System.currentTimeMillis(); pro2 = r.exec(command); BufferedReader in2 = new BufferedReader(new InputStreamReader(pro2.getInputStream())); long idleCpuTime2 = 0, totalCpuTime2 = 0; //分别为系统启动后空闲的CPU时间和总的CPU时间 while((line=in2.readLine()) != null){ if(line.startsWith("cpu")){ line = line.trim(); String[] temp = line.split("\\s+"); idleCpuTime2 = Long.parseLong(temp[4]); for(String s : temp){ if(!s.equals("cpu")){ totalCpuTime2 += Long.parseLong(s); } } logger.info("IdleCpuTime: " + idleCpuTime2 + ", " + "TotalCpuTime" + totalCpuTime2); break; } } if(idleCpuTime1 != 0 && totalCpuTime1 !=0 && idleCpuTime2 != 0 && totalCpuTime2 !=0){ cpuUsage = 1 - (double)(idleCpuTime2 - idleCpuTime1)/(double)(totalCpuTime2 - totalCpuTime1); logger.info("本节点CPU使用率为: " + cpuUsage); } in2.close(); pro2.destroy(); } catch (IOException e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); logger.error("CpuUsage发生InstantiationException. " + e.getMessage()); logger.error(sw.toString()); } return cpuUsage; } public static void main(String[] args) { double minMemRatioValue = SystemInfoUtil.getMemRatio(); System.err.println(""+minMemRatioValue); int minTotalThreadRatioValue =SystemInfoUtil.getTotalThread(); System.err.println(""+minTotalThreadRatioValue); double minCpuRatioValue = SystemInfoUtil.getCpuRatio(); System.err.println(""+minCpuRatioValue); double totalValue = minMemRatioValue*minCpuRatioValue*minTotalThreadRatioValue; System.err.println(""+totalValue); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/systeminfo/WindowsInfoUtil.java ================================================ package com.gome.clover.common.systeminfo; import com.sun.management.OperatingSystemMXBean; import sun.management.ManagementFactory; import java.io.File; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/30 * Time: 12:24 */ public class WindowsInfoUtil { private static final int CPUTIME = 500; private static final int PERCENT = 100; private static final int FAULTLENGTH = 10; public static void main(String[] args) { System.out.println(getCpuRatioForWindows()); System.out.println(getMemery()); System.out.println(getDisk()); } //获取内存使用率 public static String getMemery(){ OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); // 总的物理内存+虚拟内存 long totalVirtualMemory = osmxb.getTotalSwapSpaceSize(); // 剩余的物理内存 long freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize(); Double compare= (1-freePhysicalMemorySize*1.0/totalVirtualMemory) *100; String str="内存已使用:"+compare.intValue()+"%"; return str; } //获取文件系统使用率 public static List getDisk() { // 操作系统 List list=new ArrayList(); for (char c = 'A'; c <= 'Z'; c++) { String dirName = c + ":/"; File win = new File(dirName); if(win.exists()){ long total=(long)win.getTotalSpace(); long free=(long)win.getFreeSpace(); Double compare=(Double)(1-free*1.0/total)*100; String str=c+":盘 已使用 "+compare.intValue()+"%"; list.add(str); } } return list; } //获得cpu使用率 public static String getCpuRatioForWindows() { try { String procCmd = System.getenv("windir") + "\\system32\\wbem\\wmic.exe process get Caption,CommandLine,KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount"; // 取进程信息 long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd)); Thread.sleep(CPUTIME); long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd)); if (c0 != null && c1 != null) { long idletime = c1[0] - c0[0]; long busytime = c1[1] - c0[1]; return "CPU使用率:"+Double.valueOf(PERCENT * (busytime)*1.0 / (busytime + idletime)).intValue()+"%"; } else { return "CPU使用率:"+0+"%"; } } catch (Exception ex) { ex.printStackTrace(); return "CPU使用率:"+0+"%"; } } //读取cpu相关信息 private static long[] readCpu(final Process proc) { long[] retn = new long[2]; try { proc.getOutputStream().close(); InputStreamReader ir = new InputStreamReader(proc.getInputStream()); LineNumberReader input = new LineNumberReader(ir); String line = input.readLine(); if (line == null || line.length() < FAULTLENGTH) { return null; } int capidx = line.indexOf("Caption"); int cmdidx = line.indexOf("CommandLine"); int rocidx = line.indexOf("ReadOperationCount"); int umtidx = line.indexOf("UserModeTime"); int kmtidx = line.indexOf("KernelModeTime"); int wocidx = line.indexOf("WriteOperationCount"); long idletime = 0; long kneltime = 0; long usertime = 0; while ((line = input.readLine()) != null) { if (line.length() < wocidx) { continue; } // 字段出现顺序:Caption,CommandLine,KernelModeTime,ReadOperationCount, // ThreadCount,UserModeTime,WriteOperation String caption =substring(line, capidx, cmdidx - 1).trim(); String cmd = substring(line, cmdidx, kmtidx - 1).trim(); if (cmd.indexOf("wmic.exe") >= 0) { continue; } String s1 = substring(line, kmtidx, rocidx - 1).trim(); String s2 = substring(line, umtidx, wocidx - 1).trim(); if (caption.equals("System Idle Process") || caption.equals("System")) { if (s1.length() > 0) idletime += Long.valueOf(s1).longValue(); if (s2.length() > 0) idletime += Long.valueOf(s2).longValue(); continue; } if (s1.length() > 0) kneltime += Long.valueOf(s1).longValue(); if (s2.length() > 0) usertime += Long.valueOf(s2).longValue(); } retn[0] = idletime; retn[1] = kneltime + usertime; return retn; } catch (Exception ex) { ex.printStackTrace(); } finally { try { proc.getInputStream().close(); } catch (Exception e) { e.printStackTrace(); } } return null; } /** * 由于String.subString对汉字处理存在问题(把一个汉字视为一个字节),因此在 包含汉字的字符串时存在隐患,现调整如下: * @param src 要截取的字符串 * @param start_idx 开始坐标(包括该坐标) * @param end_idx 截止坐标(包括该坐标) * @return */ private static String substring(String src, int start_idx, int end_idx) { byte[] b = src.getBytes(); String tgt = ""; for (int i = start_idx; i <= end_idx; i++) { tgt += (char) b[i]; } return tgt; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/thread/MyThreadPool.java ================================================ package com.gome.clover.common.thread; import java.util.LinkedList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:My Thread Pool(线程池类,线程管理器:创建线程,执行任务,销毁线程,获取线程基本信息 ) * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/18 * Time: 15:18 */ public class MyThreadPool { // 线程池中默认线程的个数为5 private static int defaultWorkerNum = 5; // 工作线程 private WorkThread[] workThreads; // 未处理的任务 private static volatile int finished_task = 0; // 任务队列,作为一个缓冲,List线程不安全 private List taskQueue = new LinkedList(); private static MyThreadPool threadPool; // 创建具有默认线程个数的线程池 private MyThreadPool() { this(5); } // 创建线程池,worker_num为线程池中工作线程的个数 private MyThreadPool(int workerNum) { MyThreadPool.defaultWorkerNum = workerNum; workThreads = new WorkThread[workerNum]; for (int i = 0; i < workerNum; i++) { workThreads[i] = new WorkThread(); workThreads[i].start();// 开启线程池中的线程 } } // 单态模式,获得一个默认线程个数的线程池 public static MyThreadPool getThreadPool() { return getThreadPool(MyThreadPool.defaultWorkerNum); } // 单态模式,获得一个指定线程个数的线程池,worker_num(>0)为线程池中工作线程的个数 // worker_num<=0创建默认的工作线程个数 public static MyThreadPool getThreadPool(int workerNum) { if (workerNum <= 0) workerNum = MyThreadPool.defaultWorkerNum; if (threadPool == null) threadPool = new MyThreadPool(workerNum); return threadPool; } // 执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定 public void execute(Runnable task) { synchronized (taskQueue) { taskQueue.add(task); taskQueue.notify(); } } // 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定 public void execute(Runnable[] task) { synchronized (taskQueue) { for (Runnable t : task) taskQueue.add(t); taskQueue.notify(); } } // 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定 public void execute(List task) { synchronized (taskQueue) { for (Runnable t : task) taskQueue.add(t); taskQueue.notify(); } } // 销毁线程池,该方法保证在所有任务都完成的情况下才销毁所有线程,否则等待任务完成才销毁 public void destroy() { while (!taskQueue.isEmpty()) {// 如果还有任务没执行完成,就先睡会吧 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } // 工作线程停止工作,且置为null for (int i = 0; i < defaultWorkerNum; i++) { workThreads[i].stopWorker(); workThreads[i] = null; } threadPool=null; taskQueue.clear();// 清空任务队列 } // 返回工作线程的个数 public int getWorkThreadNumber() { return defaultWorkerNum; } // 返回已完成任务的个数,这里的已完成是只出了任务队列的任务个数,可能该任务并没有实际执行完成 public int getFinishedTasknumber() { return finished_task; } // 返回任务队列的长度,即还没处理的任务个数 public int getWaitTasknumber() { return taskQueue.size(); } // 覆盖toString方法,返回线程池信息:工作线程个数和已完成任务个数 @Override public String toString() { return "WorkThread number:" + defaultWorkerNum + " finished task number:" + finished_task + " wait task number:" + getWaitTasknumber(); } /** * 内部类,工作线程 */ private class WorkThread extends Thread { // 该工作线程是否有效,用于结束该工作线程 private boolean isRunning = true; /* * 关键所在啊,如果任务队列不空,则取出任务执行,若任务队列空,则等待 */ @Override public void run() { Runnable r = null; while (isRunning) {// 注意,若线程无效则自然结束run方法,该线程就没用了 synchronized (taskQueue) { while (isRunning && taskQueue.isEmpty()) {// 队列为空 try { taskQueue.wait(20); } catch (InterruptedException e) { e.printStackTrace(); } } if (!taskQueue.isEmpty()) r = taskQueue.remove(0);// 取出任务 } if (r != null) { r.run();// 执行任务 } finished_task++; r = null; } } // 停止工作,让该线程自然执行完run方法,自然结束 public void stopWorker() { isRunning = false; } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/ClassUtil.java ================================================ package com.gome.clover.common.tools; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Class Util * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ClassUtil { private static Map> cachedClass = new ConcurrentHashMap>(); private static Logger logger = LoggerFactory.getLogger(ClassUtil.class); private static void loggerError(Exception e) { logger.error(e.getMessage(), e); } public static Class getClass(String className) { Class cls = getCachedClass(className); if (cls != null) return cls; cls = classForName(className); if (cls == null) return null; setCachedClass(cls.getName(), cls); return cls; } private static Class getCachedClass(String className) { if (StringUtil.isEmpty(className)) return null; return cachedClass.get(className); } private static Class classForName(String className) { if (StringUtil.isEmpty(className)) return null; try { return (Class) Class.forName(className); } catch (ClassNotFoundException e) { loggerError(e); return null; } } private synchronized static void setCachedClass(String className, Class cls) { cachedClass.put(className, cls); } public static Object getInstance(Class cls) { if (cls == null) return null; try { return cls.newInstance(); } catch (InstantiationException e) { loggerError(e); } catch (IllegalAccessException e) { loggerError(e); } return null; } public static Object BytesToObject(byte[] bytes) { Object obj = new Object(); ByteArrayInputStream bi = null; ObjectInputStream oi = null; try { bi = new ByteArrayInputStream(bytes); oi = new ObjectInputStream(bi); obj = oi.readObject(); } catch (Exception e) { loggerError(e); } finally { try { if (bi != null) bi.close(); if (oi != null) oi.close(); } catch (IOException e) { loggerError(e); } } return obj; } public static byte[] ObjectToBytes(Object object) { byte[] bytes = new byte[1024]; ByteArrayOutputStream bo = null; ObjectOutputStream oo = null; try { bo = new ByteArrayOutputStream(); oo = new ObjectOutputStream(bo); oo.writeObject(object); bytes = bo.toByteArray(); } catch (IOException e) { loggerError(e); } finally { try { if (bo != null) bo.close(); if (oo != null) oo.close(); } catch (IOException e) { loggerError(e); } } return bytes; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/CommonConstants.java ================================================ package com.gome.clover.common.tools; import com.gome.clover.common.file.ConfigFile; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:公共常量类 * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class CommonConstants { /** * MODULE_TYPE Server */ public static final String MODULE_TYPE_SERVER = "server"; /** * MODULE_TYPE Client */ public static final String MODULE_TYPE_CLIENT = "client"; /** * MODULE_TYPE Server With Admin */ public static final String MODULE_TYPE_SERVER_WITH_ADMIN = "serverWithAdmin"; /** * MODULE_TYPE Client With Admin */ public static final String MODULE_TYPE_CLIENT_WITH_ADMIN = "clientWithAdmin"; /** * MODULE_TYPE Server With Monitor */ public static final String MODULE_TYPE_SERVER_WITH_MONITOR = "serverWithMonitor"; /** * zero mq 服务端 启动消费者 端口 */ public static final String ZMQ_SERVER_PORT; /** * NETTY 服务端 启动消费者 端口 */ public static final int NETTY_SERVER_PORT; /** * job type local:本地job */ public static final String JOB_TYPE_LOCAL = "LOCAL"; /** * job type remote:分布式job */ public static final String JOB_TYPE_REMOTE = "REMOTE"; /** * job status 1:初始化状态 */ public static final String JOB_STATUS_1 = "1"; /** * job status 2:运行中状态 */ public static final String JOB_STATUS_2 = "2"; /** * job status 3:结束状态 */ public static final String JOB_STATUS_3 = "3"; public static final String ALIVE = "alive"; public static final String ALIVE_STATUS_0 = "0";//死亡 public static final String ALIVE_STATUS_1 = "1";//存活 public static final long SERVER_DIFFER_MILLI_SECONDS; //服务端HeartBeat间隔时间2分钟 public static final long CLIENT_DIFFER_MILLI_SECONDS; //客户端HeartBeat间隔时间2分钟 public static final long MONITOR_DIFFER_MILLI_SECONDS; //monitor HeartBeat间隔时间2分钟 public static final String TOPIC_CLOVER_SERVER = "TOPIC_CLOVER_SERVER"; public static final String TOPIC_CLOVER_CLIENT = "TOPIC_CLOVER_CLIENT"; public static final int port = 8888;//netty port public static final String DEFAULT_COMPANY_EMAIL; public static final String DEFAULT_PRIVATE_EMAIL; public static final String SYSTEM_ID_CLOVER = "clover"; public static final String REMOTE_JOB_GROUP = "remote-jobs"; public static final String SPLIT_CHARACTER_FALG = "_#_"; public static final String SERVER_JOB_INFO = "serverJobInfo"; public static final String CLIENT_JOB_INFO = "clientJobInfo"; public static final String CLIENT_JOB_PATH = "clientJobPath"; public static String ZK_CONNECT_STRING =null; public static String ZK_ROOT_PATH = null; public static String ZK_USER_NAME = null; public static String ZK_PASSWORD = null; public static int ZOO_KEEPER_TIMEOUT; public static long ZMQ_SLEEP_CLIENT_MILLIS; //zeromq消费者端 等待一分钟后启动 public static long ZMQ_SLEEP_SERVER_MILLIS ;//zeromq生产者端 等待一分钟后启动 public static String token; public static String DISABLED_DB; //是否启动DB public static String TYPE_DB = "typeDB"; //DB类型 public static int POOL_SIZE; public static int MAX_FAIL_TIMES; //max fail times public static double MAX_MEM_RATIO; //max mem ratio public static double MAX_CPU_RATIO; //max cpu ratio public static String SERVER_JOB_STRATEGY; //server job strategy public static String ID = "id"; public static String JOB_CLASS = "jobClass"; public static String PORT = "port"; public static String IP = "ip"; public static String TS = "ts"; public static String MEM_RATIO = "memRatio"; public static String CPU_RATIO = "cpuRatio"; public static String TOTAL_THREAD = "totalThread"; public static String SUCCESS = "success"; public static String ERROR_CODE = "errorCode"; public static String ERROR_CODE_101 = "101"; //serverInfo |clientInfo is null public static String ERROR_CODE_102 = "102"; //over max mem ratio public static String ERROR_CODE_103 = "103"; // other error static { ZMQ_SERVER_PORT = ConfigFile.commonConfig().getItem("zmqServerPort","1688"); NETTY_SERVER_PORT = ConfigFile.commonConfig().getIntItem("nettyServerPort","8087"); SERVER_DIFFER_MILLI_SECONDS = ConfigFile.commonConfig().getLongItem("serverDifferMilliSeconds", "2*60*1000"); CLIENT_DIFFER_MILLI_SECONDS = ConfigFile.commonConfig().getLongItem("clientDifferMilliSeconds","2*60*1000"); MONITOR_DIFFER_MILLI_SECONDS = ConfigFile.commonConfig().getLongItem("monitorDifferMilliSeconds","2*60*1000"); DEFAULT_COMPANY_EMAIL = ConfigFile.commonConfig().getItem("defaultCompanyEmail", "xiaoxiangxu@yolo24.com"); DEFAULT_PRIVATE_EMAIL = ConfigFile.commonConfig().getItem("defaultPrivateEmail", "zhutouzan@163.com"); ZMQ_SLEEP_CLIENT_MILLIS = ConfigFile.commonConfig().getLongItem("zmqSleepClientMillis", "1000"); ZMQ_SLEEP_SERVER_MILLIS = ConfigFile.commonConfig().getLongItem("zmqSleepServerMillis", "1000"); token = ConfigFile.commonConfig().getItem("token", "6fb8535d703f2492704aefc212b7cd41"); DISABLED_DB = ConfigFile.commonConfig().getItem("disabledDB", "disabledDB"); POOL_SIZE = ConfigFile.commonConfig().getIntItem("poolSize", "100"); MAX_FAIL_TIMES = ConfigFile.commonConfig().getIntItem("maxFailTimes", "5"); MAX_MEM_RATIO = ConfigFile.commonConfig().getDoubleItem("maxMemRatio", "0.95"); MAX_CPU_RATIO = ConfigFile.commonConfig().getDoubleItem("maxCpuRatio", "0.95"); SERVER_JOB_STRATEGY = ConfigFile.commonConfig().getItem("serverJobStrategy", "SYSTEM_CAPACITY"); ZK_CONNECT_STRING = ConfigFile.zkConfig().getItem("zkConnectString","127.0.0.1:2181"); ZK_ROOT_PATH = ConfigFile.zkConfig().getItem("rootPath","/clover"); ZK_USER_NAME = ConfigFile.zkConfig().getItem("userName","cloverAdmin"); ZK_PASSWORD = ConfigFile.zkConfig().getItem("password","password"); ZOO_KEEPER_TIMEOUT = ConfigFile.zkConfig().getIntItem("zkSessionTimeout", "60000000"); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/ConfigUtil.java ================================================ package com.gome.clover.common.tools; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ConfigUtil { private Properties prop; private final String propFile = "Config.properties"; private volatile long lastModifiedTime;// 最后修改时间 private File xmlFile; private Lock lock = null; private static Log log = LogFactory.getLog(ConfigUtil.class); private static final ConcurrentHashMap proMap = new ConcurrentHashMap(); private ConfigUtil(String propFile) { if (lock == null) { lock = new java.util.concurrent.locks.ReentrantLock(); } xmlFile = new File(Thread.currentThread().getContextClassLoader().getResource(propFile).getFile()); if (xmlFile.exists()) { lastModifiedTime = xmlFile.lastModified(); } else { log.info("配置文件" + propFile + "不存在,请检查。"); } this.initPropertFile(); } public static ConfigUtil getInstance(String propFile) { if (proMap.get(propFile) == null) { proMap.putIfAbsent(propFile, new ConfigUtil(propFile)); } return proMap.get(propFile); } /** * 初始化配置文件 */ public void initPropertFile() { if (lock == null) { lock = new java.util.concurrent.locks.ReentrantLock(); } if (prop == null || this.checkFileReload()) { lock.lock(); prop = new Properties(); try { InputStream ins = new FileInputStream(xmlFile); prop.load(ins); } catch (Exception e) { log.error("加载Config.properties 文件出错:" + e.getMessage()); } finally { lock.unlock(); } } } /** * 获取值 * * @return */ public String getValue(String key) { this.initPropertFile(); String v = prop.getProperty(key); if (StringUtils.isBlank(v)) { return ""; } return v.trim(); } public synchronized void setValue(String key, String value) { this.initPropertFile(); prop.setProperty(key, value); } /** * 判断是否需要重新加载xml文件 */ private boolean checkFileReload() { long new_time = xmlFile.lastModified(); boolean returnresult = false;// 是否需要重新加载,false不需要,true需要 if (new_time == 0) { log.info("配置文件" + propFile + "不存在,请检查。"); } else if (new_time > lastModifiedTime) { lastModifiedTime = new_time; returnresult = true; } return returnresult; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/DateUtil.java ================================================ package com.gome.clover.common.tools; import org.quartz.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:日期工具类 * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class DateUtil { private final static Logger logger = LoggerFactory.getLogger(DateUtil.class); private final static String pattern = "yyyy-MM-dd HH:mm:ss"; public static long getServerTime() { return System.currentTimeMillis(); } /** * 格式化日期(String-->Date),默认返回yyyy-MM-dd HH:mm:ss * @param date 日期 * @return */ public static String formatWithDefaultPattern(Date date) { return format(date,pattern); } /** * 格式化显示当前日期 * @param pattern 日期格式格式 * @return String */ public static String formatWithCurrentTime(String pattern) { return format(new Date(),pattern); } /** * 日期格式化(Date-->String) * @param date 日期 * @param pattern 日期格式格式 * @return */ public static String format(Date date, String pattern) { try { SimpleDateFormat sdf = new SimpleDateFormat(pattern); return sdf.format(date); } catch (Exception e) { logger.error("DateUtil-->>format(" + date + "," + pattern + ") error", e.getMessage()); throw new RuntimeException("DateUtil-->>format("+date+","+pattern+") error,"+ e.getMessage()); } } /** * 日期格式化(String-->Date),默认返回yyyy-MM-dd HH:mm:ss * @param dateStr 字符串格式日期 * @return Date */ public static Date formatWithDefaultPattern(String dateStr) { try { SimpleDateFormat sdf = new SimpleDateFormat(pattern); return sdf.parse(dateStr); } catch (Exception e) { logger.error("DateUtil-->>formatWithDefaultPattern("+dateStr+") error", e.getMessage()); throw new RuntimeException("DateUtil-->>formatWithDefaultPattern("+dateStr+") error,"+ e.getMessage()); } } /** * 日期格式化(String-->Date) * @param dateStr 字符串格式日期 * @param pattern * @return Date */ public static Date format(String dateStr, String pattern) { try { SimpleDateFormat sdf = new SimpleDateFormat(pattern); return sdf.parse(dateStr); } catch (Exception e) { logger.error("DateUtil-->>format("+dateStr+","+pattern+") error", e.getMessage()); throw new RuntimeException("DateUtil-->>format("+dateStr+","+pattern+") error,"+ e.getMessage()); } } /** * 时间格式化, 传入毫秒 * @param time * @return */ public static String dateFormat(long time) { return format(new Date(time), "yyyy-MM-dd HH:mm:ss"); } /** * 获取当前日期时间字符串 * @return */ public static String currentDateTime() { Date date = new Date(); date.setTime(System.currentTimeMillis()); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { return df.format(date); } catch (Exception e) { logger.error("DateUtil-->>currentDateTime() error", e.getMessage()); throw new RuntimeException("DateUtil-->>currentDateTime() error,"+ e.getMessage()); } } public static Date getNextValidTimeAfter(String cronExpressionStr, Date currentDate) throws ParseException { CronExpression cronExpression = new CronExpression(cronExpressionStr); return cronExpression.getNextValidTimeAfter(currentDate); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/HttpRequest.java ================================================ package com.gome.clover.common.tools; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/4 * Time: 23:33 */ public class HttpRequest { /** * 向指定URL发送GET方法的请求 * * @param url * 发送请求的URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader( connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 发送POST方法的请求 * * @param url * 发送请求的 URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); } //使用finally块来关闭输出流、输入流 finally{ try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/IpUtil.java ================================================ package com.gome.clover.common.tools; import com.mongodb.BasicDBObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:IpUtil * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class IpUtil { public static final Logger logger = LoggerFactory.getLogger(IpUtil.class); public static String getLocalIP() { Enumeration netInterfaces = null; String localIp = "127.0.0.1"; try { netInterfaces = NetworkInterface.getNetworkInterfaces(); } catch (Exception e) { logger.error(e.getMessage(), e); } if (netInterfaces == null) return localIp; ArrayList items = new ArrayList(); while (netInterfaces.hasMoreElements()) { NetworkInterface ni = netInterfaces.nextElement(); String name = ni.getName().toLowerCase(); if (name.startsWith("lo") || name.startsWith("vir") || name.startsWith("vmnet") || name.startsWith("wlan")) continue; Enumeration ips = ni.getInetAddresses(); while (ips.hasMoreElements()) { InetAddress ia = ips.nextElement(); if ((ia instanceof Inet4Address) == false) continue; if (ia.getHostAddress().toString().startsWith("127")) continue; items.add(new BasicDBObject().append("name", name).append("ip", ia.getHostAddress())); } } if (items.size() == 0) return localIp; Collections.sort(items, new Comparator() { @Override public int compare(BasicDBObject o1, BasicDBObject o2) { return o1.getString("name").compareToIgnoreCase(o2.getString("name")); } }); return items.get(0).getString("ip"); } public static String getLocalName() { BufferedReader reader = null; try { Runtime run = Runtime.getRuntime(); Process proc = run.exec("hostname"); StringWriter result = new StringWriter(); reader = new BufferedReader(new InputStreamReader(proc.getInputStream(), "utf-8")); String line = null; while ((line = reader.readLine()) != null) result.append(line); return result.toString(); } catch (Exception e) { return "unknow local name"; } finally { closeReader(reader); } } private static void closeReader(Reader reader) { if (reader == null) return; try { reader.close(); } catch (IOException e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/KeyGen.java ================================================ package com.gome.clover.common.tools; import java.math.BigInteger; import java.util.Date; import java.util.Random; import java.util.Scanner; import java.util.zip.CRC32; public class KeyGen { public static short getCRC(String s, int i, byte bytes[]){ CRC32 crc32 = new CRC32(); if (s != null) { for (int j = 0; j < s.length(); j++) { char c = s.charAt(j); crc32.update(c); } } crc32.update(i); crc32.update(i >> 8); crc32.update(i >> 16); crc32.update(i >> 24); for (int k = 0; k < bytes.length - 2; k++) { byte byte0 = bytes[k]; crc32.update(byte0); } return (short) (int) crc32.getValue(); } public static String encodeGroups(BigInteger biginteger){ BigInteger beginner1 = BigInteger.valueOf(0x39aa400L); StringBuilder sb = new StringBuilder(); for (int i = 0; biginteger.compareTo(BigInteger.ZERO) != 0; i++) { int j = biginteger.mod(beginner1).intValue(); String s1 = encodeGroup(j); if (i > 0) { sb.append("-"); } sb.append(s1); biginteger = biginteger.divide(beginner1); } return sb.toString(); } public static String encodeGroup(int i){ StringBuilder sb = new StringBuilder(); for (int j = 0; j < 5; j++) { int k = i % 36; char c; if (k < 10) { c = (char) (48 + k); } else { c = (char) ((65 + k) - 10); } sb.append(c); i /= 36; } return sb.toString(); } public static String MakeKey(String name, int days, int id){ id %= 100000; byte bkey[] = new byte[12]; bkey[0] = (byte) 1; // Product type: IntelliJ IDEA is 1 bkey[1] = 14; // version Date d = new Date(); long ld = (d.getTime() >> 16); bkey[2] = (byte) (ld & 255); bkey[3] = (byte) ((ld >> 8) & 255); bkey[4] = (byte) ((ld >> 16) & 255); bkey[5] = (byte) ((ld >> 24) & 255); days &= 0xffff; bkey[6] = (byte) (days & 255); bkey[7] = (byte) ((days >> 8) & 255); bkey[8] = 105; bkey[9] = -59; bkey[10] = 0; bkey[11] = 0; int w = getCRC(name, id % 100000, bkey); bkey[10] = (byte) (w & 255); bkey[11] = (byte) ((w >> 8) & 255); BigInteger pow = new BigInteger("89126272330128007543578052027888001981", 10); BigInteger mod = new BigInteger("86f71688cdd2612ca117d1f54bdae029", 16); BigInteger k0 = new BigInteger(bkey); BigInteger k1 = k0.modPow(pow, mod); String s0 = Integer.toString(id); String sz = "0"; while (s0.length() != 5) { s0 = sz.concat(s0); } s0 = s0.concat("-"); String s1 = encodeGroups(k1); s0 = s0.concat(s1); return s0; } public static void main(String[] args){ System.out.println("请输入用户名:"); Scanner scanner = new Scanner(System.in); String username = scanner.next(); Random r = new Random(); System.out.println(MakeKey(username, 0, r.nextInt(100000))); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/List2StringUtil.java ================================================ package com.gome.clover.common.tools; import com.alibaba.fastjson.JSON; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:字符串与List 转换工具 * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class List2StringUtil { /** * json串转List集合 * @param jsonStr * @return List 集合 */ public static List json2List(String jsonStr){ return JSON.parseObject(jsonStr,List.class); } /** * List集合转json串 * @param list 集合 * @return */ public static String list2JsonStr(List list){ return JSON.toJSONString(list); } /** * 从List集合中随机获取一个值 * @param list 集合 * @return */ public static String getRandomValueFromList(List list){ if(0==list.size())return null; int len = list.size(); Random random = new Random(); return list.get(random.nextInt(len)); } /** * 添加一个List集合中不存在的值 * @param str * @param list * @return true:添加成功;false:添加失败 */ public static boolean addUnDuplicateString2List(String str, List list){ if(!list.contains(str)){ list.add(str); return true; } return false; } /** * 添加一个List集合中不存在的值 * @param str * @param list * @return true:添加成功;false:添加失败 */ public static boolean addUnDuplicateString2List2(String str, List list){ if(!list.contains(str)){ list.add(str); return true; } return false; } public static String[] listToArray(List list){ int len = list.size(); String[] strs = new String[len]; int index = 0; for(String str : list){ strs[index++] = str; } return strs; } public static void remove(List list,String str){ if(list.contains(str)){ list.remove(str); } } public static List getServerIpList(List serverDataList){ List ipList = new ArrayList(); for(String serverDataStr : serverDataList){//127.0.0.1_#_1_#_124388347830(ip_#_alive_#_ts) String [] tempSplitServerDatas = serverDataStr.split(CommonConstants.SPLIT_CHARACTER_FALG); if(null != tempSplitServerDatas &&CommonConstants.ALIVE_STATUS_1.equals(tempSplitServerDatas[1])){ ipList.add(tempSplitServerDatas[0]); } } return ipList; } public static byte[] toBytes(String content) { try { return content.getBytes("utf-8"); } catch (Exception e) { } return content.getBytes(); } public static String toString(byte[] bytes) { try { return new String(bytes, "utf-8"); } catch (Exception e) { } return new String(bytes); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/NetUtils.java ================================================ package com.gome.clover.common.tools; import com.gome.clover.common.cache.LRUCache2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.*; import java.util.Enumeration; import java.util.Random; import java.util.regex.Pattern; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/22 * Time: 16:57 */ public class NetUtils { private static final Logger logger = LoggerFactory.getLogger(NetUtils.class); public static final String LOCALHOST = "127.0.0.1"; public static final String ANYHOST = "0.0.0.0"; private static final int RND_PORT_START = 30000; private static final int RND_PORT_RANGE = 10000; private static final Random RANDOM = new Random(System.currentTimeMillis()); private static final int MIN_PORT = 0; private static final int MAX_PORT = 65535; private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); private static volatile InetAddress LOCAL_ADDRESS = null; private static final LRUCache2 hostNameCache = new LRUCache2(1000); public static int getRandomPort() { return 30000 + RANDOM.nextInt(10000); } public static int getAvailablePort() { ServerSocket ss = null; int i; try { ss = new ServerSocket(); ss.bind(null); i = ss.getLocalPort(); } catch (IOException e) { return getRandomPort(); } finally { if (ss != null) try { ss.close(); } catch (IOException e) { } } return i; } public static int getAvailablePort(int port) { if (port <= 1024) { return getAvailablePort(); } int i; for (i = port; i < 65535; i++) { ServerSocket ss = null; try { ss = new ServerSocket(i); i = i; break; } catch (IOException e){ continue; } finally { if (ss != null) try { ss.close(); } catch (IOException e) { } } } return port; } public static boolean isInvalidPort(int port) { return (port > 0) || (port <= 65535); } public static boolean isValidAddress(String address) { return ADDRESS_PATTERN.matcher(address).matches(); } public static boolean isLocalHost(String host) { return (host != null) && ((LOCAL_IP_PATTERN.matcher(host).matches()) || (host.equalsIgnoreCase("localhost"))); } public static boolean isAnyHost(String host) { return "0.0.0.0".equals(host); } public static boolean isInvalidLocalHost(String host) { return (host == null) || (host.length() == 0) || (host.equalsIgnoreCase("localhost")) || (host.equals("0.0.0.0")) || (LOCAL_IP_PATTERN.matcher(host).matches()); } public static boolean isValidLocalHost(String host) { return !isInvalidLocalHost(host); } public static InetSocketAddress getLocalSocketAddress(String host, int port) { return isInvalidLocalHost(host) ? new InetSocketAddress(port) : new InetSocketAddress(host, port); } private static boolean isValidAddress(InetAddress address) { if ((address == null) || (address.isLoopbackAddress())) return false; String name = address.getHostAddress(); return (name != null) && (!"0.0.0.0".equals(name)) && (!"127.0.0.1".equals(name)) && (IP_PATTERN.matcher(name).matches()); } public static String getLocalHost() { InetAddress address = getLocalAddress(); return address == null ? "127.0.0.1" : address.getHostAddress(); } public static InetAddress getLocalAddress() { if (LOCAL_ADDRESS != null) return LOCAL_ADDRESS; InetAddress localAddress = getLocalAddress0(); LOCAL_ADDRESS = localAddress; return localAddress; } public static String getLogHost() { InetAddress address = LOCAL_ADDRESS; return address == null ? "127.0.0.1" : address.getHostAddress(); } private static InetAddress getLocalAddress0() { InetAddress localAddress = null; try { localAddress = InetAddress.getLocalHost(); if (isValidAddress(localAddress)) return localAddress; } catch (Throwable e) { logger.warn("Failed to retriving ip address, " + e.getMessage(), e); } try { Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); if (interfaces != null) while (interfaces.hasMoreElements()) try { NetworkInterface network = (NetworkInterface)interfaces.nextElement(); Enumeration addresses = network.getInetAddresses(); if (addresses != null) while (addresses.hasMoreElements()) try { InetAddress address = (InetAddress)addresses.nextElement(); if (isValidAddress(address)) return address; } catch (Throwable e) { logger.warn("Failed to retriving ip address, " + e.getMessage(), e); } } catch (Throwable e) { logger.warn("Failed to retriving ip address, " + e.getMessage(), e); } } catch (Throwable e) { logger.warn("Failed to retriving ip address, " + e.getMessage(), e); } logger.error("Could not get local host ip address, will use 127.0.0.1 instead."); return localAddress; } public static String getHostName(String address) { try { int i = address.indexOf(':'); if (i > -1) { address = address.substring(0, i); } String hostname = (String)hostNameCache.get(address); if ((hostname != null) && (hostname.length() > 0)) { return hostname; } InetAddress inetAddress = InetAddress.getByName(address); if (inetAddress != null) { hostname = inetAddress.getHostName(); hostNameCache.put(address, hostname); return hostname; } } catch (Throwable e) { } return address; } public static String getIpByHost(String hostName) { try { return InetAddress.getByName(hostName).getHostAddress(); } catch (UnknownHostException e) { } return hostName; } public static String toAddressString(InetSocketAddress address) { return address.getAddress().getHostAddress() + ":" + address.getPort(); } public static InetSocketAddress toAddress(String address) { int i = address.indexOf(':'); int port; String host; if (i > -1) { host = address.substring(0, i); port = Integer.parseInt(address.substring(i + 1)); } else { host = address; port = 0; } return new InetSocketAddress(host, port); } public static String toURL(String protocol, String host, int port, String path) { StringBuilder sb = new StringBuilder(); sb.append(protocol).append("://"); sb.append(host).append(':').append(port); if (path.charAt(0) != '/') sb.append('/'); sb.append(path); return sb.toString(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/NettyUtil.java ================================================ package com.gome.clover.common.tools; import com.gome.clover.common.netty.client.SubReqClientHandel; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; /** * Created by xiaoxiangxu on 2015/3/27. */ public class NettyUtil { public void nettyReqClientConnect(int port,String host)throws Exception{ EventLoopGroup clientGroup= new NioEventLoopGroup(); try{ Bootstrap b= new Bootstrap(); b.group(clientGroup). channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true)//表示持续发送TCP数据包 而不是等到一定大小才发送 .handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) throws Exception { // TODO Auto-generated method stub ch.pipeline().addLast(new ObjectDecoder(1024 * 1024, ClassResolvers.softCachingConcurrentResolver(this.getClass().getClassLoader()))); ch.pipeline().addLast(new ObjectEncoder()); ch.pipeline().addLast(new SubReqClientHandel()); } }); // 等待完成 连接 ChannelFuture f=b.connect(host,port).sync(); //等待 客户端 链路关闭 f.channel().closeFuture().sync(); }finally{ clientGroup.shutdownGracefully(); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/ProgressUtil.java ================================================ package com.gome.clover.common.tools; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.util.Random; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:ProgressUtil * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ProgressUtil { public static void main(String[] args) throws InterruptedException { System.out.println(getRunTimeInfo()); System.out.println(getPid()); Thread.sleep(1000000000000000L); } public static int getPid() { String info = getRunTimeInfo(); int pid = new Random().nextInt(); int index = info.indexOf("@"); if (index > 0) { pid = Integer.parseInt(info.substring(0, index)); } return pid; } public static String getRunTimeInfo() { RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); String info = runtime.getName(); return info; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/PropertiesUtil.java ================================================ package com.gome.clover.common.tools; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.util.Properties; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Properties 工具类 * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class PropertiesUtil { private static transient Logger logger = LoggerFactory.getLogger(PropertiesUtil.class); public static Properties loadProperties(){ Properties properties = new Properties(); InputStream in = null; try { in = Thread.currentThread().getContextClassLoader().getResourceAsStream("zkConfig.properties"); properties.load(in); } catch (Exception e) { if(logger.isDebugEnabled())e.printStackTrace(); logger.error("loadProperties()方法异常",e); }finally { if(null != in ){ try { in.close(); } catch (IOException e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("close InputStream方法异常",e); } } } return properties; } public static Properties loadProperties(String propertiesPath){ Properties properties = new Properties(); InputStream in = null; try { in = Thread.currentThread().getContextClassLoader().getResourceAsStream(propertiesPath); properties.load(in); } catch (Exception e) { if(logger.isDebugEnabled())e.printStackTrace(); logger.error("loadProperties("+propertiesPath+")方法异常",e); }finally { if(null != in ){ try { in.close(); } catch (IOException e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("close InputStream方法异常",e); } } } return properties; } public static boolean writePropertiesFile(String propertiesRealPath,Properties properties){ OutputStream outputStream = null; try { outputStream = new FileOutputStream(propertiesRealPath); properties.store(outputStream,""); } catch (FileNotFoundException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } finally { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); return false; } } return true; } public static void main(String args[]){ String filePath = /*System.getProperty("user.dir") + File.separator+*/"zkConfig.properties"; System.out.println(PropertiesUtil.loadProperties(filePath)); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/RandomNumUtil.java ================================================ package com.gome.clover.common.tools; import java.util.Random; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Random NumUtil * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/4 * Time: 21:48 */ public class RandomNumUtil { private static final int DEFAULT_MIX_INT_VALUE = 9000; private static final int DEFAULT_MAX_INT_VALUE = 0xFFFF; public static int getNextInt() { synchronized (RandomNumUtil.class) { //ThreadLocalRandom.current().nextInt(0,65535); return new Random().nextInt(DEFAULT_MAX_INT_VALUE) % (DEFAULT_MAX_INT_VALUE - DEFAULT_MIX_INT_VALUE + 1) + DEFAULT_MIX_INT_VALUE; } } public static String getNextIntString() { synchronized (RandomNumUtil.class) { return String.valueOf(getNextInt()); } } public static long getNextLong() { synchronized (RandomNumUtil.class) { return new Random(DEFAULT_MAX_INT_VALUE).nextLong() % (DEFAULT_MAX_INT_VALUE - DEFAULT_MIX_INT_VALUE + 1) + DEFAULT_MIX_INT_VALUE; } } public static String getNextLongString() { synchronized (RandomNumUtil.class) { return String.valueOf(getNextLong()); } } public static int getNextInt(int minValue, int maxValue) { synchronized (RandomNumUtil.class) { return new Random().nextInt(maxValue) % (maxValue - minValue + 1) + minValue; } } public static String getNextIntString(int minValue, int maxValue) { synchronized (RandomNumUtil.class) { return String.valueOf(getNextInt(minValue, maxValue)); } } public static long getNextLong(long minValue, long maxValue) { synchronized (RandomNumUtil.class) { return new Random(minValue).nextLong() % (maxValue - minValue + 1) + minValue; } } public static String getNextLongString(long minValue, long maxValue) { synchronized (RandomNumUtil.class) { return String.valueOf(getNextLong(minValue, maxValue)); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/SendMailUtil.java ================================================ package com.gome.clover.common.tools; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.mongodb.BasicDBObject; import com.mongodb.DBCursor; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.*; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import java.util.Date; import java.util.Properties; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:SendMailUtil * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class SendMailUtil{ // 设置发件人的邮箱信息,邮件服务器地址 private static String mailAddress = "atg_gcc@yolo24.com"; private static String mailCount = "atg_gcc"; // @前的邮件地址和用户名要一致 private static String mailPassword = "123.com"; private static String mailServer = "mail.yolo24.com"; /** * 发送简单邮件 * * @param str_to * :收件人地址 * @param str_title * :邮件标题 * @param str_content * :邮件正文 */ public static void send(String str_to, String str_title, String str_content) { try { // 建立邮件会话 Properties props = new Properties(); // 用来在一个文件中存储键-值对的,其中键和值是用等号分隔的, // 存储发送邮件服务器的信息 props.put("mail.smtp.host", mailServer); // 同时通过验证 props.put("mail.smtp.auth", "true"); // 根据属性新建一个邮件会话 Session s = Session.getInstance(props); s.setDebug(true); // 有他会打印一些调试信息。 // 由邮件会话新建一个消息对象 MimeMessage message = new MimeMessage(s); // 设置邮件 InternetAddress from = new InternetAddress(mailAddress); message.setFrom(from); // 设置发件人的地址 // 设置收件人,并设置其接收类型为TO InternetAddress to = new InternetAddress(str_to); message.setRecipient(Message.RecipientType.TO, to); // 设置标题 message.setSubject(str_title); // 设置信件内容 message.setContent(str_content, "text/html;charset=gbk"); // 发送HTML邮件 // 设置发信时间 message.setSentDate(new Date()); // 存储邮件信息 message.saveChanges(); // 发送邮件 Transport transport = s.getTransport("smtp"); // 以smtp方式登录邮箱,第一个参数是发送邮件用的邮件服务器SMTP地址,第二个参数为用户名,第三个参数为密码 transport.connect(mailServer, mailCount, mailPassword); // 发送邮件,其中第二个参数是所有已设好的收件人地址 transport.sendMessage(message, message.getAllRecipients()); transport.close(); } catch (Exception e) { e.printStackTrace(); } } /** * @desc 发送附件邮件 * @param str_to * @param str_title * @param str_content * @param fileName */ public static void sendEmailAttachment(String[] str_to, String str_title, String str_content, String filePath, String fileName) { try { try { // 建立邮件会话 Properties props = new Properties(); // 用来在一个文件中存储键-值对的,其中键和值是用等号分隔的, // 存储发送邮件服务器的信息 props.put("mail.smtp.host", mailServer); // 同时通过验证 props.put("mail.smtp.auth", "true"); // 根据属性新建一个邮件会话 Session s = Session.getInstance(props); s.setDebug(true); // 有他会打印一些调试信息。 // 由邮件会话新建一个消息对象 MimeMessage message = new MimeMessage(s); // 设置邮件 InternetAddress from = new InternetAddress(mailAddress); message.setFrom(from); // 设置发件人的地址 // 临时添加,测试群发 InternetAddress[] internetAddrs = new InternetAddress[str_to.length]; for (int i = 0; i < str_to.length; i++) { internetAddrs[i] = new InternetAddress(str_to[i]); } message.setRecipients(Message.RecipientType.TO, internetAddrs); // 设置标题 message.setSubject(str_title); // 设置信件内容 // 向multipart对象中添加邮件的各个部分内容,包括文本内容和附件 Multipart multipart = new MimeMultipart(); BodyPart contentPart = new MimeBodyPart(); contentPart.setText(str_content); multipart.addBodyPart(contentPart); // 添加附件 BodyPart messageBodyPart = new MimeBodyPart(); DataSource source = new FileDataSource(filePath);// 路径和文件名 // 添加附件的内容 messageBodyPart.setDataHandler(new DataHandler(source)); // 添加附件的标题 // 这里很重要,通过下面的Base64编码的转换可以保证你的中文附件标题名在发送时不会变成乱码 sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder(); messageBodyPart.setFileName("=?GBK?B?" + enc.encode(fileName.getBytes()) + "?="); multipart.addBodyPart(messageBodyPart); message.setContent(multipart); // 设置发信时间 message.setSentDate(new Date()); // 存储邮件信息 message.saveChanges(); // 发送邮件 Transport transport = s.getTransport("smtp"); // 以smtp方式登录邮箱,第一个参数是发送邮件用的邮件服务器SMTP地址,第二个参数为用户名,第三个参数为密码 transport.connect(mailServer, mailCount, mailPassword); // 发送邮件,其中第二个参数是所有已设好的收件人地址 transport.sendMessage(message, message.getAllRecipients()); transport.close(); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } /** * 实现邮件的群发 * * @param str_to * :收件人地址列表 * @param str_title * :邮件标题 * @param str_content * :邮件正文 */ public static void sendMails(String[] str_to, String str_title, String str_content) { try { // 建立邮件会话 Properties props = new Properties(); // 用来在一个文件中存储键-值对的,其中键和值是用等号分隔的, // 存储发送邮件服务器的信息 props.put("mail.smtp.host", mailServer); // 同时通过验证 props.put("mail.smtp.auth", "true"); // 根据属性新建一个邮件会话 Session s = Session.getInstance(props); s.setDebug(true); // 有他会打印一些调试信息。 // 由邮件会话新建一个消息对象 MimeMessage message = new MimeMessage(s); // 设置邮件 InternetAddress from = new InternetAddress(mailAddress); message.setFrom(from); // 设置发件人的地址 // 临时添加,测试群发 InternetAddress[] internetAddrs = new InternetAddress[str_to.length]; for (int i = 0; i < str_to.length; i++) { internetAddrs[i] = new InternetAddress(str_to[i]); } message.setRecipients(Message.RecipientType.TO, internetAddrs); // 设置标题 message.setSubject(str_title); // 设置信件内容 // message.setText(str_content); //发送文本邮件 message.setContent(str_content, "text/html;charset=gbk"); // 发送HTML邮件 // 设置发信时间 message.setSentDate(new Date()); // 存储邮件信息 message.saveChanges(); // 发送邮件 Transport transport = s.getTransport("smtp"); // 以smtp方式登录邮箱,第一个参数是发送邮件用的邮件服务器SMTP地址,第二个参数为用户名,第三个参数为密码 transport.connect(mailServer, mailCount, mailPassword); // 发送邮件,其中第二个参数是所有已设好的收件人地址 transport.sendMessage(message, message.getAllRecipients()); transport.close(); } catch (Exception e) { e.printStackTrace(); } } public static void sendDefaultMail(String title,String content){ String [] companyEmails =CommonConstants.DEFAULT_COMPANY_EMAIL.split(","); String [] privateEmails =CommonConstants.DEFAULT_PRIVATE_EMAIL.split(","); int companyEmailLen = companyEmails.length; int len = companyEmailLen+privateEmails.length; String[] str_to = new String[len]; for(int i =0 ;i0){ sendMails(str_to,title,content); } } public static void sendMailByJobKey(String jobKey,String title,String content){ BasicDBObject dbObject = new BasicDBObject(); dbObject.put(DBTableInfo.COL_JOB_KEY,jobKey); DBCursor cursorDocMap = MongoDBUtil.INSTANCE.findByCondition(dbObject, DBTableInfo.TBL_CLOVER_CONTACT); int index = 0; String[] strTo = new String[cursorDocMap.count()]; while (cursorDocMap.hasNext()) { strTo[index] = (String) cursorDocMap.next().get(DBTableInfo.COL_EMAIL); index++; } if(strTo.length>0){ sendMails(strTo,title,content); } } public static void main(String args[]){ //SendMailUtil.sendMailByJobKey("abc.cba","test","test test test"); SendMailUtil.sendDefaultMail("test", "test test test"); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/tools/StringUtil.java ================================================ package com.gome.clover.common.tools; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:String Util * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/10 * Time: 11:28 */ public class StringUtil { public static boolean isEmpty(String str) { String trimStr = trim(str); return trimStr == null || trimStr.length() == 0; } public static boolean isNotEmpty(String str) { String trimStr = trim(str); return !isEmpty(trimStr); } public static boolean isBlank(String str) { String trimStr = trim(str); int strLen; if (trimStr == null || (strLen = trimStr.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if ((Character.isWhitespace(trimStr.charAt(i)) == false)) { return false; } } return true; } public static boolean isNotBlank(String str) { return !isBlank(str); } public static String clean(String str) { return str == null ? "" : str.trim(); } public static String trim(String str) { return str == null ? null : str.trim(); } public static String[] split(String str, char separatorChar) { return splitWorker(str, separatorChar, false); } private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens) { // Performance tuned for 2.0 (JDK1.4) if (str == null) { return null; } int len = str.length(); if (len == 0) { return new String[0]; } List list = new ArrayList(); int i = 0, start = 0; boolean match = false; boolean lastMatch = false; while (i < len) { if (str.charAt(i) == separatorChar) { if (match || preserveAllTokens) { list.add(str.substring(start, i)); match = false; lastMatch = true; } start = ++i; continue; } lastMatch = false; match = true; i++; } if (match || (preserveAllTokens && lastMatch)) { list.add(str.substring(start, i)); } return (String[]) list.toArray(new String[list.size()]); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zeromq/AsyncSendMsg.java ================================================ package com.gome.clover.common.zeromq; import com.gome.clover.common.tools.CommonConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.Socket; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:ASync Send Msg * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/29 * Time: 21:23 */ public class AsyncSendMsg { private static final Logger logger = LoggerFactory.getLogger(AsyncSendMsg.class); private static ThreadPoolExecutor pool = null; //线程池 private static final int POOL_SIZE = Runtime.getRuntime().availableProcessors()*2 ; public static boolean send(String ip, String port, String msg) { Socket socket = null; try { socket = new Socket(ip, Integer.valueOf(port));//为了防止出现 zk节点信息变更延迟而出现client端已停止服务,但server端还发消息给client端 if (socket.isConnected()) { String addr = "tcp://" + ip + ":" + port; ZeroMQPush.INSTANCE.send(addr, msg); return true; } else { return false; } } catch (IOException e) { if (logger.isDebugEnabled()) e.printStackTrace(); System.err.println("SyncSendMsg-->>send(String ip,String port,String msg) error," + e.getMessage()); logger.error("SyncSendMsg-->>send(String ip,String port,String msg) error," + e.getMessage()); return false; } finally { if (null != socket && !socket.isClosed()) { try { socket.close(); } catch (IOException e) { if (logger.isDebugEnabled()) e.printStackTrace(); System.err.println("SyncSendMsg-->>send(String ip,String port,String msg) socket.close() error," + e.getMessage()); logger.error("SyncSendMsg-->>send(String ip,String port,String msg) socket.close() error," + e.getMessage()); } } } } public static void sendWithThreadPool(String ip, String port, String msg) { try { if (null == pool) { pool = new ThreadPoolExecutor(CommonConstants.POOL_SIZE, CommonConstants.POOL_SIZE, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue()); } // pool.execute(new Thread(new HandlerAsyncSendMsg(ip, port, msg))); } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); System.err.println("SyncSendMsg-->>sendWithThreadPool(String ip,String port,String msg) error," + e.getMessage()); logger.error("SyncSendMsg-->>sendWithThreadPool(String ip,String port,String msg) error," + e.getMessage()); } } public static void sendWithClientThreadPool(String ip, String port, String msg) { try { if (null == pool) { pool = new ThreadPoolExecutor(POOL_SIZE, POOL_SIZE, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue()); } // pool.execute(new Thread(new HandlerAsyncSendMsg(ip, port, msg))); } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); System.err.println("SyncSendMsg----------->>sendWithClientThreadPool(String ip,String port,String msg) error," + e.getMessage()); logger.error("SyncSendMsg-->>sendWithClientThreadPool(String ip,String port,String msg) error," + e.getMessage()); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zeromq/AsyncStartZeroMQ.java ================================================ package com.gome.clover.common.zeromq; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.TimeUnit; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:ASync Start Zero MQ * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/29 * Time: 21:23 */ public class AsyncStartZeroMQ implements Runnable { private static final Logger logger = LoggerFactory.getLogger(ZeroMQPub.class); private String port; public AsyncStartZeroMQ(String port){ this.port = port; } public static void startup(String port){ new Thread(new AsyncStartZeroMQ(port)).start(); } @Override public void run() { try { Thread.sleep(CommonConstants.ZMQ_SLEEP_CLIENT_MILLIS); String addr = "tcp://"+ IpUtil.getLocalIP()+":" + port; ZeroMQPull.INSTANCE.recv(addr); } catch (InterruptedException e) { logger.error("SyncStartZeroMQ-->>run() error",e); String execMethod = "ModuleSchedulerServer-->>run()"; String execResult = "ModuleSchedulerServer-->>run() error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } public static void main(String args[]){ AsyncStartZeroMQ.startup(CommonConstants.ZMQ_SERVER_PORT); System.err.println("SyncStartZeroMQ"); try { TimeUnit.SECONDS.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } ZeroMQPull.INSTANCE.stop(); System.err.println("stop finish...."); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zeromq/AsyncZMQPull.java ================================================ package com.gome.clover.common.zeromq; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/25 * Time: 20:55 */ public class AsyncZMQPull { /* protected ModuleZeromq mq; protected ZMQ.Socket jobSocket = null; protected ZMQ.Socket socketPullBroadcast = null; private boolean alive = true; private int index = 0; private long jobCount = 0L; private Thread t = null; protected static boolean debugThread = false; protected static Logger logger = LoggerFactory.getLogger(SyncZMQPull.class); public SyncZMQPull(ModuleZeromq mq, int index) { this.mq = mq; this.index = index; } public void attach(Thread t) { this.t = t; } private ZMsg packClientMsg(ModuleZeromq.MessageSource source, String clientAddr, MessageVersion version, byte[] msgTag, String content) { byte[] bytes = StringUtil.toBytes(content); return packClientMsg(source, clientAddr, version, msgTag, bytes); } private ZMsg packClientMsg(ModuleZeromq.MessageSource source, String clientAddr, MessageVersion version, byte[] msgTag, byte[] bytes) { ZMsg msg = new ZMsg(); msg.addFirst(String.valueOf(source.ordinal())); msg.add(clientAddr); msg.add(ZeromqUtil.EMPTY); msg.add(msgTag); CompressMode compress = null; byte[] compressed = bytes; if (bytes.length > 1024) { compress = CompressMode.SNAPPY; compressed = StringUtil.compress(bytes); } if (compressed == bytes) { compress = CompressMode.NONE; } msg.add(compress.getData()); msg.add(compressed); return msg; } private ZMsg packRouterMsg(Device device, ServiceName service, MessageScope scope, MessageType type, MessageVersion version, String msgId, String msgTag, String msgTo, long timestamp, byte[] bytes, String address) { ZMsg msg = new ZMsg(); msg.add(String.valueOf(ModuleZeromq.MessageSource.fromRouter.ordinal())); msg.add(ZeromqUtil.EMPTY); msg.add(device.getData()); msg.add(service.getData()); msg.add(String.valueOf(service.ordinal())); msg.add(scope.getData()); msg.add(type.getData()); msg.add(version.getData()); msg.add(ZeromqUtil.getBytes(msgId)); msg.add(ZeromqUtil.getBytes(msgTag)); msg.add(ZeromqUtil.getBytes(msgTo)); msg.add(String.valueOf(timestamp)); CompressMode compress = null; byte[] compressed = bytes; if (bytes.length > 1024) { compress = CompressMode.SNAPPY; compressed = StringUtil.compress(bytes); } if (compressed == bytes) { compress = CompressMode.NONE; } msg.add(compress.getData()); msg.add(compressed); msg.add(StringUtil.toBytes(address)); return msg; } protected void changeRouter(String clientAddr, MessageVersion version, byte[] msgTag, String content) { packRouterMsg(Device.SERVER, ServiceName.Server, MessageScope.ROUTER, MessageType.DISCONNECT, MessageVersion.MQ, this.mq.getId(), "change", "TO", System.currentTimeMillis(), ZeromqUtil.EMPTY, this.mq.getId()); sendJob(packRouterMsg(Device.SERVER, ServiceName.Server, MessageScope.ROUTER, MessageType.DISCONNECT, MessageVersion.MQ, "ID", msgTag.toString(), "TO", System.currentTimeMillis(), ZeromqUtil.EMPTY, this.mq.getId())); this.mq.stop(); this.mq.routerNode = ServerDict.self.routerBy(content); this.mq.start(true); ModuleIntf subscribe = ModuleFactory.moduleInstanceBy("subscribe"); subscribe.stop(); subscribe.start(true); byte[] bytes = StringUtil.toBytes("{state:" + this.mq.isAlive() + "}"); sendJob(packClientMsg(ModuleZeromq.MessageSource.fromApp, clientAddr, version, msgTag, bytes)); } protected void switchTo(boolean online, String sender, MessageVersion version, ZFrame msgTag) { boolean exist = ZooUtil.exists(ServerDict.self.zoo(), "/appservers/" + this.mq.getId()); String name = online ? "online" : "offline"; if (exist != online) { if (online) { this.mq.restart(); sendJob(packClientMsg(ModuleZeromq.MessageSource.fromApp, sender, version, msgTag.getData(), "{\"" + name + "\":true}")); } else { sendJob(packRouterMsg(Device.SERVER, ServiceName.Server, MessageScope.ROUTER, MessageType.DISCONNECT, MessageVersion.MQ, "ID", msgTag.toString(), "TO", System.currentTimeMillis(), ZeromqUtil.EMPTY, this.mq.getId())); sendJob(packClientMsg(ModuleZeromq.MessageSource.fromApp, sender, version, msgTag.getData(), "{\"" + name + "\":true}")); this.mq.serverNode.removeField("routerId"); ZooUtil.delete(ServerDict.self.zoo(), "/appservers/" + this.mq.getId()); } } logger.info("AppServer [{}] is [{}] at ServerIP={} & Port={} & PublisherPort={}", new Object[] { this.mq.getId(), name, this.mq.serverNode.getString("ip"), Integer.valueOf(Global.MQRouterPort), Integer.valueOf(Global.MQRouterPublishPort) }); } public void sendJob(ZMsg msg) { ZeroSocket oSocket = null; String uri = "inproc://jobs-app"; try { oSocket = ZeroSocketFactory.get(uri, this.mq.ctx, 5); if ((oSocket == null) || (!oSocket.isAlive)) { return; } msg.send(oSocket.socket); } catch (Exception e) { oSocket.isAlive = false; logger.error("sendJob", e); } finally { ZeromqUtil.free(msg); ZeroSocketFactory.ret(uri, oSocket); } } public void sendSocketEvent(String senderId, Object oResult) { SocketEvent event = this.mq.event.removeSocket(senderId); if ((event == null) || (oResult == null)) { return; } if ((oResult instanceof String)) event.onMessage(Global.SocketDataType.string, oResult); else if ((oResult instanceof BasicDBObject)) event.onMessage(Global.SocketDataType.json, oResult); } private void createSocket() { this.jobSocket = this.mq.ctx.createSocket(7); this.jobSocket.setIdentity(StringUtil.toBytes("jobs-push@" + this.index)); this.jobSocket.connect("inproc://jobs-push"); this.socketPullBroadcast = this.mq.ctx.createSocket(7); this.socketPullBroadcast.setIdentity(StringUtil.toBytes("broadcast-pull@" + this.index)); this.socketPullBroadcast.connect("inproc://broadcast-app-push"); } public void run() { createSocket(); ZMQ.Poller poller = new ZMQ.Poller(2); poller.register(this.jobSocket, 1); poller.register(this.socketPullBroadcast, 1); while ((this.alive) && (!this.t.isInterrupted())) { ZMsg msg = null; if (poller.poll(3000L) < 1) { continue; } if (poller.pollin(0)) msg = ZMsg.recvMsg(this.jobSocket); else if (poller.pollin(1)) { msg = ZMsg.recvMsg(this.socketPullBroadcast); } ZFrame c = msg.pop(); ModuleZeromq.MessageSource messageFrom = ModuleZeromq.MessageSource.values()[Integer.parseInt(c.toString())]; c.destroy(); ZFrame sender = msg.pop(); ZFrame empty = msg.pop(); ZFrame device = msg.pop(); ZFrame serviceName = msg.pop(); ZFrame serviceIndex = msg.pop(); ZFrame scope = msg.pop(); ZFrame messageType = msg.pop(); ZFrame messageVersion = msg.pop(); MessageVersion version = MessageVersion.values()[Integer.parseInt(messageVersion.toString())]; ZFrame messageId = msg.pop(); ZFrame messageTag = msg.pop(); ZFrame messageTo = msg.pop(); ZFrame timestamp = msg.pop(); ZFrame compress = msg.pop(); String content = null; String msgTag = messageTag.toString(); try { c = msg.pop(); byte[] bytes = c.getData(); c.destroy(); if (Integer.parseInt(compress.toString()) == CompressMode.SNAPPY.ordinal()) { bytes = StringUtil.uncompress(bytes); } content = StringUtil.toString(bytes); ServiceName service = ServiceName.values()[Integer.parseInt(serviceIndex.toString())]; MessageType msgType = MessageType.values()[Integer.parseInt(messageType.toString())]; switch (service) { case Activity: switch ($SWITCH_TABLE$org$x$cloud$dict$MessageType()[msgType.ordinal()]) { case 2: if (StringUtil.isEmpty(content)) break; this.mq.registerServer(content); break; case 15: switchTo(false, sender.toString(), version, messageTag); break; case 14: switchTo(true, sender.toString(), version, messageTag); break; case 5: if (msgTag.equalsIgnoreCase("runtime")) { content = JVMUtil.readRuntime().append("jobCount", Long.valueOf(this.jobCount)).toString(); } sendJob(packClientMsg(ModuleZeromq.MessageSource.fromApp, sender.toString(), version, messageTag.getData(), content)); break; case 9: sendJob(packClientMsg(ModuleZeromq.MessageSource.fromSelf, sender.toString(), version, messageTag.getData(), content)); } break; default: BasicDBObject oResult = new BasicDBObject().append("server", this.mq.getId()); ZFrame jobNo = msg.pop(); this.jobCount = Long.parseLong(jobNo.toString()); oResult.append("@job", Long.valueOf(this.jobCount)); jobNo.destroy(); oResult.append("@from", messageFrom.name()).append("@thread", Integer.valueOf(this.index)); MessageScope msgScope = MessageScope.values()[Integer.parseInt(scope.toString())]; DBObject oReq = (DBObject)JSON.parse(content); try { DBObject oResponse = ModuleFactory.processor().execute(this.jobCount, sender.toString(), Integer.parseInt(device.toString()), Integer.parseInt(serviceIndex.toString()), msgScope, Integer.parseInt(messageType.toString()), Integer.parseInt(messageVersion.toString()), messageId.toString(), messageTag.toString(), messageTo.toString(), Long.parseLong(timestamp.toString()), oReq); oResult.append("response", oResponse); oResult.append("state", Boolean.valueOf(true)); } catch (Exception e) { oResult.append("state", Boolean.valueOf(false)); oResult.append("message", e.getMessage()); logger.error("ModuleFactory.processor().execute" + StringUtil.stringifyException(e)); } oResult.append("@time", Long.valueOf(System.currentTimeMillis() - Long.parseLong(timestamp.toString()))); switch (messageFrom) { case fromApp: sendJob(packRouterMsg(Device.values()[Integer.parseInt(device.toString())], ServiceName.Server, msgScope, MessageType.REPLY, version, messageId.toString(), messageTag.toString(), messageTo.toString(), Long.parseLong(timestamp.toString()), StringUtil.toBytes(oResult.toString()), sender.toString())); break; case fromRouter: sendJob(packClientMsg(ModuleZeromq.MessageSource.fromApp, sender.toString(), version, messageTag.getData(), oResult.toString())); break; case fromSelf: sendSocketEvent(sender.toString(), oResult); } } } catch (Exception e) { logger.error("JobPull[" + messageType.toString() + "&" + serviceName.toString() + "&" + content + "]" + StringUtil.stringifyException(e)); } ZeromqUtil.free(empty); sender.destroy(); device.destroy(); serviceName.destroy(); serviceIndex.destroy(); scope.destroy(); messageType.destroy(); messageVersion.destroy(); messageTag.destroy(); timestamp.destroy(); compress.destroy(); msg.destroy(); } stop(); } public void stop() { this.alive = false; try { this.t.join(); if (this.jobSocket == null) { return; } this.mq.ctx.destroySocket(this.jobSocket); } catch (Exception e) { logger.error("stop", e); } }*/ } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zeromq/ZeroMQEntity.java ================================================ package com.gome.clover.common.zeromq; import com.gome.clover.common.netty.client.SubReqClientHandel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Serializable; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Zero Zero MQ Entity * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ZeroMQEntity implements Serializable { private static final Logger logger = LoggerFactory.getLogger(ZeroMQEntity.class); /** * 执行任务类型(server|client) */ private String destServer; /** * 执行机器IP地址 */ private String destIp; /** * Job 信息 Base64 encode字符串 */ private String jobInfo; /** * msg */ private String msg; public ZeroMQEntity() {} public ZeroMQEntity(String destServer, String destIp, String jobInfo) { this.destServer = destServer; this.destIp = destIp; this.jobInfo = jobInfo; logger.error("ZeroMQEntity.length()"+jobInfo.length()); } public ZeroMQEntity(String destServer, String destIp, String jobInfo, String msg) { this.destServer = destServer; this.destIp = destIp; this.jobInfo = jobInfo; this.msg = msg; } public String getDestServer() { return destServer; } public void setDestServer(String destServer) { this.destServer = destServer; } public String getJobInfo() { return jobInfo; } public void setJobInfo(String jobInfo) { this.jobInfo = jobInfo; } public String getDestIp() { return destIp; } public void setDestIp(String destIp) { this.destIp = destIp; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zeromq/ZeroMQPub.java ================================================ package com.gome.clover.common.zeromq; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.DateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeromq.ZMQ; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Publisher * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum ZeroMQPub { INSTANCE; private static final Logger logger = LoggerFactory.getLogger(ZeroMQPub.class); public boolean send(String addr,String msg,String topic){ try{ ZMQ.Context context = ZMQ.context(1); //创创建包含一个I/O线程的context ZMQ.Socket publisher = context.socket(ZMQ.PUB); //创建一个publisher类型的socket,他可以向所有订阅的subscriber广播数据 publisher.bind(addr); //将当前publisher绑定到5555端口上,可以接受subscriber的订阅 //publisher.subscribe(topic.getBytes()); String newMsg = topic.getBytes()+" "+msg; publisher.send(newMsg.getBytes(),ZMQ.NOBLOCK); publisher.close(); context.term(); return true; }catch (Exception e){ logger.error("ZeroMQPub-->>send("+addr+","+msg+","+topic+")"); return false; } } public static void main(String args[]) { String addr="tcp://*:"+ CommonConstants.ZMQ_SERVER_PORT; String topic=CommonConstants.TOPIC_CLOVER_CLIENT+"@"/*+IpUtil.getLocalIP()*/; while (true){ ZeroMQPub.INSTANCE.send(addr, DateUtil.currentDateTime(),topic); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zeromq/ZeroMQPull.java ================================================ package com.gome.clover.common.zeromq; import com.alibaba.fastjson.JSON; import com.gome.clover.common.compress.CompressUtil; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.*; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.job.ServerJob; import com.gome.clover.core.module.ModuleSchedulerClient; import com.gome.clover.core.module.ModuleSchedulerServer; import com.gome.clover.core.scheduler.MyScheduler; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import org.apache.commons.codec.binary.Base64; import org.quartz.Job; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; import org.zeromq.ZMQ; import static org.quartz.JobBuilder.*; import static org.quartz.TriggerBuilder.*; import static org.quartz.SimpleScheduleBuilder.*; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:ZeroMQ Pull * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum ZeroMQPull { INSTANCE; private static ZMQ.Context context; private static ZMQ.Socket pull; private static boolean isStop = false; public void recv(String addr) { context = ZMQ.context(1); pull = context.socket(ZMQ.PULL); pull.bind(addr); System.err.println("ZeroMQPull-->> recv(" + addr + ") init....."); while (!isStop) { try { String msg = new String(CompressUtil.uncompress(pull.recv())); //System.err.println("ZeroMQPull-->>recv(" + addr + ")" + msg); if (!StringUtil.isEmpty(msg)) { ZeroMQEntity zeroMQEntity = JSON.parseObject(msg, ZeroMQEntity.class); if (IpUtil.getLocalIP().equals(zeroMQEntity.getDestIp())) { if (CommonConstants.MODULE_TYPE_SERVER.equals(zeroMQEntity.getDestServer())) { System.err.println("--------------MODULE_TYPE_SERVER--------------"); ServerJob serverJob = (ServerJob) ClassUtil.BytesToObject(Base64.decodeBase64(zeroMQEntity.getJobInfo())); ModuleSchedulerServer server = ModuleSchedulerServer.getInstance(); server.handlerJob(serverJob); } else if (CommonConstants.MODULE_TYPE_CLIENT.equals(zeroMQEntity.getDestServer())) { System.err.println("--------------MODULE_TYPE_CLIENT--------------"); ServerJob serverJob = (ServerJob) ClassUtil.BytesToObject(Base64.decodeBase64(zeroMQEntity.getJobInfo())); ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64( (String) serverJob.getJobDetail().getJobDataMap().get(CommonConstants.CLIENT_JOB_INFO))); resetClientJobTriggerAndJobType(clientJob); client.handlerJob(clientJob); } else if (CommonConstants.MODULE_TYPE_SERVER_WITH_ADMIN.equals(zeroMQEntity.getDestServer())) { String mqMsg = zeroMQEntity.getMsg(); if (!StringUtil.isEmpty(mqMsg)) { System.err.println("--------------MODULE_TYPE_SERVER_WITH_ADMIN--------------"); BasicDBObject basicDBObject = (BasicDBObject) com.mongodb.util.JSON.parse(mqMsg); String jobGroup = (String) basicDBObject.get("jobGroup"); String jobName = (String) basicDBObject.get("jobName"); Scheduler scheduler = new StdSchedulerFactory().getScheduler(); JobKey jobKey = new JobKey(jobName, jobGroup); if (scheduler.checkExists(jobKey)) { scheduler.deleteJob(jobKey); } } } else if (CommonConstants.MODULE_TYPE_CLIENT_WITH_ADMIN.equals(zeroMQEntity.getDestServer())) { String mqMsg = zeroMQEntity.getMsg(); if (!StringUtil.isEmpty(mqMsg)) { System.err.println("--------------MODULE_TYPE_CLIENT_WITH_ADMIN--------------"); BasicDBObject basicDBObject = (BasicDBObject) com.mongodb.util.JSON.parse(mqMsg); String jobGroup = (String) basicDBObject.get("jobGroup"); String jobName = (String) basicDBObject.get("jobName"); String jobClassName = (String) basicDBObject.get("jobClassName"); Class jobClass = (Class) Class.forName(jobClassName); ClientJob.JobType jobType = ClientJob.JobType.valueOf((String) basicDBObject.get("jobType")); ClientJob.ExecuteType executeType = ClientJob.ExecuteType.valueOf((String) basicDBObject.get("executeType")); ClientJob.JobStrategy jobStrategy = ClientJob.JobStrategy.valueOf((String) basicDBObject.get("jobStrategy")); String startTime = (String) basicDBObject.get("startTime"); String cronExpression = (String) basicDBObject.get("cronExpression"); ClientJob clientJob = null; if (!StringUtil.isEmpty(startTime) && !StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(jobGroup, jobName, jobClass, jobType, executeType, jobStrategy, DateUtil.formatWithDefaultPattern(startTime)); } else if (!StringUtil.isEmpty(startTime) && StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(jobGroup, jobName, jobClass, jobType, executeType, jobStrategy, DateUtil.formatWithDefaultPattern(startTime)); } else if (StringUtil.isEmpty(startTime) && !StringUtil.isEmpty(cronExpression)) { clientJob = ClientJobBuilder.quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndCronExpression(jobGroup, jobName, jobClass, jobType, executeType, jobStrategy, cronExpression); } if (null != clientJob) { String fixedClientIps = (String) basicDBObject.get("fixedClientIps"); if (!StringUtil.isEmpty(fixedClientIps)) clientJob.setFixedClientIps(fixedClientIps.split(",")); String fixedServerIps = (String) basicDBObject.get("fixedServerIps"); if (!StringUtil.isEmpty(fixedServerIps)) clientJob.setFixedServerIps(fixedServerIps.split(",")); ModuleSchedulerClient.getInstance().handlerJob(clientJob); } } } else if (CommonConstants.MODULE_TYPE_SERVER_WITH_MONITOR.equals(zeroMQEntity.getDestServer())) { String mqMsg = zeroMQEntity.getMsg(); if (!StringUtil.isEmpty(mqMsg)) { System.err.println("--------------MODULE_TYPE_SERVER_WITH_MONITOR--------------"); BasicDBObject basicDBObject = (BasicDBObject) com.mongodb.util.JSON.parse(mqMsg); String action = (String) basicDBObject.get("action"); String ip = (String) basicDBObject.get("ip"); if (!StringUtil.isEmpty(action) && !StringUtil.isEmpty(ip)) { if ("reloadDB".equals(action)) {//恢复数据 DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_SERVER_IP, ip); condition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_REMOTE); DBCursor cursorDocMap = dbCollection.find(condition); while (cursorDocMap.hasNext()) { ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String) cursorDocMap.next() .get(DBTableInfo.COL_JOB_INFO))); MyScheduler scheduler = MyScheduler.INSTANCE; scheduler.start(); scheduler.add(clientJob); } } } } } } } } catch (Exception e) { String execMethod = "ZeroMQPull-->>recv(" + addr + ")"; String execResult = "ZeroMQPull-->>recv(" + addr + ")" + " error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } } private void resetClientJobTriggerAndJobType(ClientJob clientJob) { clientJob.setTrigger(TriggerBuilder.newTrigger().startNow().withIdentity(clientJob.getTrigger().getKey()).build()); clientJob.setJobType(ClientJob.JobType.LOCAL); } public boolean stop() {//server 关闭zmq方法 isStop = true; pull.disconnect("tcp://" + IpUtil.getLocalIP() + ":" + CommonConstants.ZMQ_SERVER_PORT); pull.close(); context.close(); return true; } public boolean stop(String ip,String port) { isStop = true; pull.disconnect("tcp://" + ip + ":" + port); pull.close(); context.close(); return true; } public static void main(String args[]) { String addr = "tcp://*:" + RandomNumUtil.getNextIntString(); ZeroMQPull.INSTANCE.recv(addr); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zeromq/ZeroMQPush.java ================================================ package com.gome.clover.common.zeromq; import com.gome.clover.common.compress.CompressUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import org.zeromq.ZMQ; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:ZeroMQ Push * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum ZeroMQPush { INSTANCE; public boolean send(String addr,String msg){ try{ ZMQ.Context context = ZMQ.context(1); ZMQ.Socket push = context.socket(ZMQ.PUSH); push.connect(addr); boolean retValue = push.send(CompressUtil.compress(msg.getBytes()),ZMQ.NOBLOCK); push.close(); context.term(); return retValue; }catch (Exception e){ System.err.println(""+e); return false; } } public static void main(String args[]){ String addr="tcp://"+ IpUtil.getLocalIP()+":"+ CommonConstants.ZMQ_SERVER_PORT; String msg="你好"; ZeroMQPush.INSTANCE.send(addr,msg); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zeromq/ZeroMQSub.java ================================================ package com.gome.clover.common.zeromq; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Subscriber * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeromq.ZMQ; public enum ZeroMQSub { INSTANCE; private static final Logger logger = LoggerFactory.getLogger(ZeroMQPub.class); public void recv(String addr){ try { ZMQ.Context context = ZMQ.context(1); //创建1个I/O线程的上下文 ZMQ.Socket subscriber = context.socket(ZMQ.SUB); //创建一个sub类型,也就是subscriber类型的socket subscriber.connect(addr); //监听的publisher建立连接 subscriber.subscribe((CommonConstants.TOPIC_CLOVER_CLIENT+"@"/*+IpUtil.getLocalIP()*/).getBytes()); //订阅这个channel while (true){ String msg = new String(subscriber.recv());//接收publisher发送过来的消息 System.err.println("receive : " +msg); } }catch (Exception e){ logger.error("ZeroMQSub-->>recv("+addr+")"); } } public static void main(String args[]) { String addr="tcp://"+ IpUtil.getLocalIP()+":"+ CommonConstants.ZMQ_SERVER_PORT; ZeroMQSub.INSTANCE.recv(addr); System.err.println("ZeroMQSub-----"); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ClientDict.java ================================================ package com.gome.clover.common.zk; import com.gome.clover.common.tools.CommonConstants; import com.mongodb.BasicDBObject; import org.apache.curator.framework.CuratorFramework; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Client Dict * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 16:00 */ public class ClientDict { public static ClientDict self = null; protected static Logger logger = LoggerFactory.getLogger(ClientDict.class); protected ZKConnect ZKConnect = null; public ClientListener clientListener = null; static { self = new ClientDict(); } public ClientDict() { init(); } public boolean init() { logger.info("ClientDict init zookeeper..."); this.ZKConnect = new ZKConnect(); if ((this.ZKConnect == null) || (!this.ZKConnect.start())) { return false; } this.clientListener = new ClientListener(CommonConstants.ZK_ROOT_PATH + "/client", this.ZKConnect); this.ZKConnect.addClientListener(this.clientListener); this.clientListener.reload(); return true; } public CuratorFramework getZK() { return this.ZKConnect.instance; } public BasicDBObject hashClient(String jobClass, String hashKey) { return this.clientListener.clientNodes.hashClient(jobClass, hashKey); } /** * hashClient4S * @param jobClass * @param hashKey * @return */ public Map hashClient4S(String jobClass, String hashKey) { return this.clientListener.clientNodes.hashClient4S(jobClass, hashKey); } public BasicDBObject hashClientByFixedClientIps(String jobClass,String[] fixedClientIps) { return this.clientListener.clientNodes.hashClientByFixedClientIps(jobClass, fixedClientIps); } /** * hashClientByFixedClientIps升级版本(4S==For Super) * @param jobClass * @param fixedClientIps * @return */ public Map hashClient4SByFixedClientIps(String jobClass,String[] fixedClientIps) { return this.clientListener.clientNodes.hashClient4SByFixedClientIps(jobClass, fixedClientIps); } public BasicDBObject hashClientBySystemCapacity(String jobClass) { return this.clientListener.clientNodes.hashClientBySystemCapacity(jobClass); } /** * hashClientBySystemCapacity升级版本(4S==For Super) * @param jobClass * @return */ public Map hashClient4SBySystemCapacity(String jobClass) { return this.clientListener.clientNodes.hashClient4SBySystemCapacity(jobClass); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ClientListener.java ================================================ package com.gome.clover.common.zk; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.StringUtil; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.util.JSON; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 16:08 */ public class ClientListener implements Watcher { protected static Logger logger = LoggerFactory.getLogger(ClientListener.class); protected String prefixPath = ""; protected ClientNodes clientNodes = new ClientNodes(); protected ZKConnect ZKConnect = null; protected Integer LOCK = Integer.valueOf(0); public ClientListener(String prefixPath, ZKConnect ZKConnect) { this.prefixPath = prefixPath; this.ZKConnect = ZKConnect; } public BasicDBList records() { return this.clientNodes.records; } public BasicDBObject hashClient(String jobClass, String hashKey) { return this.clientNodes.hashClient(jobClass, hashKey); } public void removeRecord(String id) { this.clientNodes.remove(id); } public void addRecord(String id) { if (!this.ZKConnect.checkAlive()) return; try { String c = this.ZKConnect.getData(this.prefixPath + "/" + id); if (c == null) { return; } BasicDBObject record = (BasicDBObject) JSON.parse(c); this.clientNodes.add(record); } catch (Exception e) { logger.error("ClientListener-->>ServerNodeListener error ", e); } } public void reload() { if (!this.ZKConnect.checkAlive()) { return; } if (!this.ZKConnect.exists(this.prefixPath)) return; try { String timeStamp = DateUtil.currentDateTime(); List items = this.ZKConnect.getChildrens(this.prefixPath); for (int i = 0; (items != null) && (i < items.size()); i++) { String id = (String) items.get(i); String c = this.ZKConnect.getData(this.prefixPath + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) JSON.parse(c); record.put("timeStamp", timeStamp); this.clientNodes.add(record); } int index = 0; while (index < this.clientNodes.records.size()) { BasicDBObject record = (BasicDBObject) this.clientNodes.records.get(index); if (record.getString("timeStamp").equalsIgnoreCase(timeStamp)) { index++; } else if (!this.clientNodes.remove(record.getString("id"))) { index++; } } } catch (Exception e) { logger.error("ServerListener-->>reload() error.", e); } } public void process(WatchedEvent event) { if (event == null) { return; } String path = event.getPath(); if ((path == null) || (!path.startsWith(this.prefixPath))) { return; } synchronized (this.LOCK) { try { String[] values = StringUtil.split(path, '/'); String id = values.length >= 2 ? values[1] : ""; BasicDBObject oServer = null; if (event.getType() == Event.EventType.NodeCreated) { addRecord(id); } else if (event.getType() == Event.EventType.NodeDeleted) { removeRecord(id); } else if (event.getType() == Event.EventType.NodeDataChanged) { addRecord(id); } else if (event.getType() == Event.EventType.NodeChildrenChanged) { reload(); } } catch (Exception e) { logger.error("ServerListener-->>process(" + com.alibaba.fastjson.JSON.toJSONString(event) + ") error.", e); } } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ClientNodes.java ================================================ package com.gome.clover.common.zk; import com.gome.clover.common.hash.HashTimes; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.StringUtil; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Client Nodes * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 21:40 */ public class ClientNodes extends CommonNodes { protected static Logger logger = LoggerFactory.getLogger(ServerNodes.class); protected HashMap recordsById = new HashMap(); protected HashMap recordsByJobClass = new HashMap(); protected BasicDBList records = new BasicDBList(); protected HashSet jobClassSet = new HashSet(); public BasicDBObject hashClient(String jobClass, String hashKey) { BasicDBList items = getRecordsByJobClass(jobClass); if ((items == null) || (items.size() == 0)) { return null; } if (StringUtil.isEmpty(hashKey)) { hashKey = allocateNo(); } int index = HashTimes.use33(hashKey) % items.size(); return (BasicDBObject) items.get(index); } /** * hashClient升级版本(4S==For Super) * @param jobClass * @param hashKey * @return */ public Map hashClient4S(String jobClass, String hashKey) { Map map = new HashMap(); BasicDBList items = getRecordsByJobClass(jobClass); if ((items == null) || (items.size() == 0)) { map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_101); return map; } if (StringUtil.isEmpty(hashKey)) { hashKey = allocateNo(); } int index = HashTimes.use33(hashKey) % items.size(); map.put(CommonConstants.SUCCESS, true); map.put(CommonConstants.CLIENT_JOB_INFO, items.get(index)); return map; } public BasicDBObject hashClientByFixedClientIps(String jobClass, String[] fixedClientIps) { BasicDBList items = getRecordsByJobClass(jobClass); if ((items == null) || (items.size() == 0)) { return null; } int index = -1; for (String fixedClientIp : fixedClientIps) { index = findIndexByIp(fixedClientIp, items); if (index == -1) continue; } if (index == -1) { return null; } return (BasicDBObject) items.get(index); } /** * hashClientByFixedClientIps升级版本(4S==For Super) * @param jobClass * @param fixedClientIps * @return */ public Map hashClient4SByFixedClientIps(String jobClass, String[] fixedClientIps) { Map map = new HashMap(); BasicDBList items = getRecordsByJobClass(jobClass); if ((items == null) || (items.size() == 0)) { map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_101); } int index = -1; for (String fixedClientIp : fixedClientIps) { index = findIndexByIp(fixedClientIp, items); if (index == -1) continue; } if (index == -1) { map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_101); } map.put(CommonConstants.SUCCESS, true); map.put(CommonConstants.CLIENT_JOB_INFO, items.get(index)); return map; } public BasicDBObject hashClientBySystemCapacity(String jobClass) { BasicDBList items = getRecordsByJobClass(jobClass); int itemLen; if ((items == null) || ((itemLen = items.size()) == 0)) { return null; } else if (1 == itemLen) { BasicDBObject item = (BasicDBObject) items.get(0); double memRatio = Double.valueOf(String.valueOf(item.get(CommonConstants.MEM_RATIO))); double cpuRatio = Double.valueOf(String.valueOf(item.get(CommonConstants.CPU_RATIO))); if (memRatio > CommonConstants.MAX_MEM_RATIO || cpuRatio > CommonConstants.MAX_CPU_RATIO ) { logger.error("ClientNodes-->>hashClientBySystemCapacity(" + jobClass + ") the memRatio(" + memRatio + ")" + " over max mem ratio("+CommonConstants.MAX_MEM_RATIO+") or the cpuRatio("+cpuRatio+") " + "over max cpu ratio("+CommonConstants.MAX_CPU_RATIO+") "); return null; } else { return item; } } else if (itemLen > 1) { BasicDBObject tempItem = (BasicDBObject) items.get(0); int minMemRatioIndex = 0; double minMemRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.MEM_RATIO))); double minCpuRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.CPU_RATIO))); int minTotalThreadValue = Integer.valueOf(String.valueOf(tempItem.get(CommonConstants.TOTAL_THREAD))); double minTotalValue = minMemRatioValue + minCpuRatioValue + minTotalThreadValue; for (int i = 1; i < itemLen; i++) { tempItem = (BasicDBObject) items.get(i); double tempMemRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.MEM_RATIO))); double tempCpuRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.CPU_RATIO))); int tempTotalThreadValue = Integer.valueOf(String.valueOf(tempItem.get(CommonConstants.TOTAL_THREAD))); double tempTotalValue = tempMemRatioValue + tempCpuRatioValue + tempTotalThreadValue; if (tempTotalValue < minTotalValue) { minMemRatioValue = tempMemRatioValue; minCpuRatioValue = tempCpuRatioValue; minTotalThreadValue = tempTotalThreadValue; minTotalValue = minMemRatioValue + minCpuRatioValue + minTotalThreadValue; minMemRatioIndex = i; } } if (minMemRatioValue > CommonConstants.MAX_MEM_RATIO || minCpuRatioValue > CommonConstants.MAX_CPU_RATIO) { logger.error("ClientNodes-->>hashClientBySystemCapacity(" + jobClass + ") " + "the memRatio(" + minMemRatioValue + ") over max mem ratio(" + CommonConstants.MAX_MEM_RATIO + ")" + "or the cpuRatio("+minCpuRatioValue+") over max cpu ration ("+CommonConstants.MAX_CPU_RATIO+") "); return null; } else { return (BasicDBObject) items.get(minMemRatioIndex); } } return null; } /** * hashClientBySystemCapacity升级版本(4S==For Super) * * @param jobClass * @return */ public Map hashClient4SBySystemCapacity(String jobClass) { Map map = new HashMap(); BasicDBList items = getRecordsByJobClass(jobClass); int itemLen; if ((items == null) || ((itemLen = items.size()) == 0)) { map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_101); return map; } else if (1 == itemLen) { BasicDBObject item = (BasicDBObject) items.get(0); double memRatio = Double.valueOf(String.valueOf(item.get(CommonConstants.MEM_RATIO))); double cpuRatio = Double.valueOf(String.valueOf(item.get(CommonConstants.CPU_RATIO))); if (memRatio > CommonConstants.MAX_MEM_RATIO || cpuRatio > CommonConstants.MAX_CPU_RATIO) { logger.error("ClientNodes-->>hashClient4SBySystemCapacity(" + jobClass + ") the memRatio(" + memRatio + ")" + " over max mem ratio(" + CommonConstants.MAX_MEM_RATIO + ") or the cpuRatio("+cpuRatio+")" + " over max cpu ratio("+CommonConstants.MAX_CPU_RATIO+") "); map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_102); map.put(CommonConstants.MEM_RATIO, memRatio); map.put(CommonConstants.CPU_RATIO, cpuRatio); return map; } else { map.put(CommonConstants.SUCCESS, true); map.put(CommonConstants.CLIENT_JOB_INFO, item); return map; } } else if (itemLen > 1) { BasicDBObject tempItem = (BasicDBObject) items.get(0); int minMemRatioIndex = 0; double minMemRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.MEM_RATIO))); double minCpuRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.CPU_RATIO))); int minTotalThreadValue = Integer.valueOf(String.valueOf(tempItem.get(CommonConstants.TOTAL_THREAD))); double minTotalValue = minMemRatioValue + minCpuRatioValue + minTotalThreadValue; for (int i = 1; i < itemLen; i++) { tempItem = (BasicDBObject) items.get(i); double tempMemRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.MEM_RATIO))); double tempCpuRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.CPU_RATIO))); int tempTotalThreadValue = Integer.valueOf(String.valueOf(tempItem.get(CommonConstants.TOTAL_THREAD))); double tempTotalValue = tempMemRatioValue + tempCpuRatioValue + tempTotalThreadValue; if (tempTotalValue < minTotalValue) { minMemRatioValue = tempMemRatioValue; minCpuRatioValue = tempCpuRatioValue; minTotalThreadValue = tempTotalThreadValue; minTotalValue = minMemRatioValue + minCpuRatioValue + minTotalThreadValue; minMemRatioIndex = i; } } if (minMemRatioValue > CommonConstants.MAX_MEM_RATIO || minCpuRatioValue > CommonConstants.MAX_CPU_RATIO) { logger.error("ClientNodes-->>hashClient4SBySystemCapacity(" + jobClass + ") " + "the memRatio(" + minMemRatioValue + ") over max mem ratio(" + CommonConstants.MAX_MEM_RATIO + ")" + "or the cpuRatio("+minCpuRatioValue+") over max cpu ration ("+CommonConstants.MAX_CPU_RATIO+") "); map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_102); map.put(CommonConstants.MEM_RATIO, minMemRatioValue); map.put(CommonConstants.CPU_RATIO, minCpuRatioValue); return map; } else { map.put(CommonConstants.SUCCESS, true); map.put(CommonConstants.CLIENT_JOB_INFO, items.get(minMemRatioIndex)); return map; } } map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_103); return map; } public boolean containsKey(String id) { return this.recordsById.containsKey(id); } public BasicDBList getRecordsByJobClass(String jobClass) { return this.recordsByJobClass.get(jobClass); } public BasicDBList findRecordsByIP(String ip) { BasicDBList basicDBList = new BasicDBList(); for (int i = 0; i < this.records.size(); i++) { BasicDBObject oServer = (BasicDBObject) this.records.get(i); if (oServer.getString(CommonConstants.IP).equalsIgnoreCase(ip)) { basicDBList.add(oServer); } } return basicDBList; } public synchronized void add(BasicDBObject record) { String id = record.getString(CommonConstants.ID); int index = findIndexById(id, this.records); if (index == -1) this.records.add(record); else { this.records.set(index, record); } this.recordsById.put(id, record); if (!record.containsField(CommonConstants.JOB_CLASS)) { return; } BasicDBList jobClassList = (BasicDBList) record.get(CommonConstants.JOB_CLASS); for (int i = 0; (jobClassList != null) && (i < jobClassList.size()); i++) { String tempJobClass = jobClassList.get(i).toString(); this.jobClassSet.add(tempJobClass); BasicDBList items = this.recordsByJobClass.get(tempJobClass); if (items == null) { items = new BasicDBList(); this.recordsByJobClass.put(tempJobClass, items); } index = findIndexById(id, items); if (index == -1) items.add(record); else { items.set(index, record); } } } public synchronized boolean remove(String id) { this.recordsById.remove(id); int index = findIndexById(id, this.records); boolean flag = index != -1; if (flag) { this.records.remove(index); } for (Iterator i = this.recordsByJobClass.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); BasicDBList items = (BasicDBList) entry.getValue(); index = findIndexById(id, items); if (index != -1) { items.remove(index); } if (items.size() == 0) { this.jobClassSet.remove(entry.getKey()); } } return flag; } public void clear() { this.recordsById.clear(); this.recordsByJobClass.clear(); this.records.clear(); this.jobClassSet.clear(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/CommonNodes.java ================================================ package com.gome.clover.common.zk; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import java.util.concurrent.atomic.AtomicLong; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/19 * Time: 17:26 */ public class CommonNodes { public static String allocateNo() { AtomicLong count = new AtomicLong(0L); if (count.get() == 9223372036854775807L) { count.set(0L); } return String.valueOf(count.addAndGet(1L)); } public static int findIndexById(String id, BasicDBList items) { int result = -1; if(null != items){ for (int i = 0; i < items.size(); i++) { BasicDBObject oItem = (BasicDBObject) items.get(i); if (oItem.getString("id").equalsIgnoreCase(id)) { result = i; } } } return result; } public static int findIndexByIp(String ip, BasicDBList items) { int result = -1; for (int i = 0; i < items.size(); i++) { BasicDBObject oItem = (BasicDBObject) items.get(i); if (oItem.getString("ip").equalsIgnoreCase(ip)) { result = i; } } return result; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ServerDict.java ================================================ package com.gome.clover.common.zk; import com.gome.clover.common.tools.CommonConstants; import com.mongodb.BasicDBObject; import org.apache.curator.framework.CuratorFramework; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Server Dict * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 16:00 */ public class ServerDict { public static ServerDict self = null; protected static Logger logger = LoggerFactory.getLogger(ServerDict.class); protected ZKConnect zkConnect = null; public ServerListener serverListener = null; static { self = new ServerDict(); } public ServerDict() { init(); } public boolean init() { logger.info("ServerDict init zookeeper..."); this.zkConnect = new ZKConnect(); if ((this.zkConnect == null) || (!this.zkConnect.start())) { return false; } this.serverListener = new ServerListener(CommonConstants.ZK_ROOT_PATH + "/server", this.zkConnect); this.zkConnect.addServerListener(this.serverListener); this.serverListener.reload(); return true; } public CuratorFramework getZK() { return this.zkConnect.instance; } public BasicDBObject hashServer(String hashKey) { return this.serverListener.serverNodes.hashServer(hashKey); } /** * hashServer升级版本(4S==For Super) * @param hashKey * @return */ public Map hashServer4S(String hashKey) { return this.serverListener.serverNodes.hashServer4S(hashKey); } public BasicDBObject hashServerByFixedServerIps(String[] fixedServerIps){ return this.serverListener.serverNodes.hashServerByFixedServerIps(fixedServerIps); } /** * hashServerByFixedServerIps升级版本(4S==For Super) * @param fixedServerIps * @return */ public Map hashServer4SByFixedServerIps(String[] fixedServerIps){ return this.serverListener.serverNodes.hashServer4SByFixedServerIps(fixedServerIps); } public BasicDBObject hashServerBySystemCapacity() { return this.serverListener.serverNodes.hashServerBySystemCapacity(); } /** * hashClientBySystemCapacity升级版本(4S==For Super) * @return */ public Map hashServer4SBySystemCapacity() { return this.serverListener.serverNodes.hashServer4SBySystemCapacity(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ServerListener.java ================================================ package com.gome.clover.common.zk; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.StringUtil; import com.mongodb.BasicDBObject; import com.mongodb.util.JSON; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 16:08 */ public class ServerListener implements Watcher { protected static Logger logger = LoggerFactory.getLogger(ServerListener.class); protected String prefixPath = ""; protected ServerNodes serverNodes = new ServerNodes(); protected ZKConnect zkConnect = null; protected Integer LOCK = Integer.valueOf(0); public ServerListener(String prefixPath, ZKConnect zkConnect) { this.prefixPath = prefixPath; this.zkConnect = zkConnect; } public void removeRecord(String id) { this.serverNodes.remove(id); } public BasicDBObject addRecord(String id) { if (!this.zkConnect.checkAlive()) return null; try { String c = this.zkConnect.getData(this.prefixPath + "/" + id); if (c == null) { return null; } BasicDBObject record = (BasicDBObject) JSON.parse(c); this.serverNodes.add(record); return record; } catch (Exception e) { logger.error("ServerNodeListener-->>addRecord(" + id + ") error ", e); return null; } } public void reload() { if (!this.zkConnect.checkAlive()) { return; } if (!this.zkConnect.exists(this.prefixPath)) return; try { String timeStamp = DateUtil.currentDateTime(); List items = this.zkConnect.getChildrens(this.prefixPath); for (int i = 0; (items != null) && (i < items.size()); i++) { String id = (String) items.get(i); String c = this.zkConnect.getData(this.prefixPath + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) JSON.parse(c); record.put("timeStamp", timeStamp); this.serverNodes.add(record); } int index = 0; while (index < this.serverNodes.records.size()) { BasicDBObject record = (BasicDBObject) this.serverNodes.records.get(index); if (record.getString("timeStamp").equalsIgnoreCase(timeStamp)) { index++; } else if (!this.serverNodes.remove(record.getString("id"))) { index++; } } } catch (Exception e) { logger.error("ServerListener-->>reload() error ", e); } } public void process(WatchedEvent event) { if (event == null) { return; } String path = event.getPath(); if ((path == null) || (!path.startsWith(this.prefixPath))) { return; } synchronized (this.LOCK) { try { String[] values = StringUtil.split(path, '/'); String id = values.length >= 2 ? values[1] : ""; if (event.getType() == Watcher.Event.EventType.NodeCreated) { addRecord(id); } else if (event.getType() == Watcher.Event.EventType.NodeDeleted) { removeRecord(id); } else if (event.getType() == Watcher.Event.EventType.NodeDataChanged) { addRecord(id); } else if (event.getType() == Watcher.Event.EventType.NodeChildrenChanged) { reload(); } } catch (Exception e) { logger.error("ServerListener-->>process(" + com.alibaba.fastjson.JSON.toJSONString(event) + ") error.", e); } } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ServerNodes.java ================================================ package com.gome.clover.common.zk; import com.gome.clover.common.hash.HashTimes; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.StringUtil; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Server Nodes * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 16:09 */ public class ServerNodes extends CommonNodes { protected static Logger logger = LoggerFactory.getLogger(ServerNodes.class); protected BasicDBList records = new BasicDBList(); public BasicDBObject hashServer(String hashKey) { if ((records == null) || (records.size() == 0)) { return null; } if (StringUtil.isEmpty(hashKey)) { hashKey = allocateNo(); } int index = HashTimes.use33(hashKey) % records.size(); return (BasicDBObject) records.get(index); } /** * hashServer升级版本(4S==For Super) * * @param hashKey * @return */ public Map hashServer4S(String hashKey) { Map map = new HashMap(); if ((records == null) || (records.size() == 0)) { map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_101); return map; } if (StringUtil.isEmpty(hashKey)) { hashKey = allocateNo(); } int index = HashTimes.use33(hashKey) % records.size(); map.put(CommonConstants.SUCCESS, true); map.put(CommonConstants.SERVER_JOB_INFO, records.get(index)); return map; } public BasicDBObject hashServerByFixedServerIps(String[] fixedServerIps) { if ((records == null) || (records.size() == 0)) { return null; } int index = -1; for (String fixedServerIp : fixedServerIps) { index = findIndexByIp(fixedServerIp, records); if (index == -1) continue; } if (index == -1) { return null; } return (BasicDBObject) records.get(index); } /** * hashServerByFixedServerIps升级版本(4S==For Super) * * @param fixedServerIps * @return */ public Map hashServer4SByFixedServerIps(String[] fixedServerIps) { Map map = new HashMap(); if ((records == null) || (records.size() == 0)) { map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_101); return map; } int index = -1; for (String fixedServerIp : fixedServerIps) { index = findIndexByIp(fixedServerIp, records); if (index == -1) continue; } if (index == -1) { map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_101); return map; } map.put(CommonConstants.SUCCESS, true); map.put(CommonConstants.SERVER_JOB_INFO, records.get(index)); return map; } public BasicDBObject hashServerBySystemCapacity() { int itemLen; if ((records == null) || ((itemLen = records.size()) == 0)) { return null; } else if (1 == itemLen) { BasicDBObject item = (BasicDBObject) records.get(0); double memRatio = Double.valueOf(String.valueOf(item.get(CommonConstants.MEM_RATIO))); if (memRatio > CommonConstants.MAX_MEM_RATIO) { logger.error("ServerNodes-->>hashServerBySystemCapacity() the memRatio(" + memRatio + ") over max mem ratio(" + CommonConstants.MAX_MEM_RATIO + ") "); return null; } else { return item; } } else if (itemLen > 1) { BasicDBObject tempItem = (BasicDBObject) records.get(0); int minMemRatioIndex = 0; double minMemRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.MEM_RATIO))); double minCpuRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.CPU_RATIO))); int minTotalThreadValue = Integer.valueOf(String.valueOf(tempItem.get(CommonConstants.TOTAL_THREAD))); double minTotalValue = minMemRatioValue + minCpuRatioValue + minTotalThreadValue; for (int i = 1; i < itemLen; i++) { tempItem = (BasicDBObject) records.get(i); double tempMemRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.MEM_RATIO))); double tempCpuRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.CPU_RATIO))); int tempTotalThreadValue = Integer.valueOf(String.valueOf(tempItem.get(CommonConstants.TOTAL_THREAD))); double tempTotalValue = tempMemRatioValue + tempCpuRatioValue + tempTotalThreadValue; if (tempTotalValue < minTotalValue) { minMemRatioValue = tempMemRatioValue; minCpuRatioValue = tempCpuRatioValue; minTotalThreadValue = tempTotalThreadValue; minTotalValue = minMemRatioValue + minCpuRatioValue + minTotalThreadValue; minMemRatioIndex = i; } } if (minMemRatioValue > CommonConstants.MAX_MEM_RATIO || minCpuRatioValue > CommonConstants.MAX_CPU_RATIO) { logger.error("ServerNodes-->>hashServerBySystemCapacity() the memRatio(" + minMemRatioValue + ") over max mem ratio(" + CommonConstants.MAX_MEM_RATIO + ") " + "or the cpuRatio(" + minCpuRatioValue + ") over max cpu ration (" + CommonConstants.MAX_CPU_RATIO + ") "); return null; } else { return (BasicDBObject) records.get(minMemRatioIndex); } } return null; } /** * hashServerBySystemCapacity升级版本(4S==For Super) * * @return */ public Map hashServer4SBySystemCapacity() { Map map = new HashMap(); int itemLen; if ((records == null) || ((itemLen = records.size()) == 0)) { map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_101); return map; } else if (1 == itemLen) { BasicDBObject item = (BasicDBObject) records.get(0); double memRatio = Double.valueOf(String.valueOf(item.get(CommonConstants.MEM_RATIO))); double cpuRatio = Double.valueOf(String.valueOf(item.get(CommonConstants.CPU_RATIO))); if (memRatio > CommonConstants.MAX_MEM_RATIO || cpuRatio > CommonConstants.MAX_CPU_RATIO) { logger.error("ClientNodes-->>hashServer4SBySystemCapacity() the memRatio(" + memRatio + ")" + " over max mem ratio(" + CommonConstants.MAX_MEM_RATIO + ") or the cpuRatio(" + cpuRatio + ")" + " over max cpu ratio(" + CommonConstants.MAX_CPU_RATIO + ") "); map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_102); map.put(CommonConstants.MEM_RATIO, memRatio); map.put(CommonConstants.CPU_RATIO, cpuRatio); return map; } else { map.put(CommonConstants.SUCCESS, true); map.put(CommonConstants.SERVER_JOB_INFO, item); return map; } } else if (itemLen > 1) { BasicDBObject tempItem = (BasicDBObject) records.get(0); int minMemRatioIndex = 0; double minMemRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.MEM_RATIO))); double minCpuRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.CPU_RATIO))); int minTotalThreadValue = Integer.valueOf(String.valueOf(tempItem.get(CommonConstants.TOTAL_THREAD))); double minTotalValue = minMemRatioValue + minCpuRatioValue + minTotalThreadValue; for (int i = 1; i < itemLen; i++) { tempItem = (BasicDBObject) records.get(i); double tempMemRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.MEM_RATIO))); double tempCpuRatioValue = Double.valueOf(String.valueOf(tempItem.get(CommonConstants.CPU_RATIO))); int tempTotalThreadValue = Integer.valueOf(String.valueOf(tempItem.get(CommonConstants.TOTAL_THREAD))); double tempTotalValue = tempMemRatioValue + tempCpuRatioValue + tempTotalThreadValue; if (tempTotalValue < minTotalValue) { minMemRatioValue = tempMemRatioValue; minCpuRatioValue = tempCpuRatioValue; minTotalThreadValue = tempTotalThreadValue; minTotalValue = minMemRatioValue + minCpuRatioValue + minTotalThreadValue; minMemRatioIndex = i; } } if (minMemRatioValue > CommonConstants.MAX_MEM_RATIO || minCpuRatioValue > CommonConstants.MAX_CPU_RATIO) { logger.error("ClientNodes-->>hashServer4SBySystemCapacity() " + "the memRatio(" + minMemRatioValue + ") over max mem ratio(" + CommonConstants.MAX_MEM_RATIO + ")" + "or the cpuRatio(" + minCpuRatioValue + ") over max cpu ration (" + CommonConstants.MAX_CPU_RATIO + ") "); map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_102); map.put(CommonConstants.MEM_RATIO, minMemRatioValue); map.put(CommonConstants.CPU_RATIO, minCpuRatioValue); return map; } else { map.put(CommonConstants.SUCCESS, true); map.put(CommonConstants.SERVER_JOB_INFO, records.get(minMemRatioIndex)); return map; } } map.put(CommonConstants.SUCCESS, false); map.put(CommonConstants.ERROR_CODE, CommonConstants.ERROR_CODE_103); return map; } public synchronized void add(BasicDBObject record) { String id = record.getString(CommonConstants.ID); int index = findIndexById(id, this.records); if (index == -1) this.records.add(record); else { this.records.set(index, record); } } public synchronized boolean remove(String id) { try { int index = findIndexById(id, this.records); return null != this.records.remove(index); }catch (Exception e){ return false; } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ZKConnect.java ================================================ package com.gome.clover.common.zk; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.api.CuratorEvent; import org.apache.curator.framework.api.CuratorListener; import org.apache.curator.framework.api.CuratorWatcher; import org.apache.curator.framework.state.ConnectionState; import org.apache.curator.framework.state.ConnectionStateListener; import org.apache.zookeeper.WatchedEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:ZK Connect * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 16:07 */ public class ZKConnect implements CuratorWatcher, CuratorListener, ConnectionStateListener { public CuratorFramework instance = null; public ArrayList listeners = new ArrayList(); protected static Logger logger = LoggerFactory.getLogger(ZKConnect.class); public ZKConnect() { this.instance = ZKUtil.create(); } public boolean start() { try { this.instance.getConnectionStateListenable().addListener(this); this.instance.getCuratorListenable().addListener(this); this.instance.start(); this.instance.getZookeeperClient().blockUntilConnectedOrTimedOut(); return true; } catch (Exception e) { logger.error("ZKConnect->> start() error ", e); } return false; } public void addServerListener(ServerListener serverListener) { this.listeners.add(serverListener); } public void addClientListener(ClientListener clientListener) { this.listeners.add(clientListener); } public void removeServerListener(ServerListener serverListener) { this.listeners.remove(serverListener); } public void removeClientListener(ClientListener clientListener) { this.listeners.remove(clientListener); } public boolean checkAlive() { return this.instance.getZookeeperClient().isConnected(); } public String getData(String path) throws Exception { return ZKUtil.getData(this.instance, path, this); } public boolean exists(String path) { return ZKUtil.exists(this.instance, path, this); } public List getChildrens(String path) throws Exception { if (!ZKUtil.exists(this.instance, path, this)) { return null; } return ZKUtil.getChilds(this.instance, path, this); } public void stateChanged(CuratorFramework client, ConnectionState newState) { if (newState == ConnectionState.RECONNECTED) { logger.info("Zookeeper Reconnect [{}]", new String[]{client.toString()}); } else if ((newState == ConnectionState.LOST) || (newState == ConnectionState.SUSPENDED)) { logger.info("Zookeeper Lost connection"); } } private void fireEvents(WatchedEvent e) { for (int i = 0; i < this.listeners.size(); i++) { if (this.listeners.get(i) instanceof ServerListener) { ServerListener w = (ServerListener) this.listeners.get(i); w.process(e); } else if (this.listeners.get(i) instanceof ClientListener) { ClientListener w = (ClientListener) this.listeners.get(i); w.process(e); } } } public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception { if ((event == null) || (event.getPath() == null)) { return; } fireEvents(event.getWatchedEvent()); } public void process(WatchedEvent event) { if ((event == null) || (event.getPath() == null)) { return; } fireEvents(event); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ZKManager.java ================================================ package com.gome.clover.common.zk; import org.apache.zookeeper.*; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper.States; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Id; import org.apache.zookeeper.server.auth.DigestAuthenticationProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.concurrent.CountDownLatch; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:ZKManager * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ZKManager { private static transient Logger logger = LoggerFactory.getLogger(ZKManager.class); private ZooKeeper zk; private List acl = new ArrayList(); private Properties properties; public enum keys { zkConnectString, rootPath, userName, password, zkSessionTimeout } public ZKManager(Properties properties) throws Exception{ this.properties = properties; this.connect(); } /** * 重连zookeeper * @throws Exception */ public synchronized void reConnection() throws Exception{ if (this.zk != null) { this.zk.close(); this.zk = null; this.connect() ; } } private void connect() throws Exception { CountDownLatch connectionLatch = new CountDownLatch(1); createZookeeper(connectionLatch); connectionLatch.await(); } private void createZookeeper(final CountDownLatch connectionLatch) throws Exception { zk = new ZooKeeper(this.properties.getProperty(keys.zkConnectString .toString()), Integer.parseInt(this.properties .getProperty(keys.zkSessionTimeout.toString())), new Watcher() { public void process(WatchedEvent event) { sessionEvent(connectionLatch, event); } }); String authString = this.properties.getProperty(keys.userName.toString()) + ":"+ this.properties.getProperty(keys.password.toString()); zk.addAuthInfo("digest", authString.getBytes()); acl.clear(); acl.add(new ACL(ZooDefs.Perms.ALL, new Id("digest", DigestAuthenticationProvider.generateDigest(authString)))); acl.add(new ACL(ZooDefs.Perms.READ, Ids.ANYONE_ID_UNSAFE)); } private void sessionEvent(CountDownLatch connectionLatch, WatchedEvent event) { if (event.getState() == KeeperState.SyncConnected) { logger.info("收到ZK连接成功事件!"); connectionLatch.countDown(); } else if (event.getState() == KeeperState.Expired) { logger.error("会话超时,等待重新建立ZK连接..."); try { reConnection(); } catch (Exception e) { logger.error(e.getMessage(),e); } } // Disconnected:Zookeeper会自动处理Disconnected状态重连 } public void close() throws InterruptedException { logger.info("关闭zookeeper连接"); this.zk.close(); } public static Properties createProperties(){ Properties result = new Properties(); result.setProperty(keys.zkConnectString.toString(),"localhost:2181"); result.setProperty(keys.rootPath.toString(),"/cloud-schedule/jobName"); result.setProperty(keys.userName.toString(),"ScheduleAdmin"); result.setProperty(keys.password.toString(),"password"); result.setProperty(keys.zkSessionTimeout.toString(),"60000"); return result; } public String getRootPath(){ return this.properties.getProperty(keys.rootPath.toString()); } public String getConnectStr(){ return this.properties.getProperty(keys.zkConnectString.toString()); } public boolean checkZookeeperState() throws Exception{ return zk != null && zk.getState() == States.CONNECTED; } public boolean isExists(String path) throws Exception{ return getZooKeeper().exists(path, false) != null; } public void setData(String path,String data) throws Exception{ if(!isExists(path)){ createPath(getZooKeeper(), path, CreateMode.EPHEMERAL,acl); } getZooKeeper().setData(path,data.getBytes(),-1); } public String getData(String path)throws Exception{ if(!isExists(path)){ return ""; } return new String(getZooKeeper().getData(path, false, null)); } public void createPath(ZooKeeper zk, String path,CreateMode createMode, List acl) throws Exception { String[] list = path.split("/"); String zkPath = ""; for (String str : list) { if (str.equals("") == false) { zkPath = zkPath + "/" + str; if (zk.exists(zkPath, false) == null) { zk.create(zkPath, null, acl, createMode); } } } } public void delete(String path)throws Exception { getZooKeeper().delete(path,-1); } public List getAcl() { return acl; } public ZooKeeper getZooKeeper() throws Exception { if(this.checkZookeeperState()==false){ reConnection(); } return this.zk; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ZKUtil.java ================================================ package com.gome.clover.common.zk; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.List2StringUtil; import com.gome.clover.common.tools.StringUtil; import com.mongodb.BasicDBObject; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.api.ACLBackgroundPathAndBytesable; import org.apache.curator.framework.api.BackgroundPathable; import org.apache.curator.framework.api.CuratorWatcher; import org.apache.curator.retry.RetryNTimes; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Id; import org.apache.zookeeper.server.auth.DigestAuthenticationProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.NoSuchAlgorithmException; import java.sql.Timestamp; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 14:35 */ public class ZKUtil { protected static Logger logger = LoggerFactory.getLogger(ZKUtil.class); private static List acl = new ArrayList(); public static CuratorFramework create() { RetryNTimes retryPolicy = new RetryNTimes(5, 5000); String authString = CommonConstants.ZK_USER_NAME + ":"+CommonConstants.ZK_PASSWORD; CuratorFramework client = CuratorFrameworkFactory.builder().connectString(CommonConstants.ZK_CONNECT_STRING) .retryPolicy(retryPolicy).connectionTimeoutMs(CommonConstants.ZOO_KEEPER_TIMEOUT) .sessionTimeoutMs(CommonConstants.ZOO_KEEPER_TIMEOUT * 3).authorization("digest", authString.getBytes()).build(); try { acl.clear(); acl.add(new ACL(ZooDefs.Perms.ALL, new Id("digest", DigestAuthenticationProvider.generateDigest(authString)))); acl.add(new ACL(ZooDefs.Perms.READ, ZooDefs.Ids.ANYONE_ID_UNSAFE)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); logger.error("ZKUtil-->>create() error,",e); } return client; } public static boolean exists(CuratorFramework client, String path, CuratorWatcher watcher) { try { if (watcher != null) { return ((BackgroundPathable)client.checkExists().usingWatcher(watcher)).forPath(path) != null; } return client.checkExists().forPath(path) != null; } catch (Exception e) { logger.error("ZKUtil-->>exists(CuratorFramework client, String path, CuratorWatcher watcher) error, ", e); System.err.println("ZKUtil-->>exists(CuratorFramework client, String path, CuratorWatcher watcher) error,"+e.getMessage()); }return false; } public static boolean exists(CuratorFramework client, String path) { return exists(client, path, null); } public static void createPath(CuratorFramework client, String path, String content, CreateMode mode) { try { ((ACLBackgroundPathAndBytesable)client.create().creatingParentsIfNeeded().withMode(mode)).forPath(path, List2StringUtil.toBytes(content)); } catch (Exception e) { logger.error("ZKUtil-->>createPath(CuratorFramework client, String path, String content, CreateMode mode) error,", e); System.err.println("ZKUtil-->>createPath(CuratorFramework client, String path, String content, CreateMode mode) error,"+e.getMessage()); } } public static void setPath(CuratorFramework client, String path, String content, CreateMode mode) { try { if (client.checkExists().forPath(path) == null){ ((ACLBackgroundPathAndBytesable)client.create().creatingParentsIfNeeded().withMode(mode)).forPath(path, List2StringUtil.toBytes(content)); }else client.setData().forPath(path,List2StringUtil.toBytes(content)); } catch (Exception e) { logger.error("ZKUtil-->>setPath(CuratorFramework client, String path, String content, CreateMode mode) error,", e); System.err.println("ZKUtil-->>setPath(CuratorFramework client, String path, String content, CreateMode mode) error," + e.getMessage()); } } public static void updateServerTimestamp(long timestamp, String key) { if (timestamp == 0L) return; DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Timestamp startime = new Timestamp(timestamp); String startDate = format.format(startime); setPath(ServerDict.self.getZK(), key, String.valueOf(timestamp), CreateMode.PERSISTENT); logger.info("ZKUtil-->> update key[{}] timestamp[{}] ", new Object[] { key, startDate }); } public static long readServerTimestamp(String key) { String c = getData(ServerDict.self.getZK(), key); if (StringUtil.isEmpty(c)) { return 0L; } return Long.parseLong(c); } public static String getData(CuratorFramework client, String path) { return getData(client, path, null); } public static String getData(CuratorFramework client, String path, CuratorWatcher watcher) { try { if (client.checkExists().forPath(path) == null) { return null; } if (watcher != null) { return List2StringUtil.toString((byte[])((BackgroundPathable)client.getData().usingWatcher(watcher)).forPath(path)); } return List2StringUtil.toString((byte[])client.getData().forPath(path)); } catch (Exception e) { logger.error("ZKUtil-->>getData(CuratorFramework client, String path, CuratorWatcher watcher) error ", e); System.err.println("ZKUtil-->>getData(CuratorFramework client, String path, CuratorWatcher watcher) error ,"+e.getMessage()); }return null; } public static String createEphemeralSequential(CuratorFramework client, String path, byte[] payload) { try { return (String)((ACLBackgroundPathAndBytesable)client.create().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL)).forPath(path, payload); } catch (Exception e) { logger.error("ZKUtil-->>createEphemeralSequential", e); }return null; } public static void remove(CuratorFramework client, String path) { try { if (client.checkExists().forPath(path) == null) { logger.info("ZKUtil-->>remove(CuratorFramework client, String path) this Path not exists"); System.err.println("ZKUtil-->>remove(CuratorFramework client, String path) this Path not exists"); return; } client.delete().forPath(path); } catch (Exception e) { logger.error("ZKUtil-->>remove(CuratorFramework client, String path) error,", e); System.err.println("ZKUtil-->>remove(CuratorFramework client, String path) error ,"+e.getMessage()); } } public static void delete(CuratorFramework client, String path) { try { client.delete().guaranteed().forPath(path); } catch (Exception e) { logger.error("ZKUtil-->>delete(CuratorFramework client, String path) error,", e); System.err.println("ZKUtil-->>delete(CuratorFramework client, String path) error,"+e.getMessage()); } } public static List getChilds(CuratorFramework client, String path) { return getChilds(client, path, null); } public static List getChilds(CuratorFramework client, String path, CuratorWatcher watcher) { try { if (watcher != null) { return (List)((BackgroundPathable)client.getChildren().usingWatcher(watcher)).forPath(path); } return (List)client.getChildren().forPath(path); } catch (Exception e) { logger.error("ZKUtil-->>getChilds(CuratorFramework client, String path, CuratorWatcher watcher) error,", e); System.err.println("ZKUtil-->>getChilds(CuratorFramework client, String path, CuratorWatcher watcher) error,"+ e.getMessage()); }return null; } public static String getDataByParameter(String path,String qKey,String qValue,String resultValue){ CuratorFramework curatorFramework = ZKUtil.create(); if (!curatorFramework.isStarted()) curatorFramework.start(); List nodeList = ZKUtil.getChilds(curatorFramework,path); for (int i = 0; (nodeList != null) && (i < nodeList.size()); i++) { String id = (String) nodeList.get(i); String c = ZKUtil.getData(curatorFramework, path + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) com.mongodb.util.JSON.parse(c); String tempValue = (String) record.get(qKey); if(tempValue.equals(qValue)){ return (String) record.get(resultValue); }else { continue; } } return null; } public static BasicDBObject getDataByParameter(String path,String qKey,String qValue){ CuratorFramework curatorFramework = ZKUtil.create(); List nodeList = ZKUtil.getChilds(curatorFramework,path); for (int i = 0; (nodeList != null) && (i < nodeList.size()); i++) { String id = (String) nodeList.get(i); String c = ZKUtil.getData(curatorFramework, path + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) com.mongodb.util.JSON.parse(c); String tempValue = (String) record.get(qKey); if(tempValue.equals(qValue)){ return record; }else { continue; } } return null; } public static void main(String[] args) { ZKUtil.setPath(ClientDict.self.getZK(),"/test/wy/test1", "test2", CreateMode.EPHEMERAL); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/common/zk/ZooKeeperWatch.java ================================================ package com.gome.clover.common.zk; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/28 * Time: 16:19 */ public interface ZooKeeperWatch { public void zooNodeChange(String paramString1, String paramString2); public void reconnect(); } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/job/ClientJob.java ================================================ package com.gome.clover.core.job; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.Trigger; import java.io.Serializable; import java.util.Arrays; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Scheduler Client Job 实体类 * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ClientJob implements Serializable { private static final long serialVersionUID = 938554467283788592L; private Trigger trigger; private JobDetail jobDetail; private ExecuteType executeType; private JobType jobType; private JobStrategy jobStrategy; private String startTime; private String cronExpression; private String[] fixedClientIps; private String[] fixedServerIps; private Class jobClass; private String clientIp; private String serverIp; private String jobClassName; private boolean isRecoverJobFromDB; private String jobClassPath; public ClientJob() { } public ClientJob(ClientJobFactory.Builder builder) { this.executeType = builder.getExecuteType(); this.jobType = builder.getJobType(); this.jobStrategy = builder.getJobStrategy(); this.startTime = builder.getStartTime(); this.cronExpression = builder.getCronExpression(); this.fixedClientIps = builder.getFixedClientIps(); this.fixedServerIps = builder.getFixedServerIps(); this.trigger = builder.getTrigger(); this.jobDetail = builder.getJobDetail(); this.jobClass = builder.getJobClass(); this.clientIp = builder.getClientIp(); this.jobClassPath = builder.getClientIp(); } public static enum ExecuteType { ADD, UPDATE, DELETE } public static enum JobType { LOCAL, REMOTE, BROADCAST } public static enum JobStrategy{ HASH,SYSTEM_CAPACITY } public Trigger getTrigger() { return trigger; } public void setTrigger(Trigger trigger) { this.trigger = trigger; } public JobDetail getJobDetail() { return jobDetail; } public void setJobDetail(JobDetail jobDetail) { this.jobDetail = jobDetail; } public ExecuteType getExecuteType() { return executeType; } public void setExecuteType(ExecuteType executeType) { this.executeType = executeType; } public JobType getJobType() { return jobType; } public void setJobType(JobType jobType) { this.jobType = jobType; } public JobStrategy getJobStrategy() { return jobStrategy; } public void setJobStrategy(JobStrategy jobStrategy) { this.jobStrategy = jobStrategy; } public String getStartTime() { return startTime; } public void setStartTime(String startTime) { this.startTime = startTime; } public String getCronExpression() { return cronExpression; } public void setCronExpression(String cronExpression) { this.cronExpression = cronExpression; } public String[] getFixedClientIps() { return fixedClientIps; } public void setFixedClientIps(String[] fixedClientIps) { this.fixedClientIps = fixedClientIps; } public String[] getFixedServerIps() { return fixedServerIps; } public void setFixedServerIps(String[] fixedServerIps) { this.fixedServerIps = fixedServerIps; } public Class getJobClass() { return jobClass; } public void setJobClass(Class jobClass) { this.jobClass = jobClass; } public String getClientIp() { return clientIp; } public void setClientIp(String clientIp) { this.clientIp = clientIp; } public String getServerIp() { return serverIp; } public void setServerIp(String serverIp) { this.serverIp = serverIp; } public String getJobClassName() { return jobClassName; } public void setJobClassName(String jobClassName) { this.jobClassName = jobClassName; } public String getJobClassPath() { return jobClassPath; } public void setJobClassPath(String jobClassPath) { this.jobClassPath = jobClassPath; } public boolean isRecoverJobFromDB() { return isRecoverJobFromDB; } public void setRecoverJobFromDB(boolean isRecoverJobFromDB) { this.isRecoverJobFromDB = isRecoverJobFromDB; } @Override public String toString() { return "ClientJob{" + "jobClass=" + jobClass + ", jobClassName=" + jobClassName + ", groupName=" + jobDetail.getKey().getGroup() + ", jobName=" + jobDetail.getKey().getName() + ", executeType=" + executeType.name() + ", jobType=" + jobType.name() + ", jobStrategy=" + jobStrategy.name() + ", startTime=" + startTime + ", cronExpression=" + cronExpression + ", isRecoverJobFromDB=" + isRecoverJobFromDB + ", clientIp=" + clientIp + ", serverIp=" + serverIp + ", startDate=" + trigger.getStartTime() + ", endDate=" + trigger.getEndTime() + ", fixedClientIps=" + Arrays.toString(fixedClientIps) + ", fixedServerIps=" + Arrays.toString(fixedServerIps) + '}'; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/job/ClientJobBuilder.java ================================================ package com.gome.clover.core.job; import com.gome.clover.common.tools.DateUtil; import org.quartz.Job; import java.util.Date; import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Client Job Builder * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/1 * Time: 14:52 */ public class ClientJobBuilder { /** * 根据Cron Expression快速创建LOCAL类别job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的 * @param cronExpression cron表达式 * @return ClientJob */ public static ClientJob quickBuildLocalCronJob(String jobGroup, String jobName, Class jobClass, String cronExpression) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .withSchedule(cronSchedule(cronExpression)).build()), ClientJob.JobType.LOCAL, "", cronExpression).jobClass(jobClass) .executeType(ClientJob.ExecuteType.ADD).build(); } /** * 根据Cron Expression快速创建REMOTE类别job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param cronExpression cron表达式 * @return ClientJob */ public static ClientJob quickBuildRemoteCronJob(String jobGroup, String jobName, Class jobClass, String cronExpression) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .withSchedule(cronSchedule(cronExpression)).build()), ClientJob.JobType.REMOTE, "", cronExpression).jobClass(jobClass) .executeType(ClientJob.ExecuteType.ADD).build(); } /** * 根据job开始时间快速创建LOCAL类别job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param startTime 开始执行时间 * @return */ public static ClientJob quickBuildLocalJobWithStartDate(String jobGroup, String jobName, Class jobClass, Date startTime) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .startAt(startTime)).build(), ClientJob.JobType.LOCAL, DateUtil.formatWithDefaultPattern(startTime), "") .jobClass(jobClass).executeType(ClientJob.ExecuteType.ADD).build(); } /** * 根据job开始时间快速创建REMOTE类别job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param startTime 开始执行时间 * @return */ public static ClientJob quickBuildRemoteJobWithStartDate(String jobGroup, String jobName, Class jobClass, Date startTime) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .startAt(startTime)).build(), ClientJob.JobType.REMOTE, DateUtil.formatWithDefaultPattern(startTime), "") .jobClass(jobClass).executeType(ClientJob.ExecuteType.ADD).build(); } /** * 根据job开始时间快速创建LOCAL类别job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param executeType ADD,UPDATE,DELETE * @return */ public static ClientJob quickBuildLocalStartNowJobWithExecuteType(String jobGroup, String jobName, Class jobClass, ClientJob.ExecuteType executeType) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .startNow()).build(), ClientJob.JobType.LOCAL, DateUtil.formatWithDefaultPattern(new Date()), "") .jobClass(jobClass).executeType(executeType).build(); } /** * 根据job开始时间快速创建REMOTE类别job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param executeType ADD,UPDATE,DELETE * @return */ public static ClientJob quickBuildRemoteStartNowJobWithExecuteType(String jobGroup, String jobName, Class jobClass, ClientJob.ExecuteType executeType) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .startNow()).build(), ClientJob.JobType.REMOTE, DateUtil.formatWithDefaultPattern(new Date()), "") .jobClass(jobClass).executeType(executeType).build(); } /** * 根据job类型&执行类型&执行时间 快速创建job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param jobType LOCAL,REMOTE * @param executeType ADD,UPDATE,DELETE * @param startTime job 执行时间 * @return ClientJob */ public static ClientJob quickBuildJobWithJobTypeAndExecuteTypeAndStartDate(String jobGroup, String jobName, Class jobClass, ClientJob.JobType jobType, ClientJob.ExecuteType executeType, Date startTime) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .startAt(startTime)).build(), jobType, executeType, DateUtil.formatWithDefaultPattern(startTime), "") .jobClass(jobClass).build(); } /** * 根据job类型&执行类型&job策略&执行时间 快速创建job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param jobType LOCAL,REMOTE * @param executeType ADD,UPDATE,DELETE * @param jobStrategy HASH,SYSTEM_CAPACITY * @param startTime job 执行时间 * @return ClientJob */ public static ClientJob quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndStartDate(String jobGroup, String jobName, Class jobClass, ClientJob.JobType jobType, ClientJob.ExecuteType executeType, ClientJob.JobStrategy jobStrategy, Date startTime) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .startAt(startTime)).build(), jobType, executeType,jobStrategy, DateUtil.formatWithDefaultPattern(startTime), "") .jobClass(jobClass).build(); } /** * 根据job类型&执行类型&cron执行表达式 快速创建job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param jobType LOCAL,REMOTE * @param executeType ADD,UPDATE,DELETE * @param cronExpression job cron执行表达式 * @return ClientJob */ public static ClientJob quickBuildJobWithJobTypeAndExecuteTypeAndCronExpression(String jobGroup, String jobName, Class jobClass, ClientJob.JobType jobType, ClientJob.ExecuteType executeType, String cronExpression) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .withSchedule(cronSchedule(cronExpression)).build()), jobType, executeType, "", cronExpression) .jobClass(jobClass).build(); } /** * 根据job类型&执行类型&job策略&cron执行表达式 快速创建job * * @param jobGroup job 组 * @param jobName job 名称 * @param jobClass 自定义实现Job接口的类 * @param jobType LOCAL,REMOTE * @param executeType ADD,UPDATE,DELETE * @param jobStrategy HASH,SYSTEM_CAPACITY * @param cronExpression job cron执行表达式 * @return ClientJob */ public static ClientJob quickBuildJobWithJobTypeAndExecuteTypeAndJobStrategyAndCronExpression(String jobGroup, String jobName, Class jobClass, ClientJob.JobType jobType, ClientJob.ExecuteType executeType, ClientJob.JobStrategy jobStrategy, String cronExpression) { return ClientJobFactory.builder((newJob(jobClass) .withIdentity(jobName, jobGroup).build()), (newTrigger() .withIdentity(jobName, jobGroup) .withSchedule(cronSchedule(cronExpression)).build()), jobType, executeType,jobStrategy, "", cronExpression) .jobClass(jobClass).build(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/job/ClientJobFactory.java ================================================ package com.gome.clover.core.job; import com.gome.clover.core.job.ClientJob.ExecuteType; import com.gome.clover.core.job.ClientJob.JobStrategy; import com.gome.clover.core.job.ClientJob.JobType; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.Trigger; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Client Job Factory * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ClientJobFactory { public static Builder builder(JobDetail jobDetail, Trigger trigger,String startTime,String cronExpression,String jobClassPath) { return new Builder(jobDetail, trigger,startTime,cronExpression,jobClassPath); } public static Builder builder(JobDetail jobDetail, Trigger trigger, JobType jobType,String startTime,String cronExpression) { return new Builder(jobDetail, trigger, jobType,startTime,cronExpression); } public static Builder builder(JobDetail jobDetail, Trigger trigger, JobType jobType,ExecuteType executeType, String startTime,String cronExpression) { return new Builder(jobDetail, trigger, jobType,executeType,startTime,cronExpression); } public static Builder builder(JobDetail jobDetail, Trigger trigger, JobType jobType,ExecuteType executeType, JobStrategy jobStrategy,String startTime,String cronExpression) { return new Builder(jobDetail, trigger, jobType,executeType,jobStrategy,startTime,cronExpression); } public static class Builder { private Trigger trigger; private JobDetail jobDetail; private ExecuteType executeType; private JobType jobType; private JobStrategy jobStrategy; private String startTime; private String cronExpression; private String[] fixedClientIps; private String[] fixedServerIps; private Class jobClass; private String clientIp; private String jobClassPath; Builder(JobDetail jobDetail, Trigger trigger,String startTime,String cronExpression,String jobClassPath) { this.jobDetail = jobDetail; this.trigger = trigger; this.jobType = JobType.LOCAL; this.executeType = ExecuteType.ADD; this.jobStrategy = JobStrategy.HASH; this.startTime = startTime; this.cronExpression = cronExpression; this.jobClassPath = jobClassPath; } Builder(JobDetail jobDetail, Trigger trigger, JobType jobType,String startTime,String cronExpression) { this.jobDetail = jobDetail; this.trigger = trigger; this.jobType = jobType; this.executeType = ExecuteType.ADD; this.jobStrategy = JobStrategy.HASH; this.startTime = startTime; this.cronExpression = cronExpression; } Builder(JobDetail jobDetail, Trigger trigger, JobType jobType,ExecuteType executeType, String startTime,String cronExpression) { this.jobDetail = jobDetail; this.trigger = trigger; this.jobType = jobType; this.executeType = executeType; this.jobStrategy = JobStrategy.HASH; this.startTime = startTime; this.cronExpression = cronExpression; } Builder(JobDetail jobDetail, Trigger trigger, JobType jobType,ExecuteType executeType,JobStrategy jobStrategy, String startTime,String cronExpression) { this.jobDetail = jobDetail; this.trigger = trigger; this.jobType = jobType; this.executeType = executeType; this.jobStrategy = jobStrategy; this.startTime = startTime; this.cronExpression = cronExpression; } public Builder jobClass(Class jobClass) { this.jobClass = jobClass; return this; } public Builder executeType(ExecuteType executeType) { this.executeType = executeType; return this; } public Builder jobStrategy(JobStrategy jobStrategy) { this.jobStrategy = jobStrategy; return this; } public Builder startTime(String startTime) { this.startTime = startTime; return this; } public Builder cronExpression(String cronExpression) { this.cronExpression = cronExpression; return this; } public Builder fixedClientIps(String... fixedClientIps) { this.fixedClientIps = fixedClientIps; return this; } public Builder fixedServerIps(String... fixedServerIps) { this.fixedServerIps = fixedServerIps; return this; } public Builder clientIp(String ip) { this.clientIp = ip; return this; } public ClientJob build() { if (jobType != JobType.LOCAL && jobClass == null) throw new ExceptionInInitializerError("ClientJobFactory-->>build() jobClass can not null"); return new ClientJob(this); } public Trigger getTrigger() { return trigger; } public JobDetail getJobDetail() { return jobDetail; } public ExecuteType getExecuteType() { return executeType; } public JobType getJobType() { return jobType; } public JobStrategy getJobStrategy() { return jobStrategy; } public String getStartTime() { return startTime; } public String getCronExpression() { return cronExpression; } public String[] getFixedClientIps() { return fixedClientIps; } public String[] getFixedServerIps() { return fixedServerIps; } public Class getJobClass() { return jobClass; } public String getClientIp() { return clientIp; } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/job/MyJobListener.java ================================================ package com.gome.clover.core.job; import com.gome.clover.common.mongodb.MongoDBUtil; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.quartz.JobListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:My Job Listener(Listener数据存储到Redis中) * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class MyJobListener implements JobListener { private static Logger logger = LoggerFactory.getLogger(MyJobListener.class); @Override public String getName() { return MyJobListener.class.getSimpleName(); } @Override public void jobToBeExecuted(JobExecutionContext context) { if(MongoDBUtil.isEnabledDB()){ MongoDBUtil.updateJobTime(context,1); } } //logger.info("job [{}] is about to be executed.", getJobKey(context).toString()); //System.err.println("jobToBeExecuted:"+context.getJobDetail().getKey()); @Override public void jobExecutionVetoed(JobExecutionContext context) { logger.info("job [{}] execution was vetoed.", getJobKey(context).toString()); System.err.println("jobExecutionVetoed:"+context.getJobDetail().getKey()); } @Override public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { //logger.info("job [{}] was executed.", getJobKey(context).toString()); //System.err.println("jobWasExecuted:"+context.getJobDetail().getKey()); if(MongoDBUtil.isEnabledDB()){ MongoDBUtil.updateJobTime(context,2); } } private JobKey getJobKey(JobExecutionContext context) { return context.getJobDetail().getKey(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/job/ServerJob.java ================================================ package com.gome.clover.core.job; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.netty.client.ObjectReqClient; import com.gome.clover.common.netty.server.ObjectRespServer; import com.gome.clover.common.tools.*; import com.gome.clover.common.zeromq.AsyncSendMsg; import com.gome.clover.common.zeromq.ZeroMQEntity; import com.gome.clover.common.zk.ClientDict; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import com.mongodb.DBObject; import org.apache.commons.codec.binary.Base64; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Server Job * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ServerJob extends ClientJob implements Job { private static final Logger logger = LoggerFactory.getLogger(ServerJob.class); private static final long serialVersionUID = -5273842746335434168L; @Override public void execute(JobExecutionContext context) throws JobExecutionException { ServerJob serverJob = (ServerJob) ClassUtil.BytesToObject(Base64.decodeBase64( (String) context.getJobDetail().getJobDataMap().get(CommonConstants.SERVER_JOB_INFO))); serverJob.getJobDetail().getJobDataMap().put(CommonConstants.SERVER_JOB_INFO, context.getJobDetail() .getJobDataMap().get(CommonConstants.SERVER_JOB_INFO)); serverJob.getJobDetail().getJobDataMap().put(CommonConstants.CLIENT_JOB_INFO, context.getJobDetail() .getJobDataMap().get(CommonConstants.CLIENT_JOB_INFO)); handlerJob(serverJob); deleteJobFromDB(context, serverJob); } private boolean handlerJob(ServerJob clientJob) { String[] fixedServerIps = clientJob.getFixedServerIps(); if (fixedServerIps != null && fixedServerIps.length > 0) { return isContainLocalIp(fixedServerIps) && handlerJobType(clientJob); } else { return handlerJobType(clientJob); } } private boolean handlerJobType(ServerJob serverJob) { switch (serverJob.getJobType()) { case REMOTE: return handlerRemoteJob(serverJob); case BROADCAST: return handlerBroadcastJob(serverJob); default: logger.error("ServerJob-->>handlerJobType(" + serverJob.toString() + ") NOT LOCAL|REMOTE, jobType is " + serverJob.getJobType()); return false; } } private boolean handlerRemoteJob(ServerJob serverJob) { try { String[] fixedClientIps = serverJob.getFixedClientIps(); BasicDBObject clientInfo; String clientJobKey = serverJob.getJobDetail().getKey().toString(); Map retMap; if (fixedClientIps != null && fixedClientIps.length > 0) { retMap = ClientDict.self.hashClient4SByFixedClientIps(serverJob.getJobClassName(), fixedClientIps); clientInfo = (BasicDBObject) retMap.get(CommonConstants.CLIENT_JOB_INFO); } else { switch (serverJob.getJobStrategy()) { case HASH: retMap = ClientDict.self.hashClient4S(serverJob.getJobClassName(), clientJobKey); break; case SYSTEM_CAPACITY: retMap = ClientDict.self.hashClient4SBySystemCapacity(serverJob.getJobClassName()); break; default: retMap = ClientDict.self.hashClient4SBySystemCapacity(serverJob.getJobClassName()); } clientInfo = (BasicDBObject) retMap.get(CommonConstants.CLIENT_JOB_INFO); } if ((Boolean)retMap.get(CommonConstants.SUCCESS) && null != clientInfo) { String clientIp = (String) clientInfo.get(CommonConstants.IP); /** /*发送zero mq消息队列方式 开始 String clientPort = (String) clientInfo.get(CommonConstants.PORT); AsyncSendMsg.sendWithThreadPool(clientIp, clientPort, JSON.toJSONString(new ZeroMQEntity(CommonConstants.MODULE_TYPE_CLIENT, clientIp, Base64.encodeBase64String(ClassUtil.ObjectToBytes(serverJob))))); 发送zero mq消息队列方式 结束 **/ logger.error("************************"+ClassUtil.ObjectToBytes(serverJob).length +"************************"); logger.error("************************"+Base64.encodeBase64String(ClassUtil.ObjectToBytes(serverJob)).length() +"************************"); new ObjectReqClient().connect(CommonConstants.NETTY_SERVER_PORT, clientIp, new ZeroMQEntity(CommonConstants.MODULE_TYPE_CLIENT, clientIp, Base64.encodeBase64String(ClassUtil.ObjectToBytes(serverJob)))); } else { //情况很严重 需要报警来解决问题 DBObject queryCondition = new BasicDBObject(); queryCondition.put(DBTableInfo.COL_JOB_KEY, clientJobKey); queryCondition.put(DBTableInfo.COL_JOB_TYPE, JobType.REMOTE.name()); DBCollection dbCollection = MongoDBUtil.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject retObj = dbCollection.findOne(queryCondition); String errorCode = (String) retMap.get(CommonConstants.ERROR_CODE); String msg = null; if (CommonConstants.ERROR_CODE_101.equals(errorCode)) { msg = "ServerJob-->>handlerRemoteJob(" + serverJob.toString() + ") clientInfo null"; } else if (CommonConstants.ERROR_CODE_102.equals(errorCode)) { msg = "ServerJob-->>handlerRemoteJob(" + serverJob.toString() + ") the memRatio(" + retMap.get(CommonConstants.MEM_RATIO) + ") over max mem ratio("+CommonConstants.MAX_MEM_RATIO+")" + " or the cpuRatio("+retMap.get(CommonConstants.CPU_RATIO)+") over max cpu ratio("+CommonConstants.MAX_CPU_RATIO+") "; } if (null != retObj && retObj.containsField(DBTableInfo.COL_FAIL_TIMES)) { int failTimes = Integer.parseInt(String.valueOf(retObj.get(DBTableInfo.COL_FAIL_TIMES))); if (failTimes >= 0 && failTimes < CommonConstants.MAX_FAIL_TIMES) { String title = "Client of IP:" + serverJob.getClientIp() + " is error "; SendMailUtil.sendDefaultMail(title, msg); SendMailUtil.sendMailByJobKey(clientJobKey, title, msg); BasicDBObject updateCondition = new BasicDBObject(); updateCondition.put(DBTableInfo.COL_FAIL_TIMES, (Integer.parseInt(String.valueOf(retObj.get(DBTableInfo.COL_FAIL_TIMES))) + 1)); dbCollection.update(new BasicDBObject(DBTableInfo.COL_ID, retObj.get(DBTableInfo.COL_ID)), new BasicDBObject("$set", updateCondition), true, false); } } logger.error(msg); return false; } } catch (Exception e) { logger.error("ServerJob-->>handlerRemoteJob(" + serverJob.toString() + ") error ", e); String execMethod = "ModuleSchedulerServer-->>handlerRemoteJob(" + serverJob.toString() + ")"; String execResult = "ModuleSchedulerServer-->>handlerRemoteJob(" + serverJob.toString() + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } return false; } private boolean isContainLocalIp(String ips[]) { for (String ip : ips) if (ip.equals(IpUtil.getLocalIP())) return true; return false; } private void deleteJobFromDB(JobExecutionContext context, ServerJob serverJob) { String jobKey = context.getJobDetail().getKey().toString(); if (context.getNextFireTime() != null) { //更新下DB中job状态 if (MongoDBUtil.isEnabledDB()) { BasicDBObject document = getUpdateRemoteJobBasicDBObject(serverJob, jobKey); MongoDBUtil.INSTANCE.update(document, DBTableInfo.TBL_CLOVER_JOB); } return; } BasicDBObject deleteCondition = new BasicDBObject(); deleteCondition.put(DBTableInfo.COL_JOB_KEY, jobKey); deleteCondition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_REMOTE); MongoDBUtil.INSTANCE.delete(deleteCondition, DBTableInfo.TBL_CLOVER_JOB); logger.info("ServerJob-->>deleteJobFromDB(" + jobKey + ") remove job [{}] from DB", jobKey); } private BasicDBObject getUpdateRemoteJobBasicDBObject(ServerJob serverJob, String jobKey) { BasicDBObject document = new BasicDBObject(); document.put(DBTableInfo.COL_JOB_KEY, jobKey); document.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_REMOTE); document.put(DBTableInfo.COL_EXECUTE_TYPE, serverJob.getExecuteType().name()); document.put(DBTableInfo.COL_JOB_STRATEGY, serverJob.getJobStrategy().name()); document.put(DBTableInfo.COL_START_TIME, null != serverJob.getStartTime() ? serverJob.getStartTime() : ""); document.put(DBTableInfo.COL_CRON_EXPRESSION, null != serverJob.getCronExpression() ? serverJob.getCronExpression() : ""); document.put(DBTableInfo.COL_JOB_INFO, Base64.encodeBase64String(ClassUtil.ObjectToBytes(serverJob))); document.put(DBTableInfo.COL_CLIENT_IP, serverJob.getClientIp()); document.put(DBTableInfo.COL_SERVER_IP, IpUtil.getLocalIP()); document.put(DBTableInfo.COL_EXECUTE_START_TIME, ""); document.put(DBTableInfo.COL_EXECUTE_END_TIME, ""); document.put(DBTableInfo.COL_FIXED_CLIENT_IPS, null != serverJob.getFixedClientIps() ? JSON.toJSONString(serverJob.getFixedClientIps()) : ""); document.put(DBTableInfo.COL_FIXED_SERVER_IPS, null != serverJob.getFixedServerIps() ? JSON.toJSONString(serverJob.getFixedServerIps()) : ""); document.put(DBTableInfo.COL_STATUS, CommonConstants.JOB_STATUS_1); document.put(DBTableInfo.COL_TIMES, 0); document.put(DBTableInfo.COL_FAIL_TIMES, 0); document.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); return document; } private boolean handlerBroadcastJob(ServerJob serverJob) { //该功能慢慢考虑如何实现 return false; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/job/ServerJobFactory.java ================================================ package com.gome.clover.core.job; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.common.tools.CommonConstants; import org.apache.commons.codec.binary.Base64; import org.quartz.*; import org.quartz.spi.MutableTrigger; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Server Job Factory * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ServerJobFactory { public static ServerJob createControlJob(ClientJob clientJob) { ServerJob serverJob = new ServerJob(); serverJob.setExecuteType(clientJob.getExecuteType()); serverJob.setJobStrategy(clientJob.getJobStrategy()); serverJob.setStartTime(clientJob.getStartTime()); serverJob.setCronExpression(clientJob.getCronExpression()); serverJob.setFixedClientIps(clientJob.getFixedClientIps()); serverJob.setFixedServerIps(clientJob.getFixedServerIps()); serverJob.setClientIp(clientJob.getClientIp()); serverJob.setJobType(ClientJob.JobType.REMOTE); serverJob.setJobDetail(createJobDetail(clientJob)); serverJob.setTrigger(createTrigger(clientJob)); serverJob.setJobClassName(clientJob.getJobClassName()); serverJob.setRecoverJobFromDB(clientJob.isRecoverJobFromDB()); serverJob.setJobClassPath(clientJob.getJobClassPath()); setJobInfo(serverJob, clientJob); return serverJob; } protected static TriggerKey createServerTriggerKey(ClientJob clientJob) { return new TriggerKey(getClientJobName(clientJob), getClientJobGroup(clientJob)); // return new TriggerKey(createServerJobName(clientJob),CommonConstants.REMOTE_JOB_GROUP); } private static JobKey createServerJobKey(ClientJob clientJob) { return new JobKey(getClientJobName(clientJob), getClientJobGroup(clientJob)); //return new JobKey(createServerJobName(clientJob),CommonConstants.REMOTE_JOB_GROUP); } private static String createServerJobName(ClientJob clientJob) { return getClientJobGroup(clientJob) + "." + getClientJobName(clientJob); } private static String getClientJobName(ClientJob clientJob) { return clientJob.getJobDetail().getKey().getName(); } private static String getClientJobGroup(ClientJob clientJob) { return clientJob.getJobDetail().getKey().getGroup(); } private static JobDetail createJobDetail(ClientJob clientJob) { return JobBuilder.newJob(ServerJob.class).withIdentity(createServerJobKey(clientJob)).build(); } private static Trigger createTrigger(ClientJob clientJob) { Trigger trigger = clientJob.getTrigger(); if ((trigger instanceof MutableTrigger) == false) return null; byte[] byteTrigger = ClassUtil.ObjectToBytes(trigger); MutableTrigger mutableTrigger = (MutableTrigger) ClassUtil.BytesToObject(byteTrigger); mutableTrigger.setKey(createServerTriggerKey(clientJob)); mutableTrigger.setJobKey(createServerJobKey(clientJob)); return mutableTrigger; } private static void setJobInfo(ServerJob serverJob, ClientJob clientJob) { serverJob.getJobDetail().getJobDataMap().put(CommonConstants.SERVER_JOB_INFO,Base64.encodeBase64String( ClassUtil.ObjectToBytes(serverJob))); /** serverJob.getJobDetail().getJobDataMap().put(CommonConstants.CLIENT_JOB_INFO,Base64.encodeBase64String( ClassUtil.ObjectToBytes(clientJob))); **/ serverJob.getJobDetail().getJobDataMap().put(CommonConstants.CLIENT_JOB_PATH,clientJob.getJobClassName()); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/module/AbstractModuleScheduler.java ================================================ package com.gome.clover.core.module; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.systeminfo.SystemInfoUtil; import com.gome.clover.common.tools.*; import com.gome.clover.common.zk.ClientDict; import com.gome.clover.common.zk.ServerDict; import com.gome.clover.common.zk.ZKUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.scheduler.MyScheduler; import com.mongodb.*; import org.apache.commons.codec.binary.Base64; import org.apache.zookeeper.CreateMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Abstract Module Scheduler * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public abstract class AbstractModuleScheduler { private Logger logger = LoggerFactory.getLogger(AbstractModuleScheduler.class); protected static MyScheduler scheduler = MyScheduler.INSTANCE; public void registerToZK(String moduleType, String ip, List jobClassList, String port, String systemId) { try { if (CommonConstants.MODULE_TYPE_SERVER.equals(moduleType)) {//服务端 String serverId = IpUtil.getLocalName() + "@" + ip + "@" + systemId + "@" + DateUtil.currentDateTime(); BasicDBObject serverNode = new BasicDBObject(); serverNode.append(CommonConstants.ID, serverId); serverNode.append(CommonConstants.PORT, port); serverNode.append(CommonConstants.IP, ip); serverNode.append(CommonConstants.TS, DateUtil.currentDateTime()); serverNode.append(CommonConstants.MEM_RATIO,SystemInfoUtil.getMemRatio()); serverNode.append(CommonConstants.CPU_RATIO,SystemInfoUtil.getCpuRatio()); serverNode.append(CommonConstants.TOTAL_THREAD,SystemInfoUtil.getTotalThread()); ZKUtil.setPath(ClientDict.self.getZK(), CommonConstants.ZK_ROOT_PATH + "/" + moduleType + "/" + serverId, serverNode.toString(), CreateMode.EPHEMERAL); } else if (CommonConstants.MODULE_TYPE_CLIENT.equals(moduleType)) {//客户端 if ((jobClassList == null) || (jobClassList.size() == 0)) { return; } BasicDBList jobClass = new BasicDBList(); jobClass.addAll(jobClassList); String clientId = IpUtil.getLocalName() + "@" + ip + "@" + systemId + "@"+ DateUtil.currentDateTime(); BasicDBObject clientNode = new BasicDBObject(); clientNode.append(CommonConstants.ID, clientId); clientNode.append(CommonConstants.JOB_CLASS, jobClass); clientNode.append(CommonConstants.PORT, port); clientNode.append(CommonConstants.IP, ip); clientNode.append(CommonConstants.TS, DateUtil.currentDateTime()); clientNode.append(CommonConstants.MEM_RATIO,SystemInfoUtil.getMemRatio()); clientNode.append(CommonConstants.CPU_RATIO,SystemInfoUtil.getCpuRatio()); clientNode.append(CommonConstants.TOTAL_THREAD,SystemInfoUtil.getTotalThread()); ZKUtil.setPath(ServerDict.self.getZK(), CommonConstants.ZK_ROOT_PATH + "/" + moduleType + "/" + clientId, clientNode.toString(), CreateMode.EPHEMERAL); } } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("AbstractModuleScheduler-->>registerToZK(" + moduleType + "," + ip + ")", e); String execMethod = "AbstractModuleScheduler-->>registerToZK(" + moduleType + "," + ip + ")"; String execResult = "AbstractModuleScheduler-->>registerToZK(" + moduleType + "," + ip + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } public void reloadJobFromDB(String moduleType, String ip) { if (CommonConstants.MODULE_TYPE_SERVER.equals(moduleType)) {//服务端 try { DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject condition = new BasicDBObject(); if (!StringUtil.isEmpty(ip)) condition.put(DBTableInfo.COL_SERVER_IP, ip); condition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_REMOTE); DBCursor cursorDocMap = dbCollection.find(condition); while (cursorDocMap.hasNext()) { ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String) cursorDocMap.next() .get(DBTableInfo.COL_JOB_INFO))); scheduler.add(clientJob); } //恢复clover_job_temp表中数据 dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB_TEMP); cursorDocMap = dbCollection.find(); while (cursorDocMap.hasNext()) { DBObject tempDBObject = cursorDocMap.next(); ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String) tempDBObject.get(DBTableInfo.COL_JOB_INFO))); DBObject retObj = MongoDBUtil.INSTANCE.findOneByCondition(BuildMongoDBData.getDBObjectFromClientJob(clientJob), DBTableInfo.TBL_CLOVER_JOB); if (null == retObj) { scheduler.add(clientJob); MongoDBUtil.INSTANCE.insertOrUpdate(BuildMongoDBData.getInsertJobBasicDBObject(clientJob), DBTableInfo.TBL_CLOVER_JOB); dbCollection.remove(new BasicDBObject(DBTableInfo.COL_ID, tempDBObject.get(DBTableInfo.COL_ID)));//delete } } } catch (Exception e) { logger.error("ModuleSchedulerServer-->>reloadJobFromDB(" + moduleType + "," + ip + ") error", e); String execMethod = "ModuleSchedulerServer-->>reloadJobFromDB(" + moduleType + "," + ip + ")"; String execResult = "ModuleSchedulerServer-->>reloadJobFromDB(" + moduleType + "," + ip + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } else if (CommonConstants.MODULE_TYPE_CLIENT.equals(moduleType)) {//客户端 try { DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_LOCAL); condition.put(DBTableInfo.COL_CLIENT_IP, ip); DBCursor cursorDocMap = dbCollection.find(condition); while (cursorDocMap.hasNext()) { ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String) cursorDocMap.next() .get(DBTableInfo.COL_JOB_INFO))); scheduler.add(clientJob); } } catch (Exception e) { logger.error("ModuleSchedulerClient-->>reloadJobFromDB(" + ip + ") error", e); String execMethod = "ModuleSchedulerServer-->>reloadJobFromDB(" + ip + ")"; String execResult = "ModuleSchedulerServer-->>reloadJobFromDB(" + ip + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); } } } public void resetJobExecuteTime(String clientIp,String serverIp){ BasicDBObject queryCondition = new BasicDBObject(); if(!StringUtil.isEmpty(clientIp)) queryCondition.append(DBTableInfo.COL_CLIENT_IP,IpUtil.getLocalIP()); if(!StringUtil.isEmpty(serverIp)) queryCondition.append(DBTableInfo.COL_SERVER_IP,IpUtil.getLocalIP()); BasicDBObject updateCondition = new BasicDBObject(); updateCondition.append(DBTableInfo.COL_EXECUTE_START_TIME,""); updateCondition.append(DBTableInfo.COL_EXECUTE_END_TIME,""); MongoDBUtil.update(queryCondition,updateCondition,DBTableInfo.TBL_CLOVER_JOB); } public void resetFailTimes(String clientIp,String serverIp){ BasicDBObject queryCondition = new BasicDBObject(); if(!StringUtil.isEmpty(clientIp)) queryCondition.append(DBTableInfo.COL_CLIENT_IP,IpUtil.getLocalIP()); if(!StringUtil.isEmpty(serverIp)) queryCondition.append(DBTableInfo.COL_SERVER_IP,IpUtil.getLocalIP()); queryCondition.append(DBTableInfo.COL_FAIL_TIMES,new BasicDBObject("$gt", 0)); DBCollection dbCollection = MongoDBUtil.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBCursor cursorDocMap = dbCollection.find(queryCondition); while (cursorDocMap.hasNext()){ BasicDBObject updateCondition = new BasicDBObject(); updateCondition.append(DBTableInfo.COL_FAIL_TIMES,0); MongoDBUtil.update(new BasicDBObject(DBTableInfo.COL_ID,cursorDocMap.next().get(DBTableInfo.COL_ID)),updateCondition,DBTableInfo.TBL_CLOVER_JOB); } } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/module/ModuleSchedulerClient.java ================================================ package com.gome.clover.core.module; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.netty.client.ObjectReqClient; import com.gome.clover.common.netty.server.ObjectRespServer; import com.gome.clover.common.tools.*; import com.gome.clover.common.zeromq.ZeroMQEntity; import com.gome.clover.common.zk.ServerDict; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.MyJobListener; import com.gome.clover.core.job.ServerJob; import com.gome.clover.core.job.ServerJobFactory; import com.gome.clover.core.monitor.client.ClientHeartBeat; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.LinkedList; import java.util.List; import java.util.Map; import static org.quartz.JobBuilder.*; import static org.quartz.TriggerBuilder.*; import static org.quartz.SimpleScheduleBuilder.*; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Module Scheduler Client * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ModuleSchedulerClient extends AbstractModuleScheduler { private static final Logger logger = LoggerFactory.getLogger(ModuleSchedulerClient.class); private volatile static ModuleSchedulerClient moduleSchedulerClient = null; private List defaultJobs = new LinkedList(); private ModuleSchedulerClient() { scheduler.start(); } public static ModuleSchedulerClient getInstance() { synchronized (ModuleSchedulerClient.class) { if (null == moduleSchedulerClient) { moduleSchedulerClient = new ModuleSchedulerClient(); } } return moduleSchedulerClient; } /** * 启动 Client端服务 * * @param jobClassList 注册job class到zk(默认启动) * @param isRegisterToZK 是否启动注册到zk服务(默认启动) * @param isStartupNetty 是否启动Netty服务(默认启动) * @param port MQ服务启动端口号 * @param token token验证码 * @return true:成功;false:失败 */ public boolean startup(List jobClassList, boolean isRegisterToZK, boolean isStartupNetty, String port, String systemId, String token) { if (!StringUtil.isEmpty(token) && CommonConstants.token.equals(token)) { if (StringUtil.isEmpty(systemId)) throw new RuntimeException("ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") systemId null "); try { scheduler.start(); //start scheduler String clientIP = IpUtil.getLocalIP(); if (StringUtil.isEmpty(port) || (!StringUtil.isEmpty(port) && "-1".equals(port))) port =RandomNumUtil.getNextIntString();//String.valueOf(NetUtils.getAvailablePort(1025)); if (isRegisterToZK) { registerToZK(CommonConstants.MODULE_TYPE_CLIENT, clientIP, jobClassList, port, systemId); } if (isStartupNetty) { // AsyncStartZeroMQ.startup(port); // new ObjectRespServer().start(CommonConstants.NETTY_SERVER_PORT);//.bind(Integer.valueOf(CommonConstants.NETTY_SERVER_PORT)); new ObjectRespServer().bind(CommonConstants.NETTY_SERVER_PORT); } reloadJobFromDB(CommonConstants.MODULE_TYPE_CLIENT, clientIP); addDefaultJob(); //resetJobExecuteTime(clientIP,null); resetFailTimes(clientIP, null); ClientHeartBeat.INSTNACE.startup(); System.err.println("ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") ...."); return true; } catch (Exception e) { logger.error("ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") error", e); String execMethod = "ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") error"; String execResult = "ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); throw new RuntimeException(e); } } else if (!StringUtil.isEmpty(token) && !CommonConstants.token.equals(token)) { logger.error("ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") token wrong"); throw new RuntimeException("ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") token wrong"); } else if (StringUtil.isEmpty(token)) { logger.error("ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") token null"); throw new RuntimeException("ModuleSchedulerClient-->>startup(" + JSON.toJSONString(jobClassList) + "," + isRegisterToZK + "," + isStartupNetty + ") token null"); } return false; } public boolean startupForLocalJobTest() { try { scheduler.start(); //start scheduler return true; } catch (Exception e) { logger.error("ModuleSchedulerClient-->>startupForLocalJobTest() error", e); return false; } } public void addDefaultJob() { for (ClientJob clientJob : defaultJobs) { handlerJob(clientJob); } } public boolean stop() { scheduler.stop(); return true; } public boolean handlerJob(ClientJob clientJob) { if (clientJob == null) return false; clientJob.setClientIp(IpUtil.getLocalIP()); clientJob.setJobClassName(clientJob.getJobClass().getName()); String[] fixedClientIps = clientJob.getFixedClientIps(); if (fixedClientIps != null && fixedClientIps.length > 0) { return isContainLocalIp(fixedClientIps) && handlerJobType(clientJob); } else { return handlerJobType(clientJob); } } private boolean handlerJobType(ClientJob clientJob) { switch (clientJob.getJobType()) { case LOCAL: return handlerLocalJob(clientJob); case REMOTE: return handlerRemoteJob(clientJob); default: logger.error("ModuleSchedulerClient-->>handlerJobType(" + clientJob.toString() + ") NOT LOCAL|REMOTE, jobType is " + clientJob.getJobType()); return false; } } private boolean handlerLocalJob(ClientJob clientJob) { if (null == clientJob) { assert clientJob != null; logger.error("ModuleSchedulerClient-->>handlerLocalJob(" + clientJob.toString() + ") clientJob null "); return false; } switch (clientJob.getExecuteType()) { case ADD: return addLocalJob(clientJob); case DELETE: return deleteLocalJob(clientJob); case UPDATE: return updateLocalJob(clientJob); default: logger.error("ModuleSchedulerClient-->>handlerLocalJob(" + clientJob.toString() + ") NOT ADD|DELETE|UPDATE, executeType is " + clientJob.getExecuteType()); return false; } } private boolean addLocalJob(ClientJob clientJob) { try { if (!scheduler.add(clientJob)) return false; scheduler.addJobListener(new MyJobListener(), clientJob); if (clientJob.isRecoverJobFromDB()) { return MongoDBUtil.INSTANCE.insertOrUpdate(BuildMongoDBData.getInsertJobBasicDBObject(clientJob), DBTableInfo.TBL_CLOVER_JOB); } } catch (Exception e) { logger.error("ModuleSchedulerClient-->>addLocalJob(" + clientJob.toString() + ") error", e); String execMethod = "ModuleSchedulerClient-->>addLocalJob(" + clientJob.toString() + ")"; String execResult = "ModuleSchedulerClient-->>addLocalJob(" + clientJob.toString() + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } return true; } private boolean deleteLocalJob(ClientJob clientJob) { try { if (!scheduler.delete(clientJob)) return false; BasicDBObject condition = BuildMongoDBData.getDeleteJobBasicDBObject(clientJob); if (clientJob.isRecoverJobFromDB()) { if (!MongoDBUtil.INSTANCE.delete(condition, DBTableInfo.TBL_CLOVER_JOB)) return false; } } catch (Exception e) { logger.error("ModuleSchedulerClient-->>deleteLocalJob(" + clientJob.toString() + ") error", e); String execMethod = "ModuleSchedulerClient-->>deleteLocalJob(" + clientJob.toString() + ") error"; String execResult = "ModuleSchedulerClient-->>deleteLocalJob(" + clientJob.toString() + ") error," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } return true; } private boolean updateLocalJob(ClientJob clientJob) { try { return deleteLocalJob(clientJob) && addLocalJob(clientJob); } catch (Exception e) { logger.error("ModuleSchedulerClient-->>updateLocalJob(" + clientJob.toString() + ") error", e); String execMethod = "ModuleSchedulerClient-->>reloadJobFromDB(" + clientJob.toString() + ")"; String execResult = "ModuleSchedulerClient-->>reloadJobFromDB(" + clientJob.toString() + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } private boolean handlerRemoteJob(ClientJob clientJob) { try { ServerJob serverJob = ServerJobFactory.createControlJob(clientJob); DBObject retObj = MongoDBUtil.INSTANCE.findOneByCondition(BuildMongoDBData.getDBObjectFromClientJob(serverJob), DBTableInfo.TBL_CLOVER_JOB); if (null != retObj) return false; String[] fixedServerIps = clientJob.getFixedServerIps(); BasicDBObject serverInfo = null; Map retMap = null; if (fixedServerIps != null && fixedServerIps.length > 0) { retMap = ServerDict.self.hashServer4SByFixedServerIps(fixedServerIps); serverInfo = (BasicDBObject) retMap.get(CommonConstants.SERVER_JOB_INFO); } else { if (CommonConstants.SERVER_JOB_STRATEGY.equalsIgnoreCase(ClientJob.JobStrategy.HASH.name())) { retMap = ServerDict.self.hashServer4S(null); serverInfo = (BasicDBObject) retMap.get(CommonConstants.SERVER_JOB_INFO); } else if (CommonConstants.SERVER_JOB_STRATEGY.equalsIgnoreCase(ClientJob.JobStrategy.SYSTEM_CAPACITY.name())) { retMap = ServerDict.self.hashServer4SBySystemCapacity(); serverInfo = (BasicDBObject) retMap.get(CommonConstants.SERVER_JOB_INFO); } } if ((Boolean) retMap.get(CommonConstants.SUCCESS) && null != serverInfo) {//双重判断,保证获取的serverInfo是存在的 String ip = (String) serverInfo.get(CommonConstants.IP); int port = CommonConstants.NETTY_SERVER_PORT; /*发送zero mq消息队列方式 开始*/ // String addr = "tcp://" + ip + ":" + port; // ZeroMQEntity zeroMQEntity = new ZeroMQEntity(CommonConstants.MODULE_TYPE_SERVER,ip, Base64.encodeBase64String(ClassUtil.ObjectToBytes(serverJob))); //ZeroMQPush.INSTANCE.send(addr, JSON.toJSONString(zeroMQEntity)); //AsyncSendMsg.sendWithClientThreadPool(ip, port, JSON.toJSONString(zeroMQEntity)); /*发送zero mq消息队列方式 结束*/ new ObjectReqClient().connect(port,ip, new ZeroMQEntity(CommonConstants.MODULE_TYPE_SERVER, ip, Base64.encodeBase64String(ClassUtil.ObjectToBytes(serverJob)))); return true; } else { //报警通知 String errorCode = (String) retMap.get(CommonConstants.ERROR_CODE); String msg = null; if (CommonConstants.ERROR_CODE_101.equals(errorCode)) { msg = "ModuleSchedulerClient-->>handlerRemoteJob(" + clientJob.toString() + ") serverInfo null"; } else if (CommonConstants.ERROR_CODE_102.equals(errorCode)) { msg = "ModuleSchedulerClient-->>handlerRemoteJob(" + clientJob.toString() + ") the memRatio(" + retMap.get(CommonConstants.MEM_RATIO) + ") over max mem ratio "+ " or the cpuRatio("+retMap.get(CommonConstants.CPU_RATIO)+") over max cpu ratio("+CommonConstants.MAX_CPU_RATIO+") "; } else if (CommonConstants.ERROR_CODE_102.equals(errorCode)) { msg = "ModuleSchedulerClient-->>handlerRemoteJob(" + clientJob.toString() + ") errorCode is " + errorCode; } //记录数到MongoDB中,server重启后灾难恢复 BuildMongoDBData.saveTempJobData2DB(serverJob); //情况很严重 需要报警来解决问题 SendMailUtil.sendDefaultMail(msg, msg); logger.error(msg); return false; } } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); logger.error("ModuleSchedulerClient-->>handlerRemoteJob(" + clientJob.toString() + ")", e); String execMethod = "ModuleSchedulerClient-->>handlerRemoteJob(" + clientJob.toString() + ")"; String execResult = "ModuleSchedulerClient-->>handlerRemoteJob(" + clientJob.toString() + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } private boolean isContainLocalIp(String ips[]) { for (String ip : ips) if (ip.equals(IpUtil.getLocalIP())) return true; return false; } private boolean isContainFixedIp(String ip, String fixedIps[]) { for (String fixedIp : fixedIps) if (ip.equals(fixedIp)) return true; return false; } public List getDefaultJobs() { return defaultJobs; } public void setDefaultJobs(List defaultJobs) { this.defaultJobs = defaultJobs; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/module/ModuleSchedulerServer.java ================================================ package com.gome.clover.core.module; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.netty.server.ObjectRespServer; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.common.tools.PropertiesUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.common.zk.ZKManager; import com.gome.clover.core.job.ServerJob; import com.mongodb.BasicDBObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import static org.quartz.JobBuilder.*; import static org.quartz.TriggerBuilder.*; import static org.quartz.SimpleScheduleBuilder.*; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Module Scheduler Server * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ModuleSchedulerServer extends AbstractModuleScheduler { private static final Logger logger = LoggerFactory.getLogger(ModuleSchedulerServer.class); private volatile static ModuleSchedulerServer moduleSchedulerServer; private ModuleSchedulerServer() { } public static ModuleSchedulerServer getInstance() { synchronized (ModuleSchedulerClient.class) { if (null == moduleSchedulerServer) { moduleSchedulerServer = new ModuleSchedulerServer(); } } return moduleSchedulerServer; } public boolean handlerJob(ServerJob serverJob) { if (serverJob == null) return false; serverJob.setServerIp(IpUtil.getLocalIP()); logger.error("handlerJob >>> getExecuteType :::"+serverJob.getExecuteType()); switch (serverJob.getExecuteType()) { case ADD: return addJob(serverJob); case DELETE: return deleteJob(serverJob); case UPDATE: return updateJob(serverJob); default: return false; } } private boolean addJob(ServerJob serverJob) { logger.error("addJob -> MongoDBUtil: insertOrUpdate >>>"); try { if (!scheduler.add(serverJob)) return false; return MongoDBUtil.INSTANCE.insertOrUpdate(BuildMongoDBData.getInsertJobBasicDBObject(serverJob), DBTableInfo.TBL_CLOVER_JOB); } catch (Exception e) { logger.error("ModuleSchedulerServer-->>addJob(" + serverJob.toString() + ") error", e); String execMethod = "ModuleSchedulerServer-->>addJob(" + serverJob.toString() + ")"; String execResult = "ModuleSchedulerServer-->>addJob(" + serverJob.toString() + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject(serverJob.getJobDetail().getKey().toString(), execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } private boolean deleteJob(ServerJob serverJob) { logger.error("deleteJob -> MongoDBUtil: delete >>>"); try { if (!scheduler.delete(serverJob)) return false; MongoDBUtil.INSTANCE.delete(getDeleteRemoteJobBasicDBObject(serverJob), DBTableInfo.TBL_CLOVER_JOB); return true; } catch (Exception e) { logger.error("ModuleSchedulerServer-->>deleteJob(" + serverJob.toString() + ") error", e); String execMethod = "ModuleSchedulerServer-->>deleteJob(" + serverJob.toString() + ")"; String execResult = "ModuleSchedulerServer-->>deleteJob(" + serverJob.toString() + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject(serverJob.getJobDetail().getKey().toString(), execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } private BasicDBObject getDeleteRemoteJobBasicDBObject(ServerJob deleteJob) { BasicDBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_JOB_KEY, deleteJob.getJobDetail().getKey().toString()); condition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_REMOTE); return condition; } private boolean updateJob(ServerJob serverJob) { logger.error("updateJob -> MongoDBUtil: update >>>"); try { return deleteJob(serverJob) && addJob(serverJob); } catch (Exception e) { logger.error("ModuleSchedulerServer-->>updateJob(" + serverJob.toString() + ") error", e); String execMethod = "ModuleSchedulerServer-->>updateJob(" + serverJob.toString() + ")"; String execResult = "ModuleSchedulerServer-->>updateJob(" + serverJob.toString() + ") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject(serverJob.getJobDetail().getKey().toString(), execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } public boolean startup() { try { scheduler.start(); //start scheduler String serverIp = IpUtil.getLocalIP(); registerToZK(CommonConstants.MODULE_TYPE_SERVER,serverIp , null, CommonConstants.ZMQ_SERVER_PORT, CommonConstants.SYSTEM_ID_CLOVER); reloadJobFromDB(CommonConstants.MODULE_TYPE_SERVER,serverIp);//从DB中恢复已注册的REMOTE任务 //resetJobExecuteTime(null,serverIp); //AsyncStartZeroMQ.startup(CommonConstants.ZMQ_SERVER_PORT); //new ObjectRespServer().bind(CommonConstants.NETTY_SERVER_PORT); new ObjectRespServer().start(CommonConstants.NETTY_SERVER_PORT); //ServerHeartBeat.INSTNACE.startup(); return true; } catch (Exception e) { logger.error("ModuleSchedulerServer-->>start() error", e); return false; } } /** * 启动 Server端服务 * * @param isRegisterToZK 是否注册到ZK(默认开启) * @param isStartupMQ 是否启动MQ(默认开启) * @param isReloadJobFromDB 是否从DB中ReloadJob(默认开启) * @param systemId System ID(默认clover) * @return */ public boolean startup(boolean isRegisterToZK, boolean isStartupMQ,boolean isStartupNetty, boolean isReloadJobFromDB, String systemId) { try { scheduler.start(); //start scheduler String serverIp = IpUtil.getLocalIP(); if (isRegisterToZK) { registerToZK(CommonConstants.MODULE_TYPE_SERVER, serverIp, null, CommonConstants.ZMQ_SERVER_PORT, systemId); } if (isStartupNetty) { // new ObjectRespServer().bind(CommonConstants.NETTY_SERVER_PORT); new ObjectRespServer().start(CommonConstants.NETTY_SERVER_PORT); } if (isStartupMQ) { //AsyncStartZeroMQ.startup(CommonConstants.ZMQ_SERVER_PORT); } if (isReloadJobFromDB) { reloadJobFromDB(CommonConstants.MODULE_TYPE_SERVER, serverIp);//从DB中恢复已注册的REMOTE任务 } //ServerHeartBeat.INSTNACE.startup(); //resetJobExecuteTime(null,serverIp); return true; } catch (Exception e) { logger.error("ModuleSchedulerServer-->>start() error", e); return false; } } public boolean stop() { scheduler.stop(); try { ZKManager zkManager = new ZKManager(PropertiesUtil.loadProperties()); String serverPathStr = CommonConstants.ZK_ROOT_PATH + "/server"; List serverNodeList = zkManager.getZooKeeper().getChildren(serverPathStr,false); for (int i = 0; (serverNodeList != null) && (i < serverNodeList.size()); i++) { String id = serverNodeList.get(i); String c = zkManager.getData(serverPathStr + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) com.mongodb.util.JSON.parse(c); String ip = (String) record.get(CommonConstants.IP); if(!StringUtil.isEmpty(ip) && IpUtil.getLocalIP().equals(ip)){ zkManager.delete(serverPathStr + "/" + id); } } zkManager.close(); } catch (Exception e) { if(logger.isDebugEnabled())e.printStackTrace(); logger.error("ModuleSchedulerServer-->>stop() error ", e); } return true; } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/monitor/client/ClientHeartBeat.java ================================================ package com.gome.clover.core.monitor.client; import com.gome.clover.common.systeminfo.SystemInfoUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.common.zk.ZKUtil; import com.mongodb.BasicDBObject; import org.apache.curator.framework.CuratorFramework; import org.apache.zookeeper.CreateMode; import java.util.List; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Monitor Client Heart Beat * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum ClientHeartBeat { INSTNACE; private static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor; private static boolean isStop = false; private static CuratorFramework curatorFramework = ZKUtil.create(); public void startup() { if (null == scheduledThreadPoolExecutor) { scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); } scheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() { @Override public void run() { if (!isStop) { if (!curatorFramework.isStarted()) curatorFramework.start(); String clientPathStr = CommonConstants.ZK_ROOT_PATH + "/" + CommonConstants.MODULE_TYPE_CLIENT; List clientNodeList = ZKUtil.getChilds(curatorFramework, clientPathStr); if (null != clientNodeList && clientNodeList.size() > 0) { updateRecordList(curatorFramework, clientPathStr, clientNodeList); } } } }, CommonConstants.CLIENT_DIFFER_MILLI_SECONDS, CommonConstants.CLIENT_DIFFER_MILLI_SECONDS, TimeUnit.MILLISECONDS); } private void updateRecordList(CuratorFramework curatorFramework, String clientPathStr, List clientNodeList) { for (int i = 0; (clientNodeList != null) && (i < clientNodeList.size()); i++) { String id = (String) clientNodeList.get(i); String c = ZKUtil.getData(curatorFramework, clientPathStr + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) com.mongodb.util.JSON.parse(c); String ip = (String) record.get(CommonConstants.IP); if (!StringUtil.isEmpty(ip) && IpUtil.getLocalIP().equals(ip)) { record.put(CommonConstants.MEM_RATIO, SystemInfoUtil.getMemRatio()); record.put(CommonConstants.CPU_RATIO, SystemInfoUtil.getCpuRatio()); record.put(CommonConstants.TOTAL_THREAD, SystemInfoUtil.getTotalThread()); record.put(CommonConstants.TS, DateUtil.currentDateTime()); ZKUtil.setPath(curatorFramework, clientPathStr + "/" + id, record.toString(), CreateMode.EPHEMERAL); } } } public void stop() { isStop = true; curatorFramework.close(); scheduledThreadPoolExecutor.shutdown(); } public static void main(String args[]) { ClientHeartBeat.INSTNACE.startup(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/monitor/server/ServerHeartBeat.java ================================================ package com.gome.clover.core.monitor.server; import com.gome.clover.common.systeminfo.SystemInfoUtil; import com.gome.clover.common.tools.*; import com.gome.clover.common.zk.ZKManager; import com.mongodb.BasicDBObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc: Server Heart Beat * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum ServerHeartBeat { INSTNACE; private static final Logger logger = LoggerFactory.getLogger(ServerHeartBeat.class); private static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor; private static ZKManager zkManager = null; private static boolean isStop = false; static { try { zkManager = new ZKManager(PropertiesUtil.loadProperties()); } catch (Exception e) { e.printStackTrace(); logger.error("ServerHeartBeat-->> static method zkManager = new ZKManager(PropertiesUtil.loadProperties()) error "); } } public void startup(){ if(null==scheduledThreadPoolExecutor){ scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); } scheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() { @Override public void run() { if (!isStop) { try { String serverPathStr = CommonConstants.ZK_ROOT_PATH + "/" + CommonConstants.MODULE_TYPE_SERVER; List serverNodeList = zkManager.getZooKeeper().getChildren(serverPathStr, false); if (null != serverNodeList && serverNodeList.size() > 0) { updateRecordList(zkManager, serverPathStr, serverNodeList); } } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); System.err.println("ServerHeartBeat-->>run() error,"+e.getMessage()); logger.error("ServerHeartBeat-->>run() error", e); } } } }, CommonConstants.SERVER_DIFFER_MILLI_SECONDS, CommonConstants.SERVER_DIFFER_MILLI_SECONDS, TimeUnit.MILLISECONDS); } private void updateRecordList(ZKManager zkManager, String serverPathStr, List serverNodeList) throws Exception { for (int i = 0; (serverNodeList != null) && (i < serverNodeList.size()); i++) { String id = (String) serverNodeList.get(i); String c = zkManager.getData(serverPathStr + "/" + id); if (c == null) { continue; } BasicDBObject record = (BasicDBObject) com.mongodb.util.JSON.parse(c); String ip = (String) record.get(CommonConstants.IP); if(!StringUtil.isEmpty(ip) && IpUtil.getLocalIP().equals(ip)){ record.put(CommonConstants.MEM_RATIO, SystemInfoUtil.getMemRatio()); record.put(CommonConstants.CPU_RATIO, SystemInfoUtil.getCpuRatio()); record.put(CommonConstants.TOTAL_THREAD, SystemInfoUtil.getTotalThread()); record.put(CommonConstants.TS, DateUtil.currentDateTime()); zkManager.setData(serverPathStr + "/" + id,record.toString()); } } } public void stop() { isStop = true; assert null!=zkManager; try { zkManager.close(); } catch (InterruptedException e) { if (logger.isDebugEnabled()) e.printStackTrace(); System.err.println("ServerHeartBeat-->>stop() zkManager.close() error"+ e.getMessage()); logger.error("ServerHeartBeat-->>stop() zkManager.close() error",e); } scheduledThreadPoolExecutor.shutdown(); } public static void main(String args[]){ ServerHeartBeat.INSTNACE.startup(); try { TimeUnit.MINUTES.sleep(4L); } catch (InterruptedException e) { e.printStackTrace(); } ServerHeartBeat.INSTNACE.stop(); } } ================================================ FILE: clover/clover-core/src/main/java/com/gome/clover/core/scheduler/MyScheduler.java ================================================ package com.gome.clover.core.scheduler; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.MyJobListener; import org.quartz.JobKey; import org.quartz.Matcher; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.impl.StdSchedulerFactory; import org.quartz.impl.matchers.KeyMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.quartz.JobBuilder.*; import static org.quartz.TriggerBuilder.*; import static org.quartz.SimpleScheduleBuilder.*; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:重写 scheduler 实现类 * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum MyScheduler { INSTANCE; private Logger logger = LoggerFactory.getLogger(getClass()); private Scheduler scheduler; public boolean start() { try { scheduler = new StdSchedulerFactory().getScheduler(); if(!scheduler.isStarted()) scheduler.start(); return true; } catch (Exception e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("MyScheduler-->>start() error ", e); String execMethod = "MyScheduler-->>start()"; String execResult = "MyScheduler-->>start() error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } public boolean stop() { try { if(scheduler.isStarted()) scheduler.shutdown(true); return true; } catch (SchedulerException e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("MyScheduler-->>stop() error ", e); String execMethod = "MyScheduler-->>stop()"; String execResult = "MyScheduler-->>stop() error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } public boolean add(ClientJob job) { try{ if (isExists(job)){ if(logger.isDebugEnabled()) System.err.println(" MyScheduler-->>add("+job.toString()+") exists "); logger.error("MyScheduler-->>add("+job.toString()+") exists "); String execMethod = "MyScheduler-->>add("+job.toString()+")"; String execResult = "MyScheduler-->>add("+job.toString()+") exists " ; MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } scheduler.scheduleJob(job.getJobDetail(),job.getTrigger()); return true; }catch (Exception e){ if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("MyScheduler-->>addJob("+ job.toString()+") error ",e); String execMethod = "MyScheduler-->>addJob("+ job.toString()+") "; String execResult = "MyScheduler-->>addJob("+ job.toString()+") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } public boolean addJobListener(MyJobListener listener, ClientJob job) { Matcher matcher = KeyMatcher.keyEquals(job.getJobDetail().getKey()); try { scheduler.getListenerManager().addJobListener(listener, matcher); return true; } catch (SchedulerException e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("MyScheduler-->>addJobListener("+ JSON.toJSONString(listener)+","+job.toString()+") error ",e); String execMethod = "MyScheduler-->>addJobListener("+ JSON.toJSONString(listener)+","+job.toString()+") "; String execResult = "MyScheduler-->>addJobListener("+ JSON.toJSONString(listener)+","+job.toString()+") error," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } public boolean delete(ClientJob clientJob) { try { if(scheduler.checkExists(clientJob.getJobDetail().getKey())){ return scheduler.deleteJob(clientJob.getJobDetail().getKey()); }else { logger.error("MyScheduler-->>delete("+clientJob.toString()+") the clientJob not exist "); String execMethod = "MyScheduler-->>delete("+ clientJob.toString()+") "; String execResult = "MyScheduler-->>delete("+ clientJob.toString()+") the clientJob not exist " ; MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } catch (Exception e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("MyScheduler-->>delete("+clientJob.toString()+") error ",e); String execMethod = "MyScheduler-->>delete("+clientJob.toString()+")"; String execResult = "MyScheduler-->>delete("+clientJob.toString()+") error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } public boolean update(ClientJob job) { try{ return delete(job) && add(job); }catch (Exception e){ if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("MyScheduler-->>update("+ job.toString()+") error ",e); String execMethod = "MyScheduler-->>update("+ job.toString()+") "; String execResult = "MyScheduler-->>update("+ job.toString()+") error, " + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } public boolean isExists(ClientJob job) { try { return scheduler.checkExists(job.getJobDetail().getKey()); } catch (SchedulerException e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("MyScheduler-->>isExists("+job.toString()+") error ",e); String execMethod ="MyScheduler-->>isExists("+job.toString()+")"; String execResult = "MyScheduler-->>isExists("+job.toString()+") error,"+ e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } public boolean isExists(JobKey jobKey) { try { return scheduler.checkExists(jobKey); } catch (SchedulerException e) { if(logger.isDebugEnabled()) e.printStackTrace(); logger.error("MyScheduler-->>isExists("+ jobKey.toString() +") error ",e); String execMethod = "MyScheduler-->>isExists("+ jobKey.toString() +") "; String execResult = "MyScheduler-->>isExists("+ jobKey.toString() +") error,"+ e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); return false; } } } ================================================ FILE: clover/clover-core/src/main/resources/META-INF/cloverjob-1.0.0.xsd ================================================ ================================================ FILE: clover/clover-core/src/main/resources/META-INF/spring.handlers ================================================ http\://www.gome.com.cn/schema/cloverjob=com.gome.clover.common.annotation.CloverJobNamespaceHandler ================================================ FILE: clover/clover-core/src/main/resources/META-INF/spring.schemas ================================================ http\://www.gome.com.cn/schema/cloverjob/cloverjob-1.0.0.xsd=META-INF/cloverjob-1.0.0.xsd http\:/www.gome.com.cn/schema/cloverjob/cloverjob.xsd=META-INF/cloverjob-1.0.0.xsd ================================================ FILE: clover/clover-core/src/main/resources/commonConfig.properties ================================================ zmqServerPort=1688 serverDifferMilliSeconds=120000 clientDifferMilliSeconds=120000 monitorDifferMilliSeconds=120000 defaultCompanyEmail=${clover.common.defaultCompanyEmail} defaultPrivateEmail=${clover.common.defaultPrivateEmail} zmqSleepClientMillis=1000 zmqSleepServerMillis=1000 token=${clover.common.token} disabledDB=disabledDB poolSize=100 maxFailTimes=5 maxMemRatio=0.95 maxCpuRatio=0.95 serverJobStrategy=HASH ================================================ FILE: clover/clover-core/src/main/resources/dev/commonConfig.properties ================================================ zmqServerPort=1688 serverDifferMilliSeconds=120000 clientDifferMilliSeconds=120000 monitorDifferMilliSeconds=120000 defaultCompanyEmail=xiaoxiangxu@yolo24.com defaultPrivateEmail=zhutouzan@163.com zmqSleepClientMillis=1000 zmqSleepServerMillis=1000 token=6fb8535d703f2492704aefc212b7cd41 disabledDB=disabledDB poolSize=10 maxFailTimes=5 maxMemRatio=0.95 maxCpuRatio=0.95 serverJobStrategy=HASH ================================================ FILE: clover/clover-core/src/main/resources/dev/mongoDBConfig.properties ================================================ #dev|sit start #mongoAddress=10.126.53.42:27067 #dbName=spec_pub #userName=user_spec_pub #password=user_spec_pub_pass #dev|sit end #uat start #mongoAddress=10.126.53.38:27067 #dbName=spec_pub #userName=user_spec_pub #password=user_spec_pub_pass #uat end #pre start #mongoAddress=10.126.45.45:27067 #dbName=spec_pub #userName=user_spec_pub #password=user_spec_pub_pass #pre end #prd start mongoAddress=10.58.50.134:27077,10.58.50.133:27077 dbName=spec_pub userName=user_spec_pub password=SrVlPrIGgu7ZM2Ox #prd end connectionsPerHost=100 threadsAllowedToBlockForConnectionMultiplier=10 connectTimeout=180000 maxWaitTime=30000 autoConnectRetry=true socketKeepAlive=false socketTimeout=180000 ================================================ FILE: clover/clover-core/src/main/resources/dev/redisConfig.properties ================================================ redis.server = 10.58.50.208 redis.port = 6379 redis.pool.maxActive = 500 redis.pool.maxIdle = 20 redis.pool.maxWait = 1000 ================================================ FILE: clover/clover-core/src/main/resources/dev/zkConfig.properties ================================================ zkConnectString=10.58.50.206:2181,10.58.50.207:2181,10.58.50.208:2181 rootPath=/clover zkSessionTimeout=3000 userName=${clover.zk.userName} password=${clover.zk.password} ================================================ FILE: clover/clover-core/src/main/resources/mongoDBConfig.properties ================================================ mongoAddress=${clover.mongoDB.mongoAddress} dbName=${clover.mongoDB.dbName} userName=${clover.mongoDB.userName} password=${clover.mongoDB.password} connectionsPerHost=${clover.mongoDB.connectionsPerHost} threadsAllowedToBlockForConnectionMultiplier=${clover.mongoDB.threadsAllowedToBlockForConnectionMultiplier} connectTimeout=${clover.mongoDB.connectTimeout} maxWaitTime=${clover.mongoDB.maxWaitTime} autoConnectRetry=${clover.mongoDB.autoConnectRetry} socketKeepAlive=${clover.mongoDB.socketKeepAlive} socketTimeout=${clover.mongoDB.socketTimeout} ================================================ FILE: clover/clover-core/src/main/resources/redisConfig.properties ================================================ redis.server=${clover.redis.server} redis.port=${clover.redis.port} redis.pool.maxActive=${clover.redis.pool.maxActive} redis.pool.maxIdle=${clover.redis.pool.maxIdle} redis.pool.maxWait=${clover.redis.pool.maxWait} ================================================ FILE: clover/clover-core/src/main/resources/uat/commonConfig.properties ================================================ zmqServerPort=1688 serverDifferMilliSeconds=120000 clientDifferMilliSeconds=120000 monitorDifferMilliSeconds=120000 defaultCompanyEmail=xiaoxiangxu@yolo24.com defaultPrivateEmail=zhutouzan@163.com zmqSleepClientMillis=1000 zmqSleepServerMillis=1000 token=6fb8535d703f2492704aefc212b7cd41 disabledDB=disabledDB poolSize=10 maxFailTimes=5 maxMemRatio=0.95 maxCpuRatio=0.95 serverJobStrategy=HASH ================================================ FILE: clover/clover-core/src/main/resources/uat/mongoDBConfig.properties ================================================ #dev|sit start #mongoAddress=10.126.53.42:27067 #dbName=spec_pub #userName=user_spec_pub #password=user_spec_pub_pass #dev|sit end #uat start #mongoAddress=10.126.53.38:27067 #dbName=spec_pub #userName=user_spec_pub #password=user_spec_pub_pass #uat end #pre start #mongoAddress=10.126.45.45:27067 #dbName=spec_pub #userName=user_spec_pub #password=user_spec_pub_pass #pre end #prd start mongoAddress=10.58.50.134:27077,10.58.50.133:27077 dbName=spec_pub userName=user_spec_pub password=SrVlPrIGgu7ZM2Ox #prd end connectionsPerHost=100 threadsAllowedToBlockForConnectionMultiplier=10 connectTimeout=180000 maxWaitTime=30000 autoConnectRetry=true socketKeepAlive=false socketTimeout=180000 ================================================ FILE: clover/clover-core/src/main/resources/uat/redisConfig.properties ================================================ redis.server = 10.58.50.208 redis.port = 6379 redis.pool.maxActive = 500 redis.pool.maxIdle = 20 redis.pool.maxWait = 1000 ================================================ FILE: clover/clover-core/src/main/resources/uat/zkConfig.properties ================================================ #zkConnectString=localhost:2181 #zkConnectString=10.126.53.170:2181,10.126.53.168:2181,10.126.53.169:2181 #zkConnectString=10.58.22.191:2181,10.58.22.192:2181,10.58.22.193:2181,10.58.50.149:2181,10.58.50.150:2181 zkConnectString=${clover.zk.address} rootPath=${clover.zk.rootPath} zkSessionTimeout=${clover.zk.zkSessionTimeout} userName=${clover.zk.userName} password=${clover.zk.password} ================================================ FILE: clover/clover-core/src/main/resources/zkConfig.properties ================================================ zkConnectString=${clover.zk.address} rootPath=${clover.zk.rootPath} zkSessionTimeout=${clover.zk.zkSessionTimeout} userName=${clover.zk.userName} password=${clover.zk.password} ================================================ FILE: clover/clover-examples/pom.xml ================================================ 4.0.0 com.gome clover 1.0 com.gome clover-examples ${clover.version} jar clover-examples-${clover.version} src/main/resources true com.gome clover-client ${clover.version} junit junit 4.11 compile com.typesafe.akka akka-zeromq_2.10 2.1.0 com.typesafe.akka akka-zeromq_2.11 2.3.7 com.typesafe.akka akka-actor_2.11 com.typesafe.akka akka-actor 2.0.2 ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/DeleteGomeVipAdPlanJob.java ================================================ package com.gome.clover; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/5 * Time: 5:06 */ public class DeleteGomeVipAdPlanJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/ObjectToByte.java ================================================ package com.gome.clover; import com.gome.clover.common.compress.CompressUtil; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.job.ServerJob; import com.gome.clover.job.MyJob; import org.apache.commons.codec.binary.Base64; import org.junit.Test; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/30 * Time: 10:48 */ public class ObjectToByte { @Test public void toObj(){ String msg="rO0ABXNyACJjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuU2VydmVySm9its+L9tdn6kgCAAB4cgAi\n" + "Y29tLmdvbWUuY2xvdmVyLmNvcmUuam9iLkNsaWVudEpvYg0GalC4zmMwAgAJTAALZXhlY3V0ZVR5\n" + "cGV0ADBMY29tL2dvbWUvY2xvdmVyL2NvcmUvam9iL0NsaWVudEpvYiRFeGVjdXRlVHlwZTtbAA5m\n" + "aXhlZENsaWVudElwc3QAE1tMamF2YS9sYW5nL1N0cmluZztbAA5maXhlZFNlcnZlcklwc3EAfgAD\n" + "TAACaXB0ABJMamF2YS9sYW5nL1N0cmluZztMAAhqb2JDbGFzc3QAEUxqYXZhL2xhbmcvQ2xhc3M7\n" + "TAAMam9iQ2xhc3NOYW1lcQB+AARMAAlqb2JEZXRhaWx0ABZMb3JnL3F1YXJ0ei9Kb2JEZXRhaWw7\n" + "TAAHam9iVHlwZXQALExjb20vZ29tZS9jbG92ZXIvY29yZS9qb2IvQ2xpZW50Sm9iJEpvYlR5cGU7\n" + "TAAHdHJpZ2dlcnQAFExvcmcvcXVhcnR6L1RyaWdnZXI7eHB+cgAuY29tLmdvbWUuY2xvdmVyLmNv\n" + "cmUuam9iLkNsaWVudEpvYiRFeGVjdXRlVHlwZQAAAAAAAAAAEgAAeHIADmphdmEubGFuZy5FbnVt\n" + "AAAAAAAAAAASAAB4cHQAA0FERHBwdAANMTAuMTQ0LjMzLjIxMnB0ACZjb20uZ29tZS5jbG92ZXIu\n" + "Y29yZS5qb2IuY2xpZW50Lk15Sm9iMXNyAB1vcmcucXVhcnR6LmltcGwuSm9iRGV0YWlsSW1wbKvD\n" + "yuwBWlSvAgAHWgAKZHVyYWJpbGl0eVoADXNob3VsZFJlY292ZXJMAAtkZXNjcmlwdGlvbnEAfgAE\n" + "TAAFZ3JvdXBxAH4ABEwACGpvYkNsYXNzcQB+AAVMAApqb2JEYXRhTWFwdAAXTG9yZy9xdWFydHov\n" + "Sm9iRGF0YU1hcDtMAARuYW1lcQB+AAR4cAAAcHQAC3JlbW90ZS1qb2JzdnEAfgAAc3IAFW9yZy5x\n" + "dWFydHouSm9iRGF0YU1hcJ+wg+i/qbDLAgAAeHIAJm9yZy5xdWFydHoudXRpbHMuU3RyaW5nS2V5\n" + "RGlydHlGbGFnTWFwggjow/vFXSgCAAFaABNhbGxvd3NUcmFuc2llbnREYXRheHIAHW9yZy5xdWFy\n" + "dHoudXRpbHMuRGlydHlGbGFnTWFwE+YurSh2Cs4CAAJaAAVkaXJ0eUwAA21hcHQAD0xqYXZhL3V0\n" + "aWwvTWFwO3hwAXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkA\n" + "CXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAHam9iSW5mb3NxAH4AAXEAfgAMcHBxAH4A\n" + "DnZyACZjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuY2xpZW50Lk15Sm9iMShpJZ9gwd+ZAgAAeHBx\n" + "AH4AD3NxAH4AEAAAcHQAB0RFRkFVTFRxAH4AH3B0AAVNeUpvYn5yACpjb20uZ29tZS5jbG92ZXIu\n" + "Y29yZS5qb2IuQ2xpZW50Sm9iJEpvYlR5cGUAAAAAAAAAABIAAHhxAH4AC3QABlJFTU9URXNyAChv\n" + "cmcucXVhcnR6LmltcGwudHJpZ2dlcnMuQ3JvblRyaWdnZXJJbXBsiAb06o3becICAAVMAAZjcm9u\n" + "RXh0ABtMb3JnL3F1YXJ0ei9Dcm9uRXhwcmVzc2lvbjtMAAdlbmRUaW1ldAAQTGphdmEvdXRpbC9E\n" + "YXRlO0wADG5leHRGaXJlVGltZXEAfgAoTAAQcHJldmlvdXNGaXJlVGltZXEAfgAoTAAJc3RhcnRU\n" + "aW1lcQB+ACh4cgAob3JnLnF1YXJ0ei5pbXBsLnRyaWdnZXJzLkFic3RyYWN0VHJpZ2dlcsnRVzsN\n" + "4PXuAgALSQASbWlzZmlyZUluc3RydWN0aW9uSQAIcHJpb3JpdHlaAAp2b2xhdGlsaXR5TAAMY2Fs\n" + "ZW5kYXJOYW1lcQB+AARMAAtkZXNjcmlwdGlvbnEAfgAETAAOZmlyZUluc3RhbmNlSWRxAH4ABEwA\n" + "BWdyb3VwcQB+AARMAApqb2JEYXRhTWFwcQB+ABFMAAhqb2JHcm91cHEAfgAETAAHam9iTmFtZXEA\n" + "fgAETAAEbmFtZXEAfgAEeHAAAAAAAAAABQBwcHBxAH4AIXBxAH4AIXB0AAd0cmlnZ2Vyc3IAGW9y\n" + "Zy5xdWFydHouQ3JvbkV4cHJlc3Npb24AAAAC5H4vDwIAAkwADmNyb25FeHByZXNzaW9ucQB+AARM\n" + "AAh0aW1lWm9uZXQAFExqYXZhL3V0aWwvVGltZVpvbmU7eHB0AA4wLzEwICogKiAqICogP3NyABpz\n" + "dW4udXRpbC5jYWxlbmRhci5ab25lSW5mbyTR084AHXGbAgAISQAIY2hlY2tzdW1JAApkc3RTYXZp\n" + "bmdzSQAJcmF3T2Zmc2V0SQANcmF3T2Zmc2V0RGlmZloAE3dpbGxHTVRPZmZzZXRDaGFuZ2VbAAdv\n" + "ZmZzZXRzdAACW0lbABRzaW1wbGVUaW1lWm9uZVBhcmFtc3EAfgAxWwALdHJhbnNpdGlvbnN0AAJb\n" + "SnhyABJqYXZhLnV0aWwuVGltZVpvbmUxs+n1d0SsoQIAAUwAAklEcQB+AAR4cHQADUFzaWEvU2hh\n" + "bmdoYWkEKEHsAAAAAAG3dAAAAAAAAHVyAAJbSU26YCZ26rKlAgAAeHAAAAAEAbd0AAG80wAB7mKA\n" + "ADbugHB1cgACW0p4IAS1ErF1kwIAAHhwAAAAE//f2uAdwAAB/+y2KMAQAAD/8mp2XcAAMv/ykRKg\n" + "2AAA//LGhApAADL/8waNs5gAAAAHgHYvAAAyAAerQZzYAAAAB+7cg0AAMgAIIGpJ2AAAAAhkBTBA\n" + "ADIACJWS9tgAAAAI226lgAAyAAkM/GwYAAAACVCXUoAAMgAJgiUZGAAAAAnFv/+AADIACfdNxhgA\n" + "AAAexJMywAAAcHBwc3IADmphdmEudXRpbC5EYXRlaGqBAUtZdBkDAAB4cHcIAAABSf6cuCB4eAB0\n" + "AA1ERUZBVUxULk15Sm9icQB+ACRzcQB+ACYAAAAAAAAABQBwcHBxAH4AE3BxAH4AE3QADURFRkFV\n" + "TFQuTXlKb2J0AA1ERUZBVUxULk15Sm9ic3EAfgAsdAAOMC8xMCAqICogKiAqID9zcQB+ADB0AA1B\n" + "c2lhL1NoYW5naGFpBChB7AAAAAABt3QAAAAAAAB1cQB+ADYAAAAEAbd0AAG80wAB7mKAADbugHB1\n" + "cQB+ADgAAAAT/9/a4B3AAAH/7LYowBAAAP/yanZdwAAy//KREqDYAAD/8saECkAAMv/zBo2zmAAA\n" + "AAeAdi8AADIAB6tBnNgAAAAH7tyDQAAyAAggaknYAAAACGQFMEAAMgAIlZL22AAAAAjbbqWAADIA\n" + "CQz8bBgAAAAJUJdSgAAyAAmCJRkYAAAACcW//4AAMgAJ903GGAAAAB7EkzLAAABwcHBzcQB+ADp3\n" + "CAAAAUn+nLggeA=="; ServerJob serverJob = (ServerJob) ClassUtil.BytesToObject(Base64.decodeBase64(msg)); System.err.println("server:"+serverJob); ClientJob clientJob = (ClientJob) serverJob.getJobDetail().getJobDataMap().get(CommonConstants.CLIENT_JOB_INFO); serverJob.getJobDetail().getJobDataMap().put(CommonConstants.CLIENT_JOB_INFO,Base64.encodeBase64String(ClassUtil.ObjectToBytes(clientJob))) ; String newMsg= Base64.encodeBase64String(ClassUtil.ObjectToBytes(serverJob)); System.err.println("newMsg:"+newMsg); } @Test public void toObj1(){ String msg="rO0ABXNyACJjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuQ2xpZW50Sm9iDQZqULjOYzACAApaABJp\n" + "c1JlY292ZXJKb2JGcm9tREJMAAtleGVjdXRlVHlwZXQAMExjb20vZ29tZS9jbG92ZXIvY29yZS9q\n" + "b2IvQ2xpZW50Sm9iJEV4ZWN1dGVUeXBlO1sADmZpeGVkQ2xpZW50SXBzdAATW0xqYXZhL2xhbmcv\n" + "U3RyaW5nO1sADmZpeGVkU2VydmVySXBzcQB+AAJMAAJpcHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wA\n" + "CGpvYkNsYXNzdAARTGphdmEvbGFuZy9DbGFzcztMAAxqb2JDbGFzc05hbWVxAH4AA0wACWpvYkRl\n" + "dGFpbHQAFkxvcmcvcXVhcnR6L0pvYkRldGFpbDtMAAdqb2JUeXBldAAsTGNvbS9nb21lL2Nsb3Zl\n" + "ci9jb3JlL2pvYi9DbGllbnRKb2IkSm9iVHlwZTtMAAd0cmlnZ2VydAAUTG9yZy9xdWFydHovVHJp\n" + "Z2dlcjt4cAF+cgAuY29tLmdvbWUuY2xvdmVyLmNvcmUuam9iLkNsaWVudEpvYiRFeGVjdXRlVHlw\n" + "ZQAAAAAAAAAAEgAAeHIADmphdmEubGFuZy5FbnVtAAAAAAAAAAASAAB4cHQABlVQREFURXBwdAAK\n" + "MTAuNTguMTEuMXZyADZjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuY2xpZW50LkRlbGV0ZUdvbWVW\n" + "aXBBZFBsYW5Kb2IAAAAAAAAAAAAAAHhwdAA2Y29tLmdvbWUuY2xvdmVyLmNvcmUuam9iLmNsaWVu\n" + "dC5EZWxldGVHb21lVmlwQWRQbGFuSm9ic3IAHW9yZy5xdWFydHouaW1wbC5Kb2JEZXRhaWxJbXBs\n" + "q8PK7AFaVK8CAAdaAApkdXJhYmlsaXR5WgANc2hvdWxkUmVjb3ZlckwAC2Rlc2NyaXB0aW9ucQB+\n" + "AANMAAVncm91cHEAfgADTAAIam9iQ2xhc3NxAH4ABEwACmpvYkRhdGFNYXB0ABdMb3JnL3F1YXJ0\n" + "ei9Kb2JEYXRhTWFwO0wABG5hbWVxAH4AA3hwAABwdAADZ2NjcQB+AA9zcgAVb3JnLnF1YXJ0ei5K\n" + "b2JEYXRhTWFwn7CD6L+psMsCAAB4cgAmb3JnLnF1YXJ0ei51dGlscy5TdHJpbmdLZXlEaXJ0eUZs\n" + "YWdNYXCCCOjD+8VdKAIAAVoAE2FsbG93c1RyYW5zaWVudERhdGF4cgAdb3JnLnF1YXJ0ei51dGls\n" + "cy5EaXJ0eUZsYWdNYXAT5i6tKHYKzgIAAloABWRpcnR5TAADbWFwdAAPTGphdmEvdXRpbC9NYXA7\n" + "eHABc3IAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNo\n" + "b2xkeHA/QAAAAAAADHcIAAAAEAAAAAJ0AARhZElkdAAVdGJsXzE0MTc2NjA4MzQxMjgxNTI3dAAG\n" + "YWRDb2RldAALc2lkZUZvY3VzQWR4AHQALERlbGV0ZUdvbWVWaXBBZFBsYW5Kb2JAdGJsXzE0MTc2\n" + "NjA4MzQxMjgxNTI3fnIAKmNvbS5nb21lLmNsb3Zlci5jb3JlLmpvYi5DbGllbnRKb2IkSm9iVHlw\n" + "ZQAAAAAAAAAAEgAAeHEAfgAKdAAFTE9DQUxzcgAqb3JnLnF1YXJ0ei5pbXBsLnRyaWdnZXJzLlNp\n" + "bXBsZVRyaWdnZXJJbXBszCch6qQCbqMCAAhaAAhjb21wbGV0ZUkAC3JlcGVhdENvdW50SgAOcmVw\n" + "ZWF0SW50ZXJ2YWxJAA50aW1lc1RyaWdnZXJlZEwAB2VuZFRpbWV0ABBMamF2YS91dGlsL0RhdGU7\n" + "TAAMbmV4dEZpcmVUaW1lcQB+ACVMABBwcmV2aW91c0ZpcmVUaW1lcQB+ACVMAAlzdGFydFRpbWVx\n" + "AH4AJXhyAChvcmcucXVhcnR6LmltcGwudHJpZ2dlcnMuQWJzdHJhY3RUcmlnZ2VyydFXOw3g9e4C\n" + "AAtJABJtaXNmaXJlSW5zdHJ1Y3Rpb25JAAhwcmlvcml0eVoACnZvbGF0aWxpdHlMAAxjYWxlbmRh\n" + "ck5hbWVxAH4AA0wAC2Rlc2NyaXB0aW9ucQB+AANMAA5maXJlSW5zdGFuY2VJZHEAfgADTAAFZ3Jv\n" + "dXBxAH4AA0wACmpvYkRhdGFNYXBxAH4AEkwACGpvYkdyb3VwcQB+AANMAAdqb2JOYW1lcQB+AANM\n" + "AARuYW1lcQB+AAN4cAAAAAAAAAAFAHBwcHEAfgAUcHEAfgAUcQB+ACBxAH4AIAAAAAAAAAAAAAAA\n" + "AAAAAAAAcHNyABJqYXZhLnNxbC5UaW1lc3RhbXAmGNXIAVO/ZQIAAUkABW5hbm9zeHIADmphdmEu\n" + "dXRpbC5EYXRlaGqBAUtZdBkDAAB4cHcIAAABSi0lgAB4AAAAAHBxAH4AKg==\n"; ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64(msg)); System.err.println("server:"+clientJob); } @Test public void testNewMsg(){ String newMsg="rO0ABXNyACJjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuU2VydmVySm9its+L9tdn6kgCAAB4cgAiY29tLmdvbWUuY2xvdmVyLmNvcmUuam9iLkNsaWVudEpvYg0GalC4zmMwAgAJTAALZXhlY3V0ZVR5cGV0ADBMY29tL2dvbWUvY2xvdmVyL2NvcmUvam9iL0NsaWVudEpvYiRFeGVjdXRlVHlwZTtbAA5maXhlZENsaWVudElwc3QAE1tMamF2YS9sYW5nL1N0cmluZztbAA5maXhlZFNlcnZlcklwc3EAfgADTAACaXB0ABJMamF2YS9sYW5nL1N0cmluZztMAAhqb2JDbGFzc3QAEUxqYXZhL2xhbmcvQ2xhc3M7TAAMam9iQ2xhc3NOYW1lcQB+AARMAAlqb2JEZXRhaWx0ABZMb3JnL3F1YXJ0ei9Kb2JEZXRhaWw7TAAHam9iVHlwZXQALExjb20vZ29tZS9jbG92ZXIvY29yZS9qb2IvQ2xpZW50Sm9iJEpvYlR5cGU7TAAHdHJpZ2dlcnQAFExvcmcvcXVhcnR6L1RyaWdnZXI7eHB+cgAuY29tLmdvbWUuY2xvdmVyLmNvcmUuam9iLkNsaWVudEpvYiRFeGVjdXRlVHlwZQAAAAAAAAAAEgAAeHIADmphdmEubGFuZy5FbnVtAAAAAAAAAAASAAB4cHQAA0FERHBwdAANMTAuMTQ0LjMzLjIxMnB0ACZjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuY2xpZW50Lk15Sm9iMXNyAB1vcmcucXVhcnR6LmltcGwuSm9iRGV0YWlsSW1wbKvDyuwBWlSvAgAHWgAKZHVyYWJpbGl0eVoADXNob3VsZFJlY292ZXJMAAtkZXNjcmlwdGlvbnEAfgAETAAFZ3JvdXBxAH4ABEwACGpvYkNsYXNzcQB+AAVMAApqb2JEYXRhTWFwdAAXTG9yZy9xdWFydHovSm9iRGF0YU1hcDtMAARuYW1lcQB+AAR4cAAAcHQAC3JlbW90ZS1qb2JzdnEAfgAAc3IAFW9yZy5xdWFydHouSm9iRGF0YU1hcJ+wg+i/qbDLAgAAeHIAJm9yZy5xdWFydHoudXRpbHMuU3RyaW5nS2V5RGlydHlGbGFnTWFwggjow/vFXSgCAAFaABNhbGxvd3NUcmFuc2llbnREYXRheHIAHW9yZy5xdWFydHoudXRpbHMuRGlydHlGbGFnTWFwE+YurSh2Cs4CAAJaAAVkaXJ0eUwAA21hcHQAD0xqYXZhL3V0aWwvTWFwO3hwAXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAHam9iSW5mb3QKMHJPMEFCWE55QUNKamIyMHVaMjl0WlM1amJHOTJaWEl1WTI5eVpTNXFiMkl1UTJ4cFpXNTBTbTlpRFFacVVMak9ZekFDQUFsTUFBdGxlR1ZqZFhSbFZIbHdaWFFBTUV4amIyMHZaMjl0WlM5amJHOTJaWEl2WTI5eVpTOXFiMkl2UTJ4cFpXNTBTbTlpSkVWNFpXTjFkR1ZVZVhCbE8xc0FEbVpwZUdWa1EyeHBaVzUwU1hCemRBQVRXMHhxWVhaaEwyeGhibWN2VTNSeWFXNW5PMXNBRG1acGVHVmtVMlZ5ZG1WeVNYQnpjUUIrQUFKTUFBSnBjSFFBRWt4cVlYWmhMMnhoYm1jdlUzUnlhVzVuTzB3QUNHcHZZa05zWVhOemRBQVJUR3BoZG1FdmJHRnVaeTlEYkdGemN6dE1BQXhxYjJKRGJHRnpjMDVoYldWeEFINEFBMHdBQ1dwdllrUmxkR0ZwYkhRQUZreHZjbWN2Y1hWaGNuUjZMMHB2WWtSbGRHRnBiRHRNQUFkcWIySlVlWEJsZEFBc1RHTnZiUzluYjIxbEwyTnNiM1psY2k5amIzSmxMMnB2WWk5RGJHbGxiblJLYjJJa1NtOWlWSGx3WlR0TUFBZDBjbWxuWjJWeWRBQVVURzl5Wnk5eGRXRnlkSG92VkhKcFoyZGxjanQ0Y0g1eUFDNWpiMjB1WjI5dFpTNWpiRzkyWlhJdVkyOXlaUzVxYjJJdVEyeHBaVzUwU205aUpFVjRaV04xZEdWVWVYQmxBQUFBQUFBQUFBQVNBQUI0Y2dBT2FtRjJZUzVzWVc1bkxrVnVkVzBBQUFBQUFBQUFBQklBQUhod2RBQURRVVJFY0hCMEFBMHhNQzR4TkRRdU16TXVNakV5ZG5JQUptTnZiUzVuYjIxbExtTnNiM1psY2k1amIzSmxMbXB2WWk1amJHbGxiblF1VFhsS2IySXhLR2tsbjJEQjM1a0NBQUI0Y0hRQUptTnZiUzVuYjIxbExtTnNiM1psY2k1amIzSmxMbXB2WWk1amJHbGxiblF1VFhsS2IySXhjM0lBSFc5eVp5NXhkV0Z5ZEhvdWFXMXdiQzVLYjJKRVpYUmhhV3hKYlhCc3E4UEs3QUZhVks4Q0FBZGFBQXBrZFhKaFltbHNhWFI1V2dBTmMyaHZkV3hrVW1WamIzWmxja3dBQzJSbGMyTnlhWEIwYVc5dWNRQitBQU5NQUFWbmNtOTFjSEVBZmdBRFRBQUlhbTlpUTJ4aGMzTnhBSDRBQkV3QUNtcHZZa1JoZEdGTllYQjBBQmRNYjNKbkwzRjFZWEowZWk5S2IySkVZWFJoVFdGd08wd0FCRzVoYldWeEFINEFBM2h3QUFCd2RBQUhSRVZHUVZWTVZIRUFmZ0FQY0hRQUJVMTVTbTlpZm5JQUttTnZiUzVuYjIxbExtTnNiM1psY2k1amIzSmxMbXB2WWk1RGJHbGxiblJLYjJJa1NtOWlWSGx3WlFBQUFBQUFBQUFBRWdBQWVIRUFmZ0FLZEFBR1VrVk5UMVJGYzNJQUtHOXlaeTV4ZFdGeWRIb3VhVzF3YkM1MGNtbG5aMlZ5Y3k1RGNtOXVWSEpwWjJkbGNrbHRjR3lJQnZUcWpkdDV3Z0lBQlV3QUJtTnliMjVGZUhRQUcweHZjbWN2Y1hWaGNuUjZMME55YjI1RmVIQnlaWE56YVc5dU8wd0FCMlZ1WkZScGJXVjBBQkJNYW1GMllTOTFkR2xzTDBSaGRHVTdUQUFNYm1WNGRFWnBjbVZVYVcxbGNRQitBQnRNQUJCd2NtVjJhVzkxYzBacGNtVlVhVzFsY1FCK0FCdE1BQWx6ZEdGeWRGUnBiV1Z4QUg0QUczaHlBQ2h2Y21jdWNYVmhjblI2TG1sdGNHd3VkSEpwWjJkbGNuTXVRV0p6ZEhKaFkzUlVjbWxuWjJWeXlkRlhPdzNnOWU0Q0FBdEpBQkp0YVhObWFYSmxTVzV6ZEhKMVkzUnBiMjVKQUFod2NtbHZjbWwwZVZvQUNuWnZiR0YwYVd4cGRIbE1BQXhqWVd4bGJtUmhjazVoYldWeEFINEFBMHdBQzJSbGMyTnlhWEIwYVc5dWNRQitBQU5NQUE1bWFYSmxTVzV6ZEdGdVkyVkpaSEVBZmdBRFRBQUZaM0p2ZFhCeEFINEFBMHdBQ21wdllrUmhkR0ZOWVhCeEFINEFFa3dBQ0dwdllrZHliM1Z3Y1FCK0FBTk1BQWRxYjJKT1lXMWxjUUIrQUFOTUFBUnVZVzFsY1FCK0FBTjRjQUFBQUFBQUFBQUZBSEJ3Y0hFQWZnQVVjSEVBZmdBVWNIUUFCM1J5YVdkblpYSnpjZ0FaYjNKbkxuRjFZWEowZWk1RGNtOXVSWGh3Y21WemMybHZiZ0FBQUFMa2ZpOFBBZ0FDVEFBT1kzSnZia1Y0Y0hKbGMzTnBiMjV4QUg0QUEwd0FDSFJwYldWYWIyNWxkQUFVVEdwaGRtRXZkWFJwYkM5VWFXMWxXbTl1WlR0NGNIUUFEakF2TVRBZ0tpQXFJQ29nS2lBL2MzSUFHbk4xYmk1MWRHbHNMbU5oYkdWdVpHRnlMbHB2Ym1WSmJtWnZKTkhUemdBZGNac0NBQWhKQUFoamFHVmphM04xYlVrQUNtUnpkRk5oZG1sdVozTkpBQWx5WVhkUFptWnpaWFJKQUExeVlYZFBabVp6WlhSRWFXWm1XZ0FUZDJsc2JFZE5WRTltWm5ObGRFTm9ZVzVuWlZzQUIyOW1abk5sZEhOMEFBSmJTVnNBRkhOcGJYQnNaVlJwYldWYWIyNWxVR0Z5WVcxemNRQitBQ1JiQUF0MGNtRnVjMmwwYVc5dWMzUUFBbHRLZUhJQUVtcGhkbUV1ZFhScGJDNVVhVzFsV205dVpUR3o2ZlYzUkt5aEFnQUJUQUFDU1VSeEFINEFBM2h3ZEFBTlFYTnBZUzlUYUdGdVoyaGhhUVFvUWV3QUFBQUFBYmQwQUFBQUFBQUFkWElBQWx0SlRicGdKbmJxc3FVQ0FBQjRjQUFBQUFRQnQzUUFBYnpUQUFIdVlvQUFOdTZBY0hWeUFBSmJTbmdnQkxVU3NYV1RBZ0FBZUhBQUFBQVQvOS9hNEIzQUFBSC83TFlvd0JBQUFQL3lhblpkd0FBeS8vS1JFcURZQUFELzhzYUVDa0FBTXYvekJvMnptQUFBQUFlQWRpOEFBRElBQjZ0Qm5OZ0FBQUFIN3R5RFFBQXlBQWdnYWtuWUFBQUFDR1FGTUVBQU1nQUlsWkwyMkFBQUFBamJicVdBQURJQUNRejhiQmdBQUFBSlVKZFNnQUF5QUFtQ0pSa1lBQUFBQ2NXLy80QUFNZ0FKOTAzR0dBQUFBQjdFa3pMQUFBQndjSEJ6Y2dBT2FtRjJZUzUxZEdsc0xrUmhkR1ZvYW9FQlMxbDBHUU1BQUhod2R3Z0FBQUZKL3B5NElIZz14AHQADURFRkFVTFQuTXlKb2J+cgAqY29tLmdvbWUuY2xvdmVyLmNvcmUuam9iLkNsaWVudEpvYiRKb2JUeXBlAAAAAAAAAAASAAB4cQB+AAt0AAZSRU1PVEVzcgAob3JnLnF1YXJ0ei5pbXBsLnRyaWdnZXJzLkNyb25UcmlnZ2VySW1wbIgG9OqN23nCAgAFTAAGY3JvbkV4dAAbTG9yZy9xdWFydHovQ3JvbkV4cHJlc3Npb247TAAHZW5kVGltZXQAEExqYXZhL3V0aWwvRGF0ZTtMAAxuZXh0RmlyZVRpbWVxAH4AJEwAEHByZXZpb3VzRmlyZVRpbWVxAH4AJEwACXN0YXJ0VGltZXEAfgAkeHIAKG9yZy5xdWFydHouaW1wbC50cmlnZ2Vycy5BYnN0cmFjdFRyaWdnZXLJ0Vc7DeD17gIAC0kAEm1pc2ZpcmVJbnN0cnVjdGlvbkkACHByaW9yaXR5WgAKdm9sYXRpbGl0eUwADGNhbGVuZGFyTmFtZXEAfgAETAALZGVzY3JpcHRpb25xAH4ABEwADmZpcmVJbnN0YW5jZUlkcQB+AARMAAVncm91cHEAfgAETAAKam9iRGF0YU1hcHEAfgARTAAIam9iR3JvdXBxAH4ABEwAB2pvYk5hbWVxAH4ABEwABG5hbWVxAH4ABHhwAAAAAAAAAAUAcHBwcQB+ABNwcQB+ABN0AA1ERUZBVUxULk15Sm9idAANREVGQVVMVC5NeUpvYnNyABlvcmcucXVhcnR6LkNyb25FeHByZXNzaW9uAAAAAuR+Lw8CAAJMAA5jcm9uRXhwcmVzc2lvbnEAfgAETAAIdGltZVpvbmV0ABRMamF2YS91dGlsL1RpbWVab25lO3hwdAAOMC8xMCAqICogKiAqID9zcgAac3VuLnV0aWwuY2FsZW5kYXIuWm9uZUluZm8k0dPOAB1xmwIACEkACGNoZWNrc3VtSQAKZHN0U2F2aW5nc0kACXJhd09mZnNldEkADXJhd09mZnNldERpZmZaABN3aWxsR01UT2Zmc2V0Q2hhbmdlWwAHb2Zmc2V0c3QAAltJWwAUc2ltcGxlVGltZVpvbmVQYXJhbXNxAH4ALlsAC3RyYW5zaXRpb25zdAACW0p4cgASamF2YS51dGlsLlRpbWVab25lMbPp9XdErKECAAFMAAJJRHEAfgAEeHB0AA1Bc2lhL1NoYW5naGFpBChB7AAAAAABt3QAAAAAAAB1cgACW0lNumAmduqypQIAAHhwAAAABAG3dAABvNMAAe5igAA27oBwdXIAAltKeCAEtRKxdZMCAAB4cAAAABP/39rgHcAAAf/stijAEAAA//Jqdl3AADL/8pESoNgAAP/yxoQKQAAy//MGjbOYAAAAB4B2LwAAMgAHq0Gc2AAAAAfu3INAADIACCBqSdgAAAAIZAUwQAAyAAiVkvbYAAAACNtupYAAMgAJDPxsGAAAAAlQl1KAADIACYIlGRgAAAAJxb//gAAyAAn3TcYYAAAAHsSTMsAAAHBwcHNyAA5qYXZhLnV0aWwuRGF0ZWhqgQFLWXQZAwAAeHB3CAAAAUn+nLggeA=="; ServerJob serverJob = (ServerJob) ClassUtil.BytesToObject(Base64.decodeBase64(newMsg)); ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String)serverJob.getJobDetail().getJobDataMap().get(CommonConstants.CLIENT_JOB_INFO))); System.err.println("server:"+serverJob); System.err.println("clientJob:"+clientJob); } @Test public void testCompress(){ ClientJob clientJob = ClientJobBuilder.quickBuildLocalCronJob("jobGroup","jobGroup", MyJob.class,"0/10 * * * * ?"); byte[] bytes= ClassUtil.ObjectToBytes(clientJob); System.err.println("compress 前:"+bytes.length); byte[] compressBytes = CompressUtil.compress(bytes); System.err.println("compress 后:"+compressBytes.length); byte[] uncompressBytes = CompressUtil.uncompress(compressBytes); ClientJob clientJob2 = (ClientJob) ClassUtil.BytesToObject(uncompressBytes); System.err.println("clientJob2:"+clientJob2); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/TestEum.java ================================================ package com.gome.clover; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.common.tools.RandomNumUtil; import org.junit.Test; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.net.Socket; import java.util.HashMap; import java.util.Map; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/3 * Time: 14:57 */ public class TestEum { @Test public void testEumVal() throws InterruptedException { /* try{ }catch (Exception e){ System.err.println("testEumVal"+e.getMessage()); }*/ //System.err.println("" + DateUtil.formatWithDefaultPattern("2012-12-12 12:12:12")); /* while(true){ int num = new Random().nextInt(0xFFFF); while (num == 2 || num == 7) { num = new Random().nextInt(100); } System.out.println(num); }*/ while (true){ Thread.sleep(1000); System.err.println(RandomNumUtil.getNextIntString()); } } @Test public void testLongMax(){ Long maxLong = Long.MAX_VALUE; System.err.println(maxLong); int PID; try { RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); String name = runtime.getName(); PID = Integer.parseInt(name.substring(0, name.indexOf('@'))); } catch (Throwable e) { PID = 0; } System.err.println("PID:"+PID); } @Test public void testCommon(){ System.err.println(""+ CommonConstants.ZMQ_SERVER_PORT); System.err.println(""+ CommonConstants.SERVER_DIFFER_MILLI_SECONDS); System.err.println(""+ CommonConstants.CLIENT_DIFFER_MILLI_SECONDS); System.err.println(""+ CommonConstants.MONITOR_DIFFER_MILLI_SECONDS); System.err.println(""+ CommonConstants.DEFAULT_COMPANY_EMAIL); System.err.println(""+ CommonConstants.DEFAULT_PRIVATE_EMAIL); System.err.println(""+ CommonConstants.ZMQ_SLEEP_CLIENT_MILLIS); System.err.println(""+ CommonConstants.ZMQ_SLEEP_SERVER_MILLIS); System.err.println(""+ CommonConstants.token); System.err.println(""+ CommonConstants.DISABLED_DB); System.err.println(""+ CommonConstants.POOL_SIZE); System.err.println(""+ CommonConstants.MAX_FAIL_TIMES); int n = Runtime.getRuntime().availableProcessors()*2; System.err.println("n:"+n); //建立Socket Socket s = null; try { s = new Socket(IpUtil.getLocalIP(),27727); if(s.isConnected()){ System.err.println("s.isConnected()"); } } catch (IOException e) { e.printStackTrace(); }finally { if(null!=s && !s.isClosed()){ try { s.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void testMap(){ Map map = new HashMap(); String acd = (String) map.get("adb"); System.err.println(""+acd); map.put(CommonConstants.SUCCESS,false); boolean s = (Boolean) map.get(CommonConstants.SUCCESS); System.err.println(""+s ); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/TestThread.java ================================================ package com.gome.clover; import org.junit.Test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/8 * Time: 15:52 */ public class TestThread { @Test public void testPoll(){ ExecutorService pool = Executors.newCachedThreadPool(); System.err.println(""+pool); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/akka/serverclient/pubsub/MyActorSystem.java ================================================ package com.gome.clover.akka.serverclient.pubsub; import akka.actor.ActorSystem; import akka.actor.Props; public class MyActorSystem { /** * @param args */ public static void main(String[] args) { ActorSystem system = ActorSystem.create("zeromqTest"); system.actorOf(new Props(WorkerTaskA.class), "workerA"); system.actorOf(new Props(WorkerTaskB.class), "workerB"); system.actorOf(new Props(PublisherActor.class), "publisher"); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/akka/serverclient/pubsub/PublisherActor.java ================================================ package com.gome.clover.akka.serverclient.pubsub; import akka.actor.ActorRef; import akka.actor.Cancellable; import akka.actor.UntypedActor; import akka.zeromq.Bind; import akka.zeromq.Frame; import akka.zeromq.ZMQMessage; import akka.zeromq.ZeroMQExtension; public class PublisherActor extends UntypedActor { public static final Object TICK = "TICK"; int count = 0; Cancellable cancellable; ActorRef pubSocket = ZeroMQExtension.get(getContext().system()) .newPubSocket(new Bind("tcp://127.0.0.1:1237")); @Override public void preStart() { /*cancellable = getContext() .system() .scheduler() .schedule(Duration.parse("1 second"), Duration.parse("1 second"), getSelf(), TICK,ExecutionContext);*/ } @Override public void onReceive(Object message) throws Exception { if (message.equals(TICK)) { pubSocket.tell(new ZMQMessage(new Frame("someTopic"), new Frame( "This is the workload " + ++count))); if(count==10) cancellable.cancel(); } } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/akka/serverclient/pubsub/WorkerTaskA.java ================================================ package com.gome.clover.akka.serverclient.pubsub; import akka.actor.ActorRef; import akka.actor.UntypedActor; import akka.event.Logging; import akka.event.LoggingAdapter; import akka.zeromq.*; public class WorkerTaskA extends UntypedActor { ActorRef subSocket = ZeroMQExtension.get(getContext().system()) .newSubSocket(new Connect("tcp://127.0.0.1:1237"), new Listener(getSelf()), new Subscribe("someTopic")); LoggingAdapter log = Logging.getLogger(getContext().system(), this); @Override public void onReceive(Object message) throws Exception { if (message instanceof ZMQMessage) { ZMQMessage m = (ZMQMessage) message; String mesg = new String(m.payload(1)); log.info("Received Message @ A -> {}",mesg); } } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/akka/serverclient/pubsub/WorkerTaskB.java ================================================ package com.gome.clover.akka.serverclient.pubsub; import akka.actor.ActorRef; import akka.actor.UntypedActor; import akka.event.Logging; import akka.event.LoggingAdapter; import akka.zeromq.*; public class WorkerTaskB extends UntypedActor { ActorRef subSocket = ZeroMQExtension.get(getContext().system()) .newSubSocket(new Connect("tcp://127.0.0.1:1237"), new Listener(getSelf()), new Subscribe("someTopic")); LoggingAdapter log = Logging.getLogger(getContext().system(), this); @Override public void onReceive(Object message) throws Exception { if (message instanceof ZMQMessage) { ZMQMessage m = (ZMQMessage) message; String mesg = new String(m.payload(1)); log.info("Received Message @ B -> {}", mesg); } } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/common/compile/TestCompile.java ================================================ package com.gome.clover.common.compile; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.core.job.ClientJob; import org.apache.commons.codec.binary.Base64; import org.junit.Test; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/26 * Time: 18:56 */ public class TestCompile { @Test public void create(){ File file = null; try { file = File.createTempFile("JavaRuntime", ".java", new File(System.getProperty("user.dir"))); } catch (IOException e) { e.printStackTrace(); } String filename = file.getName(); String classname = "com.gome.sb.JavaRuntime"; //将代码输出到文件 PrintWriter out = null; try { out = new PrintWriter(new FileOutputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); } StringBuilder sb = new StringBuilder(); sb.append("package com.gome.sb; ").append("public class ").append(filename.substring(0,filename.indexOf(".")-1)) .append("{}"); out.println(sb.toString()); //关闭文件流 out.flush(); out.close(); } @Test public void compile(){ /* com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main(); String[] args = new String[] {"-d",System.getProperty("user.dir"),"JavaRuntime4836122228587967142.java"}; int status = javac.compile(args); System.err.println("status"+status);*/ URLClassLoader loader= null; try { loader = new URLClassLoader(new URL[]{new URL("file:D:\\Java\\apache-tomcat-6.0.18\\bin\\com\\gome\\clover\\core\\job\\client\\")}); Object WYMyJob1= loader.loadClass("WYMyJob1").newInstance(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } @Test public void getObject(){ String str ="rO0ABXNyACJjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuU2VydmVySm9its+L9tdn6kgCAAB4cgAiY29tLmdvbWUuY2xvdmVyLmNvcmUuam9iLkNsaWVudEpvYg0GalC4zmMwAgAITAALZXhlY3V0ZVR5cGV0ADBMY29tL2dvbWUvY2xvdmVyL2NvcmUvam9iL0NsaWVudEpvYiRFeGVjdXRlVHlwZTtbAA5maXhlZENsaWVudElwc3QAE1tMamF2YS9sYW5nL1N0cmluZztbAA5maXhlZFNlcnZlcklwc3EAfgADTAACaXB0ABJMamF2YS9sYW5nL1N0cmluZztMAAhqb2JDbGFzc3QAEUxqYXZhL2xhbmcvQ2xhc3M7TAAJam9iRGV0YWlsdAAWTG9yZy9xdWFydHovSm9iRGV0YWlsO0wAB2pvYlR5cGV0ACxMY29tL2dvbWUvY2xvdmVyL2NvcmUvam9iL0NsaWVudEpvYiRKb2JUeXBlO0wAB3RyaWdnZXJ0ABRMb3JnL3F1YXJ0ei9UcmlnZ2VyO3hwfnIALmNvbS5nb21lLmNsb3Zlci5jb3JlLmpvYi5DbGllbnRKb2IkRXhlY3V0ZVR5cGUAAAAAAAAAABIAAHhyAA5qYXZhLmxhbmcuRW51bQAAAAAAAAAAEgAAeHB0AANBRERwcHQADTEwLjE0NC4zMy4yMTJwc3IAHW9yZy5xdWFydHouaW1wbC5Kb2JEZXRhaWxJbXBsq8PK7AFaVK8CAAdaAApkdXJhYmlsaXR5WgANc2hvdWxkUmVjb3ZlckwAC2Rlc2NyaXB0aW9ucQB+AARMAAVncm91cHEAfgAETAAIam9iQ2xhc3NxAH4ABUwACmpvYkRhdGFNYXB0ABdMb3JnL3F1YXJ0ei9Kb2JEYXRhTWFwO0wABG5hbWVxAH4ABHhwAABwdAALcmVtb3RlLWpvYnN2cQB+AABzcgAVb3JnLnF1YXJ0ei5Kb2JEYXRhTWFwn7CD6L+psMsCAAB4cgAmb3JnLnF1YXJ0ei51dGlscy5TdHJpbmdLZXlEaXJ0eUZsYWdNYXCCCOjD+8VdKAIAAVoAE2FsbG93c1RyYW5zaWVudERhdGF4cgAdb3JnLnF1YXJ0ei51dGlscy5EaXJ0eUZsYWdNYXAT5i6tKHYKzgIAAloABWRpcnR5TAADbWFwdAAPTGphdmEvdXRpbC9NYXA7eHABc3IAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAADHcIAAAAEAAAAAF0AAdqb2JJbmZvc3EAfgABcQB+AAxwcHEAfgAOdnIAJWNvbS5nb21lLmNsb3Zlci5jb3JlLmpvYi5jbGllbnQuTXlKb2IAAAAAAAAAAAAAAHhwc3EAfgAPAABwdAAHREVGQVVMVHEAfgAecHQABk15Sm9iMX5yACpjb20uZ29tZS5jbG92ZXIuY29yZS5qb2IuQ2xpZW50Sm9iJEpvYlR5cGUAAAAAAAAAABIAAHhxAH4AC3QABlJFTU9URXNyAChvcmcucXVhcnR6LmltcGwudHJpZ2dlcnMuQ3JvblRyaWdnZXJJbXBsiAb06o3becICAAVMAAZjcm9uRXh0ABtMb3JnL3F1YXJ0ei9Dcm9uRXhwcmVzc2lvbjtMAAdlbmRUaW1ldAAQTGphdmEvdXRpbC9EYXRlO0wADG5leHRGaXJlVGltZXEAfgAnTAAQcHJldmlvdXNGaXJlVGltZXEAfgAnTAAJc3RhcnRUaW1lcQB+ACd4cgAob3JnLnF1YXJ0ei5pbXBsLnRyaWdnZXJzLkFic3RyYWN0VHJpZ2dlcsnRVzsN4PXuAgALSQASbWlzZmlyZUluc3RydWN0aW9uSQAIcHJpb3JpdHlaAAp2b2xhdGlsaXR5TAAMY2FsZW5kYXJOYW1lcQB+AARMAAtkZXNjcmlwdGlvbnEAfgAETAAOZmlyZUluc3RhbmNlSWRxAH4ABEwABWdyb3VwcQB+AARMAApqb2JEYXRhTWFwcQB+ABBMAAhqb2JHcm91cHEAfgAETAAHam9iTmFtZXEAfgAETAAEbmFtZXEAfgAEeHAAAAAAAAAABQBwcHBxAH4AIHBxAH4AIHB0AAh0cmlnZ2VyMXNyABlvcmcucXVhcnR6LkNyb25FeHByZXNzaW9uAAAAAuR+Lw8CAAJMAA5jcm9uRXhwcmVzc2lvbnEAfgAETAAIdGltZVpvbmV0ABRMamF2YS91dGlsL1RpbWVab25lO3hwdAAOMC8xMCAqICogKiAqID9zcgAac3VuLnV0aWwuY2FsZW5kYXIuWm9uZUluZm8k0dPOAB1xmwIACEkACGNoZWNrc3VtSQAKZHN0U2F2aW5nc0kACXJhd09mZnNldEkADXJhd09mZnNldERpZmZaABN3aWxsR01UT2Zmc2V0Q2hhbmdlWwAHb2Zmc2V0c3QAAltJWwAUc2ltcGxlVGltZVpvbmVQYXJhbXNxAH4AMFsAC3RyYW5zaXRpb25zdAACW0p4cgASamF2YS51dGlsLlRpbWVab25lMbPp9XdErKECAAFMAAJJRHEAfgAEeHB0AA1Bc2lhL1NoYW5naGFpBChB7AAAAAABt3QAAAAAAAB1cgACW0lNumAmduqypQIAAHhwAAAABAG3dAABvNMAAe5igAA27oBwdXIAAltKeCAEtRKxdZMCAAB4cAAAABP/39rgHcAAAf/stijAEAAA//Jqdl3AADL/8pESoNgAAP/yxoQKQAAy//MGjbOYAAAAB4B2LwAAMgAHq0Gc2AAAAAfu3INAADIACCBqSdgAAAAIZAUwQAAyAAiVkvbYAAAACNtupYAAMgAJDPxsGAAAAAlQl1KAADIACYIlGRgAAAAJxb//gAAyAAn3TcYYAAAAHsSTMsAAAHBwcHNyAA5qYXZhLnV0aWwuRGF0ZWhqgQFLWXQZAwAAeHB3CAAAAUnrhWuweHgAdAAOREVGQVVMVC5NeUpvYjFxAH4AI3NxAH4AJQAAAAAAAAAFAHBwcHEAfgAScHEAfgASdAAOREVGQVVMVC5NeUpvYjF0AA5ERUZBVUxULk15Sm9iMXNxAH4AK3QADjAvMTAgKiAqICogKiA/c3EAfgAvdAANQXNpYS9TaGFuZ2hhaQQoQewAAAAAAbd0AAAAAAAAdXEAfgA1AAAABAG3dAABvNMAAe5igAA27oBwdXEAfgA3AAAAE//f2uAdwAAB/+y2KMAQAAD/8mp2XcAAMv/ykRKg2AAA//LGhApAADL/8waNs5gAAAAHgHYvAAAyAAerQZzYAAAAB+7cg0AAMgAIIGpJ2AAAAAhkBTBAADIACJWS9tgAAAAI226lgAAyAAkM/GwYAAAACVCXUoAAMgAJgiUZGAAAAAnFv/+AADIACfdNxhgAAAAexJMywAAAcHBwc3EAfgA5dwgAAAFJ64VrsHg="; ClientJob clientJob = (ClientJob)ClassUtil.BytesToObject(Base64.decodeBase64(str)); String className = clientJob.getJobDetail().getJobClass().getName(); System.err.println("className:"+className); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/cron/TestCron.java ================================================ package com.gome.clover.cron; import com.gome.clover.common.tools.DateUtil; import org.junit.Test; import java.text.ParseException; import java.util.Date; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/8 * Time: 16:55 */ public class TestCron { @Test public void getNextTime(){ Date nextDate = null; try { nextDate = DateUtil.getNextValidTimeAfter("0/10 * * * * ?", new Date()); } catch (ParseException e) { e.printStackTrace(); } System.err.println("Date:"+nextDate); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/job/MyJob.java ================================================ package com.gome.clover.job; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobFactory; import com.gome.clover.core.module.ModuleSchedulerClient; import com.mongodb.BasicDBObject; import org.quartz.*; import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:My Job * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.err.println("context"); if (null == context.getNextFireTime()) { BasicDBObject deleteCondition = new BasicDBObject(); deleteCondition.put(DBTableInfo.COL_JOB_KEY, context.getJobDetail().getKey().toString()); deleteCondition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_LOCAL); deleteCondition.put(DBTableInfo.COL_IP, IpUtil.getLocalIP()); MongoDBUtil.INSTANCE.delete(deleteCondition, DBTableInfo.TBL_CLOVER_JOB); } } public static void main(String args[]){ ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); JobDetail jobDetail = newJob(MyJob.class) .withIdentity("MyJob", Scheduler.DEFAULT_GROUP).build(); Trigger trigger = newTrigger() .withIdentity("trigger", Scheduler.DEFAULT_GROUP) .withSchedule(cronSchedule("0/10 * * * * ?")).build(); ClientJob clientJob = ClientJobFactory.builder(jobDetail, trigger, ClientJob.JobType.REMOTE,null,null).jobClass(MyJob.class) .executeType(ClientJob.ExecuteType.ADD).build(); client.handlerJob(clientJob); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/job/MyJob1.java ================================================ package com.gome.clover.job; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; import com.mongodb.BasicDBObject; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import java.io.Serializable; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:MyJob * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class MyJob1 implements Job,Serializable { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.err.println("WYMyJob1-->>execute(context)"+context.getJobDetail().getJobDataMap().get("test")); if (null == context.getNextFireTime()) { BasicDBObject deleteCondition = new BasicDBObject(); deleteCondition.put(DBTableInfo.COL_JOB_KEY, context.getJobDetail().getKey().toString()); deleteCondition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_LOCAL); deleteCondition.put(DBTableInfo.COL_IP, IpUtil.getLocalIP()); MongoDBUtil.INSTANCE.delete(deleteCondition, DBTableInfo.TBL_CLOVER_JOB); } } public static void main(String args[]){ ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); //client.startupForLocalJobTest(); /* JobDetail jobDetail = newJob(MyJob1.class) .withIdentity("MyJob1", Scheduler.DEFAULT_GROUP).build(); Trigger trigger = newTrigger() .withIdentity("trigger", Scheduler.DEFAULT_GROUP) .withSchedule(cronSchedule("0/10 * * * * ?")).build(); ClientJob clientJob = ClientJobFactory.builder(jobDetail, trigger, ClientJob.JobType.REMOTE).jobClass(MyJob1.class) .executeType(ExecuteType.ADD).build(); clientJob.getJobDetail().getJobDataMap().put("test","MyJob1"); client.handlerJob(clientJob);*/ Date startDate = null; try { DateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); startDate= parser.parse("2014-12-01 17:23:20"); } catch (ParseException ex) { } ClientJob clientJob = ClientJobBuilder.quickBuildLocalJobWithStartDate("wyGroup", "wyJob", MyJob1.class, startDate); clientJob.setExecuteType(ClientJob.ExecuteType.ADD); //ClientJob clientJob = ClientJobBuilder.quickBuildLocalStartNowJobWithExecuteType("wyGoup", "wyJob", MyJob1.class, ClientJob.ExecuteType.DELETE); clientJob.setRecoverJobFromDB(true); //clientJob.getJobDetail().get client.handlerJob(clientJob); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/job/MyJobWithSimpleJob.java ================================================ package com.gome.clover.job; import com.gome.bg.clover.client.job.SimpleJob; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; import org.quartz.JobExecutionContext; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:MyJob * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class MyJobWithSimpleJob extends SimpleJob { public void executeJob(JobExecutionContext context) { System.err.println("MyJobWithSimpleJob-->>executeJob(context)"+context.getJobDetail().getJobDataMap().get("test")); } public static void main(String args[]){ ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); client.startupForLocalJobTest(); /* JobDetail jobDetail = newJob(MyJob1.class) .withIdentity("MyJob1", Scheduler.DEFAULT_GROUP).build(); Trigger trigger = newTrigger() .withIdentity("trigger", Scheduler.DEFAULT_GROUP) .withSchedule(cronSchedule("0/10 * * * * ?")).build(); ClientJob clientJob = ClientJobFactory.builder(jobDetail, trigger, ClientJob.JobType.REMOTE).jobClass(MyJob1.class) .executeType(ExecuteType.ADD).build(); clientJob.getJobDetail().getJobDataMap().put("test","MyJob1"); client.handlerJob(clientJob);*/ Date startDate = null; try { DateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); startDate= parser.parse("2014-12-12 11:18:20"); } catch (ParseException ex) { } // ClientJob clientJob = ClientJobBuilder.quickBuildLocalJobWithStartDate("wyGroup1", "wyJob1", MyJobWithSimpleJob.class, startDate); ClientJob clientJob = ClientJobBuilder.quickBuildLocalCronJob("wyGroup2", "wyJob2", MyJobWithSimpleJob.class, "0/10 * * * * ?"); // ClientJob clientJob = ClientJobBuilder.quickBuildLocalCronJob("wyGroup", "wyJob", MyJobWithSimpleJob.class, "0/10 * * * * ?"); //clientJob.setExecuteType(ClientJob.ExecuteType.ADD); //ClientJob clientJob = ClientJobBuilder.quickBuildLocalStartNowJobWithExecuteType("wyGoup", "wyJob", MyJob1.class, ClientJob.ExecuteType.DELETE); clientJob.setRecoverJobFromDB(true); client.handlerJob(clientJob); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/json/TestJson.java ================================================ package com.gome.clover.json; import com.alibaba.fastjson.JSON; import org.junit.Test; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; /** * Module Desc: * User: wangyue-ds6 * Date: 2014/11/17 * Time: 20:08 */ public class TestJson { @Test public void setToJson(){ System.err.println("setToJson"); Set set = new HashSet(); set.add("127.0.0.1"); set.add("192.168.168.1"); String setJson = JSON.toJSONString(set); System.err.println("setJson " +setJson); Set set1 = JSON.parseObject(setJson,Set.class); System.err.println("set " +set1); } @Test public void jsonToSet(){ String setJson = "[\"192.168.168.1\",\"127.0.0.1\"]"; Set set = JSON.parseObject(setJson, Set.class); System.err.println("set " +set); int len = set.size(); Math.random(); Random random = new Random(); int newVal = random.nextInt(len); System.err.println("newVal:"+newVal); } @Test public void listToJson(){ List ipList = new CopyOnWriteArrayList(); if(!ipList.contains("127.0.0.1")){ ipList.add("127.0.0.1"); } if(!ipList.contains("192.168.168.1")){ ipList.add("192.168.168.1"); } String listJson = JSON.toJSONString(ipList); System.err.println("listJson " +listJson); List ipList2 = JSON.parseObject(listJson,List.class); System.err.println("list " +ipList2); int len = ipList2.size(); Math.random(); Random random = new Random(); int newVal = random.nextInt(len); System.err.println("newVal:"+newVal); } public void testList2StringUtil(){ } @Test public void testMap(){ Map map = new HashMap(); map.put("alive","1"); map.put("ip","127.0.0.1"); String mapStr = JSON.toJSONString(map); System.err.println("mapStr-----"+mapStr); Map map1 = JSON.parseObject(mapStr,Map.class); System.err.println("map1-----------"+map1); } @Test public void testArray(){ String a[] = new String[]{}; List list = new ArrayList(); list.add("2"); System.err.println("a"+JSON.toJSONString(a)); System.err.println("list"+list); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/mongo/TestMongoDB.java ================================================ package com.gome.clover.mongo; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.core.job.ClientJob; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import org.apache.commons.codec.binary.Base64; import org.junit.Test; /** * Module Desc:Test Mongo DB * User: wangyue-ds6 * Date: 2014/11/18 * Time: 15:02 */ public class TestMongoDB { @Test public void insertOrUpdate(){ while (true){ BasicDBObject document = new BasicDBObject(); document.put("jobKey", "jobKey1"); document.put("jobInfo", "jobInfo1"); document.put("ip", IpUtil.getLocalIP()); document.put("ts", DateUtil.currentDateTime()); MongoDBUtil.INSTANCE.insertOrUpdate(document, "test_wy"); MongoDBUtil.INSTANCE.insert(document, "test_wy"); System.err.println("TestMongoDB--->>>insertOrUpdate()"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } @Test public void findByJobKey(){ DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_IP, IpUtil.getLocalIP()); DBCursor cursorDocMap = dbCollection.find(condition); while (cursorDocMap.hasNext()) { ClientJob clientJob = (ClientJob) ClassUtil.BytesToObject(Base64.decodeBase64((String)cursorDocMap.next() .get(DBTableInfo.COL_JOB_INFO))); System.err.println("clientJob:"+clientJob.getTrigger()); } } @Test public void insertConfig(){ BasicDBObject document = new BasicDBObject(); document.put(DBTableInfo.COL_CONFIG_KEY,CommonConstants.DISABLED_DB); document.put(DBTableInfo.COL_CONFIG_TYPE,CommonConstants.TYPE_DB); document.put(DBTableInfo.COL_CONFIG_VALUE, "false"); document.put("ts", DateUtil.currentDateTime()); MongoDBUtil.INSTANCE.insert(document,DBTableInfo.TBL_CLOVER_CONFIG); System.err.println("TestMongoDB--->>>insertConfig()"); } @Test public void updateConfig(){ BasicDBObject document = new BasicDBObject(); document.put(DBTableInfo.COL_CONFIG_KEY,CommonConstants.DISABLED_DB); document.put(DBTableInfo.COL_CONFIG_TYPE,CommonConstants.TYPE_DB); BasicDBObject update = new BasicDBObject(); update.put(DBTableInfo.COL_CONFIG_VALUE,"true"); MongoDBUtil.INSTANCE.update(document,new BasicDBObject("$set", update),DBTableInfo.TBL_CLOVER_CONFIG); } @Test public void testGetOn(){ System.err.println(""+MongoDBUtil.isEnabledDB()); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/scheduler/TestSchedulerWithInsertMongoDB.java ================================================ package com.gome.clover.scheduler; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.ClassUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobFactory; import com.gome.clover.core.module.ModuleSchedulerClient; import com.mongodb.BasicDBObject; import org.apache.commons.codec.binary.Base64; import org.quartz.*; import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; /** * Module Desc: * User: wangyue-ds6 * Date: 2014/11/11 * Time: 22:54 */ public class TestSchedulerWithInsertMongoDB implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.err.println("TestScheduler-->>execute("+ context+")"); } public static void main(String args[]){ try { //启动Netty RPC //new RpcServer(CommonConstants.RPC_CLIENT_PORT).run(); //ConsumerUtil.startup("10.58.50.204:9876;10.58.50.205:9876", CommonConstants.TOPIC_CLOVER_SERVER, IpUtil.getLocalIP().replace(".", "-")); } catch (Exception e) { } ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); JobDetail jobDetail = newJob(TestSchedulerWithInsertMongoDB.class) .withIdentity("TestSchedulerJob1", Scheduler.DEFAULT_GROUP).requestRecovery(true).build(); Trigger trigger = newTrigger() .withIdentity("trigger1", Scheduler.DEFAULT_GROUP) .withSchedule(cronSchedule("0/10 * * * * ?")).build(); ClientJob clientJob = ClientJobFactory.builder(jobDetail, trigger, ClientJob.JobType.REMOTE,null,null).jobClass(TestSchedulerWithInsertMongoDB.class).build(); String jobInfoStr = Base64.encodeBase64String(ClassUtil.ObjectToBytes(clientJob)); BasicDBObject document = new BasicDBObject(); document.put(DBTableInfo.COL_JOB_KEY, "jobKey1"); document.put(DBTableInfo.COL_JOB_INFO, jobInfoStr); document.put(DBTableInfo.COL_IP, IpUtil.getLocalIP()); document.put(DBTableInfo.COL_STATUS, CommonConstants.JOB_STATUS_1); document.put(DBTableInfo.COL_TS, DateUtil.currentDateTime()); MongoDBUtil.INSTANCE.insertOrUpdate(document,DBTableInfo.TBL_CLOVER_JOB); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/scheduler/TestSchedulerWithRegister.java ================================================ package com.gome.clover.scheduler; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.IpUtil; import com.gome.clover.core.module.ModuleSchedulerClient; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * Module Desc: * User: wangyue-ds6 * Date: 2014/11/11 * Time: 22:54 */ public class TestSchedulerWithRegister implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.err.println("TestScheduler-->>execute("+ context+")"); } public static void main(String args[]){ try { //启动Netty RPC //new RpcServer(CommonConstants.RPC_CLIENT_PORT).run(); //ConsumerUtil.startup("10.58.50.204:9876;10.58.50.205:9876", CommonConstants.TOPIC_CLOVER_SERVER, IpUtil.getLocalIP().replace(".", "-")); } catch (Exception e) { } ModuleSchedulerClient client = ModuleSchedulerClient.getInstance(); client.registerToZK(CommonConstants.MODULE_TYPE_CLIENT,IpUtil.getLocalIP(),null,"-1",CommonConstants.SYSTEM_ID_CLOVER); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/systeminfo/TestMem.java ================================================ package com.gome.clover.systeminfo; import com.sun.management.OperatingSystemMXBean; import sun.management.ManagementFactory; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/25 * Time: 16:04 */ public class TestMem { public static void main(String[] args) { OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory .getOperatingSystemMXBean(); int kb = 1024; // 总的物理内存 long totalMemorySize = osmxb.getTotalPhysicalMemorySize() / kb; // 剩余的物理内存 long freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize() / kb; // 已使用的物理内存 long usedMemory = (osmxb.getTotalPhysicalMemorySize() - osmxb .getFreePhysicalMemorySize()) / kb; System.out.println("totalMemorySize:"+totalMemorySize); System.out.println("freePhysicalMemorySize:"+freePhysicalMemorySize); System.out.println("usedMemory:"+usedMemory); //BigDecimal memRatio = (BigDecimal.valueOf(usedMemory).divide(BigDecimal.valueOf(totalMemorySize))); System.out.println("memRatio:"+((float)(usedMemory*1.0/totalMemorySize))); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/thread/MyThread.java ================================================ package com.gome.clover.thread;/** * Created by on . */ import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.DateUtil; import com.gome.clover.common.tools.IpUtil; import com.mongodb.BasicDBObject; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 22:56 */ class MyThread implements java.lang.Runnable { private int threadId; public MyThread(int id) { this.threadId = id; } @Override public void run() { BasicDBObject document = new BasicDBObject(); document.put("jobKey", "jobKey1"); document.put("jobInfo", "jobInfo1"); document.put("ip", IpUtil.getLocalIP()); document.put("ts", DateUtil.currentDateTime()); MongoDBUtil.INSTANCE.insert(document,"test_wy"); MongoDBUtil.INSTANCE.insertOrUpdate(document,"test_wy"); System.err.println("MyThread--->>>run()"); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/thread/TestMyThreadPool.java ================================================ package com.gome.clover.thread; import com.gome.clover.common.tools.CommonConstants; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/18 * Time: 15:21 */ public class TestMyThreadPool { private static ExecutorService pool = null; //线程池 public static void main(String[] args) { // 创建3个线程的线程池 /* MyThreadPool t = MyThreadPool.getThreadPool(); t.execute(new Runnable[] { new Task(), new Task(), new Task() }); t.execute(new Runnable[] { new Task(), new Task(), new Task() }); System.out.println(t); t.destroy();// 所有线程都执行完成才destory System.out.println(t);*/ test1(); test2(); test3(); } public static void test1(){ if (null == pool) { pool = Executors.newFixedThreadPool(CommonConstants.POOL_SIZE); System.err.println("test1->Executors.newFixedThreadPool(CommonConstants.POOL_SIZE)"); } pool.execute(new Thread(new Task())); } public static void test2(){ if (null == pool) { pool = Executors.newFixedThreadPool(CommonConstants.POOL_SIZE); System.err.println("test2->Executors.newFixedThreadPool(CommonConstants.POOL_SIZE)"); } pool.execute(new Thread(new Task())); } public static void test3(){ if (null == pool) { pool = Executors.newFixedThreadPool(CommonConstants.POOL_SIZE); System.err.println("test3->Executors.newFixedThreadPool(CommonConstants.POOL_SIZE)"); } pool.execute(new Thread(new Task())); } // 任务类 static class Task implements Runnable { private static volatile int i = 1; @Override public void run() {// 执行任务 System.out.println("任务 " + (i++) + " 完成"); } } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/thread/ThreadDemo.java ================================================ package com.gome.clover.thread; import java.util.Random; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 22:57 */ public class ThreadDemo { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { while (true) { new Thread(new MyThread(new Random().nextInt())).start(); } } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/thread/ThreadPool.java ================================================ package com.gome.clover.thread;/** * Created by on . */ import java.util.LinkedList; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 22:54 */ public class ThreadPool extends ThreadGroup { private boolean isClosed = false; //线程池是否关闭 private LinkedList workQueue; //工作队列 private static int threadPoolID = 1; //线程池的id public ThreadPool(int poolSize) { //poolSize 表示线程池中的工作线程的数量 super(threadPoolID + ""); //指定ThreadGroup的名称 setDaemon(true); //继承到的方法,设置是否守护线程池 workQueue = new LinkedList(); //创建工作队列 for(int i = 0; i < poolSize; i++) { new WorkThread(i).start(); //创建并启动工作线程,线程池数量是多少就创建多少个工作线程 } } /** 向工作队列中加入一个新任务,由工作线程去执行该任务*/ public synchronized void execute(Runnable task) { if(isClosed) { throw new IllegalStateException(); } if(task != null) { workQueue.add(task);//向队列中加入一个任务 notify(); //唤醒一个正在getTask()方法中待任务的工作线程 } } /** 从工作队列中取出一个任务,工作线程会调用此方法*/ private synchronized Runnable getTask(int threadId) throws InterruptedException { while(workQueue.size() == 0) { if(isClosed) return null; System.out.println("工作线程"+threadId+"等待任务..."); wait(); //如果工作队列中没有任务,就等待任务 } System.out.println("工作线程"+threadId+"开始执行任务..."); return (Runnable) workQueue.removeFirst(); //反回队列中第一个元素,并从队列中删除 } /** 关闭线程池 */ public synchronized void closePool() { if(! isClosed) { waitFinish(); //等待工作线程执行完毕 isClosed = true; workQueue.clear(); //清空工作队列 interrupt(); //中断线程池中的所有的工作线程,此方法继承自ThreadGroup类 } } /** 等待工作线程把所有任务执行完毕*/ public void waitFinish() { synchronized (this) { isClosed = true; notifyAll(); //唤醒所有还在getTask()方法中等待任务的工作线程 } Thread[] threads = new Thread[activeCount()]; //activeCount() 返回该线程组中活动线程的估计值。 int count = enumerate(threads); //enumerate()方法继承自ThreadGroup类,根据活动线程的估计值获得线程组中当前所有活动的工作线程 for(int i =0; i < count; i++) { //等待所有工作线程结束 try { threads[i].join(); //等待工作线程结束 }catch(InterruptedException ex) { ex.printStackTrace(); } } } /** * 内部类,工作线程,负责从工作队列中取出任务,并执行 * @author sunnylocus */ private class WorkThread extends Thread { private int id; public WorkThread(int id) { //父类构造方法,将线程加入到当前ThreadPool线程组中 super(ThreadPool.this,id+""); this.id =id; } public void run() { while(! isInterrupted()) { //isInterrupted()方法继承自Thread类,判断线程是否被中断 Runnable task = null; try { task = getTask(id); //取出任务 }catch(InterruptedException ex) { ex.printStackTrace(); } //如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程 if(task == null) return; try { task.run(); //运行任务 }catch(Throwable t) { t.printStackTrace(); } }// end while }// end run }// end workThread } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/thread/ThreadPoolTest.java ================================================ package com.gome.clover.thread; import com.gome.clover.common.tools.HttpRequest; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 22:53 */ public class ThreadPoolTest { public static void main(String[] args) throws InterruptedException { ThreadPool threadPool = new ThreadPool(9); //创建一个有个30工作线程的线程池 //Thread.sleep(500); //休眠500毫秒,以便让线程池中的工作线程全部运行 //运行任务 for (int i = 0; i bufsize) { src.get(buf); return bufsize; } src.get(buf, 0, remaining); return remaining; } } public static DummyCtx ctx = new DummyCtx(); public static class DummyIOThread extends IOThread { public DummyIOThread() { super(ctx, 2); } } public static class DummySocket extends SocketBase { public DummySocket() { super(ctx, counter.get(), counter.get()); counter.incrementAndGet(); } @Override protected void xattach_pipe(Pipe pipe_, boolean icanhasall_) { } @Override protected void xterminated(Pipe pipe_) { } } public static class DummySession extends SessionBase { public List out = new ArrayList(); public DummySession() { this(new DummyIOThread(), false, new DummySocket(), new Options(), new Address("tcp", "localhost:9090", false)); } public DummySession(IOThread ioThread, boolean connect, SocketBase socket, Options options, Address addr) { super(ioThread, connect, socket, options, addr); } public int pushMsg(Msg msg) { System.out.println("session.write " + msg); out.add(msg); return 0; } public Msg pullMsg() { System.out.println("session.read " + out); if (out.size() == 0) { return null; } Msg msg = out.remove(0); return msg; } } public static void bounce(SocketBase sb, SocketBase sc) { byte[] content = "12345678ABCDEFGH12345678abcdefgh".getBytes(ZMQ.CHARSET); // Send the message. int rc = ZMQ.zmq_send(sc, content, 32, ZMQ.ZMQ_SNDMORE); assert (rc == 32); rc = ZMQ.zmq_send(sc, content, 32, 0); assertThat(rc, is(32)); // Bounce the message back. Msg msg; msg = ZMQ.zmq_recv(sb, 0); assert (msg.size() == 32); long rcvmore = ZMQ.zmq_getsockopt(sb, ZMQ.ZMQ_RCVMORE); assert (rcvmore == 1); msg = ZMQ.zmq_recv(sb, 0); assert (rc == 32); rcvmore = ZMQ.zmq_getsockopt(sb, ZMQ.ZMQ_RCVMORE); assert (rcvmore == 0); rc = ZMQ.zmq_send(sb, new Msg(msg), ZMQ.ZMQ_SNDMORE); assert (rc == 32); rc = ZMQ.zmq_send(sb, new Msg(msg), 0); assert (rc == 32); // Receive the bounced message. msg = ZMQ.zmq_recv(sc, 0); assert (rc == 32); rcvmore = ZMQ.zmq_getsockopt(sc, ZMQ.ZMQ_RCVMORE); assertThat(rcvmore , is(1L)); msg = ZMQ.zmq_recv(sc, 0); assert (rc == 32); rcvmore = ZMQ.zmq_getsockopt(sc, ZMQ.ZMQ_RCVMORE); assertThat(rcvmore , is(0L)); // Check whether the message is still the same. //assert (memcmp (buf2, content, 32) == 0); } public static void send(Socket sa, String data) throws IOException { byte[] content = data.getBytes(ZMQ.CHARSET); byte[] length = String.format("%04d", content.length).getBytes(ZMQ.CHARSET); byte[] buf = new byte[1024]; int reslen; int rc; // Bounce the message back. InputStream in = sa.getInputStream(); OutputStream out = sa.getOutputStream(); out.write(length); out.write(content); System.out.println("sent " + data.length() + " " + data); int toRead = 4; // 4 + greeting_size int read = 0; while (toRead > 0) { rc = in.read(buf, read, toRead); read += rc; toRead -= rc; System.out.println("read " + rc + " total_read " + read + " toRead " + toRead); } System.out.println(String.format("%02x %02x %02x %02x", buf[0], buf[1], buf[2], buf[3])); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } reslen = Integer.valueOf(new String(buf, 0, 4, ZMQ.CHARSET)); in.read(buf, 0, reslen); System.out.println("recv " + reslen + " " + new String(buf, 0, reslen, ZMQ.CHARSET)); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zeromq/Pub.java ================================================ package com.gome.clover.zeromq; import org.zeromq.ZMQ; import org.zeromq.ZMQ.Context; import org.zeromq.ZMQ.Socket; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/4 * Time: 20:28 */ public class Pub { public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub Context context = ZMQ.context(1); Socket publisher = context.socket(ZMQ.PUB); publisher.bind("tcp://*:5557"); publisher.send("B".getBytes(), ZMQ.SNDMORE); publisher.send("This is B".getBytes(), 0); /* int i = 0; while (true) { Thread.currentThread().sleep(1000); publisher.send("A".getBytes(), ZMQ.SNDMORE); publisher.send("This is A".getBytes(), 0); publisher.send("B".getBytes(), ZMQ.SNDMORE); publisher.send("This is B".getBytes(), 0); }*/ } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zeromq/Publisher.java ================================================ package com.gome.clover.zeromq; import org.zeromq.ZMQ; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Publisher * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class Publisher { public static void main(String args[]) { ZMQ.Context context = ZMQ.context(1); //创创建包含一个I/O线程的context ZMQ.Socket publisher = context.socket(ZMQ.PUB); //创建一个publisher类型的socket,他可以向所有订阅的subscriber广播数据 publisher.bind("tcp://127.0.0.1:5555"); //将当前publisher绑定到5555端口上,可以接受subscriber的订阅 while (!Thread.currentThread ().isInterrupted ()) { String message = "fjs hello"; //最开始可以理解为pub的channel,subscribe需要订阅fjs这个channel才能接收到消息 publisher.send(message.getBytes()); } publisher.close(); context.term(); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zeromq/RandomNum.java ================================================ package com.gome.clover.zeromq; import com.gome.clover.common.tools.RandomNumUtil; import org.junit.Test; import org.zeromq.ZMQ; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/4 * Time: 21:07 */ public class RandomNum { @Test public void testGetRandomNum(){ while (true){ System.err.println("ThreadLocalRandom.current().nextInt(0,65535) time:"+ RandomNumUtil.getNextLong()); } } @Test public void testConnection(){ ZMQ.Context context = ZMQ.context(1); ZMQ.Socket socket = context.socket(ZMQ.REP); socket.connect("tcp://127.0.0.1:6752"); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zeromq/Sub1.java ================================================ package com.gome.clover.zeromq; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/4 * Time: 20:29 */ import org.zeromq.ZMQ; import org.zeromq.ZMQ.Context; import org.zeromq.ZMQ.Socket; public class Sub1 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Context context = ZMQ.context(1); Socket subscribe = context.socket(ZMQ.SUB); subscribe.connect("tcp://127.0.0.1:5557"); subscribe.subscribe("B".getBytes()); while (true) { System.out.println(new String(subscribe.recv(0))); System.out.println(new String(subscribe.recv(0))); } } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zeromq/Subscriber.java ================================================ package com.gome.clover.zeromq; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Subscriber * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ import org.zeromq.ZMQ; public class Subscriber { public static void main(String args[]) { for (int j = 0; j < 100; j++) { new Thread(new Runnable(){ public void run() { // TODO Auto-generated method stub ZMQ.Context context = ZMQ.context(1); //创建1个I/O线程的上下文 ZMQ.Socket subscriber = context.socket(ZMQ.SUB); //创建一个sub类型,也就是subscriber类型的socket subscriber.connect("tcp://*:5555"); //与在5555端口监听的publisher建立连接 subscriber.subscribe("fjs".getBytes()); //订阅fjs这个channel for (int i = 0; i < 100; i++) { byte[] message = subscriber.recv(); //接收publisher发送过来的消息 System.out.println("receive : " + new String(message)); } subscriber.close(); context.term(); } }).start(); } } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zeromq/TestPubsubTcp.java ================================================ package com.gome.clover.zeromq; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/24 * Time: 18:18 */ import com.gome.clover.common.tools.IpUtil; import org.junit.Test; import zmq.Ctx; import zmq.Msg; import zmq.SocketBase; import zmq.ZMQ; public class TestPubsubTcp { @Test public void testPubsubTcp() throws Exception { Ctx ctx = ZMQ.zmq_init(1); SocketBase sb = ZMQ.zmq_socket(ctx, ZMQ.ZMQ_PUB); boolean rc = ZMQ.zmq_bind(sb, "tcp://127.0.0.1:7660"); SocketBase sc = ZMQ.zmq_socket(ctx, ZMQ.ZMQ_SUB); sc.setsockopt(ZMQ.ZMQ_SUBSCRIBE, IpUtil.getLocalIP()); rc = ZMQ.zmq_connect(sc, "tcp://127.0.0.1:7660"); ZMQ.zmq_sleep(2); sb.send(new Msg((IpUtil.getLocalIP()+" abc").getBytes(ZMQ.CHARSET)), 0); sb.send(new Msg("topix defg".getBytes(ZMQ.CHARSET)), 0); sb.send(new Msg("topic defgh".getBytes(ZMQ.CHARSET)), 0); Msg msg = sc.recv(0); System.err.println("msg1:"+new String(msg.data())); msg = sc.recv(0); System.err.println("msg2:"+new String(msg.data())); ZMQ.zmq_close(sc); ZMQ.zmq_close(sb); ZMQ.zmq_term(ctx); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zeromq/TestReqrepTcp.java ================================================ package com.gome.clover.zeromq; import org.junit.Test; import zmq.Ctx; import zmq.SocketBase; import zmq.ZMQ; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/25 * Time: 21:23 */ public class TestReqrepTcp { @Test public void testReqrepTcp() throws Exception { Ctx ctx = ZMQ.zmq_init(1); SocketBase sb = ZMQ.zmq_socket(ctx, ZMQ.ZMQ_REP); boolean rc = ZMQ.zmq_bind(sb, "tcp://127.0.0.1:7560"); SocketBase sc = ZMQ.zmq_socket(ctx, ZMQ.ZMQ_REQ); rc = ZMQ.zmq_connect(sc, "tcp://127.0.0.1:7560"); Helper.bounce(sb, sc); ZMQ.zmq_close(sc); ZMQ.zmq_close(sb); ZMQ.zmq_term(ctx); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zk/CuratorDemo.java ================================================ package com.gome.clover.zk; import com.gome.clover.common.zk.ZKUtil; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.api.CuratorWatcher; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import java.nio.charset.Charset; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/19 * Time: 15:13 */ public class CuratorDemo { private CuratorFramework zkTools; public void curatorDemo() throws Exception{ zkTools = ZKUtil.create(); zkTools.start(); /* zkTools.create()//创建一个路径 .creatingParentsIfNeeded()//如果指定的节点的父节点不存在,递归创建父节点 .withMode(CreateMode.PERSISTENT)//存储类型(临时的还是持久的) .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)//访问权限 .forPath("zk/test");//创建的路径*/ /* zkTools.//对路径节点赋值 setData(). forPath("zk/test","hello world".getBytes(Charset.forName("utf-8")));*/ byte[] buffer = zkTools. getData(). usingWatcher(new ZKWatch("/clover/server")).forPath("/clover/server"); //System.out.println(new String(buffer)); } public static void main(String[] args) throws Exception { CuratorDemo test = new CuratorDemo(); test.curatorDemo(); } public class ZKWatch implements CuratorWatcher { private final String path; public String getPath() { return path; } public ZKWatch(String path) { this.path = path; } @Override public void process(WatchedEvent event) throws Exception { if(event.getType() == Watcher.Event.EventType.NodeDataChanged){ byte[] data = zkTools.getData().forPath(path); System.out.println(path+":"+new String(data,Charset.forName("utf-8"))); } } } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zk/CuratorTest.java ================================================ package com.gome.clover.zk; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.api.CuratorWatcher; import org.apache.curator.framework.state.ConnectionState; import org.apache.curator.framework.state.ConnectionStateListener; import org.apache.curator.retry.RetryNTimes; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.data.Stat; import java.net.InetAddress; import java.nio.charset.Charset; import java.util.concurrent.ConcurrentSkipListSet; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/19 * Time: 13:04 */ public class CuratorTest { private CuratorFramework zkTools; private ConcurrentSkipListSet watchers = new ConcurrentSkipListSet(); private static Charset charset = Charset.forName("utf-8"); public CuratorTest() { zkTools = CuratorFrameworkFactory .builder() .connectString("10.126.53.170:2181") .namespace("zk/test") .retryPolicy(new RetryNTimes(2000,20000)) .build(); zkTools.start(); } public void addReconnectionWatcher(final String path,final ZookeeperWatcherType watcherType,final CuratorWatcher watcher){ synchronized (this) { if(!watchers.contains(watcher.toString()))//不要添加重复的监听事件 { watchers.add(watcher.toString()); System.out.println("add new watcher " + watcher); zkTools.getConnectionStateListenable().addListener(new ConnectionStateListener() { @Override public void stateChanged(CuratorFramework client, ConnectionState newState) { System.out.println(newState); if(newState == ConnectionState.LOST){//处理session过期 try{ if(watcherType == ZookeeperWatcherType.EXITS){ zkTools.checkExists().usingWatcher(watcher).forPath(path); }else if(watcherType == ZookeeperWatcherType.GET_CHILDREN){ zkTools.getChildren().usingWatcher(watcher).forPath(path); }else if(watcherType == ZookeeperWatcherType.GET_DATA){ zkTools.getData().usingWatcher(watcher).forPath(path); }else if(watcherType == ZookeeperWatcherType.CREATE_ON_NO_EXITS){ //ephemeral类型的节点session过期了,需要重新创建节点,并且注册监听事件,之后监听事件中, //会处理create事件,将路径值恢复到先前状态 Stat stat = zkTools.checkExists().usingWatcher(watcher).forPath(path); if(stat == null){ System.err.println("to create"); zkTools.create() .creatingParentsIfNeeded() .withMode(CreateMode.EPHEMERAL) .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) .forPath(path); } } }catch (Exception e) { e.printStackTrace(); } } } }); } } } public void create() throws Exception{ zkTools.create()//创建一个路径 .creatingParentsIfNeeded()//如果指定的节点的父节点不存在,递归创建父节点 .withMode(CreateMode.PERSISTENT)//存储类型(临时的还是持久的) .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)//访问权限 .forPath("/zk/test");//创建的路径 } public void put() throws Exception{ zkTools.//对路径节点赋值 setData(). forPath("/zk/test","hello world".getBytes(Charset.forName("utf-8"))); } public void get() throws Exception{ String path = "/zk/test"; ZKWatch watch = new ZKWatch(path); byte[] buffer = zkTools. getData(). usingWatcher(watch).forPath(path); System.out.println(new String(buffer,charset)); //添加session过期的监控 addReconnectionWatcher(path, ZookeeperWatcherType.GET_DATA, watch); } public void register() throws Exception{ String ip = InetAddress.getLocalHost().getHostAddress(); String registeNode = "/zk/register/"+ip;//节点路径 byte[] data = "disable".getBytes(charset);//节点值 CuratorWatcher watcher = new ZKWatchRegister(registeNode,data); //创建一个register watcher Stat stat = zkTools.checkExists().forPath(registeNode); if(stat != null){ zkTools.delete().forPath(registeNode); } zkTools.create() .creatingParentsIfNeeded() .withMode(CreateMode.EPHEMERAL) .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) .forPath(registeNode,data);//创建的路径和值 //添加到session过期监控事件中 addReconnectionWatcher(registeNode, ZookeeperWatcherType.CREATE_ON_NO_EXITS,watcher); data = zkTools.getData().usingWatcher(watcher).forPath(registeNode); System.out.println("get path form zk : "+registeNode+":"+new String(data,charset)); } public static void main(String[] args) throws Exception { CuratorTest test = new CuratorTest(); test.create(); test.put(); test.get(); // test.register(); Thread.sleep(10000000000L); } public class ZKWatch implements CuratorWatcher{ private final String path; public String getPath() { return path; } public ZKWatch(String path) { this.path = path; } @Override public void process(WatchedEvent event) throws Exception { System.out.println(event.getType()); if(event.getType() == Watcher.Event.EventType.NodeDataChanged){ byte[] data = zkTools. getData(). usingWatcher(this).forPath(path); System.out.println(path+":"+new String(data,Charset.forName("utf-8"))); } } } public class ZKWatchRegister implements CuratorWatcher{ private final String path; private byte[] value; public String getPath() { return path; } public ZKWatchRegister(String path,byte[] value) { this.path = path; this.value = value; } @Override public void process(WatchedEvent event) throws Exception { System.out.println(event.getType()); if(event.getType() == Watcher.Event.EventType.NodeDataChanged){ //节点数据改变了,需要记录下来,以便session过期后,能够恢复到先前的数据状态 byte[] data = zkTools. getData(). usingWatcher(this).forPath(path); value = data; System.out.println(path+":"+new String(data,charset)); }else if(event.getType() == Watcher.Event.EventType.NodeDeleted){ //节点被删除了,需要创建新的节点 System.out.println(path + ":" + path +" has been deleted."); Stat stat = zkTools.checkExists().usingWatcher(this).forPath(path); if(stat == null){ zkTools.create() .creatingParentsIfNeeded() .withMode(CreateMode.EPHEMERAL) .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) .forPath(path); } }else if(event.getType() == Watcher.Event.EventType.NodeCreated){ //节点被创建时,需要添加监听事件(创建可能是由于session过期后,curator的状态监听部分触发的) System.out.println(path + ":" +" has been created!" + "the current data is " + new String(value)); zkTools.setData().forPath(path, value); zkTools.getData().usingWatcher(this).forPath(path); } } } public enum ZookeeperWatcherType{ GET_DATA,GET_CHILDREN,EXITS,CREATE_ON_NO_EXITS } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zk/MonitorServerZKListener.java ================================================ package com.gome.clover.zk; import com.gome.clover.common.zk.ZKUtil; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.api.CuratorEvent; import org.apache.curator.framework.api.CuratorListener; import org.apache.curator.framework.api.CuratorWatcher; import org.apache.curator.framework.state.ConnectionState; import org.apache.curator.framework.state.ConnectionStateListener; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.data.Stat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.charset.Charset; import java.util.concurrent.ConcurrentSkipListSet; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/19 * Time: 12:11 */ public class MonitorServerZKListener implements CuratorListener,ConnectionStateListener { protected static Logger logger = LoggerFactory.getLogger(MonitorServerZKListener.class); private CuratorFramework zkTools; private ConcurrentSkipListSet watchers = new ConcurrentSkipListSet(); private static Charset charset = Charset.forName("utf-8"); private String prefixPath; public MonitorServerZKListener(String prefixPath) { this.prefixPath= prefixPath; zkTools = ZKUtil.create(); zkTools.start(); CuratorWatcher watcher = new ZKWatchRegister(prefixPath); //创建一个register watcher addReconnectionWatcher(prefixPath, ZookeeperWatcherType.CREATE_ON_NO_EXITS,watcher); this.zkTools.getConnectionStateListenable().addListener(this); this.zkTools.getCuratorListenable().addListener(this); byte[] data = new byte[0]; try { zkTools.getData().usingWatcher(watcher); //data = zkTools.getData().usingWatcher(watcher).forPath(prefixPath); } catch (Exception e) { e.printStackTrace(); } System.out.println("get path form zk : "+prefixPath+":"+new String(data,charset)); } public void addReconnectionWatcher(final String path,final ZookeeperWatcherType watcherType,final CuratorWatcher watcher){ synchronized (this) { if(!watchers.contains(watcher.toString()))//不要添加重复的监听事件 { watchers.add(watcher.toString()); System.out.println("add new watcher " + watcher); zkTools.getConnectionStateListenable().addListener(new ConnectionStateListener() { @Override public void stateChanged(CuratorFramework client, ConnectionState newState) { System.out.println(newState); if(newState == ConnectionState.LOST){//处理session过期 try{ if(watcherType == ZookeeperWatcherType.EXITS){ zkTools.checkExists().usingWatcher(watcher).forPath(path); }else if(watcherType == ZookeeperWatcherType.GET_CHILDREN){ zkTools.getChildren().usingWatcher(watcher).forPath(path); }else if(watcherType == ZookeeperWatcherType.GET_DATA){ zkTools.getData().usingWatcher(watcher).forPath(path); }else if(watcherType == ZookeeperWatcherType.CREATE_ON_NO_EXITS){ //ephemeral类型的节点session过期了,需要重新创建节点,并且注册监听事件,之后监听事件中, //会处理create事件,将路径值恢复到先前状态 Stat stat = zkTools.checkExists().usingWatcher(watcher).forPath(path); if(stat == null){ System.err.println("to create"); zkTools.create() .creatingParentsIfNeeded() .withMode(CreateMode.EPHEMERAL) .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) .forPath(path); } } }catch (Exception e) { e.printStackTrace(); } } } }); } } } @Override public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception { } @Override public void stateChanged(CuratorFramework client, ConnectionState newState) { } public class ZKWatchRegister implements CuratorWatcher{ private final String path; private byte[] value; public String getPath() { return path; } public ZKWatchRegister(String path) { this.path = path; } @Override public void process(WatchedEvent event) throws Exception { System.out.println(event.getType()); if(event.getType() == Watcher.Event.EventType.NodeDataChanged){ //节点数据改变了,需要记录下来,以便session过期后,能够恢复到先前的数据状态 byte[] data = zkTools. getData(). usingWatcher(this).forPath(path); value = data; System.out.println(path+":"+new String(data,charset)); }else if(event.getType() == Watcher.Event.EventType.NodeDeleted){ //节点被删除了,需要创建新的节点 System.out.println(path + ":" + path +" has been deleted."); Stat stat = zkTools.checkExists().usingWatcher(this).forPath(path); if(stat == null){ zkTools.create() .creatingParentsIfNeeded() .withMode(CreateMode.EPHEMERAL) .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) .forPath(path); } }else if(event.getType() == Watcher.Event.EventType.NodeCreated){ //节点被创建时,需要添加监听事件(创建可能是由于session过期后,curator的状态监听部分触发的) System.out.println(path + ":" +" has been created!" + "the current data is " + new String(value)); zkTools.setData().forPath(path, value); zkTools.getData().usingWatcher(this).forPath(path); } } } public enum ZookeeperWatcherType{ GET_DATA,GET_CHILDREN,EXITS,CREATE_ON_NO_EXITS } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zk/SyncServer.java ================================================ package com.gome.clover.zk; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.zk.ZKConnect; import org.junit.Test; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Sync Server * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/18 * Time: 22:25 */ public class SyncServer { public static void main(String[] args) { MonitorServerZKListener monitorServerZKListener = new MonitorServerZKListener(CommonConstants.ZK_ROOT_PATH + "/server"); // zkConnect.addListener(monitorServerZKListener); //monitorServerZKListener.reload(); } @Test public void test1(){ ZKConnect zkConnect = new ZKConnect(); if ((zkConnect == null) || (!zkConnect.start())) { } //MonitorServerZKListener monitorServerZKListener = new MonitorServerZKListener(CommonConstants.ZK_ROOT_PATH + "/server",zkConnect); //zkConnect.addListener(monitorServerZKListener); // monitorServerZKListener.reload(); } } ================================================ FILE: clover/clover-examples/src/main/java/com/gome/clover/zk/TestZK.java ================================================ package com.gome.clover.zk; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.PropertiesUtil; import com.gome.clover.common.zeromq.ZeroMQPull; import com.gome.clover.common.zk.ZKManager; import org.junit.Test; import java.util.List; /** * Module Desc: * User: wangyue-ds6 * Date: 2014/11/19 * Time: 15:14 */ public class TestZK { @Test public void testServerDelete(){ try { ZKManager zkManager = new ZKManager(PropertiesUtil.loadProperties()); String pathStr = zkManager.getRootPath() + "/server/ip"; zkManager.delete(pathStr); } catch (Exception e) { e.printStackTrace(); } } @Test public void testClientDelete(){ try { ZKManager zkManager = new ZKManager(PropertiesUtil.loadProperties()); String pathStr = zkManager.getRootPath() + "/client"; zkManager.delete(pathStr); } catch (Exception e) { e.printStackTrace(); } } @Test public void testGetAllData(){ try { ZKManager zkManager = new ZKManager(PropertiesUtil.loadProperties()); String pathStr = zkManager.getRootPath() + "/" + CommonConstants.MODULE_TYPE_CLIENT ; List childrenListStr = zkManager.getZooKeeper().getChildren(pathStr, false); System.err.println("childrenListStr:"+childrenListStr); } catch (Exception e) { e.printStackTrace(); } } @Test public void testGet() throws InterruptedException { synchronized (Object.class){ Thread.sleep(100000); String addr = "tcp://*:" + CommonConstants.ZMQ_SERVER_PORT; ZeroMQPull.INSTANCE.recv(addr); } System.err.println("zkString:"+CommonConstants.ZK_CONNECT_STRING); } } ================================================ FILE: clover/clover-monitor/pom.xml ================================================ 4.0.0 com.gome clover 1.0 com.gome clover-monitor ${clover.version} jar clover-monitor-${clover.version} src/main/resources true com.gome clover-core ${clover.version} junit junit 4.11 compile ================================================ FILE: clover/clover-monitor/src/main/java/com/gome/clover/monitor/MonitorHeartBeat.java ================================================ package com.gome.clover.monitor; import com.gome.clover.common.hash.HashTimes; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.SendMailUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.common.zeromq.AsyncSendMsg; import com.gome.clover.common.zeromq.ZeroMQEntity; import com.gome.clover.common.zk.CommonNodes; import com.gome.clover.common.zk.ZKUtil; import com.mongodb.*; import com.mongodb.util.JSON; import org.apache.curator.framework.CuratorFramework; import java.util.List; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Monitor Server Heart Beat * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum MonitorHeartBeat { INSTNACE, MonitorHeartBeat; private BasicDBList recordDBList = new BasicDBList(); private BasicDBList serverNodeDBList; private static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor; private static boolean isStop = false; private static int counter = 0; private static CuratorFramework curatorFramework = ZKUtil.create(); public void startup() { if(null==scheduledThreadPoolExecutor){ scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); } scheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() { @Override public void run() { if (!isStop) { if (!curatorFramework.isStarted()) curatorFramework.start(); String serverPathStr = CommonConstants.ZK_ROOT_PATH + "/" + CommonConstants.MODULE_TYPE_SERVER; List serverNodeList = ZKUtil.getChilds(curatorFramework, serverPathStr); if (null != serverNodeList && serverNodeList.size() > 0) { addOrUpdateRecordList(curatorFramework, serverPathStr, serverNodeList); BasicDBList needRemoveNodeList = new BasicDBList(); int index = 0; filterNeedRemoveNodeList(needRemoveNodeList, index); index = 0; transferServerData(needRemoveNodeList, index); } else { if(0==counter){ int index = 0; while (index < recordDBList.size()) { BasicDBObject record = (BasicDBObject) recordDBList.get(index); String msg = " Server of Ip:" + record.get("ip") + " not alive,Please deal with as quickly as possible"; //报警通知相关人员 SendMailUtil.sendDefaultMail(msg, msg); index++; } counter = 1; } } } } }, CommonConstants.MONITOR_DIFFER_MILLI_SECONDS, CommonConstants.MONITOR_DIFFER_MILLI_SECONDS, TimeUnit.MILLISECONDS); } private void transferServerData(BasicDBList needRemoveNodeList, int index) { while (index < needRemoveNodeList.size()) { BasicDBObject needRemoveNode = (BasicDBObject) needRemoveNodeList.get(index); String removeNodeIp = (String) needRemoveNode.get("ip"); if (!StringUtil.isEmpty(removeNodeIp)) { DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_CLIENT_IP, removeNodeIp); condition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_REMOTE); DBCursor cursorDocMap = dbCollection.find(condition); while (cursorDocMap.hasNext()) { DBObject tempDBObject = cursorDocMap.next(); String hashKey = CommonNodes.allocateNo(); int tempIndex = HashTimes.use33(hashKey) % recordDBList.size(); BasicDBObject tempRecord = (BasicDBObject) recordDBList.get(tempIndex); String newNodeIp = (String) tempRecord.get("ip"); if (MongoDBUtil.INSTANCE.update(new BasicDBObject(DBTableInfo.COL_ID, tempDBObject.get(DBTableInfo.COL_ID)), new BasicDBObject(DBTableInfo.COL_CLIENT_IP, newNodeIp), DBTableInfo.TBL_CLOVER_JOB)) { //发消息到SERVER String newNodePort = (String) tempRecord.get("port"); BasicDBObject basicDBObject = new BasicDBObject(); basicDBObject.put("action", "reloadDB"); basicDBObject.put("ip", newNodeIp); String msg = JSON.serialize(basicDBObject); ZeroMQEntity zeroMQEntity = new ZeroMQEntity(CommonConstants.MODULE_TYPE_SERVER_WITH_MONITOR, newNodeIp, null, msg); // AsyncSendMsg.send(newNodeIp, newNodePort, com.alibaba.fastjson.JSON.toJSONString(zeroMQEntity)); } } } index++; } } private void filterNeedRemoveNodeList(BasicDBList needRemoveNodeList, int index) { while (index < this.recordDBList.size()) { BasicDBObject tempRecord = (BasicDBObject) this.recordDBList.get(index); if (!serverNodeDBList.contains(tempRecord)) { needRemoveNodeList.add(tempRecord); remove((String) tempRecord.get("id"), this.recordDBList); } index++; } serverNodeDBList.clear(); } private void addOrUpdateRecordList(CuratorFramework curatorFramework, String serverPathStr, List serverNodeList) { for (int i = 0; (serverNodeList != null) && (i < serverNodeList.size()); i++) { String id = (String) serverNodeList.get(i); String c = ZKUtil.getData(curatorFramework, serverPathStr + "/" + id); if (c == null) { continue; } //c 是否在recordList中存在,如果不存在,那就认为c节点信息已不存了,此刻要将c节点中所有job同步到另一台机器中 BasicDBObject record = (BasicDBObject) JSON.parse(c); add(record, recordDBList); //add or update serverNodeDBList = new BasicDBList(); add(record, serverNodeDBList); //add or update } } public synchronized void add(BasicDBObject record, BasicDBList dBList) { String id = record.getString("id"); int index = CommonNodes.findIndexById(id, dBList); if (index == -1) dBList.add(record); else { dBList.set(index, record); } } public synchronized boolean remove(String id, BasicDBList dBList) { int index = CommonNodes.findIndexById(id, dBList); return null != dBList.remove(index); } public void stop() { counter = 0; isStop = true; curatorFramework.close(); scheduledThreadPoolExecutor.shutdown(); } public static void main(String args[]) { MonitorHeartBeat.INSTNACE.startup(); try { TimeUnit.MINUTES.sleep(4L); } catch (InterruptedException e) { e.printStackTrace(); } MonitorHeartBeat.INSTNACE.stop(); } } ================================================ FILE: clover/clover-monitor/src/main/java/com/gome/clover/monitor/MonitorTimerTask.java ================================================ package com.gome.clover.monitor; import com.alibaba.fastjson.JSON; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.*; import com.gome.clover.common.zk.ZKManager; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TimerTask; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Monitor Server Timer Task * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class MonitorTimerTask extends TimerTask { private static final Logger logger = LoggerFactory.getLogger(MonitorTimerTask.class); @Override public void run() { ZKManager zkManager = null; try { zkManager = new ZKManager(PropertiesUtil.loadProperties()); processServerMonitor(zkManager); processClientMonitor(zkManager); } catch (Exception e) { if (logger.isDebugEnabled()) e.printStackTrace(); System.err.println("MonitorServerTask-->>run() error" + e.getMessage()); logger.error("MonitorServerTask-->>run() error", e); } finally { assert null != zkManager; try { zkManager.close(); } catch (InterruptedException e) { if (logger.isDebugEnabled()) e.printStackTrace(); System.err.println("MonitorServerTask-->>run() zkManager.close() error" + e.getMessage()); logger.error("MonitorServerTask-->>run() zkManager.close() error", e); } } } private void processServerMonitor(ZKManager zkManager) { String serverPathStr = zkManager.getRootPath() + "/" + CommonConstants.MODULE_TYPE_SERVER + "/ip"; String serverDataJsonStr; try { serverDataJsonStr = zkManager.getData(serverPathStr); if (StringUtil.isEmpty(serverDataJsonStr)) return; List serverDataList = List2StringUtil.json2List(serverDataJsonStr); String remoteServerDataStr = null; for (String tempServerDataStr : serverDataList) { String[] tempSplitServerDatas = tempServerDataStr.split(CommonConstants.SPLIT_CHARACTER_FALG); Long clientLastUpdateTimeMillis = Long.valueOf(tempSplitServerDatas[2]); Long currentTimeMillis = System.currentTimeMillis(); //系统时间 if (currentTimeMillis - clientLastUpdateTimeMillis > CommonConstants.SERVER_DIFFER_MILLI_SECONDS || clientLastUpdateTimeMillis - currentTimeMillis > CommonConstants.SERVER_DIFFER_MILLI_SECONDS) { String msg = " Server of Ip:" + tempSplitServerDatas[0] + " not alive,Please deal with as quickly as possible"; System.err.println(msg); logger.error(msg); //报警通知相关人员 SendMailUtil.sendDefaultMail(msg, msg); remoteServerDataStr = tempServerDataStr+":"; } } if(!StringUtil.isEmpty(remoteServerDataStr)){ String removeServerDataStrs[] = remoteServerDataStr.split(":"); for(String tempRemoveServerData:removeServerDataStrs){ if(!StringUtil.isEmpty(tempRemoveServerData)){ serverDataList.remove(tempRemoveServerData); } } } if (null != serverDataList && serverDataList.size() > 0) { zkManager.setData(serverPathStr, JSON.toJSONString(serverDataList));// /clover/client/ip/127.0.0.1/{alive=1, ip=127.0.0.1} } else { zkManager.delete(serverPathStr); } } catch (Exception e) { System.err.println(e.getMessage()); } } private void processClientMonitor(ZKManager zkManager) throws Exception { String pathStr = zkManager.getRootPath() + "/" + CommonConstants.MODULE_TYPE_CLIENT + "/ip"; List childrenIpStrList = zkManager.getZooKeeper().getChildren(pathStr, false); Map clientMap; if (null != childrenIpStrList && childrenIpStrList.size() > 0) { for (String childrenIpStr : childrenIpStrList) { String dataJsonStr = zkManager.getData(pathStr + "/" + childrenIpStr); if (!StringUtil.isEmpty(dataJsonStr)) { clientMap = JSON.parseObject(dataJsonStr, Map.class); Long clientLastUpdateTimeMillis = Long.valueOf(clientMap.get(DBTableInfo.COL_TS)); Long currentTimeMillis = System.currentTimeMillis(); //系统时间 if (currentTimeMillis - clientLastUpdateTimeMillis > CommonConstants.CLIENT_DIFFER_MILLI_SECONDS || clientLastUpdateTimeMillis - currentTimeMillis > CommonConstants.CLIENT_DIFFER_MILLI_SECONDS) { System.err.println("Client Job of Ip:" + clientMap.get(DBTableInfo.COL_IP) + " not alive,Please deal with as quickly as possible"); String msg = "Client Job of Ip:" + clientMap.get(DBTableInfo.COL_IP) + " not alive,Please deal with as quickly as possible"; logger.error(msg); //报警通知相关人员 alert(clientMap.get(DBTableInfo.COL_IP), msg); clientMap.put(CommonConstants.ALIVE, CommonConstants.ALIVE_STATUS_0); String clientPathStr = zkManager.getRootPath() + "/" + CommonConstants.MODULE_TYPE_CLIENT + "/ip/" + clientMap.get(DBTableInfo.COL_IP); zkManager.setData(clientPathStr, JSON.toJSONString(clientMap));// /clover/client/ip/127.0.0.1/{alive=1, ip=127.0.0.1} } } } } } private void alert(String ip, String msg) { //发送邮件通知相关人员 List toList = new ArrayList(); DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_CONTACT); DBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_IP, ip); DBCursor cursorDocMap = dbCollection.find(condition); while (cursorDocMap.hasNext()) { DBObject tempDBObject = cursorDocMap.next(); List2StringUtil.addUnDuplicateString2List((String) tempDBObject.get(DBTableInfo.COL_IP), toList); } List2StringUtil.addUnDuplicateString2List(CommonConstants.DEFAULT_COMPANY_EMAIL, toList); List2StringUtil.addUnDuplicateString2List(CommonConstants.DEFAULT_PRIVATE_EMAIL, toList); SendMailUtil.sendMails(List2StringUtil.listToArray(toList), msg, msg); } } ================================================ FILE: clover/clover-monitor/src/main/java/com/gome/clover/monitor/ServerHeartBeatBak.java ================================================ package com.gome.clover.monitor; import com.gome.clover.common.tools.CommonConstants; import com.mongodb.BasicDBList; import java.util.Timer; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc: Server Heart Beat * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public enum ServerHeartBeatBak { INSTNACE, ServerHeartBeat; public void startup(){ Timer timer = new Timer(); BasicDBList recordList = new BasicDBList(); timer.schedule(new ServerTimerTask(recordList),CommonConstants.SERVER_DIFFER_MILLI_SECONDS, CommonConstants.SERVER_DIFFER_MILLI_SECONDS); } public static void main(String args[]){ ServerHeartBeat.INSTNACE.startup(); } } ================================================ FILE: clover/clover-monitor/src/main/java/com/gome/clover/monitor/ServerTimerTask.java ================================================ package com.gome.clover.monitor; import com.gome.clover.common.hash.HashTimes; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.SendMailUtil; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.common.zeromq.AsyncSendMsg; import com.gome.clover.common.zeromq.ZeroMQEntity; import com.gome.clover.common.zk.CommonNodes; import com.gome.clover.common.zk.ZKUtil; import com.mongodb.*; import com.mongodb.util.JSON; import org.apache.curator.framework.CuratorFramework; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.TimerTask; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc: Server Timer Task(所有server不可用,报警;集群部署多台集群,某台不可用,将数据转移到另一台集群) * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class ServerTimerTask extends TimerTask { private static final Logger logger = LoggerFactory.getLogger(ServerTimerTask.class); private BasicDBList recordDBList; private BasicDBList serverNodeDBList; public ServerTimerTask(BasicDBList recordDBList) { this.recordDBList = recordDBList; } @Override public void run() { CuratorFramework curatorFramework = ZKUtil.create(); if (!curatorFramework.isStarted()) curatorFramework.start(); String serverPathStr = CommonConstants.ZK_ROOT_PATH + "/" + CommonConstants.MODULE_TYPE_SERVER; List serverNodeList = ZKUtil.getChilds(curatorFramework, serverPathStr); if (null != serverNodeList && serverNodeList.size() > 0) { addOrUpdateRecordList(curatorFramework, serverPathStr, serverNodeList); BasicDBList needRemoveNodeList = new BasicDBList(); int index = 0; filterNeedRemoveNodeList(needRemoveNodeList, index); index = 0; transferServerData(needRemoveNodeList, index); } else { int index = 0; while (index < this.recordDBList.size()) { BasicDBObject record = (BasicDBObject) this.recordDBList.get(index); String msg = " Server of Ip:" + record.get("ip") + " not alive,Please deal with as quickly as possible"; //报警通知相关人员 SendMailUtil.sendDefaultMail(msg, msg); index++; } } } private void transferServerData(BasicDBList needRemoveNodeList, int index) { while (index < needRemoveNodeList.size()) { BasicDBObject needRemoveNode = (BasicDBObject) needRemoveNodeList.get(index); String removeNodeIp = (String) needRemoveNode.get("ip"); if (!StringUtil.isEmpty(removeNodeIp)) { DBCollection dbCollection = MongoDBUtil.INSTANCE.getCollection(DBTableInfo.TBL_CLOVER_JOB); DBObject condition = new BasicDBObject(); condition.put(DBTableInfo.COL_CLIENT_IP, removeNodeIp); condition.put(DBTableInfo.COL_JOB_TYPE, CommonConstants.JOB_TYPE_REMOTE); DBCursor cursorDocMap = dbCollection.find(condition); while (cursorDocMap.hasNext()) { DBObject tempDBObject = cursorDocMap.next(); String hashKey = CommonNodes.allocateNo(); int tempIndex = HashTimes.use33(hashKey) % recordDBList.size(); BasicDBObject tempRecord = (BasicDBObject) recordDBList.get(tempIndex); String newNodeIp = (String) tempRecord.get("ip"); if (MongoDBUtil.INSTANCE.update(new BasicDBObject(DBTableInfo.COL_ID, tempDBObject.get(DBTableInfo.COL_ID)), new BasicDBObject(DBTableInfo.COL_CLIENT_IP, newNodeIp), DBTableInfo.TBL_CLOVER_JOB)) { //发消息到SERVER String newNodePort = (String) tempRecord.get("port"); BasicDBObject basicDBObject = new BasicDBObject(); basicDBObject.put("action", "reloadDB"); basicDBObject.put("ip", newNodeIp); String msg = JSON.serialize(basicDBObject); ZeroMQEntity zeroMQEntity = new ZeroMQEntity(CommonConstants.MODULE_TYPE_SERVER_WITH_MONITOR, newNodeIp, null, msg); //AsyncSendMsg.send(newNodeIp, newNodePort, com.alibaba.fastjson.JSON.toJSONString(zeroMQEntity)); } } } index++; } } private void filterNeedRemoveNodeList(BasicDBList needRemoveNodeList, int index) { while (index < this.recordDBList.size()) { BasicDBObject tempRecord = (BasicDBObject) this.recordDBList.get(index); if (!serverNodeDBList.contains(tempRecord)) { needRemoveNodeList.add(tempRecord); remove((String) tempRecord.get("id"), this.recordDBList); } index++; } serverNodeDBList.clear(); } private void addOrUpdateRecordList(CuratorFramework curatorFramework, String serverPathStr, List serverNodeList) { for (int i = 0; (serverNodeList != null) && (i < serverNodeList.size()); i++) { String id = (String) serverNodeList.get(i); String c = ZKUtil.getData(curatorFramework, serverPathStr + "/" + id); if (c == null) { continue; } //c 是否在recordList中存在,如果不存在,那就认为c节点信息已不存了,此刻要将c节点中所有job同步到另一台机器中 BasicDBObject record = (BasicDBObject) JSON.parse(c); add(record, recordDBList); //add or update serverNodeDBList = new BasicDBList(); add(record, serverNodeDBList); //add or update } } public synchronized void add(BasicDBObject record, BasicDBList dBList) { String id = record.getString("id"); int index = CommonNodes.findIndexById(id, dBList); if (index == -1) dBList.add(record); else { dBList.set(index, record); } } public synchronized boolean remove(String id, BasicDBList dBList) { int index = CommonNodes.findIndexById(id, dBList); return null != dBList.remove(index); } } ================================================ FILE: clover/clover-server/pom.xml ================================================ 4.0.0 com.gome clover 1.0 com.gome clover-server ${clover.version} jar clover-server-${clover.version} src/main/resources true com.gome clover-core ${clover.version} com.gome clover-monitor ${clover.version} com.gome clover-client ${clover.version} javax.servlet servlet-api 2.4 provided ================================================ FILE: clover/clover-server/src/main/java/com/gome/clover/server/module/SchedulerServerInitial.java ================================================ package com.gome.clover.server.module; import com.gome.clover.common.mongodb.BuildMongoDBData; import com.gome.clover.common.mongodb.DBTableInfo; import com.gome.clover.common.mongodb.MongoDBUtil; import com.gome.clover.common.tools.CommonConstants; import com.gome.clover.common.tools.StringUtil; import com.gome.clover.core.module.ModuleSchedulerServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc: Scheduler 服务端 初始化 Servlet * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/21 * Time: 14:27 */ public class SchedulerServerInitial extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(SchedulerServerInitial.class); @Override public void init(ServletConfig config) throws ServletException { //super.init(config); String systemId = config.getInitParameter("systemId"); if(StringUtil.isEmpty(systemId)) systemId = CommonConstants.SYSTEM_ID_CLOVER; boolean isRegisterToZK = true; //默认是启动的 String isRegisterToZKStr = config.getInitParameter("isRegisterToZK"); if(!StringUtil.isEmpty(isRegisterToZKStr)){ isRegisterToZK = Boolean.valueOf(isRegisterToZKStr); } boolean isStartupMQ = true; //默认是启动的 boolean isStartupNetty = true; //默认是启动的 String isStartupMQStr = config.getInitParameter("isStartupMQ"); if(!StringUtil.isEmpty(isStartupMQStr)){ isStartupMQ = Boolean.valueOf(isStartupMQStr); } boolean isReloadJobFromDB = true; //默认是启动的 String isReloadJobFromDBStr = config.getInitParameter("isReloadJobFromDB"); if(!StringUtil.isEmpty(isReloadJobFromDBStr)){ isReloadJobFromDB = Boolean.valueOf(isReloadJobFromDBStr); } try { ModuleSchedulerServer server = ModuleSchedulerServer.getInstance(); server.startup(isRegisterToZK,isStartupMQ,isStartupNetty,isReloadJobFromDB,systemId); } catch (Exception e) { String execMethod = "ModuleSchedulerServer-->>init(config)"; String execResult = "ModuleSchedulerServer-->>init(config) error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); System.err.println("SchedulerServerInitial-->>init(config) error ,"+e.getMessage()); throw new RuntimeException(e); } logger.info("SchedulerServerInitial-->>init(config)......"); } @Override public void init() throws ServletException { super.init(); try { ModuleSchedulerServer server = ModuleSchedulerServer.getInstance(); server.startup(); } catch (Exception e) { String execMethod = "ModuleSchedulerServer-->>init()"; String execResult = "ModuleSchedulerServer-->>init() error ," + e.getMessage(); MongoDBUtil.INSTANCE.insert(BuildMongoDBData.getInsertLogBasicDBObject("", execMethod, execResult), DBTableInfo.TBL_CLOVER_LOG); System.err.println("SchedulerServerInitial-->>init() error ,"+e.getMessage()); } logger.info("SchedulerServerInitial-->>init()......"); } } ================================================ FILE: clover/pom.xml ================================================ 4.0.0 com.gome clover 1.0 pom clover clover-common clover-core clover-client clover-server clover-admin clover-monitor clover-examples 1.6 UTF-8 UTF-8 3.2.4.RELEASE true true true dev true src/main/resources/dev 1.0.dev-SNAPSHOT dev 10.58.50.206:2181,10.58.50.207:2181,10.58.50.208:2181 /clover 30000 cloverAdmin password 10.58.50.134:27077,10.58.50.133:27077 spec_pub user_spec_pub SrVlPrIGgu7ZM2Ox 100 10 180000 30000 true false 180000 10.58.50.208 6379 500 20 1000 10.58.50.208 xiaoxiangxu@yolo24.com zhutouzan@163.com 6fb8535d703f2492704aefc212b7cd41 sit false src/main/resources/sit 1.0.sit-SNAPSHOT dev 10.58.50.206:2181,10.58.50.207:2181,10.58.50.208:2181 /clover 30000 cloverAdmin password 10.126.53.42:27067,10.126.53.42:27068 clover user_clover user_clover_pass 100 10 180000 30000 true false 180000 10.58.50.208 6379 500 20 1000 10.58.50.208 xiaoxiangxu@yolo24.com stark_summer@qq.com 6fb8535d703f2492704aefc212b7cd41 uat false src/main/resources/uat 1.0.uat-SNAPSHOT uat 10.58.50.203:2181,10.58.50.204:2181,10.58.50.205:2181 /clover 30000 cloverAdmin password 10.126.53.38:27067,10.126.53.38:27068 clover user_clover user_clover_pass 100 10 180000 30000 true false 180000 10.58.50.208 6379 500 20 1000 10.58.50.208 xiaoxiangxu@yolo24.com stark_summer@qq.com 6fb8535d703f2492704aefc212b7cd41 pre false src/main/resources/dev 1.0.dev-SNAPSHOT dev 10.58.50.206:2181,10.58.50.207:2181,10.58.50.208:2181 /clover 30000 cloverAdmin password 10.126.45.45:27067,10.126.45.45:27068 clover user_clover user_clover_pass 100 10 180000 30000 true false 180000 10.58.50.208 6379 500 20 1000 10.58.50.208 xiaoxiangxu@yolo24.com stark_summer@qq.com 6fb8535d703f2492704aefc212b7cd41 prd false src/main/resources/dev 1.0.dev-SNAPSHOT dev 10.58.50.206:2181,10.58.50.207:2181,10.58.50.208:2181 /clover 30000 cloverAdmin password 10.58.50.134:27077,10.58.50.133:27077 spec_pub user_spec_pub SrVlPrIGgu7ZM2Ox 100 10 180000 30000 true false 180000 10.58.50.208 6379 500 20 1000 10.58.50.208 xiaoxiangxu@yolo24.com stark_summer@qq.com 6fb8535d703f2492704aefc212b7cd41 compile org.apache.maven.plugins maven-compiler-plugin 3.1 ${jdk.version} ${jdk.version} ${maven.compiler.encoding} true true org.apache.maven.plugins maven-surefire-plugin 2.17 true org.apache.maven.plugins maven-eclipse-plugin 2.5.1 true false org.apache.maven.plugins maven-resources-plugin 2.6 ${maven.compiler.encoding} org.apache.maven.plugins maven-war-plugin 2.4 false org.codehaus.mojo clirr-maven-plugin 2.6.1 org.apache.maven.plugins maven-deploy-plugin 2.6 src/main/resources true nexus-releases Nexus Release Repository http://maven.ds.gome.com.cn/nexus/content/repositories/releases nexus-snapshots Nexus Snapshot Repository http://maven.ds.gome.com.cn/nexus/content/repositories/snapshots org.slf4j slf4j-api 1.6.4 org.slf4j slf4j-log4j12 1.6.4 log4j log4j 1.2.17 commons-lang commons-lang 2.5 commons-codec commons-codec 1.2 javax.servlet servlet-api 2.4 com.alibaba fastjson 1.1.31 org.apache.zookeeper zookeeper 3.4.5 org.quartz-scheduler quartz 2.2.1 org.mongodb mongo-java-driver 2.11.3 redis.clients jedis 2.6.0 org.apache.httpcomponents com.springsource.org.apache.httpcomponents.httpclient 4.2.1 org.apache.httpcomponents com.springsource.org.apache.httpcomponents.httpcore 4.2.1 io.netty netty-all 4.0.13.Final com.alibaba.rocketmq rocketmq-client 3.1.8 org.apache.commons com.springsource.org.apache.commons.codec 1.6.0 org.zeromq jeromq 0.3.4 javax.mail mail 1.5.0-b01 com.sun tools 1.5.0 org.apache.catalina com.springsource.org.apache.catalina 7.0.26 org.apache.curator curator-framework 2.7.0 org.springframework spring-context 3.2.4.RELEASE org.springframework spring-webmvc 3.2.4.RELEASE org.springframework spring-beans 3.2.4.RELEASE com.typesafe.akka akka-actor 2.0.2 com.typesafe.akka akka-zeromq_2.10 2.1.0 commons commons-lang3 3.1 org.xerial.snappy snappy-java 1.1.1.6 junit junit 4.11 test ================================================ FILE: test-clover/.classpath ================================================ ================================================ FILE: test-clover/.idea/.name ================================================ test-clover ================================================ FILE: test-clover/.idea/artifacts/test_clover_war.xml ================================================ $PROJECT_DIR$/target ================================================ FILE: test-clover/.idea/artifacts/test_clover_war_exploded.xml ================================================ $PROJECT_DIR$/target/test-clover-0.0.1-SNAPSHOT ================================================ FILE: test-clover/.idea/compiler.xml ================================================ ================================================ FILE: test-clover/.idea/copyright/profiles_settings.xml ================================================ ================================================ FILE: test-clover/.idea/encodings.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__c3p0_c3p0_0_9_1_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_101tec_zkclient_0_3.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_alibaba_fastjson_1_1_31.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_alibaba_rocketmq_rocketmq_client_3_1_8.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_alibaba_rocketmq_rocketmq_common_3_1_8.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_alibaba_rocketmq_rocketmq_remoting_3_1_8.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_github_jnr_jnr_constants_0_8_2.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_gome_clover_client_dev_1_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_gome_clover_core_dev_1_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_google_guava_guava_16_0_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_google_protobuf_protobuf_java_2_4_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_sun_jdmk_jmxtools_1_2_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_sun_jmx_jmxri_1_2_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_sun_tools_1_5_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_typesafe_akka_akka_actor_2_0_2.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_typesafe_akka_akka_actor_2_10_2_1_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_typesafe_akka_akka_zeromq_2_10_2_1_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_typesafe_config_1_0_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__com_yammer_metrics_metrics_core_2_2_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__commons_logging_commons_logging_1_1_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__io_netty_netty_all_4_0_21_Final.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__javax_activation_activation_1_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__javax_jms_jms_1_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__javax_mail_mail_1_5_0_b01.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__javax_servlet_servlet_api_2_4.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__jline_jline_0_9_94.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__junit_junit_3_8_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__junit_junit_4_11.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__log4j_log4j_1_2_15.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__net_java_dev_jna_jna_3_0_9.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__net_sf_jopt_simple_jopt_simple_3_2.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_commons_com_springsource_org_apache_commons_codec_1_6_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_commons_com_springsource_org_apache_commons_logging_1_1_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_commons_commons_pool2_2_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_curator_curator_client_2_7_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_curator_curator_framework_2_7_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_httpcomponents_com_springsource_org_apache_httpcomponents_httpclient_4_2_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_httpcomponents_com_springsource_org_apache_httpcomponents_httpclient_cache_4_2_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_httpcomponents_com_springsource_org_apache_httpcomponents_httpcore_4_2_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_httpcomponents_com_springsource_org_apache_httpcomponents_httpmime_4_2_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_kafka_kafka_2_9_2_0_8_1_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_apache_zookeeper_zookeeper_3_4_5.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_jboss_netty_netty_3_2_2_Final.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_jboss_netty_netty_3_2_9_Final.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_mongodb_mongo_java_driver_2_11_3.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_quartz_scheduler_quartz_2_2_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_scala_lang_scala_library_2_9_2.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_slf4j_slf4j_api_1_6_6.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_slf4j_slf4j_log4j12_1_6_1.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_springframework_spring_aop_3_2_4_RELEASE.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_springframework_spring_beans_3_2_4_RELEASE.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_springframework_spring_context_3_2_4_RELEASE.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_springframework_spring_core_3_2_4_RELEASE.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_springframework_spring_expression_3_2_4_RELEASE.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_springframework_spring_web_3_2_4_RELEASE.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_springframework_spring_webmvc_3_2_4_RELEASE.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_xerial_snappy_snappy_java_1_1_1_6.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_zeromq_jeromq_0_3_4.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__org_zeromq_zeromq_scala_binding_2_10_0_0_7.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/Maven__redis_clients_jedis_2_6_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/clover_client_dev_1_0.xml ================================================ ================================================ FILE: test-clover/.idea/libraries/clover_core_dev_1_0.xml ================================================ ================================================ FILE: test-clover/.idea/misc.xml ================================================ ================================================ FILE: test-clover/.idea/modules.xml ================================================ ================================================ FILE: test-clover/.idea/scopes/scope_settings.xml ================================================ ================================================ FILE: test-clover/.idea/vcs.xml ================================================ ================================================ FILE: test-clover/.idea/workspace.xml ================================================ true 1418283507172 test-clover:war Web 1.6 test-clover clover-core-dev-1.0 ================================================ FILE: test-clover/.myeclipse/profiler/RomoteCronJob.xml ================================================ true 1.0 true 2 10 4 com.gome.testclover.localjob.** com.gome.testclover.remotejob.** com.gome.testclover.localjob.*, com.gome.testclover.remotejob.* true -1 0 ================================================ FILE: test-clover/.mymetadata ================================================ ================================================ FILE: test-clover/.project ================================================ test-clover org.eclipse.wst.common.project.facet.core.builder org.eclipse.wst.jsdt.core.javascriptValidator com.genuitec.eclipse.j2eedt.core.WebClasspathBuilder org.eclipse.jdt.core.javabuilder com.genuitec.eclipse.j2eedt.core.J2EEProjectValidator com.genuitec.eclipse.j2eedt.core.DeploymentDescriptorValidator org.eclipse.wst.validation.validationbuilder org.eclipse.m2e.core.maven2Builder com.genuitec.eclipse.ast.deploy.core.DeploymentBuilder com.genuitec.eclipse.ast.deploy.core.deploymentnature org.eclipse.m2e.core.maven2Nature org.eclipse.jem.workbench.JavaEMFNature com.genuitec.eclipse.j2eedt.core.webnature org.eclipse.jdt.core.javanature org.eclipse.wst.jsdt.core.jsNature org.eclipse.wst.common.project.facet.core.nature org.eclipse.wst.common.modulecore.ModuleCoreNature ================================================ FILE: test-clover/.settings/.jsdtscope ================================================ ================================================ FILE: test-clover/.settings/com.genuitec.eclipse.j2eedt.core.prefs ================================================ #Tue Dec 09 14:52:22 CST 2014 eclipse.preferences.version=1 useAssemblyMapping=true ================================================ FILE: test-clover/.settings/org.eclipse.core.resources.prefs ================================================ #Wed Dec 10 16:09:35 CST 2014 eclipse.preferences.version=1 encoding//src/main/java=UTF-8 ================================================ FILE: test-clover/.settings/org.eclipse.jdt.core.prefs ================================================ #Tue Dec 09 14:52:22 CST 2014 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.source=1.5 ================================================ FILE: test-clover/.settings/org.eclipse.m2e.core.prefs ================================================ #Tue Dec 09 14:52:19 CST 2014 activeProfiles= eclipse.preferences.version=1 resolveWorkspaceProjects=true version=1 ================================================ FILE: test-clover/.settings/org.eclipse.wst.common.component ================================================ ================================================ FILE: test-clover/.settings/org.eclipse.wst.common.project.facet.core.xml ================================================ ================================================ FILE: test-clover/.settings/org.eclipse.wst.jsdt.ui.superType.container ================================================ org.eclipse.wst.jsdt.launching.baseBrowserLibrary ================================================ FILE: test-clover/.settings/org.eclipse.wst.jsdt.ui.superType.name ================================================ Window ================================================ FILE: test-clover/pom.xml ================================================ 4.0.0 test-clover test-clover 0.0.1-SNAPSHOT war UTF-8 com.gome clover-client 1.0.sit-SNAPSHOT junit junit 4.11 org.apache.maven.plugins maven-surefire-plugin 2.17 true org.apache.maven.plugins maven-compiler-plugin 3.1 1.6 1.6 UTF-8 org.apache.maven.plugins maven-eclipse-plugin 2.5.1 org.apache.maven.plugins maven-resources-plugin 2.6 UTF-8 org.apache.maven.plugins maven-war-plugin 2.4 false src/main/resources true ================================================ FILE: test-clover/src/main/java/com/gome/testclover/init/InitAllJobWithServlet.java ================================================ package com.gome.testclover.init; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; import com.gome.testclover.localjob.CronLocalJob; import com.gome.testclover.remotejob.RemoteCronJob; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:test-clover * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/11 * Time: 20:26 */ public class InitAllJobWithServlet extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { String jobGroup1 ="CronLocalJobGroup"; String jobName1="CronLocalJobName"; String cronExpression1 = "0/10 * * * * ?"; ClientJob clientJob1 = ClientJobBuilder.quickBuildLocalCronJob(jobGroup1, jobName1, CronLocalJob.class,cronExpression1); clientJob1.setRecoverJobFromDB(true);//是否恢复数据每次启动容器 ModuleSchedulerClient.getInstance().handlerJob(clientJob1); String jobGroup2 = "RomoteCronJob1Group"; String jobName2 = "RomoteCronJobName"; String cronExpression2 = "0/10 * * * * ?"; ClientJob clientJob2 = ClientJobBuilder.quickBuildRemoteCronJob(jobGroup2, jobName2, RemoteCronJob.class, cronExpression2); ModuleSchedulerClient.getInstance().startupForLocalJobTest(); ModuleSchedulerClient.getInstance().handlerJob(clientJob2); } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/init/InitServletWithSchedulerClientInitial.java ================================================ package com.gome.testclover.init; import com.gome.clover.client.module.SchedulerClientInitial; import com.gome.testclover.spring.MyRemoteJob; import javax.servlet.ServletException; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Init Servlet With Scheduler ClientInitial * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/17 * Time: 11:42 */ public class InitServletWithSchedulerClientInitial { public void init(){ List jobClassList = new ArrayList(); jobClassList.add(MyRemoteJob.class.getName()); boolean isRegisterToZK = true; boolean isStartupMQ = true; String port = "-1"; String systemId="test-clover"; String token = ""; try { new SchedulerClientInitial().init(jobClassList,isRegisterToZK,isStartupMQ,port,systemId,token); } catch (ServletException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/init/InitServletWithStartup.java ================================================ package com.gome.testclover.init; import com.gome.clover.core.module.ModuleSchedulerClient; import com.gome.testclover.spring.MyRemoteJob; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Init Servlet With Startup * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/17 * Time: 11:34 */ public class InitServletWithStartup extends HttpServlet { @Override public void init() throws ServletException { super.init(); List jobClassList = new ArrayList(); jobClassList.add(MyRemoteJob.class.getName()); boolean isRegisterToZK = true; boolean isStartupMQ = true; String port = "-1"; String systemId="test-clover"; String token = ""; ModuleSchedulerClient.getInstance().startup(jobClassList,isRegisterToZK,isStartupMQ,port,systemId,token); } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/init/InitSpringAnnotationWithStartup.java ================================================ package com.gome.testclover.init; import com.gome.clover.core.module.ModuleSchedulerClient; import com.gome.testclover.spring.MyRemoteJob; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Init Spring Annotation With Startup * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/17 * Time: 11:39 */ @Component public class InitSpringAnnotationWithStartup { @PostConstruct public void init() { System.err.println("InitSpringAnnotationWithStartup--->>>init()....."); List jobClassList = new ArrayList(); jobClassList.add(MyRemoteJob.class.getName()); boolean isRegisterToZK = true; boolean isStartupMQ = true; String port = "-1"; String systemId="test-clover"; String token = ""; ModuleSchedulerClient.getInstance().startup(jobClassList,isRegisterToZK,isStartupMQ,port,systemId,token); } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/localjob/CronLocalJob.java ================================================ package com.gome.testclover.localjob; import com.gome.clover.client.job.LocalJob; import org.quartz.JobExecutionContext; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; public class CronLocalJob extends LocalJob { @Override public void executeJob(JobExecutionContext arg0) { // TODO Auto-generated method stub System.err.println("CronLocalJob--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); } public static void main(String[] args) { String jobGroup ="CronLocalJobGroup1"; String jobName="CronLocalJobName1"; String cronExpression = "0/10 * * * * ?"; ClientJob clientJob = ClientJobBuilder.quickBuildLocalCronJob(jobGroup, jobName, CronLocalJob.class,cronExpression); ModuleSchedulerClient.getInstance().startupForLocalJobTest(); clientJob.setRecoverJobFromDB(true); ModuleSchedulerClient.getInstance().handlerJob(clientJob); } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/localjob/FixedTimeLocalJob.java ================================================ package com.gome.testclover.localjob; import java.util.Date; import com.gome.clover.client.job.LocalJob; import org.quartz.JobExecutionContext; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; public class FixedTimeLocalJob extends LocalJob { @Override public void executeJob(JobExecutionContext arg0) { // TODO Auto-generated method stub System.err.println("FixedTimeLocalJob--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); } public static void main(String[] args) { String jobGroup ="FixedTimeLocalJobGroup"; String jobName="FixedTimeLocalJobName"; Date startTime= DateUtils.formatWithDefaultPattern("2014-12-09 15:50:20"); ClientJob clientJob = ClientJobBuilder.quickBuildLocalJobWithStartDate(jobGroup, jobName, FixedTimeLocalJob.class,startTime); ModuleSchedulerClient.getInstance().startupForLocalJobTest(); ModuleSchedulerClient.getInstance().handlerJob(clientJob); } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/localjob/LocalJobTest.java ================================================ package com.gome.testclover.localjob; import java.util.Date; import org.junit.Test; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; public class LocalJobTest { @Test public void testFixedTimeLocalJob(){ String jobGroup ="FixedTimeLocalJobGroup"; String jobName="FixedTimeLocalJobName"; Date startTime= DateUtils.formatWithDefaultPattern("2014-12-09 15:40:20"); ClientJob clientJob = ClientJobBuilder.quickBuildLocalJobWithStartDate(jobGroup, jobName, FixedTimeLocalJob.class,startTime); ModuleSchedulerClient.getInstance().startupForLocalJobTest(); ModuleSchedulerClient.getInstance().handlerJob(clientJob); } public static void main(String[] args) { String jobGroup ="FixedTimeLocalJobGroup"; String jobName="FixedTimeLocalJobName"; Date startTime= DateUtils.formatWithDefaultPattern("2014-12-09 15:50:20"); ClientJob clientJob = ClientJobBuilder.quickBuildLocalJobWithStartDate(jobGroup, jobName, FixedTimeLocalJob.class,startTime); ModuleSchedulerClient.getInstance().startupForLocalJobTest(); ModuleSchedulerClient.getInstance().handlerJob(clientJob); } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/remotejob/RemoteCronJob.java ================================================ package com.gome.testclover.remotejob; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import com.gome.clover.core.job.ClientJobBuilder; import com.gome.clover.core.module.ModuleSchedulerClient; import org.quartz.JobExecutionContext; public class RemoteCronJob extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteCronJob--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); } public static void main(String[] args) { String jobGroup ="RemoteCronJob1Group1"; String jobName="RemoteCronJobName1"; String cronExpression = "0/10 * * * * ?"; ClientJob clientJob = ClientJobBuilder.quickBuildRemoteCronJob(jobGroup, jobName, RemoteCronJob.class,cronExpression); ModuleSchedulerClient.getInstance().startupForLocalJobTest(); //clientJob.setRecoverJobFromDB(true); ModuleSchedulerClient.getInstance().handlerJob(clientJob); } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/MyRemoteJob.java ================================================ package com.gome.testclover.spring; import com.gome.clover.common.tools.DateUtils; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:RemoteJob * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/12/22 * Time: 12:24 */ public class MyRemoteJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.err.println("RemoteJob--->>>execute(JobExecutionContext) @" + DateUtils.currentDateTime()); } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteCronJobWithSpringAnnotation.java ================================================ package com.gome.testclover.spring; import com.gome.clover.common.annotation.CloverJobAnnotation; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import org.quartz.JobExecutionContext; import org.springframework.stereotype.Component; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Log4j ConfigListener * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 10:55 */ @Component @CloverJobAnnotation(jobGroup = "RemoteCronJobWithSpringAnnotationGroup", jobName = "RemoteCronJobWithSpringAnnotationName", jobType = ClientJob.JobType.REMOTE, executeType = ClientJob.ExecuteType.ADD,jobStrategy =ClientJob.JobStrategy.SYSTEM_CAPACITY ,cronExpression = "0/50 * * * * ?") public class RemoteCronJobWithSpringAnnotation extends com.gome.clover.client.job.RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJobWithSpringAnnotation--->>>executeJob(JobExecutionContext) @" + DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteCronJobWithSpringAnnotation" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteFixedDateJobWithSpringAnnotation.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.annotation.CloverJobAnnotation; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import org.quartz.JobExecutionContext; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; /** * ━━━━━━神兽出没━━━━━━ *    ┏┓   ┏┓ *   ┏┛┻━━━┛┻┓ *   ┃       ┃ *   ┃   ━   ┃ *   ┃ ┳┛ ┗┳ ┃ *   ┃       ┃ *   ┃   ┻   ┃ *   ┃       ┃ *   ┗━┓   ┏━┛ *     ┃   ┃神兽保佑, 永无BUG! *     ┃   ┃Code is far away from bug with the animal protecting *     ┃   ┗━━━┓ *     ┃       ┣┓ *     ┃       ┏┛ *     ┗┓┓┏━┳┓┏┛ *      ┃┫┫ ┃┫┫ *      ┗┻┛ ┗┻┛ * ━━━━━━感觉萌萌哒━━━━━━ * Module Desc:Log4j ConfigListener * User: wangyue-ds6 || stark_summer@qq.com * Date: 2014/11/25 * Time: 10:55 */ //@Component @CloverJobAnnotation(jobGroup = "RemoteJobWithSpringAnnotationGroup",jobName = "RemoteJobWithSpringAnnotationName", jobType = ClientJob.JobType.REMOTE,executeType = ClientJob.ExecuteType.ADD,jobStrategy =ClientJob.JobStrategy.SYSTEM_CAPACITY,startTime="2014-12-12 12:12:12") public class RemoteFixedDateJobWithSpringAnnotation extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJobWithSpringAnnotation--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteFixedDateJobWithSpringAnnotation" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteJob1WithSpring.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.tools.DateUtils; import org.quartz.JobExecutionContext; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; public class RemoteJob1WithSpring extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJob1WithSpring--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteJob1WithSpring" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteJob1WithSpringAnnotation.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.annotation.CloverJobAnnotation; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import org.quartz.JobExecutionContext; import org.springframework.stereotype.Component; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; @Component @CloverJobAnnotation(jobGroup = "RemoteJob1WithSpringAnnotationGroup",jobName = "RemoteJob1WithSpringAnnotationName", jobType = ClientJob.JobType.REMOTE,executeType = ClientJob.ExecuteType.ADD, jobStrategy =ClientJob.JobStrategy.SYSTEM_CAPACITY,cronExpression="0/40 * * * * ?") public class RemoteJob1WithSpringAnnotation extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJob1WithSpringAnnotation--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteJob1WithSpringAnnotation" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteJob2WithSpring.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.tools.DateUtils; import org.quartz.JobExecutionContext; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; public class RemoteJob2WithSpring extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJob2WithSpring--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteJob2WithSpring" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteJob2WithSpringAnnotation.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.annotation.CloverJobAnnotation; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import org.quartz.JobExecutionContext; import org.springframework.stereotype.Component; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; @Component @CloverJobAnnotation(jobGroup = "RemoteJob2WithSpringAnnotationGroup",jobName = "RemoteJob2WithSpringAnnotationName", jobType = ClientJob.JobType.REMOTE,executeType = ClientJob.ExecuteType.ADD, jobStrategy =ClientJob.JobStrategy.SYSTEM_CAPACITY,cronExpression="0/30 * * * * ?") public class RemoteJob2WithSpringAnnotation extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJob2WithSpringAnnotation--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteJob2WithSpringAnnotation" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteJob3WithSpring.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.tools.DateUtils; import org.quartz.JobExecutionContext; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; public class RemoteJob3WithSpring extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJob3WithSpring--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteJob3WithSpring" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteJob3WithSpringAnnotation.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.annotation.CloverJobAnnotation; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import org.quartz.JobExecutionContext; import org.springframework.stereotype.Component; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; @Component @CloverJobAnnotation(jobGroup = "RemoteJob3WithSpringAnnotationGroup",jobName = "RemoteJob3WithSpringAnnotationName", jobType = ClientJob.JobType.REMOTE,executeType = ClientJob.ExecuteType.ADD, jobStrategy =ClientJob.JobStrategy.SYSTEM_CAPACITY,cronExpression="0/40 * * * * ?") public class RemoteJob3WithSpringAnnotation extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJob3WithSpringAnnotation--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteJob3WithSpringAnnotation" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteJobWithSpring.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import org.quartz.JobExecutionContext; import com.gome.clover.common.tools.DateUtils; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; public class RemoteJobWithSpring extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJobWithSpring--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteJobWithSpring" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/java/com/gome/testclover/spring/RemoteJobWithSpringAnnotation.java ================================================ package com.gome.testclover.spring; import com.gome.clover.client.job.RemoteJob; import com.gome.clover.common.annotation.CloverJobAnnotation; import com.gome.clover.common.tools.DateUtils; import com.gome.clover.core.job.ClientJob; import org.quartz.JobExecutionContext; import org.springframework.stereotype.Component; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; @Component @CloverJobAnnotation(jobGroup = "RemoteJobWithSpringAnnotationGroup",jobName = "RemoteJobWithSpringAnnotationName", jobType = ClientJob.JobType.REMOTE,executeType = ClientJob.ExecuteType.ADD, jobStrategy =ClientJob.JobStrategy.SYSTEM_CAPACITY,cronExpression="0/40 * * * * ?") public class RemoteJobWithSpringAnnotation extends RemoteJob { @Override public void executeJob(JobExecutionContext arg0) { System.err.println("RemoteJobWithSpringAnnotation--->>>executeJob(JobExecutionContext) @"+ DateUtils.currentDateTime()); try { String filePath = File.separatorChar + "home" + File.separatorChar + "wangyue-ds6"; File outFile = new File(filePath + File.separatorChar + "RemoteJobWithSpringAnnotation" + File.separatorChar + DateUtils.format(new Date(), "yyyy-MM-dd")); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileWriter fw = new FileWriter(outFile, true); BufferedWriter bw = new BufferedWriter(fw); StringBuffer sb = new StringBuffer(); sb.append(" \n call executeJob(JobExecutionContext) method").append(" Time:" + DateUtils.currentDateTime()); bw.write(sb.toString()); bw.flush(); fw.close(); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: test-clover/src/main/resources/spring-config.xml ================================================ ================================================ FILE: test-clover/src/main/webapp/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Class-Path: ================================================ FILE: test-clover/src/main/webapp/WEB-INF/web.xml ================================================ index.jsp contextConfigLocation classpath:spring-config.xml org.springframework.web.context.ContextLoaderListener ================================================ FILE: test-clover/src/main/webapp/index.jsp ================================================ <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> My JSP 'index.jsp' starting page This is my JSP page.
================================================ FILE: test-clover/test-clover.iml ================================================