diff --git a/java/code/src/com/redhat/rhn/common/util/FileUtils.java b/java/code/src/com/redhat/rhn/common/util/FileUtils.java index 3e54559c99f5..50db541e1cfd 100644 --- a/java/code/src/com/redhat/rhn/common/util/FileUtils.java +++ b/java/code/src/com/redhat/rhn/common/util/FileUtils.java @@ -14,6 +14,8 @@ */ package com.redhat.rhn.common.util; +import com.redhat.rhn.common.RhnRuntimeException; + import org.apache.commons.collections.buffer.CircularFifoBuffer; import org.apache.commons.io.LineIterator; import org.apache.logging.log4j.LogManager; @@ -39,6 +41,8 @@ import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.UserPrincipalLookupService; +import java.util.Arrays; +import java.util.List; import java.util.Set; @@ -66,7 +70,7 @@ public static void writeStringToFile(String contents, String path) { try { File file = new File(path); if (file.exists()) { - file.delete(); + Files.delete(file.toPath()); } file.createNewFile(); try (FileOutputStream fos = new FileOutputStream(file); @@ -80,7 +84,7 @@ public static void writeStringToFile(String contents, String path) { } catch (Exception e) { log.error("Error trying to write file to disk: [{}]", path, e); - throw new RuntimeException(e); + throw new RhnRuntimeException(e); } } @@ -145,10 +149,10 @@ public static String readStringFromFile(String path, boolean noLog) { return contents; } catch (FileNotFoundException e) { - throw new RuntimeException("File not found: " + path); + throw new RhnRuntimeException("File not found: " + path); } catch (IOException e) { - throw new RuntimeException(e); + throw new RhnRuntimeException(e); } } @@ -169,9 +173,7 @@ public static byte[] readByteArrayFromFile(File fileToRead, long start, long end log.debug("size of array: {}", size); // Create the byte array to hold the data byte[] bytes = new byte[size]; - InputStream is = null; - try { - is = new FileInputStream(fileToRead); + try (InputStream is = new FileInputStream(fileToRead)){ // Read in the bytes int offset = 0; int numRead = 0; @@ -187,17 +189,7 @@ public static byte[] readByteArrayFromFile(File fileToRead, long start, long end } catch (IOException fnf) { log.error("Could not read from: {}", fileToRead.getAbsolutePath()); - throw new RuntimeException(fnf); - } - finally { - if (is != null) { - try { - is.close(); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } + throw new RhnRuntimeException(fnf); } return bytes; } @@ -209,10 +201,8 @@ public static byte[] readByteArrayFromFile(File fileToRead, long start, long end * @return tail of file as string */ public static String getTailOfFile(String pathToFile, Integer lines) { - InputStream fileStream = null; CircularFifoBuffer buffer = new CircularFifoBuffer(lines); - try { - fileStream = new FileInputStream(pathToFile); + try (InputStream fileStream = new FileInputStream(pathToFile)) { LineIterator it = org.apache.commons.io.IOUtils.lineIterator(fileStream, (String) null); while (it.hasNext()) { @@ -221,10 +211,11 @@ public static String getTailOfFile(String pathToFile, Integer lines) { } catch (FileNotFoundException e) { log.error("File not found: {}", pathToFile); - throw new RuntimeException(e); + throw new RhnRuntimeException(e); } - finally { - org.apache.commons.io.IOUtils.closeQuietly(fileStream); + catch (IOException e) { + log.error(String.format("Failed to close file %s", pathToFile)); + throw new RhnRuntimeException(e); } // Construct a string from the buffered lines StringBuilder sb = new StringBuilder(); @@ -247,4 +238,29 @@ public static void deleteFile(Path path) { log.warn("Could not delete file: {}", path, e); } } + + /** + * Get the content of a folder + * + * @param path the path of the folder + * @return the content of the folder + */ + public static List listFolder(Path path) { + try { + File dir = path.toFile().getCanonicalFile(); + + if (!dir.exists()) { + return List.of(); + } + + String[] files = dir.list(); + if (files == null) { + throw new RhnRuntimeException("log path doesn't point to a directory: " + path); + } + return Arrays.asList(files); + } + catch (IOException e) { + throw new RhnRuntimeException("Invalid path " + path, e); + } + } } diff --git a/java/code/src/com/redhat/rhn/frontend/action/audit/AuditSearchAction.java b/java/code/src/com/redhat/rhn/frontend/action/audit/AuditSearchAction.java index 2983b0442255..b46dc552fb23 100644 --- a/java/code/src/com/redhat/rhn/frontend/action/audit/AuditSearchAction.java +++ b/java/code/src/com/redhat/rhn/frontend/action/audit/AuditSearchAction.java @@ -16,6 +16,7 @@ import com.redhat.rhn.common.util.DatePicker; import com.redhat.rhn.frontend.action.common.DateRangePicker; +import com.redhat.rhn.frontend.dto.AuditDto; import com.redhat.rhn.frontend.dto.AuditReviewDto; import com.redhat.rhn.frontend.struts.RequestContext; import com.redhat.rhn.frontend.struts.RhnAction; @@ -98,7 +99,7 @@ private Long processEndMilli(DynaActionForm dform, private DateRangePicker.DatePickerResults processTimeArgs( DynaActionForm dform, HttpServletRequest request, - Boolean processDates) { + boolean processDates) { Date start, end; DateRangePicker drp = new DateRangePicker(dform, request, new Date(processStartMilli(dform, request)), @@ -108,7 +109,7 @@ private DateRangePicker.DatePickerResults processTimeArgs( DateRangePicker.DatePickerResults dpresults = drp.processDatePickers(processDates, false); - if (processDates) { // we need to redo {start,end}{Disp,Milli} + if (processDates) { start = dpresults.getStart().getDate(); end = dpresults.getEnd().getDate(); request.setAttribute("startDisp", start.toString()); @@ -162,13 +163,13 @@ public ActionForward execute(ActionMapping mapping, HttpServletResponse response) { ActionMessages amsgs; AuditReviewDto aureview; - Boolean parseDates, submitted, unrev; + boolean parseDates, submitted, unrev; DateRangePicker.DatePickerResults dpresults; DynaActionForm dform = (DynaActionForm)form; HttpSession session = request.getSession(true); JSONWriter jsonwr = new JSONWriter(); - List result = null; - Long start, end, seqno, cacheSeqno; + List result = null; + long start, end; Map typemap; RequestContext requestContext = new RequestContext(request); String machine; @@ -182,13 +183,13 @@ public ActionForward execute(ActionMapping mapping, // what machine are we looking at? machine = dform.getString("machine"); // should we look at the DatePickers? - parseDates = (Boolean)dform.get("parseDates") != null; + parseDates = dform.get("parseDates") != null; // did we receive a form with some checkboxes checked? submitted = (autypes != null && autypes.length > 0); // can we mark this section reviewed? - unrev = (Boolean)dform.get("unreviewable") != null; + unrev = dform.get("unreviewable") != null; // get the "page creation time" to determine cache usage - seqno = (Long)dform.get("seqno"); + Long seqno = (Long)dform.get("seqno"); if (seqno == null) { log.debug("(re-)initializing cache"); @@ -223,7 +224,7 @@ else if (!submitted && request.getAttribute("machine") != null) { start = dpresults.getStart().getDate().getTime(); end = dpresults.getEnd().getDate().getTime(); - cacheSeqno = (Long)session.getAttribute("auditCacheSeqno"); + Long cacheSeqno = (Long)session.getAttribute("auditCacheSeqno"); // if the cached seqno is greater or equal to the seqno the browser // sent, we've seen it before; do a new search @@ -237,7 +238,7 @@ else if (!submitted && request.getAttribute("machine") != null) { else { log.debug("using cached result"); // may be null (indicates the cached result was null) - result = (List)session.getAttribute("auditResultCache"); + result = (List)session.getAttribute("auditResultCache"); } if (result == null) { diff --git a/java/code/src/com/redhat/rhn/frontend/dto/AuditDto.java b/java/code/src/com/redhat/rhn/frontend/dto/AuditDto.java index b45528126630..520653ae481b 100644 --- a/java/code/src/com/redhat/rhn/frontend/dto/AuditDto.java +++ b/java/code/src/com/redhat/rhn/frontend/dto/AuditDto.java @@ -14,6 +14,7 @@ */ package com.redhat.rhn.frontend.dto; +import java.io.Serializable; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; @@ -21,7 +22,7 @@ /** * AuditDto */ -public class AuditDto extends BaseDto { +public class AuditDto extends BaseDto implements Serializable { private Long id; private int serial; private Date time; diff --git a/java/code/src/com/redhat/rhn/manager/audit/AuditManager.java b/java/code/src/com/redhat/rhn/manager/audit/AuditManager.java index 8bec5c264314..cb6e4544fa87 100644 --- a/java/code/src/com/redhat/rhn/manager/audit/AuditManager.java +++ b/java/code/src/com/redhat/rhn/manager/audit/AuditManager.java @@ -16,6 +16,7 @@ import com.redhat.rhn.common.conf.Config; import com.redhat.rhn.common.db.datasource.DataResult; +import com.redhat.rhn.common.util.FileUtils; import com.redhat.rhn.frontend.dto.AuditDto; import com.redhat.rhn.frontend.dto.AuditMachineDto; import com.redhat.rhn.frontend.dto.AuditReviewDto; @@ -29,6 +30,7 @@ import java.io.FileWriter; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -78,56 +80,35 @@ public static void markReviewed(String machine, Long start, Long end, String use * @param end The end time; can be null * @return The set of matching audit logs */ - public static DataResult getAuditLogs(String[] types, String machine, - Long start, Long end) { - DataResult dr = null; - List l; - Long fileStart, fileEnd; + public static DataResult getAuditLogs(String[] types, String machine, long start, long end) { + DataResult dr = new DataResult<>(new ArrayList<>()); if (types == null) { types = new String[0]; } - if (start == null) { - start = 0L; - } - - if (end == null) { - end = Long.MAX_VALUE; - } - try { - DataResult aureviewsections = getMachineReviewSections(machine); - if (aureviewsections != null) { - for (AuditReviewDto aureview : getMachineReviewSections(machine)) { - fileStart = aureview.getStart().getTime(); - fileEnd = aureview.getEnd().getTime(); - - if (fileEnd < start || fileStart > end) { - continue; - } + for (AuditReviewDto aureview : getMachineReviewSections(machine)) { + long fileStart = aureview.getStart().getTime(); + long fileEnd = aureview.getEnd().getTime(); - File auditLog = new File( - logDirStr + "/" + aureview.getName() + "/audit/audit-" + - (fileStart / 1000) + "-" + - (fileEnd / 1000) + ".parsed"); + if (fileEnd < start || fileStart > end) { + continue; + } - l = readAuditFile(auditLog, types, start, end); + File auditLog = new File( + logDirStr + File.separator + aureview.getName() + "/audit/audit-" + + (fileStart / 1000) + "-" + + (fileEnd / 1000) + ".parsed"); - if (dr == null) { - dr = new DataResult(l); - } - else { - dr.addAll(l); - } - } + dr.addAll(readAuditFile(auditLog, types, start, end)); } } catch (IOException ioex) { log.warn("AAAAHHHH IOException", ioex); } - if (dr == null || dr.isEmpty()) { + if (dr.isEmpty()) { return null; } @@ -219,12 +200,9 @@ public static AuditReviewDto getFirstUnreviewed(String machineName) { DataResult dr = getMachineReviewSections(machineName); for (AuditReviewDto aurev : dr) { - if (aurev.getReviewedBy() == null) { // an unreviewed log! - if (firstUnreviewed == null || - aurev.getStart().getTime() < - firstUnreviewed.getStart().getTime()) { - firstUnreviewed = aurev; - } + if (aurev.getReviewedBy() == null && // an unreviewed log! + (firstUnreviewed == null || aurev.getStart().getTime() < firstUnreviewed.getStart().getTime())) { + firstUnreviewed = aurev; } } @@ -241,12 +219,9 @@ public static AuditReviewDto getLastReview(String machineName) { DataResult dr = getMachineReviewSections(machineName); for (AuditReviewDto aurev : dr) { - if (aurev.getReviewedOn() != null) { - if (lastReviewed == null || - aurev.getReviewedOn().getTime() > - lastReviewed.getReviewedOn().getTime()) { - lastReviewed = aurev; - } + if (aurev.getReviewedOn() != null && (lastReviewed == null || + aurev.getReviewedOn().getTime() > lastReviewed.getReviewedOn().getTime())) { + lastReviewed = aurev; } } @@ -303,48 +278,28 @@ public static DataResult getMachines() { * @param machineName The machine to get review sections for; can be null * @return The set of review sections */ - public static DataResult getMachineReviewSections( - String machineName) { - long start, end; - DataResult dr, rec; - File hostDir; + public static DataResult getMachineReviewSections(String machineName) { LinkedList aurevs = new LinkedList<>(); - Matcher fnmatch; Pattern fnregex = Pattern.compile("audit-(\\d+)-(\\d+).parsed"); // if machineName is null, look up all review sections by recursion if (machineName == null || machineName.isEmpty()) { - dr = null; - - for (AuditMachineDto aumachine : getMachines()) { - if (aumachine.getName() != null) { - rec = getMachineReviewSections(aumachine.getName()); - - if (dr == null) { - dr = rec; - } - else { - dr.addAll(rec); - } - } - } - - return dr; + return getMachines().stream().filter(m -> m.getName() != null) + .map(aumachine -> getMachineReviewSections(aumachine.getName())) + .reduce(new DataResult<>(new ArrayList<>()), (dr, element) -> { + dr.addAll(element); + return dr; + }); } // otherwise, just look up this one machine - hostDir = Path.of(logDirStr, machineName.replace(File.separator, ""), "audit").toFile(); - - if (!hostDir.exists()) { - return new DataResult(new LinkedList<>()); - } - - for (String auditLog : hostDir.list()) { - fnmatch = fnregex.matcher(auditLog); + Path path = Path.of(logDirStr, machineName.replace(File.separator, ""), "audit"); + for (String auditLog : FileUtils.listFolder(path)) { + Matcher fnmatch = fnregex.matcher(auditLog); if (fnmatch.matches()) { // found a matching audit file - start = Long.parseLong(fnmatch.group(1)) * 1000; - end = Long.parseLong(fnmatch.group(2)) * 1000; + long start = Long.parseLong(fnmatch.group(1)) * 1000; + long end = Long.parseLong(fnmatch.group(2)) * 1000; try { // but is it reviewed yet? aurevs.add(getReviewInfo(machineName, start, end)); @@ -357,9 +312,7 @@ public static DataResult getMachineReviewSections( } Collections.sort(aurevs); - dr = new DataResult<>(aurevs); - - return dr; + return new DataResult<>(aurevs); } /**