2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6 * ===========================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END====================================================
20 */package org.onap.aaf.auth.batch.reports;
22 import java.io.BufferedReader;
24 import java.io.FileReader;
25 import java.io.IOException;
26 import java.lang.reflect.Constructor;
27 import java.lang.reflect.InvocationTargetException;
28 import java.util.ArrayList;
29 import java.util.HashSet;
30 import java.util.List;
33 import org.onap.aaf.auth.batch.Batch;
34 import org.onap.aaf.auth.batch.reports.bodies.NotifyBody;
35 import org.onap.aaf.auth.env.AuthzTrans;
36 import org.onap.aaf.auth.org.Mailer;
37 import org.onap.aaf.auth.org.Organization.Identity;
38 import org.onap.aaf.auth.org.OrganizationException;
39 import org.onap.aaf.cadi.Access;
40 import org.onap.aaf.cadi.CadiException;
41 import org.onap.aaf.cadi.client.Holder;
42 import org.onap.aaf.cadi.util.CSV;
43 import org.onap.aaf.misc.env.APIException;
44 import org.onap.aaf.misc.env.util.Chrono;
46 public class Notify extends Batch {
47 private static final String HTML_CSS = "HTML_CSS";
48 private final Mailer mailer;
49 private final String header;
50 private final String footer;
51 private final int maxEmails;
52 private final int indent;
53 private final boolean urgent;
54 public final String guiURL;
56 public Notify(AuthzTrans trans) throws APIException, IOException, OrganizationException {
58 String mailerCls = env.getProperty("MAILER");
59 String mailFrom = env.getProperty("MAIL_FROM");
60 String header_html = env.getProperty("HEADER_HTML");
61 String footer_html = env.getProperty("FOOTER_HTML");
62 String str = env.getProperty("MAX_EMAIL");
63 guiURL = env.getProperty("GUI_URL");
64 maxEmails = str==null||str.isEmpty()?Integer.MAX_VALUE:Integer.parseInt(str);
65 if(mailerCls==null || mailFrom==null || guiURL==null || header_html==null || footer_html==null) {
66 throw new APIException("Notify requires MAILER, MAILER_FROM, GUI_URL, HEADER_HTML and FOOTER_HTML properties");
69 Class<?> mailc = Class.forName(mailerCls);
70 Constructor<?> mailcst = mailc.getConstructor(Access.class);
71 mailer = (Mailer)mailcst.newInstance(env.access());
72 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
73 throw new APIException("Unable to construct " + mailerCls,e);
77 StringBuilder sb = new StringBuilder();
78 BufferedReader br = new BufferedReader(new FileReader(header_html));
80 while((line=br.readLine())!=null) {
84 String html_css = env.getProperty(HTML_CSS);
85 int hc = sb.indexOf(HTML_CSS);
86 if(hc!=0 && html_css!=null) {
87 header = sb.replace(hc,hc+HTML_CSS.length(), html_css).toString();
89 header = sb.toString();
95 // Establish index from header
96 int lastTag = header.lastIndexOf('<');
98 int prevCR = header.lastIndexOf('\n',lastTag);
100 indent = lastTag-prevCR;
102 indent = 6; //arbitrary
111 br = new BufferedReader(new FileReader(footer_html));
113 while((line=br.readLine())!=null) {
117 footer = sb.toString();
125 * Note: We try to put things related to Notify as Main Class in Run, where we might have put in
126 * Constructor, so that we can have other Classes call just the "notify" method.
129 protected void run(AuthzTrans trans) {
130 AuthzTrans noAvg = trans.env().newTransNoAvg();
132 final Holder<List<String>> info = new Holder<>(null);
133 final Set<String> errorSet = new HashSet<>();
136 // Class Load possible data
137 NotifyBody.load(env.access());
140 // Create Intermediate Output
141 File logDir = logDir();
142 Set<File> notifyFile = new HashSet<>();
143 if(args().length>0) {
144 for(int i=0;i<args().length;++i) {
145 notifyFile.add(new File(logDir, args()[i]));
148 String fmt = "%s"+Chrono.dateOnlyStamp()+".csv";
150 for(NotifyBody nb : NotifyBody.getAll()) {
151 file = new File(logDir,String.format(fmt, nb.name()));
153 trans.info().printf("Processing '%s' in %s",nb.type(),file.getCanonicalPath());
154 notifyFile.add(file);
156 trans.info().printf("No Files found for %s",nb.name());
161 for(File f : notifyFile) {
162 CSV csv = new CSV(env.access(),f);
164 csv.visit(new CSV.Visitor() {
166 public void visit(List<String> row) throws IOException, CadiException {
167 if("info".equals(row.get(0))) {
170 if(info.get()==null) {
171 throw new CadiException("First line of Feed MUST contain 'info' record");
172 } String key = row.get(0)+'|'+info.get().get(1);
173 NotifyBody body = NotifyBody.get(key);
175 errorSet.add("No NotifyBody defined for " + key);
181 } catch (IOException | CadiException e) {
187 // now create Notification
188 for(NotifyBody nb : NotifyBody.getAll()) {
192 } catch (APIException | IOException e1) {
193 trans.error().log(e1);
195 for(String s : errorSet) {
196 trans.audit().log(s);
201 public int notify(AuthzTrans trans, NotifyBody nb) {
202 List<String> toList = new ArrayList<>();
203 List<String> ccList = new ArrayList<>();
205 String run = nb.type()+nb.name();
206 String test = dryRun?run:null;
210 for(String id : nb.users()) {
215 Identity identity = trans.org().getIdentity(trans, id);
217 trans.warn().printf("%s is invalid for this Organization. Skipping notification.",id);
219 if(!identity.isPerson()) {
220 identity = identity.responsibleTo();
223 trans.warn().printf("Responsible Identity %s is invalid for this Organization. Skipping notification.",id);
225 for(int i=1;i<=nb.escalation();++i) {
226 if(identity != null) {
227 if(i==1) { // self and Delegates
228 toList.add(identity.email());
229 List<String> dels = identity.delegate();
231 for(String d : dels) {
236 Identity s = identity.responsibleTo();
238 trans.error().printf("Identity %s has no %s", identity.fullID(),
239 identity.isPerson()?"supervisor":"sponsor");
241 ccList.add(s.email());
247 StringBuilder content = new StringBuilder();
248 content.append(String.format(header,version,Identity.mixedCase(identity.firstName())));
250 nb.body(trans, content, indent, this, id);
251 content.append(footer);
253 if(mailer.sendEmail(trans, test, toList, ccList, nb.subject(),content.toString(), urgent)) {
256 trans.error().log("Mailer failed to send Mail");
258 if(maxEmails>0 && nb.count()>=maxEmails) {
263 } catch (OrganizationException e) {
264 trans.error().log(e);
268 trans.info().printf("Notified %s for %s",last,run);
270 trans.info().printf("Emailed %d for %s",nb.count(),run);
276 protected void _close(AuthzTrans trans) {