X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=auth%2Fauth-batch%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Faaf%2Fauth%2Fbatch%2Freports%2FNotify.java;h=18c8ed6ae724cc3fec499bc04b2222dd5cd4f217;hb=deb396a3d53a84b2eb5a46d40122b4902d72c601;hp=5a0b70a1fe9a83a36a24df55c84812b44695566a;hpb=57effd69fb15e0c73f85296d10ff6b358a6cbebb;p=aaf%2Fauthz.git diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/Notify.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/Notify.java index 5a0b70a1..18c8ed6a 100644 --- a/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/Notify.java +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/batch/reports/Notify.java @@ -7,9 +7,9 @@ * 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. @@ -50,7 +50,7 @@ import org.onap.aaf.auth.org.OrganizationException; import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.PropAccess; -import org.onap.aaf.cadi.client.Holder; +import org.onap.aaf.cadi.util.Holder; import org.onap.aaf.cadi.util.CSV; import org.onap.aaf.misc.env.APIException; import org.onap.aaf.misc.env.TimeTaken; @@ -58,327 +58,338 @@ import org.onap.aaf.misc.env.Trans; import org.onap.aaf.misc.env.util.Chrono; public class Notify extends Batch { - private static final String HTML_CSS = "HTML_CSS"; - private final Mailer mailer; - private final String header; - private final String footer; - private final int maxEmails; - private final int indent; - private final boolean urgent; - public final String guiURL; - private PropAccess access; - private AuthzTrans noAvg; - private CQLBatch cqlBatch; - - public Notify(AuthzTrans trans) throws APIException, IOException, OrganizationException { - super(trans.env()); - access = env.access(); - session = super.cluster.connect(); - - String mailerCls = env.getProperty("MAILER"); - String mailFrom = env.getProperty("MAIL_FROM"); - String header_html = env.getProperty("HEADER_HTML"); - String footer_html = env.getProperty("FOOTER_HTML"); - String str = env.getProperty("MAX_EMAIL"); - guiURL = env.getProperty("GUI_URL"); - maxEmails = str==null||str.isEmpty()?Integer.MAX_VALUE:Integer.parseInt(str); - if(mailerCls==null || mailFrom==null || guiURL==null || header_html==null || footer_html==null) { - throw new APIException("Notify requires MAILER, MAILER_FROM, GUI_URL, HEADER_HTML and FOOTER_HTML properties"); - } - try { - Class mailc = Class.forName(mailerCls); - Constructor mailcst = mailc.getConstructor(Access.class); - mailer = (Mailer)mailcst.newInstance(env.access()); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new APIException("Unable to construct " + mailerCls,e); - } - - String line; - StringBuilder sb = new StringBuilder(); - BufferedReader br = new BufferedReader(new FileReader(header_html)); - try { - while((line=br.readLine())!=null) { - sb.append(line); - sb.append('\n'); - } - String html_css = env.getProperty(HTML_CSS); - String temp; - int hc = sb.indexOf(HTML_CSS); - if(hc!=0 && html_css!=null) { - temp = sb.replace(hc,hc+HTML_CSS.length(), html_css).toString(); - } else { - temp = sb.toString(); - } - header = temp.replace("AAF:ENV", batchEnv); - } finally { - br.close(); - } - - // Establish index from header - int lastTag = header.lastIndexOf('<'); - if(lastTag>0) { - int prevCR = header.lastIndexOf('\n',lastTag); - if(prevCR>0) { - indent = lastTag-prevCR; - } else { - indent = 6; //arbitrary - } - } else { - indent = 6; - } - - urgent = false; - - sb.setLength(0); - br = new BufferedReader(new FileReader(footer_html)); - try { - while((line=br.readLine())!=null) { - sb.append(line); - sb.append('\n'); - } - footer = sb.toString(); - } finally { - br.close(); - } - - noAvg = trans.env().newTransNoAvg(); - cqlBatch = new CQLBatch(noAvg.info(),session); - } - - /* - * Note: We try to put things related to Notify as Main Class in Run, where we might have put in - * Constructor, so that we can have other Classes call just the "notify" method. - */ - @Override - protected void run(AuthzTrans trans) { - - final Holder> info = new Holder<>(null); - final Set errorSet = new HashSet<>(); - String fmt = "%s"+Chrono.dateOnlyStamp()+".csv"; - - try { - // Class Load possible data - NotifyBody.load(env.access()); - - - // Create Intermediate Output - File logDir = logDir(); - Set notifyFile = new HashSet<>(); - if(args().length>0) { - for(int i=0;i row) throws IOException, CadiException { - if("info".equals(row.get(0))) { - info.set(row); - } - if(info.get()==null) { - throw new CadiException("First line of Feed MUST contain 'info' record"); - } String key = row.get(0)+'|'+info.get().get(1); - NotifyBody body = NotifyBody.get(key); - if(body==null) { - errorSet.add("No NotifyBody defined for " + key); - } else { - body.store(row); - } - } - }); - } catch (IOException | CadiException e) { - e.printStackTrace(); - } - - } - - // now create Notification - for(NotifyBody nb : NotifyBody.getAll()) { - int count = notify(noAvg, nb); - trans.info().printf("Emailed %d for %s",count,nb.name()); - } - - // - // Do Pending Approval Notifies. We do this separately, because we are consolidating - // all the new entries, etc. - // - List csvList = new ArrayList<>(); - for(String s : new String[] {"Approvals","ApprovalsNew"}) { - File f = new File(logDir(),String.format(fmt, s)); - if(f.exists()) { - csvList.add(new CSV(access,f)); - } - } - - Map mpending = new TreeMap<>(); - Holder count = new Holder<>(0); - for(CSV approveCSV : csvList) { - TimeTaken tt = trans.start("Load Analyzed Reminders",Trans.SUB,approveCSV.name()); - try { - approveCSV.visit(row -> { - switch(row.get(0)) { -// case "info": -// break; - case Pending.REMIND: - try { - String user = row.get(1); - Pending p = new Pending(row); - Pending mp = mpending.get(user); - if(mp==null) { - mpending.put(user, p); - } else { - mp.inc(p); // FYI, unlikely - } - count.set(count.get()+1); - } catch (ParseException e) { - trans.error().log(e); - } - break; - } - }); - } catch (IOException | CadiException e) { - trans.error().log(e); - } finally { - tt.done(); - } - } - trans.info().printf("Read %d Reminder Rows", count.get()); - - NotifyPendingApprBody npab = new NotifyPendingApprBody(access); - - GregorianCalendar gc = new GregorianCalendar(); - gc.add(GregorianCalendar.DAY_OF_MONTH, 7); // Get from INFO? - Date oneWeek = gc.getTime(); - CSV.Saver rs = new CSV.Saver(); - - TimeTaken tt = trans.start("Obtain Last Notifications for Approvers", Trans.SUB); - LastNotified lastN; - try { - lastN = new LastNotified(session); - lastN.add(mpending.keySet()); - } finally { - tt.done(); - } - - Pending p; - final CQLBatchLoop cbl = new CQLBatchLoop(cqlBatch,50,dryRun); - tt = trans.start("Notify for Pending", Trans.SUB); - try { - for(Entry es : mpending.entrySet()) { - p = es.getValue(); - boolean nap = p.newApprovals(); - if(!nap) { - Date dateLastNotified = lastN.lastNotified(es.getKey(),"pending",""); - if(dateLastNotified==null || dateLastNotified.after(oneWeek) ) { - nap=true; - } - } - if(nap) { - rs.row("appr", es.getKey(),p.qty(),batchEnv); - npab.store(rs.asList()); - if(notify(noAvg, npab)>0) { - // Update - cbl.preLoop(); - lastN.update(cbl.inc(),es.getKey(),"pending",""); - npab.inc(); - } - } - } - } finally { - cbl.flush(); - tt.done(); + private static final String HTML_CSS = "HTML_CSS"; + private final Mailer mailer; + private final String header; + private final String footer; + private final int maxEmails; + private final int indent; + private final boolean urgent; + public final String guiURL; + private PropAccess access; + private AuthzTrans noAvg; + private CQLBatch cqlBatch; + private LastNotified lastN; + private CQLBatchLoop cbl; + + public Notify(AuthzTrans trans) throws APIException, IOException, OrganizationException { + super(trans.env()); + access = env.access(); + session = cluster.connect(); + + String mailerCls = env.getProperty("MAILER"); + String mailFrom = env.getProperty("MAIL_FROM"); + String header_html = env.getProperty("HEADER_HTML"); + String footer_html = env.getProperty("FOOTER_HTML"); + String str = env.getProperty("MAX_EMAIL"); + guiURL = env.getProperty("GUI_URL"); + maxEmails = str==null||str.isEmpty()?Integer.MAX_VALUE:Integer.parseInt(str); + if(mailerCls==null || mailFrom==null || guiURL==null || header_html==null || footer_html==null) { + throw new APIException("Notify requires MAILER, MAILER_FROM, GUI_URL, HEADER_HTML and FOOTER_HTML properties"); + } + try { + Class mailc = Class.forName(mailerCls); + Constructor mailcst = mailc.getConstructor(Access.class); + mailer = (Mailer)mailcst.newInstance(env.access()); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new APIException("Unable to construct " + mailerCls,e); + } + + String line; + StringBuilder sb = new StringBuilder(); + File fhh = new File(header_html); + if(!fhh.exists()) { + throw new APIException(header_html + " does not exist"); + } + BufferedReader br = new BufferedReader(new FileReader(fhh)); + try { + while((line=br.readLine())!=null) { + sb.append(line); + sb.append('\n'); + } + String html_css = env.getProperty(HTML_CSS); + String temp; + int hc = sb.indexOf(HTML_CSS); + if(hc!=0 && html_css!=null) { + temp = sb.replace(hc,hc+HTML_CSS.length(), html_css).toString(); + } else { + temp = sb.toString(); + } + header = temp.replace("AAF:ENV", batchEnv); + } finally { + br.close(); + } + + // Establish index from header + int lastTag = header.lastIndexOf('<'); + if(lastTag>0) { + int prevCR = header.lastIndexOf('\n',lastTag); + if(prevCR>0) { + indent = lastTag-prevCR; + } else { + indent = 6; //arbitrary + } + } else { + indent = 6; + } + + urgent = false; + + sb.setLength(0); + fhh = new File(footer_html); + if(!fhh.exists()) { + throw new APIException(footer_html + " does not exist"); + } + + br = new BufferedReader(new FileReader(fhh)); + try { + while((line=br.readLine())!=null) { + sb.append(line); + sb.append('\n'); + } + footer = sb.toString(); + } finally { + br.close(); + } + + noAvg = trans.env().newTransNoAvg(); + cqlBatch = new CQLBatch(noAvg.debug(),session); + cbl = new CQLBatchLoop(cqlBatch,50,dryRun); + + lastN = new LastNotified(session); + } + + /* + * Note: We try to put things related to Notify as Main Class in Run, where we might have put in + * Constructor, so that we can have other Classes call just the "notify" method. + */ + @Override + protected void run(AuthzTrans trans) { + + final Holder> info = new Holder<>(null); + final Set errorSet = new HashSet<>(); + String fmt = "%s"+Chrono.dateOnlyStamp()+".csv"; + + try { + // Class Load possible data + NotifyBody.load(env.access()); + + + // Create Intermediate Output + File logDir = logDir(); + Set notifyFile = new HashSet<>(); + if(args().length>0) { + for(int i=0;i row) throws IOException, CadiException { + if("info".equals(row.get(0))) { + info.set(row); + } + if(info.get()==null) { + throw new CadiException("First line of Feed MUST contain 'info' record"); + } String key = row.get(0)+'|'+info.get().get(1); + NotifyBody body = NotifyBody.get(key); + if(body==null) { + errorSet.add("No NotifyBody defined for " + key); + } else { + body.store(row); + } + } + }); + } catch (IOException | CadiException e) { + e.printStackTrace(); + } + + } + + // now create Notification + for(NotifyBody nb : NotifyBody.getAll()) { + int count = notify(noAvg, nb); + trans.info().printf("Emailed %d for %s",count,nb.name()); + } + + // + // Do Pending Approval Notifies. We do this separately, because we are consolidating + // all the new entries, etc. + // + List csvList = new ArrayList<>(); + for(String s : new String[] {"Approvals","ApprovalsNew"}) { + File f = new File(logDir(),String.format(fmt, s)); + if(f.exists()) { + csvList.add(new CSV(access,f)); + } + } + + Map mpending = new TreeMap<>(); + Holder count = new Holder<>(0); + for(CSV approveCSV : csvList) { + TimeTaken tt = trans.start("Load Analyzed Reminders",Trans.SUB,approveCSV.name()); + try { + approveCSV.visit(row -> { + switch(row.get(0)) { +// case "info": +// break; + case Pending.REMIND: + try { + String user = row.get(1); + Pending p = new Pending(row); + Pending mp = mpending.get(user); + if(mp==null) { + mpending.put(user, p); + } else { + mp.inc(p); // FYI, unlikely + } + count.set(count.get()+1); + } catch (ParseException e) { + trans.error().log(e); + } + break; + } + }); + } catch (IOException | CadiException e) { + trans.error().log(e); + } finally { + tt.done(); + } + } + trans.info().printf("Read %d Reminder Rows", count.get()); + + NotifyPendingApprBody npab = new NotifyPendingApprBody(access); + + GregorianCalendar gc = new GregorianCalendar(); + gc.add(GregorianCalendar.DAY_OF_MONTH, 7); // Get from INFO? + Date oneWeek = gc.getTime(); + CSV.Saver rs = new CSV.Saver(); + + TimeTaken tt = trans.start("Obtain Last Notifications for Approvers", Trans.SUB); + try { + lastN.add(mpending.keySet()); + } finally { + tt.done(); + } + + Pending p; + + tt = trans.start("Notify for Pending", Trans.SUB); + List idList = new ArrayList<>(); + String id; + try { + for(Entry es : mpending.entrySet()) { + id = es.getKey(); + idList.clear(); + idList.add(id); + p = es.getValue(); + boolean nap = p.newApprovals(); + if(!nap) { + Date dateLastNotified = lastN.lastNotified(id,"pending",""); + if(dateLastNotified==null || dateLastNotified.after(oneWeek) ) { + nap=true; + } + } + if(nap) { + rs.row("appr", id,p.qty(),batchEnv); + npab.store(rs.asList()); + if(notify(noAvg, npab)>0) { + npab.record(trans,cbl.inc(), id, idList, lastN); + npab.inc(); + } + } + } + } finally { + cbl.flush(); + tt.done(); trans.info().printf("Notified %d persons of Pending Approvals", npab.count()); - } - - } catch (APIException | IOException e1) { - trans.error().log(e1); - } finally { - for(String s : errorSet) { - trans.audit().log(s); - } - } - } - - private int notify(AuthzTrans trans, NotifyBody nb) { - List toList = new ArrayList<>(); - List ccList = new ArrayList<>(); - - String run = nb.type()+nb.name(); - String test = dryRun?run:null; - - ONE_EMAIL: - for(String id : nb.users()) { - toList.clear(); - ccList.clear(); - try { - Identity identity = trans.org().getIdentity(trans, id); - if(identity==null) { - trans.warn().printf("%s is invalid for this Organization. Skipping notification.",id); - } else { - if(!identity.isPerson()) { - identity = identity.responsibleTo(); - } - if(identity==null) { - trans.warn().printf("Responsible Identity %s is invalid for this Organization. Skipping notification.",id); - } else { - for(int i=1;i<=nb.escalation();++i) { - if(identity != null) { - if(i==1) { // self and Delegates - toList.add(identity.email()); - List dels = identity.delegate(); - if(dels!=null) { - for(String d : dels) { - toList.add(d); - } - } - } else { - Identity s = identity.responsibleTo(); - if(s==null) { - trans.error().printf("Identity %s has no %s", identity.fullID(), - identity.isPerson()?"supervisor":"sponsor"); - } else { - ccList.add(s.email()); - } - } - } - } - - StringBuilder content = new StringBuilder(); - content.append(String.format(header,version,Identity.mixedCase(identity.firstName()))); - - nb.body(trans, content, indent, this, id); - content.append(footer); - - if(mailer.sendEmail(trans, test, toList, ccList, nb.subject(),content.toString(), urgent)) { - nb.inc(); - } else { - trans.error().log("Mailer failed to send Mail"); - } - if(maxEmails>0 && nb.count()>=maxEmails) { - break ONE_EMAIL; - } - } - } - } catch (OrganizationException e) { - trans.error().log(e); - } - } - return nb.count(); - } + } + + } catch (APIException | IOException e1) { + trans.error().log(e1); + } finally { + for(String s : errorSet) { + trans.audit().log(s); + } + } + } + + private int notify(AuthzTrans trans, NotifyBody nb) { + List toList = new ArrayList<>(); + List ccList = new ArrayList<>(); + List idList = new ArrayList<>(); + + String run = nb.type()+nb.name(); + String test = dryRun?run:null; + + ONE_EMAIL: + for(String id : nb.users()) { + toList.clear(); + ccList.clear(); + idList.clear(); + try { + List identities = trans.org().getIDs(trans, id, nb.escalation()); + if(identities.isEmpty()) { + trans.warn().printf("%s is invalid for this Organization. Skipping notification.",id); + } else { + Identity identity = null; + for(Identity ident : identities) { + if(identity==null) { + identity = ident; + toList.add(ident.email()); + } else { + ccList.add(ident.email()); + } + idList.add(ident.fullID()); + } + if(identity==null) { // Actually, identity can't be null here, because + break; // if(identities.isEmpty() {..} else {... + } // So this is here to avoid Sonar false positive only + StringBuilder content = new StringBuilder(); + content.append(String.format(header,version,Identity.mixedCase(identity.firstName()))); + + nb.body(trans, content, indent, this, id); + content.append(footer); + + if(mailer.sendEmail(trans, test, toList, ccList, nb.subject(),content.toString(), urgent)) { + nb.record(trans,cbl.inc(), id, idList, lastN); + nb.inc(); + } else { + trans.error().log("Mailer failed to send Mail"); + } + if(maxEmails>0 && nb.count()>=maxEmails) { + break ONE_EMAIL; + } + } + } catch (OrganizationException e) { + trans.error().log(e); + } + } + cbl.flush(); + return nb.count(); + } + + /* (non-Javadoc) + * @see org.onap.aaf.auth.batch.Batch#_close(org.onap.aaf.auth.env.AuthzTrans) + */ + @Override + protected void _close(AuthzTrans trans) { + cbl.flush(); + } }