diff --git a/escheduler-alert/pom.xml b/escheduler-alert/pom.xml new file mode 100644 index 0000000000..d98a43aac1 --- /dev/null +++ b/escheduler-alert/pom.xml @@ -0,0 +1,146 @@ + + + 4.0.0 + + cn.analysys + escheduler + 1.0.0 + + escheduler-alert + jar + + + UTF-8 + + + + junit + junit + test + + + + org.apache.commons + commons-email + + + + javax.mail + mail + + + javax.servlet + javax.servlet-api + + + + + + org.freemarker + freemarker + + + + com.alibaba + fastjson + + + + com.fasterxml.jackson.core + jackson-core + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.slf4j + slf4j-api + + + + org.apache.commons + commons-collections4 + + + + commons-logging + commons-logging + + + + org.apache.commons + commons-lang3 + + + + com.google.guava + guava + + + + ch.qos.logback + logback-classic + + + + commons-io + commons-io + + + + org.apache.commons + commons-collections4 + + + + + org.apache.poi + poi + + + + cn.analysys + escheduler-dao + + + + + + + + maven-assembly-plugin + 2.6 + + + src/main/assembly/package.xml + + false + + + + make-assembly + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + diff --git a/escheduler-alert/src/main/assembly/package.xml b/escheduler-alert/src/main/assembly/package.xml new file mode 100644 index 0000000000..68a30262fa --- /dev/null +++ b/escheduler-alert/src/main/assembly/package.xml @@ -0,0 +1,40 @@ + + cluster + + dir + + false + + + src/main/resources + + **/*.properties + **/*.xml + **/*.json + **/*.ftl + + conf + + + target/ + + escheduler-alert-${project.version}.jar + + lib + + + + + lib + true + + javax.servlet:servlet-api + org.eclipse.jetty.aggregate:jetty-all + org.slf4j:slf4j-log4j12 + + + + \ No newline at end of file diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/AlertServer.java b/escheduler-alert/src/main/java/cn/escheduler/alert/AlertServer.java new file mode 100644 index 0000000000..8de3a65d6c --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/AlertServer.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert; + +import cn.escheduler.alert.runner.AlertSender; +import cn.escheduler.alert.utils.Constants; +import cn.escheduler.common.thread.Stopper; +import cn.escheduler.dao.AlertDao; +import cn.escheduler.dao.DaoFactory; +import cn.escheduler.dao.model.Alert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * alert of start + */ +public class AlertServer { + private static final Logger logger = LoggerFactory.getLogger(AlertServer.class); + /** + * Alert Dao + */ + private AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); + + private AlertSender alertSender; + + private static AlertServer instance; + + private AlertServer() { + + } + + public static AlertServer getInstance(){ + if (null == instance) { + synchronized (AlertServer.class) { + if(null == instance) { + instance = new AlertServer(); + } + } + } + return instance; + } + + public void start(){ + logger.info("Alert Server ready start!"); + while (Stopper.isRunning()){ + try { + Thread.sleep(Constants.ALERT_SCAN_INTERVEL); + } catch (InterruptedException e) { + logger.error(e.getMessage(),e); + } + List alerts = alertDao.listWaitExecutionAlert(); + alertSender = new AlertSender(alerts, alertDao); + alertSender.run(); + } + } + + + public static void main(String[] args){ + + AlertServer alertServer = AlertServer.getInstance(); + alertServer.start(); + } +} diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/manager/EmailManager.java b/escheduler-alert/src/main/java/cn/escheduler/alert/manager/EmailManager.java new file mode 100644 index 0000000000..0c50118526 --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/manager/EmailManager.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.manager; + +import cn.escheduler.alert.utils.MailUtils; +import cn.escheduler.common.enums.ShowType; + +import java.util.List; +import java.util.Map; + +/** + * email send manager + */ +public class EmailManager { + /** + * email send + * @param receviersList + * @param receviersCcList + * @param title + * @param content + * @param showType + * @return + */ + public Map send(List receviersList,List receviersCcList,String title,String content,ShowType showType){ + + return MailUtils.sendMails(receviersList,receviersCcList,title, content, showType); + } + + /** + * msg send + * @param receviersList + * @param title + * @param content + * @param showType + * @return + */ + public Map send(List receviersList,String title,String content,ShowType showType){ + + return MailUtils.sendMails(receviersList,title, content, showType); + } +} diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/manager/MsgManager.java b/escheduler-alert/src/main/java/cn/escheduler/alert/manager/MsgManager.java new file mode 100644 index 0000000000..2a5b48e5aa --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/manager/MsgManager.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.manager; + +import cn.escheduler.dao.model.Alert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * SMS send manager + */ +public class MsgManager { + + private static final Logger logger = LoggerFactory.getLogger(MsgManager.class); + /** + * SMS send + * @param alert + */ + public void send(Alert alert){ + logger.info("send message {}",alert); + } +} diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/runner/AlertSender.java b/escheduler-alert/src/main/java/cn/escheduler/alert/runner/AlertSender.java new file mode 100644 index 0000000000..fbaf512632 --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/runner/AlertSender.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.runner; + +import cn.escheduler.alert.manager.EmailManager; +import cn.escheduler.alert.utils.Constants; +import cn.escheduler.common.enums.AlertStatus; +import cn.escheduler.common.enums.AlertType; +import cn.escheduler.dao.AlertDao; +import cn.escheduler.dao.model.Alert; +import cn.escheduler.dao.model.User; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * alert sender + */ +public class AlertSender{ + + private static final Logger logger = LoggerFactory.getLogger(AlertSender.class); + + private static final EmailManager emailManager= new EmailManager(); + + + private List alertList; + private AlertDao alertDao; + + public AlertSender(){} + public AlertSender(List alertList, AlertDao alertDao){ + super(); + this.alertList = alertList; + this.alertDao = alertDao; + } + + public void run() { + + List users; + + Map retMaps = null; + for(Alert alert:alertList){ + users = alertDao.listUserByAlertgroupId(alert.getAlertGroupId()); + + + + // receiving group list + List receviersList = new ArrayList(); + for(User user:users){ + receviersList.add(user.getEmail()); + } + // custom receiver + String receivers = alert.getReceivers(); + if (StringUtils.isNotEmpty(receivers)){ + String[] splits = receivers.split(","); + for (String receiver : splits){ + receviersList.add(receiver); + } + } + + // copy list + List receviersCcList = new ArrayList(); + + + // Custom Copier + String receiversCc = alert.getReceiversCc(); + + if (StringUtils.isNotEmpty(receiversCc)){ + String[] splits = receiversCc.split(","); + for (String receiverCc : splits){ + receviersCcList.add(receiverCc); + } + } + + if (CollectionUtils.isEmpty(receviersList) && CollectionUtils.isEmpty(receviersCcList)) { + logger.warn("alert send error : At least one receiver address required"); + alertDao.updateAlert(AlertStatus.EXECUTION_FAILURE, "execution failure,At least one receiver address required.", alert.getId()); + continue; + } + + if (alert.getAlertType() == AlertType.EMAIL){ + retMaps = emailManager.send(receviersList,receviersCcList, alert.getTitle(), alert.getContent(),alert.getShowType()); + + alert.setInfo(retMaps); + }else if (alert.getAlertType() == AlertType.SMS){ + retMaps = emailManager.send(getReciversForSMS(users), alert.getTitle(), alert.getContent(),alert.getShowType()); + alert.setInfo(retMaps); + } + + boolean flag = Boolean.parseBoolean(String.valueOf(retMaps.get(Constants.STATUS))); + if (flag){ + alertDao.updateAlert(AlertStatus.EXECUTION_SUCCESS, "execution success", alert.getId()); + logger.info("alert send success"); + }else { + alertDao.updateAlert(AlertStatus.EXECUTION_FAILURE,String.valueOf(retMaps.get(Constants.MESSAGE)),alert.getId()); + logger.info("alert send error : {}" , String.valueOf(retMaps.get(Constants.MESSAGE))); + } + } + + } + + + /** + * get a list of SMS users + * @param users + * @return + */ + private List getReciversForSMS(List users){ + List list = new ArrayList<>(); + for (User user : users){ + list.add(user.getPhone()); + } + return list; + } +} diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/utils/Constants.java b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/Constants.java new file mode 100644 index 0000000000..1f036af54b --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/Constants.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.utils; + +/** + * constants + */ +public class Constants { + + /** + * alert properties path + */ + public static final String ALERT_PROPERTIES_PATH = "/alert.properties"; + + public static final String DATA_SOURCE_PROPERTIES_PATH = "/dao/data_source.properties"; + + public static final String SINGLE_SLASH = "/"; + + /** + * UTF-8 + */ + public static final String UTF_8 = "UTF-8"; + + public static final String STATUS = "status"; + + public static final String MESSAGE = "message"; + + public static final String MAIL_PROTOCOL = "mail.protocol"; + + public static final String MAIL_SERVER_HOST = "mail.server.host"; + + public static final String MAIL_SERVER_PORT = "mail.server.port"; + + public static final String MAIL_SENDER = "mail.sender"; + + public static final String MAIL_PASSWD = "mail.passwd"; + + public static final String XLS_FILE_PATH = "xls.file.path"; + + public static final String MAIL_HOST = "mail.host"; + + public static final String MAIL_SMTP_AUTH = "mail.smtp.auth"; + + public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol"; + + public static final String TEXT_HTML_CHARSET_UTF_8 = "text/html;charset=utf-8"; + + public static final String STRING_TRUE = "true"; + + public static final String EXCEL_SUFFIX_XLS = ".xls"; + + public static final int NUMBER_1000 = 1000; + + public static final String SPRING_DATASOURCE_DRIVER_CLASS_NAME = "spring.datasource.driver-class-name"; + + public static final String SPRING_DATASOURCE_URL = "spring.datasource.url"; + + public static final String SPRING_DATASOURCE_USERNAME = "spring.datasource.username"; + + public static final String SPRING_DATASOURCE_PASSWORD = "spring.datasource.password"; + + public static final String SPRING_DATASOURCE_VALIDATION_QUERY_TIMEOUT = "spring.datasource.validationQueryTimeout"; + + public static final String SPRING_DATASOURCE_INITIAL_SIZE = "spring.datasource.initialSize"; + + public static final String SPRING_DATASOURCE_MIN_IDLE = "spring.datasource.minIdle"; + + public static final String SPRING_DATASOURCE_MAX_ACTIVE = "spring.datasource.maxActive"; + + public static final String SPRING_DATASOURCE_MAX_WAIT = "spring.datasource.maxWait"; + + public static final String SPRING_DATASOURCE_TIME_BETWEEN_EVICTION_RUNS_MILLIS = "spring.datasource.timeBetweenEvictionRunsMillis"; + + public static final String SPRING_DATASOURCE_MIN_EVICTABLE_IDLE_TIME_MILLIS = "spring.datasource.minEvictableIdleTimeMillis"; + + public static final String SPRING_DATASOURCE_VALIDATION_QUERY = "spring.datasource.validationQuery"; + + public static final String SPRING_DATASOURCE_TEST_WHILE_IDLE = "spring.datasource.testWhileIdle"; + + public static final String SPRING_DATASOURCE_TEST_ON_BORROW = "spring.datasource.testOnBorrow"; + + public static final String SPRING_DATASOURCE_TEST_ON_RETURN = "spring.datasource.testOnReturn"; + + public static final String SPRING_DATASOURCE_POOL_PREPARED_STATEMENTS = "spring.datasource.poolPreparedStatements"; + + public static final String SPRING_DATASOURCE_DEFAULT_AUTO_COMMIT = "spring.datasource.defaultAutoCommit"; + + public static final String SPRING_DATASOURCE_KEEP_ALIVE = "spring.datasource.keepAlive"; + + public static final String SPRING_DATASOURCE_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE = "spring.datasource.maxPoolPreparedStatementPerConnectionSize"; + + public static final String DEVELOPMENT = "development"; + + public static final String CLASSPATH_MAIL_TEMPLATES_ALERT_MAIL_TEMPLATE_FTL = "classpath:mail_templates/alert_mail_template.ftl"; + + public static final String TR = ""; + + public static final String TD = ""; + + public static final String TD_END = ""; + + public static final String TR_END = ""; + + public static final String TITLE = "title"; + + public static final String CONTENT = "content"; + + public static final String TH = ""; + + public static final String TH_END = ""; + + public static final int ALERT_SCAN_INTERVEL = 5000; +} diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/utils/ExcelUtils.java b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/ExcelUtils.java new file mode 100644 index 0000000000..ef9fe61932 --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/ExcelUtils.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.utils; + +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.*; + +/** + * excel utils + */ +public class ExcelUtils { + + private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class); + /** + * generate excel file + * @param content + * @param title + * @param xlsFilePath + * @return + * @throws Exception + */ + public static void genExcelFile(String content,String title,String xlsFilePath){ + List itemsList; + try { + itemsList = JSONUtils.toList(content, LinkedHashMap.class); + }catch (Exception e){ + logger.error(String.format("json format incorrect : %s",content),e); + throw new RuntimeException("json format incorrect",e); + } + + if (itemsList == null || itemsList.size() == 0){ + logger.error("itemsList is null"); + throw new RuntimeException("itemsList is null"); + } + + LinkedHashMap headerMap = itemsList.get(0); + + List headerList = new ArrayList<>(); + + Iterator> iter = headerMap.entrySet().iterator(); + while (iter.hasNext()){ + Map.Entry en = iter.next(); + headerList.add(en.getKey()); + } + + HSSFWorkbook wb = null; + FileOutputStream fos = null; + try { + // declare a workbook + wb = new HSSFWorkbook(); + // generate a table + HSSFSheet sheet = wb.createSheet(); + HSSFRow row = sheet.createRow(0); + //set the height of the first line + row.setHeight((short)500); + + + //setting excel headers + for (int i = 0; i < headerList.size(); i++) { + HSSFCell cell = row.createCell(i); + cell.setCellValue(headerList.get(i)); + } + + //setting excel body + int rowIndex = 1; + for (LinkedHashMap itemsMap : itemsList){ + Object[] values = itemsMap.values().toArray(); + row = sheet.createRow(rowIndex); + //setting excel body height + row.setHeight((short)500); + rowIndex++; + for (int j = 0 ; j < values.length ; j++){ + HSSFCell cell1 = row.createCell(j); + cell1.setCellValue(String.valueOf(values[j])); + } + } + + for (int i = 0; i < headerList.size(); i++) { + sheet.setColumnWidth(i, headerList.get(i).length() * 800); + + } + + //setting file output + fos = new FileOutputStream(xlsFilePath + Constants.SINGLE_SLASH + title + Constants.EXCEL_SUFFIX_XLS); + + wb.write(fos); + + }catch (Exception e){ + logger.error("generate excel error",e); + throw new RuntimeException("generate excel error",e); + }finally { + if (wb != null){ + try { + wb.close(); + } catch (IOException e) { + logger.error(e.getMessage(),e); + } + } + if (fos != null){ + try { + fos.close(); + } catch (IOException e) { + logger.error(e.getMessage(),e); + } + } + } + } + +} diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/utils/JSONUtils.java b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/JSONUtils.java new file mode 100644 index 0000000000..6c1c468475 --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/JSONUtils.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.utils; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * json utils + */ +public class JSONUtils { + + private static final Logger logger = LoggerFactory.getLogger(JSONUtils.class); + + /** + * object to json string + * @param object + * @return json string + */ + public static String toJsonString(Object object) { + try{ + return JSONObject.toJSONString(object,false); + } catch (Exception e) { + throw new RuntimeException("Json deserialization exception.", e); + } + } + + /** + * json to list + * + * @param json + * @param clazz c + * @param + * @return + */ + public static List toList(String json, Class clazz) { + if (StringUtils.isEmpty(json)) { + return null; + } + try { + return JSONArray.parseArray(json, clazz); + } catch (Exception e) { + logger.error("JSONArray.parseArray exception!",e); + } + + return null; + } + +} diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/utils/MailUtils.java b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/MailUtils.java new file mode 100644 index 0000000000..7746465e62 --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/MailUtils.java @@ -0,0 +1,429 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.utils; + +import cn.escheduler.common.enums.ShowType; +import freemarker.cache.StringTemplateLoader; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.mail.EmailException; +import org.apache.commons.mail.HtmlEmail; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ResourceUtils; + +import javax.mail.*; +import javax.mail.internet.*; +import java.io.*; +import java.util.*; + +import static cn.escheduler.alert.utils.PropertyUtils.getInt; +import static cn.escheduler.alert.utils.PropertyUtils.getString; + + +/** + * mail utils + */ +public class MailUtils { + + public static final Logger logger = LoggerFactory.getLogger(MailUtils.class); + + public static final String mailProtocol = getString(Constants.MAIL_PROTOCOL); + + public static final String mailServerHost = getString(Constants.MAIL_SERVER_HOST); + + public static final Integer mailServerPort = getInt(Constants.MAIL_SERVER_PORT); + + public static final String mailSender = getString(Constants.MAIL_SENDER); + + public static final String mailPasswd = getString(Constants.MAIL_PASSWD); + + public static final String xlsFilePath = getString(Constants.XLS_FILE_PATH); + + private static Template MAIL_TEMPLATE; + + static { + Configuration cfg = new Configuration(Configuration.VERSION_2_3_21); + cfg.setDefaultEncoding(Constants.UTF_8); + StringTemplateLoader stringTemplateLoader = new StringTemplateLoader(); + cfg.setTemplateLoader(stringTemplateLoader); + InputStreamReader isr = null; + try { + isr = new InputStreamReader(new FileInputStream(ResourceUtils.getFile(Constants.CLASSPATH_MAIL_TEMPLATES_ALERT_MAIL_TEMPLATE_FTL)), + Constants.UTF_8); + + MAIL_TEMPLATE = new Template("alert_mail_template", isr, cfg); + } catch (Exception e) { + MAIL_TEMPLATE = null; + } finally { + IOUtils.closeQuietly(isr); + } + } + + + /** + * send mail to receivers + * + * @param receivers + * @param title + * @param content + * @return + */ + public static Map sendMails(Collection receivers, String title, String content,ShowType showType) { + return sendMails(receivers, null, title, content, showType); + } + + /** + * send mail + * @param receivers + * @param receiversCc cc + * @param title title + * @param content content + * @param showType mail type + * @return + */ + public static Map sendMails(Collection receivers, Collection receiversCc, String title, String content, ShowType showType) { + Map retMap = new HashMap<>(); + retMap.put(Constants.STATUS, false); + + + receivers.removeIf((from) -> (StringUtils.isEmpty(from))); + + if (showType == ShowType.TABLE || showType == ShowType.TEXT){ + // send email + HtmlEmail email = new HtmlEmail(); + + try { + // set the SMTP sending server, 163 as follows: "smtp.163.com" + email.setHostName(mailServerHost); + email.setSmtpPort(mailServerPort); + //set charset + email.setCharset(Constants.UTF_8); + if (CollectionUtils.isNotEmpty(receivers)){ + // receivers mail + for (String receiver : receivers) { + email.addTo(receiver); + } + } + + if (CollectionUtils.isNotEmpty(receiversCc)){ + //cc + for (String receiverCc : receiversCc) { + email.addCc(receiverCc); + } + } + // sender mail + return getStringObjectMap(title, content, showType, retMap, email); + } catch (Exception e) { + handleException(receivers, retMap, e); + } + }else if (showType == ShowType.ATTACHMENT || showType == ShowType.TABLEATTACHMENT){ + try { + + String partContent = (showType == ShowType.ATTACHMENT ? "Please see the attachment " + title + Constants.EXCEL_SUFFIX_XLS : htmlTable(content,false)); + + attachment(receivers,receiversCc,title,content,partContent); + + retMap.put(Constants.STATUS, true); + return retMap; + }catch (Exception e){ + handleException(receivers, retMap, e); + } + } + return retMap; + + } + + /** + * html table content + * @param content + * @param showAll + * @return + */ + private static String htmlTable(String content, boolean showAll){ + if (StringUtils.isNotEmpty(content)){ + List mapItemsList = JSONUtils.toList(content, LinkedHashMap.class); + + if(!showAll && mapItemsList.size() > Constants.NUMBER_1000){ + mapItemsList = mapItemsList.subList(0,Constants.NUMBER_1000); + } + + StringBuilder contents = new StringBuilder(200); + + boolean flag = true; + + String title = ""; + for (LinkedHashMap mapItems : mapItemsList){ + + Set> entries = mapItems.entrySet(); + + Iterator> iterator = entries.iterator(); + + StringBuilder t = new StringBuilder(Constants.TR); + StringBuilder cs = new StringBuilder(Constants.TR); + while (iterator.hasNext()){ + + Map.Entry entry = iterator.next(); + t.append(Constants.TH).append(entry.getKey()).append(Constants.TH_END); + cs.append(Constants.TD).append(String.valueOf(entry.getValue())).append(Constants.TD_END); + + } + t.append(Constants.TR_END); + cs.append(Constants.TR_END); + if (flag){ + title = t.toString(); + } + flag = false; + contents.append(cs); + } + + return getTemplateContent(title,contents.toString()); + } + + return null; + } + + /** + * html table content + * @param content + * @return + */ + private static String htmlTable(String content){ + return htmlTable(content,true); + } + + /** + * html text content + * @param content + * @return + */ + private static String htmlText(String content){ + + if (StringUtils.isNotEmpty(content)){ + List list; + try { + list = JSONUtils.toList(content,String.class); + }catch (Exception e){ + logger.error("json format exception",e); + return null; + } + + StringBuilder contents = new StringBuilder(100); + for (String str : list){ + contents.append(Constants.TR); + contents.append(Constants.TD).append(str).append(Constants.TD_END); + contents.append(Constants.TR_END); + } + + return getTemplateContent(null,contents.toString()); + + } + + return null; + } + + + + + /** + * send mail as Excel attachment + * + * @param receivers + * @param title + * @throws Exception + */ + private static void attachment(Collection receivers,Collection receiversCc,String title,String content,String partContent)throws Exception{ + MimeMessage msg = getMimeMessage(receivers); + + attachContent(receiversCc, title, content,partContent, msg); + } + + /** + * get MimeMessage + * @param receivers + * @return + * @throws MessagingException + */ + private static MimeMessage getMimeMessage(Collection receivers) throws MessagingException { + Properties props = new Properties(); + props.setProperty(Constants.MAIL_HOST, mailServerHost); + props.setProperty(Constants.MAIL_SMTP_AUTH, Constants.STRING_TRUE); + props.setProperty(Constants.MAIL_TRANSPORT_PROTOCOL, mailProtocol); + Authenticator auth = new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + // mail username and password + return new PasswordAuthentication(mailSender, mailPasswd); + } + }; + // 1. The first step in creating mail: creating session + Session session = Session.getInstance(props, auth); + // Setting debug mode, can be turned off + session.setDebug(false); + // 2. creating mail: Creating a MimeMessage + MimeMessage msg = new MimeMessage(session); + // 3. set sender + msg.setFrom(new InternetAddress(mailSender)); + // 4. set receivers + for (String receiver : receivers) { + msg.addRecipients(MimeMessage.RecipientType.TO, InternetAddress.parse(receiver)); + } + return msg; + } + + /** + * + * @param receiversCc + * @param title + * @param content + * @param partContent + * @param msg + * @throws MessagingException + * @throws IOException + */ + private static void attachContent(Collection receiversCc, String title, String content, String partContent,MimeMessage msg) throws MessagingException, IOException { + /** + * set receiverCc + */ + if(CollectionUtils.isNotEmpty(receiversCc)){ + for (String receiverCc : receiversCc){ + msg.addRecipients(MimeMessage.RecipientType.CC, InternetAddress.parse(receiverCc)); + } + } + + // set receivers type to cc + // msg.addRecipients(MimeMessage.RecipientType.CC, InternetAddress.parse(propMap.get("${CC}"))); + // set subject + msg.setSubject(title); + MimeMultipart partList = new MimeMultipart(); + // set signature + MimeBodyPart part1 = new MimeBodyPart(); + part1.setContent(partContent, Constants.TEXT_HTML_CHARSET_UTF_8); + // set attach file + MimeBodyPart part2 = new MimeBodyPart(); + // make excel file + ExcelUtils.genExcelFile(content,title,xlsFilePath); + File file = new File(xlsFilePath + Constants.SINGLE_SLASH + title + Constants.EXCEL_SUFFIX_XLS); + part2.attachFile(file); + part2.setFileName(MimeUtility.encodeText(title + Constants.EXCEL_SUFFIX_XLS)); + // add components to collection + partList.addBodyPart(part1); + partList.addBodyPart(part2); + msg.setContent(partList); + // 5. send Transport + Transport.send(msg); + // 6. delete saved file + deleteFile(file); + } + + /** + * + * @param title + * @param content + * @param showType + * @param retMap + * @param email + * @return + * @throws EmailException + */ + private static Map getStringObjectMap(String title, String content, ShowType showType, Map retMap, HtmlEmail email) throws EmailException { + // sender's mailbox + email.setFrom(mailSender, mailSender); + /** + * if you need authentication information, set authentication: username-password. + * The registered name and password of the sender on the mail server respectively + */ + email.setAuthentication(mailSender, mailPasswd); + + /** + * the subject of the message to be sent + */ + email.setSubject(title); + /** + * to send information, you can use HTML tags in mail content because of the use of HtmlEmail + */ + if (showType == ShowType.TABLE) { + email.setMsg(htmlTable(content)); + } else if (showType == ShowType.TEXT) { + email.setMsg(htmlText(content)); + } + + // send + email.send(); + + retMap.put(Constants.STATUS, true); + + return retMap; + } + + /** + * file delete + * @param file + */ + public static void deleteFile(File file){ + if(file.exists()){ + if(file.delete()){ + logger.info("delete success:"+file.getAbsolutePath()+file.getName()); + }else{ + logger.info("delete fail"+file.getAbsolutePath()+file.getName()); + } + }else{ + logger.info("file not exists:"+file.getAbsolutePath()+file.getName()); + } + } + + + /** + * + * @param receivers + * @param retMap + * @param e + */ + private static void handleException(Collection receivers, Map retMap, Exception e) { + logger.error("Send email to {} failed", StringUtils.join(",", receivers), e); + retMap.put(Constants.MESSAGE, "Send email to {" + StringUtils.join(",", receivers) + "} failed," + e.toString()); + } + + /** + * + * @param title + * @param content + * @return + */ + private static String getTemplateContent(String title,String content){ + StringWriter out = new StringWriter(); + Map map = new HashMap<>(); + if(null != title){ + map.put(Constants.TITLE,title); + } + map.put(Constants.CONTENT,content); + try { + MAIL_TEMPLATE.process(map, out); + return out.toString(); + } catch (TemplateException e) { + logger.error(e.getMessage(),e); + } catch (IOException e) { + logger.error(e.getMessage(),e); + } + + return null; + } +} diff --git a/escheduler-alert/src/main/java/cn/escheduler/alert/utils/PropertyUtils.java b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/PropertyUtils.java new file mode 100644 index 0000000000..3b31a28146 --- /dev/null +++ b/escheduler-alert/src/main/java/cn/escheduler/alert/utils/PropertyUtils.java @@ -0,0 +1,193 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.utils; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import static cn.escheduler.alert.utils.Constants.ALERT_PROPERTIES_PATH; +import static cn.escheduler.alert.utils.Constants.DATA_SOURCE_PROPERTIES_PATH; + +/** + * property utils + * single instance + */ +public class PropertyUtils { + + /** + * logger + */ + private static final Logger logger = LoggerFactory.getLogger(PropertyUtils.class); + + private static final Properties properties = new Properties(); + + private static final PropertyUtils propertyUtils = new PropertyUtils(); + + private PropertyUtils(){ + init(); + } + + private void init(){ + String[] propertyFiles = new String[]{ALERT_PROPERTIES_PATH,DATA_SOURCE_PROPERTIES_PATH}; + for (String fileName : propertyFiles) { + InputStream fis = null; + try { + fis = PropertyUtils.class.getResourceAsStream(fileName); + properties.load(fis); + + } catch (IOException e) { + logger.error(e.getMessage(), e); + System.exit(1); + } finally { + IOUtils.closeQuietly(fis); + } + } + } + +/* + public static PropertyUtils getInstance(){ + return propertyUtils; + } +*/ + + /** + * get property value + * + * @param key property name + * @return + */ + public static String getString(String key) { + return properties.getProperty(key); + } + + /** + * get property value + * + * @param key property name + * @return get property int value , if key == null, then return -1 + */ + public static int getInt(String key) { + return getInt(key, -1); + } + + /** + * + * @param key + * @param defaultValue + * @return + */ + public static int getInt(String key, int defaultValue) { + String value = getString(key); + if (value == null) { + return defaultValue; + } + + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + logger.info(e.getMessage(),e); + } + return defaultValue; + } + + /** + * get property value + * + * @param key property name + * @return + */ + public static Boolean getBoolean(String key) { + String value = properties.getProperty(key.trim()); + if(null != value){ + return Boolean.parseBoolean(value); + } + + return null; + } + + /** + * + * @param key + * @return + */ + public static long getLong(String key) { + return getLong(key,-1); + } + + /** + * + * @param key + * @param defaultVal + * @return + */ + public static long getLong(String key, long defaultVal) { + String val = getString(key); + return val == null ? defaultVal : Long.parseLong(val); + } + + + /** + * + * @param key + * @param defaultVal + * @return + */ + public double getDouble(String key, double defaultVal) { + String val = getString(key); + return val == null ? defaultVal : Double.parseDouble(val); + } + + + /** + * get array + * @param key property name + * @param splitStr separator + * @return + */ + public static String[] getArray(String key, String splitStr) { + String value = getString(key); + if (value == null) { + return null; + } + try { + String[] propertyArray = value.split(splitStr); + return propertyArray; + } catch (NumberFormatException e) { + logger.info(e.getMessage(),e); + } + return null; + } + + /** + * + * @param key + * @param type + * @param defaultValue + * @param + * @return get enum value + */ + public > T getEnum(String key, Class type, + T defaultValue) { + String val = getString(key); + return val == null ? defaultValue : Enum.valueOf(type, val); + } +} diff --git a/escheduler-alert/src/main/resources/alert.properties b/escheduler-alert/src/main/resources/alert.properties new file mode 100644 index 0000000000..e2cba1160d --- /dev/null +++ b/escheduler-alert/src/main/resources/alert.properties @@ -0,0 +1,16 @@ +#alert type is EMAIL/SMS +alert.type=EMAIL + +# mail server configuration +mail.protocol=SMTP +mail.server.host=smtp.exmail.qq.com +mail.server.port=25 +mail.sender=xxxxxxx +mail.passwd=xxxxxxx + +#xls file path,need create if not exist +xls.file.path=/opt/xls + + + + diff --git a/escheduler-alert/src/main/resources/alert_logback.xml b/escheduler-alert/src/main/resources/alert_logback.xml new file mode 100644 index 0000000000..c4ca8e9d1f --- /dev/null +++ b/escheduler-alert/src/main/resources/alert_logback.xml @@ -0,0 +1,31 @@ + + + + + + + [%level] %date{yyyy-MM-dd HH:mm:ss.SSS} %logger{96}:[%line] - %msg%n + + UTF-8 + + + + + ${log.base}/escheduler-alert.log + + ${log.base}/escheduler-alert.%d{yyyy-MM-dd_HH}.%i.log + 20 + 64MB + + + + [%level] %date{yyyy-MM-dd HH:mm:ss.SSS} %logger{96}:[%line] - %msg%n + + UTF-8 + + + + + + + \ No newline at end of file diff --git a/escheduler-alert/src/main/resources/mail_templates/alert_mail_template.ftl b/escheduler-alert/src/main/resources/mail_templates/alert_mail_template.ftl new file mode 100644 index 0000000000..6a729c2097 --- /dev/null +++ b/escheduler-alert/src/main/resources/mail_templates/alert_mail_template.ftl @@ -0,0 +1,38 @@ + + + easyscheduler + + + + + + + + <#if title??> ${title} + + <#if content??> ${content} +
+ + \ No newline at end of file diff --git a/escheduler-alert/src/test/java/cn/escheduler/alert/utils/MailUtilsTest.java b/escheduler-alert/src/test/java/cn/escheduler/alert/utils/MailUtilsTest.java new file mode 100644 index 0000000000..2196480be9 --- /dev/null +++ b/escheduler-alert/src/test/java/cn/escheduler/alert/utils/MailUtilsTest.java @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package cn.escheduler.alert.utils; + + +import cn.escheduler.common.enums.AlertType; +import cn.escheduler.common.enums.ShowType; +import cn.escheduler.dao.AlertDao; +import cn.escheduler.dao.DaoFactory; +import cn.escheduler.dao.model.Alert; +import cn.escheduler.dao.model.User; +import freemarker.cache.StringTemplateLoader; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ResourceUtils; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.util.*; + + +/** + */ +public class MailUtilsTest { + private static final Logger logger = LoggerFactory.getLogger(MailUtilsTest.class); + @Test + public void testSendMails() { + String[] receivers = new String[]{"xx@xx.com"}; + String[] receiversCc = new String[]{"xxx@xxx.com"}; + + String content ="[\"id:69\"," + + "\"name:UserBehavior-0--1193959466\"," + + "\"Job name: 启动工作流\"," + + "\"State: SUCCESS\"," + + "\"Recovery:NO\"," + + "\"Run time: 1\"," + + "\"Start time: 2018-08-06 10:31:34.0\"," + + "\"End time: 2018-08-06 10:31:49.0\"," + + "\"Host: 192.168.xx.xx\"," + + "\"Notify group :4\"]"; + + Alert alert = new Alert(); + alert.setTitle("Mysql异常"); + alert.setShowType(ShowType.TEXT); + alert.setContent(content); + alert.setAlertType(AlertType.EMAIL); + alert.setAlertGroupId(4); + + MailUtils.sendMails(Arrays.asList(receivers),Arrays.asList(receiversCc),alert.getTitle(),alert.getContent(), ShowType.TEXT); + } + + + @Test + public void testQuery(){ + AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); + List alerts = alertDao.listWaitExecutionAlert(); + + String[] mails = new String[]{"xx@xx.com"}; + + for(Alert alert : alerts){ + MailUtils.sendMails(Arrays.asList(mails),"gaojing", alert.getContent(), alert.getShowType()); + } + + } + + public String list2String(){ + + LinkedHashMap map1 = new LinkedHashMap<>(); + map1.put("mysql服务名称","mysql200"); + map1.put("mysql地址","192.168.xx.xx"); + map1.put("端口","3306"); + map1.put("期间内没有使用索引的查询数握","80"); + map1.put("数据库客户端连接数","190"); + + LinkedHashMap map2 = new LinkedHashMap<>(); + map2.put("mysql服务名称","mysql210"); + map2.put("mysql地址","192.168.xx.xx"); + map2.put("端口","3306"); + map2.put("期间内没有使用索引的查询数握","10"); + map2.put("数据库客户端连接数","90"); + + List> maps = new ArrayList<>(); + maps.add(0,map1); + maps.add(1,map2); + String mapjson = JSONUtils.toJsonString(maps); + logger.info(mapjson); + + return mapjson; + + } + + @Test + public void testSendTableMail(){ + String[] mails = new String[]{"xx@xx.com"}; + Alert alert = new Alert(); + alert.setTitle("Mysql Exception"); + alert.setShowType(ShowType.TABLE); + String content= list2String(); + alert.setContent(content); + alert.setAlertType(AlertType.EMAIL); + alert.setAlertGroupId(1); + MailUtils.sendMails(Arrays.asList(mails),"gaojing", alert.getContent(), ShowType.TABLE); + } + + /** + * Used to test add alarm information, mail sent + * Text + */ + @Test + public void addAlertText(){ + AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); + Alert alert = new Alert(); + alert.setTitle("Mysql Exception"); + alert.setShowType(ShowType.TEXT); + alert.setContent("[\"告警时间:2018-02-05\", \"服务名:MYSQL_ALTER\", \"告警名:MYSQL_ALTER_DUMP\", \"获取告警异常!,接口报错,异常信息:timed out\", \"请求地址:http://blog.csdn.net/dreamInTheWorld/article/details/78539286\"]"); + alert.setAlertType(AlertType.EMAIL); + alert.setAlertGroupId(1); + alertDao.addAlert(alert); + } + + + /** + * Used to test add alarm information, mail sent + * Table + */ + @Test + public void addAlertTable(){ + AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); + Alert alert = new Alert(); + alert.setTitle("Mysql Exception"); + alert.setShowType(ShowType.TABLE); + + String content = list2String(); + alert.setContent(content); + alert.setAlertType(AlertType.EMAIL); + alert.setAlertGroupId(1); + alertDao.addAlert(alert); + } + + @Test + public void testAlertDao(){ + AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class); + List users = alertDao.listUserByAlertgroupId(3); + logger.info(users.toString()); + } + + @Test + public void testAttachmentFile()throws Exception{ + String[] mails = new String[]{"xx@xx.com"}; + Alert alert = new Alert(); + alert.setTitle("Mysql Exception"); + alert.setShowType(ShowType.ATTACHMENT); + String content = list2String(); + alert.setContent(content); + alert.setAlertType(AlertType.EMAIL); + alert.setAlertGroupId(1); + MailUtils.sendMails(Arrays.asList(mails),"gaojing",alert.getContent(),ShowType.ATTACHMENT); + } + + @Test + public void testTableAttachmentFile()throws Exception{ + String[] mails = new String[]{"xx@xx.com"}; + Alert alert = new Alert(); + alert.setTitle("Mysql Exception"); + alert.setShowType(ShowType.TABLEATTACHMENT); + String content = list2String(); + alert.setContent(content); + alert.setAlertType(AlertType.EMAIL); + alert.setAlertGroupId(1); + MailUtils.sendMails(Arrays.asList(mails),"gaojing",alert.getContent(),ShowType.TABLEATTACHMENT); + } + + @Test + public void template(){ + Template MAIL_TEMPLATE; + Configuration cfg = new Configuration(Configuration.VERSION_2_3_21); + cfg.setDefaultEncoding(Constants.UTF_8); + StringTemplateLoader stringTemplateLoader = new StringTemplateLoader(); + cfg.setTemplateLoader(stringTemplateLoader); + InputStreamReader isr = null; + try { + isr = new InputStreamReader(new FileInputStream(ResourceUtils.getFile(Constants.CLASSPATH_MAIL_TEMPLATES_ALERT_MAIL_TEMPLATE_FTL)), + Constants.UTF_8); + + MAIL_TEMPLATE = new Template("alert_mail_template", isr, cfg); + } catch (Exception e) { + MAIL_TEMPLATE = null; + } finally { + IOUtils.closeQuietly(isr); + } + + + StringWriter out = new StringWriter(); + Map map = new HashMap<>(); + map.put(Constants.TITLE,"title_test"); + try { + MAIL_TEMPLATE.process(map, out); + logger.info(out.toString()); + + } catch (TemplateException e) { + logger.error(e.getMessage(),e); + } catch (IOException e) { + logger.error(e.getMessage(),e); + } + + } + +}