/* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.sun.com/cddl/cddl.html or
* install_dir/legal/LICENSE
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at install_dir/legal/LICENSE.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id$
*
* Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved
*/
package com.sun.faban.harness.webclient;
import com.sun.faban.common.SortDirection;
import com.sun.faban.common.SortableTableModel;
import com.sun.faban.harness.ParamRepository;
import com.sun.faban.harness.common.BenchmarkDescription;
import com.sun.faban.harness.common.Config;
import com.sun.faban.harness.common.RunId;
import com.sun.faban.harness.engine.RunQ;
import com.sun.faban.harness.security.AccessController;
import com.sun.faban.harness.util.FileHelper;
import com.sun.faban.harness.util.XMLReader;
import javax.security.auth.Subject;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Result class scans through the output directory and compiles a list of run
* results. Enhance this to enable the user to sort it using different options.
*/
public class RunResult {
/**
* Status and result values when they are not available. The
* 6 character string with all lower case 'z' is after any other
* possible status string or result string in the collation sequence.
*/
private static final String NOT_AVAILABLE = "zzzzzz";
private static final String[] EMPTY_ARRAY = new String[0];
private static final int FEED_LIMIT = 25;
private static Logger logger = Logger.getLogger(RunResult.class.getName());
private static ConcurrentHashMap<String, RunResult> resultCache =
new ConcurrentHashMap<String, RunResult>(1024);
// The format in the result file
private SimpleDateFormat parseFormat = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss z yyyy");
private static SimpleDateFormat dateFormatOrig = new SimpleDateFormat(
"MM/dd/yy EEE' 'HH:mm:ss' 'z");
private long modTime = 0;
/** The run id. */
public RunId runId;
/** The run description. */
public String description;
/** The result. */
public String result;
/** The link for the result to link to. */
public String resultLink;
/** The name of the scale. */
private String scaleName;
/** The scale value. */
public String scale;
/** The unit of the scale. */
private String scaleUnit;
/** The metric. */
public ResultField<Double> metric = new ResultField<Double>();
/** The unit of the metric. */
private String metricUnit;
/** The status of the run. */
public String status;
/** The link to the run logs. */
public String logLink;
/** The timestamp of the run. */
public Date dateTime;
/** The run submitter. */
public String submitter;
/** Tags applicable to this run. */
public String[] tags;
static LinkedHashMap<String, Target> targetMap = new LinkedHashMap<String, Target>();
/**
* This getInstance0 assumes you've checked the run id is found. It will
* return an instance. If the run id is not there, the behavior is not
* defined. This is why it is a private interface.
* @param runId The run id of the run
* @return A result instance.
*/
private static RunResult getInstance0(RunId runId) {
RunResult result = new RunResult(runId);
RunResult oldResult = resultCache.putIfAbsent(runId.toString(), result);
if (oldResult != null)
result = oldResult;
try {
result.refresh();
} catch (RuntimeException e) {
logger.log(Level.WARNING, runId.toString() +
": Error reading run.", e);
result.description = "Error reading this result";
}
return result;
}
/**
* Obtains the result of a certain run id.
* @param runId The run id to query
* @return An instance of the result, or null if such runId is not found
*/
public static RunResult getInstance(RunId runId) {
if (runId.getResultDir().isDirectory())
return getInstance0(runId);
return null;
}
private RunResult(RunId runId) {
this.runId = runId;
}
private synchronized void refresh() {
File resultDir = runId.getResultDir();
long modTime = resultDir.lastModified();
if (modTime <= this.modTime) {
logger.finer("Run " + runId + " already cached.");
return;
}
logger.finer("Fetching run " + runId + " from disk.");
this.modTime = modTime;
String shortName = runId.getBenchName();
String resultFilePath;
String configFileName;
BenchmarkDescription desc = BenchmarkDescription.
getDescription(shortName, resultDir.getAbsolutePath());
if (desc == null) {
Map<String, BenchmarkDescription> benchMap =
BenchmarkDescription.getBenchDirMap();
desc = (BenchmarkDescription) benchMap.get(shortName);
}
if (desc == null) {
logger.warning(runId.toString() + ": Cannot find benchmark " +
"description in result and benchmark not deployed, " +
"trying default values");
// Assigning default values;
resultFilePath = "summary.xml";
configFileName = "run.xml";
} else {
resultFilePath = desc.resultFilePath;
configFileName = desc.configFileName;
scaleName = desc.scaleName;
scaleUnit = desc.scaleUnit;
metricUnit = desc.metric;
}
String[] statusFileContent = readStatus(runId.toString());
// run result and HREF to the summary or log file.
File resultFile = new File(resultDir, "summary.xml");
if (resultFile.exists() && resultFile.length() > 0) {
result = "PASSED";
resultLink = "/resultframe.jsp?runId=" +
this.runId + "&result=" +
resultFilePath;
//Use the XMLReader and locate the <passed> elements
XMLReader reader = new XMLReader(resultFile.
getAbsolutePath());
// Obtain the metric before we break pass/fail.
metric.text = reader.getValue("benchSummary/metric");
if (metric.text != null && metric.text.length() > 0)
metric.value = new Double(metric.text);
try {
dateTime = parseFormat.parse(
reader.getValue("benchSummary/endTime"));
} catch (ParseException e) {
// Do nothing. result.dateTime will be null and
// later we'll use the param file's mod dateTime
// for this field instead.
}
List<String> passedList = reader.getValues("passed");
for(String passed : passedList) {
if(passed.toUpperCase().indexOf("FALSE") != -1) {
result = "FAILED";
break;
}
}
}
status = statusFileContent[0];
if (!"UNKNOWN".equals(status) ||
new File(resultDir, "log.xml").isFile()) {
StringBuilder b = new StringBuilder(
"/resultframe.jsp?runId=");
b.append(this.runId);
b.append("&result=");
b.append(resultFilePath);
b.append("&show=logs");
logLink = b.toString();
} else {
logLink = "";
}
if (dateTime == null && statusFileContent[1] != null) {
try {
dateTime = parseFormat.parse(statusFileContent[1]);
} catch (ParseException e) {
// Do nothing. result.dateTime will be null and
// later we'll use the param file's mod dateTime
// for this field instead.
}
}
String paramFileName = resultDir.getAbsolutePath() +
File.separator + configFileName;
File paramFile = new File(paramFileName);
if (paramFile.isFile()) {
// Compatible with old versions of Config.RESULT_INFO
// Old version does not have timestamp in RESULT_INFO
// So we need to establish it from the paramFile timestamp.
// This block may be removed in future.
if (dateTime == null) {
dateTime = new Date(paramFile.lastModified());
}
// End compatibility block
ParamRepository par = new ParamRepository(paramFileName, false);
description = par.getParameter("fa:runConfig/fh:description");
scale = par.getParameter("fa:runConfig/fa:scale");
} else {
logger.warning(runId.toString() +
": Parameter file invalid or non-existent.");
}
File submitterFile = new File(resultDir, "META-INF" + File.separator +
"submitter");
if (submitterFile.exists())
try {
submitter = FileHelper.readStringFromFile(submitterFile).trim();
} catch (IOException e) {
logger.log(Level.WARNING, "Error reading submitter file for " +
"run " + runId, e);
}
File tagsFile = new File(resultDir, "META-INF" + File.separator +
"tags");
if (tagsFile.exists()) {
try {
tags = FileHelper.readArrayContentFromFile(tagsFile);
} catch (IOException e) {
logger.log(Level.WARNING, "Error reading tags file for " +
"run " + runId, e);
}
}else{
tags = new String[1];
tags[0] = " ";
}
}
/**
* Obtains the current status of a run.
* @param runId The id of the run in question
* @return The current status string or "UNKNOWN" in error cases
*/
public static String[] readStatus(String runId) {
char[] cBuf = null;
String[] status = new String[2];
int length = -1;
try {
FileReader reader = new FileReader(Config.OUT_DIR + runId +
'/' + Config.RESULT_INFO);
cBuf = new char[128];
length = reader.read(cBuf);
reader.close();
} catch (IOException e) {
// Do nothing, length = -1.
}
if (length == -1) {
status[0] = "UNKNOWN";
} else {
String content = new String(cBuf, 0, length);
int idx = content.indexOf('\t');
if (idx != -1) {
status[0] = content.substring(0, idx).trim();
status[1] = content.substring(++idx);
} else {
status[0] = content.trim();
}
}
return status;
}
/**
* Obtains the status of a given run. If it is queued, returns "QUEUED"
* @param runId The run id to obtain status
* @return The status string, or null if run cannot be found.
*/
public static String getStatus(RunId runId) {
String status = null;
RunResult result = getInstance(runId);
if (result == null) {
// Perhaps the runId is still in the pending queue.
String[] pending = RunQ.listPending();
for (String run : pending)
if (run.equals(runId.toString())) {
status = "QUEUED";
break;
}
if (status == null) {
return null;
}
} else {
status = result.status;
}
if (status == null) // Worse come to worse, the run dir is in bad shape.
status = "UNKNOWN";
return status;
}
/**
* Returns the SortableTableModel with tag search.
* @param user
* @param tags
* @param column
* @param sortDirection
* @return SortableTableModel
* @throws java.io.IOException
*/
public static SortableTableModel getResultTable(Subject user, String tags,
int column, String sortDirection)
throws IOException {
TagEngine tagEngine;
try {
tagEngine = TagEngine.getInstance();
} catch (ClassNotFoundException ex) {
logger.log(Level.SEVERE, "Cannot find tag engine class", ex);
throw new IOException("Cannot find tag engine class", ex);
}
Set<String> runIds = tagEngine.search(tags);
ArrayList<RunResult> resultList =
new ArrayList<RunResult>(runIds.size());
for (String runid : runIds) {
try {
RunId runId = new RunId(runid);
if (!AccessController.isViewAllowed(user, runid))
continue;
RunResult res = getInstance(runId);
if (res == null){
try{
tagEngine.removeRun(runid);
tagEngine.save();
} catch (Exception e) {
logger.log(Level.WARNING, "Cannot remove run " + runid, e);
}
} else
resultList.add(res);
} catch (Exception e) {
logger.log(Level.WARNING, "Cannot read result dir " + runid, e);
}
}
return generateTable(resultList, column, sortDirection);
}
/**
* Returns the SortableTableModel.
* @param user The authenticated subject, if any
* @param column The sort column id
* @param sortDirection The sort direction
* @return The SortableTableModel representing this table
*/
public static SortableTableModel getResultTable(Subject user, int column,
String sortDirection) {
File[] dirs = new File(Config.OUT_DIR).listFiles();
ArrayList<RunResult> runs = new ArrayList<RunResult>(dirs.length);
for (File runDir : dirs) {
if (!runDir.isDirectory()) {
continue;
}
String runIdS = runDir.getName();
try {
if (!AccessController.isViewAllowed(user, runIdS) || runIdS.contains("analysis")) {
continue;
}
RunId runId = new RunId(runIdS);
RunResult result = getInstance0(runId);
if (result == null) {
continue;
}
runs.add(result);
} catch (Exception e) {
logger.log(Level.WARNING, "Cannot read result dir " + runIdS,
e);
}
}
return generateTable(runs, column, sortDirection);
}
/**
* Generates the table.
* @param runs The runs to include in the table
* @param column The sort column
* @param sortDirection The sort direction
* @return The SortableTableModel
*/
static SortableTableModel generateTable(List<RunResult> runs, int column,
String sortDirection) {
HashSet<String> scaleNames = new HashSet<String>();
HashSet<String> scaleUnits = new HashSet<String>();
HashSet<String> metricUnits = new HashSet<String>();
// 1. Scan result for scale names, units and metric units
RunResult result0 = null;
for (RunResult result : runs) {
if (result.scaleName != null)
scaleNames.add(result.scaleName);
else
scaleNames.add("Scale");
if (result.scaleUnit != null)
scaleUnits.add(result.scaleUnit);
if (result.metricUnit != null)
metricUnits.add(result.metricUnit);
else
metricUnits.add("Metric");
if (result0 == null)
result0 = result;
}
if (result0 == null) // No rows!
return null;
// 2. Generate table header
SortableTableModel table = new SortableTableModel(9);
String sort = "<img src=/img/sort_asc.gif></img>";
if(sortDirection.equals("DESCENDING")){
sort = "<img src=\"/img/sort_asc.gif\" border=\"0\"></img>";
}else if(sortDirection.equals("ASCENDING")){
sort = "<img src=\"/img/sort_desc.gif\" border=\"0\"></img>";
}
if(column == 0)
table.setHeader(0, "RunID " + sort);
else
table.setHeader(0, "RunID");
if(column == 1)
table.setHeader(1, "Description " + sort);
else
table.setHeader(1, "Description");
if(column == 2)
table.setHeader(2, "Result " + sort);
else
table.setHeader(2, "Result");
boolean singleScale = false;
if (scaleNames.size() == 1 && scaleUnits.size() == 1) {
singleScale = true;
if (result0.scaleName.length() > 0 &&
result0.scaleUnit.length() > 0){
table.setHeader(3, result0.scaleName + " (" +
result0.scaleUnit + ')');
}else if (result0.scaleName.length() > 0){
table.setHeader(3, result0.scaleName);
}else if (result0.scaleUnit.length() > 0){
table.setHeader(3, result0.scaleUnit);
}else{
if(column == 3)
table.setHeader(3, "Scale " + sort);
else
table.setHeader(3, "Scale");
}
} else {
if(column == 3)
table.setHeader(3, "Scale " + sort);
else
table.setHeader(3, "Scale");
}
boolean singleMetric = false;
if (metricUnits.size() == 1) {
singleMetric = true;
if (result0.metricUnit.length() > 0){
table.setHeader(4, result0.metricUnit);
}else{
if(column == 4)
table.setHeader(4, "Metric " + sort);
else
table.setHeader(4, "Metric");
}
} else {
if(column == 4)
table.setHeader(4, "Metric " + sort);
else
table.setHeader(4, "Metric");
}
//table.setHeader(5, "Status");
if(column == 5)
table.setHeader(5, "Date/Time " + sort);
else
table.setHeader(5, "Date/Time");
if(column == 6)
table.setHeader(6, "Submitter " + sort);
else
table.setHeader(6, "Submitter");
if(column == 7)
table.setHeader(7, "Tags " + sort);
else
table.setHeader(7, "Tags");
// Pseudo-column for the link.
table.setHeader(8, "Link");
// 3. Generate table rows.
StringBuilder b = new StringBuilder();
// The output format.
SimpleDateFormat dateFormat = (SimpleDateFormat) dateFormatOrig.clone();
for (RunResult result : runs) {
//int idx = table.newRow();
Comparable[] row = table.newRow();
row[0] = result.runId;
if (result.description == null || result.description.length() == 0)
row[1] = "UNAVAILABLE";
else
row[1] = result.description;
row[8] = ""; // Initialize the link to zero string in case it does not get set.
ResultField<String> r = new ResultField<String>();
if (result.result != null) {
r.value = result.result;
if (result.resultLink != null){
if(result.result.equals("PASSED"))
r.text = "<img onmouseover=\"showtip('" + result.result.toString() + "')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/passed.png'></img>";
else if(result.result.equals("FAILED"))
r.text = "<img onmouseover=\"showtip('" + result.result.toString() + "')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/failed.png'></img>";
row[8] = result.resultLink;
}
} else if (result.status != null) {
r.value = result.status;
if (result.logLink != null){
if(result.status.equals("FAILED"))
r.text = "<img onmouseover=\"showtip('" + result.status.toString() + "')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/incomplete.png'></img>";
else if(result.status.equals("KILLED"))
r.text = "<img onmouseover=\"showtip('" + result.status.toString() + "')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/killed.png'></img>";
else if(result.status.equals("RECEIVED"))
r.text = "<img onmouseover=\"showtip('" + result.status.toString() + "')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/received.png'></img>";
else if(result.status.equals("STARTED"))
r.text = "<img onmouseover=\"showtip('" + result.status.toString() + "')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/running.png'></img>";
else if(result.status.equals("COMPLETED"))
r.text = "<img onmouseover=\"showtip('" + result.status.toString() + "')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/failed.png'></img>";
else if(result.status.equals("UNKNOWN"))
r.text = "<img onmouseover=\"showtip('unknown')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/unknown.png'></img>";
row[8] = result.logLink;
}
} else {
r.value = NOT_AVAILABLE;
r.text = "<img onmouseover=\"showtip('unknown')\" onmouseout=\"hideddrivetip()\" class=\"icon\"; src='/img/unknown.png'></img>";
}
row[2] = r;
ResultField<Integer> scale = new ResultField<Integer>();
if (result.scale == null || result.scale.length() < 1) {
scale.text = "N/A";
scale.value = Integer.MIN_VALUE;
} else if (singleScale) {
scale.text = result.scale;
scale.value = new Integer(result.scale);
} else {
b.append(result.scale);
if (result.scaleName.length() > 0)
b.append(' ').append(result.scaleName).append(' ');
if (result.scaleUnit.length() > 0)
b.append(' ').append(result.scaleUnit);
scale.text = b.toString();
scale.value = new Integer(result.scale);
b.setLength(0);
}
row[3] = scale;
ResultField<Double> metric = new ResultField<Double>();
if (result.metric.text == null) {
metric.text = "N/A";
metric.value = -1d;
} else if (singleMetric) {
metric.text = result.metric.text;
metric.value = result.metric.value;
} else {
b.append(result.metric);
if (result.metricUnit.length() > 0)
b.append(' ').append(result.metricUnit);
metric.text = b.toString();
metric.value = result.metric.value;
b.setLength(0);
}
row[4] = metric;
/*ResultField<String> status = new ResultField<String>();
if (result.status != null) {
status.value = result.status;
if (result.logLink != null)
status.text = "<a href=\""+ result.logLink + "\">" +
result.status + "</a>";
else
status.text = result.status;
} else {
status.value = NOT_AVAILABLE;
status.text = "UNKNOWN";
}
row[5] = status;*/
ResultField<Long> dateTime = new ResultField<Long>();
if (result.dateTime != null) {
dateTime.text = dateFormat.format(result.dateTime);
dateTime.value = result.dateTime.getTime();
} else {
dateTime.text = "N/A";
dateTime.value = 0l;
}
row[5] = dateTime;
if (result.submitter != null)
row[6] = result.submitter;
else
row[6] = " ";
if (result.tags != null && result.tags.length > 0) {
for (String tag : result.tags) {
b.append(tag).append(' ');
}
b.setLength(b.length() - 1);
row[7] = b.toString();
b.setLength(0);
} else {
row[7] = " ";
}
}
SortDirection enumValForDirection = SortDirection.valueOf(sortDirection);
table.sort(column, enumValForDirection);
return table;
}
/*
* Deletes a certain run.
* @param RunId of run run to delete
* @return true if delete succeeds, false otherwise
*/
public boolean delete(String runIdStr) {
RunId runId = new RunId(runIdStr);
File f = runId.getResultDir();
if (f.isDirectory()) {
return(FileHelper.recursiveDelete(f));
}
return(true);
}
private static HashMap<String, String> getAchievedMetricForTarget(String tags)
throws IOException {
HashMap<String, String> achievedMetricMap = new HashMap<String, String>();
TagEngine tagEngine;
try {
tagEngine = TagEngine.getInstance();
} catch (ClassNotFoundException ex) {
logger.log(Level.SEVERE, "Cannot find tag engine class", ex);
throw new IOException("Cannot find tag engine class", ex);
}
Set<String> runIds = tagEngine.search(tags);
Double achievedMetric = 0.0;
String achievedMetricUnit = " ";
for (String runid : runIds) {
try {
RunId runId = new RunId(runid);
RunResult res = getInstance(runId);
if (res != null && achievedMetric < res.metric.value){
achievedMetric = res.metric.value;
achievedMetricUnit = res.metricUnit;
}
} catch (Exception e) {
logger.log(Level.WARNING, "Cannot read result dir " + runid, e);
}
}
achievedMetricMap.put("metric", achievedMetric.toString());
achievedMetricMap.put("metricunit", achievedMetricUnit);
return achievedMetricMap;
}
/**
* Returns the target list with target search.
* @param target
* @return ArrayList
* @throws java.io.IOException
*/
public static ArrayList<Target> getTargetListForTarget(String target)
throws IOException {
ArrayList<Target> targetList = getTargetList();
if(target != null ){
targetList = new ArrayList<Target>();
Object[] keyset = targetMap.keySet().toArray();
for (int i = 0; i < keyset.length; i++) {
if (keyset[i].toString().contains(target) && targetMap.containsKey(keyset[i])) {
targetList.add(targetMap.get(keyset[i]));
}
}
}
return targetList;
}
public static ArrayList<Target> getTargetListForUserWithTg(String target, String user)
throws IOException {
ArrayList<Target> list = new ArrayList<Target>();
if(target != null && user != null){
ArrayList<Target> targetList = getTargetListForTarget(target);
for (int i = 0; i < targetList.size(); i++) {
String owner = targetList.get(i).owner.toString();
if (owner.equals(user)) {
list.add(targetList.get(i));
}
}
}
return list;
}
public static ArrayList<Target> getTargetListForUser(String user)
throws IOException {
ArrayList<Target> list = new ArrayList<Target>();
if(user != null){
ArrayList<Target> targetList = getTargetList();
for (int i = 0; i < targetList.size(); i++) {
String owner = targetList.get(i).owner.toString();
if (owner.equals(user)) {
list.add(targetList.get(i));
}
}
}
return list;
}
static SortableTableModel generateTargetTable(List<Target> targets, int column,
String sortDirection) {
// 1. Generate table header
SortableTableModel table = new SortableTableModel(9);
String sort = "<img src=/img/sort_asc.gif></img>";
if(sortDirection.equals("DESCENDING")){
sort = "<img src=\"/img/sort_asc.gif\" border=\"0\"></img>";
}else if(sortDirection.equals("ASCENDING")){
sort = "<img src=\"/img/sort_desc.gif\" border=\"0\"></img>";
}
if(column == 0)
table.setHeader(0, "Targets " + sort);
else
table.setHeader(0, "Targets");
if(column == 1)
table.setHeader(1, "Owner " + sort);
else
table.setHeader(1, "Owner");
if(column == 2)
table.setHeader(2, "Status " + sort);
else
table.setHeader(2, "Status");
if(column == 3)
table.setHeader(3, "Achieved Metric " + sort);
else
table.setHeader(3, "Achieved Metric");
if(column == 4)
table.setHeader(4, "Metric " + sort);
else
table.setHeader(4, "Metric");
if(column == 5)
table.setHeader(5, "Tags " + sort);
else
table.setHeader(5, "Tags");
// 2. Generate table rows.
for (Target target : targets) {
//int idx = table.newRow();
Comparable[] row = table.newRow();
row[0] = target.name;
row[1] = target.owner;
row[2] = target.status;
row[3] = target.achievedMetric+ " " + target.achievedMetricunit;
row[4] = target.metric + " " + target.metricunit;
row[5] = target.tags;
row[6] = target.red;
row[7] = target.orange;
row[8] = target.yellow;
}
SortDirection enumValForDirection = SortDirection.valueOf(sortDirection);
table.sort(column, enumValForDirection);
return table;
}
/**
* Obtains a list of targets currently in the system.
* @return The list of targets or an empty list if none available
* @throws IOException Error accessing targets file
*/
public static ArrayList<Target> getTargetList() throws IOException{
ArrayList<Target> targetList = new ArrayList<Target>();
File targetFile = new File(Config.CONFIG_DIR, "targets.xml");
if (targetFile.exists() && targetFile.length() > 0) {
//Use the XMLReader and locate the <passed> elements
XMLReader reader = new XMLReader(targetFile.
getAbsolutePath());
if (reader != null) {
NodeList targets = reader.getNodeListForTagName("target");
int targetCount;
if((targetCount = targets.getLength()) > 0) {
for (int i = 0; i < targetCount; i++) {
Target tg = new Target();
Node targetNode = targets.item(i);
if (targetNode.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
Element se = (Element) targetNode;
NodeList targetNodeChildNodes =
targetNode.getChildNodes();
int len = targetNodeChildNodes.getLength();
for (int k = 0; k < len; k++) {
if (targetNodeChildNodes.item(k).getNodeType() ==
Node.ELEMENT_NODE) {
String nodeName = targetNodeChildNodes.item(k).
getNodeName();
if ("name".equals(nodeName)) {
tg.name = reader.getValue("name", se);
} else if ("owner".equals(nodeName)) {
tg.owner = reader.getValue("owner", se);
} else if ("tags".equals(nodeName)) {
tg.tags = reader.getValue("tags", se);
} else if ("metric".equals(nodeName)) {
tg.metric = reader.getValue("metric", se);
} else if ("metricunit".equals(nodeName)) {
tg.metricunit = reader.getValue(
"metricunit", se);
} else if ("red".equals(nodeName)) {
tg.red = reader.getValue("red", se);
} else if ("orange".equals(nodeName)) {
tg.orange = reader.getValue("orange", se);
} else if ("yellow".equals(nodeName)) {
tg.yellow = reader.getValue("yellow", se);
}
}
}
HashMap<String, String> achievedMetricMap =
getAchievedMetricForTarget(tg.tags);
tg.achievedMetric = achievedMetricMap.get("metric");
tg.achievedMetricunit =
achievedMetricMap.get("metricunit");
Double status = ((Double.parseDouble(tg.achievedMetric)/
Double.parseDouble(tg.metric)) * 100);
tg.status = status.toString();
targetList.add(tg);
targetMap.put(tg.name.toString(), tg);
}
}
}
}
return targetList;
}
/**
* A result field representing the real value of the field used for
* sorting, and the text representation of the value.
*/
public static class ResultField<T extends Comparable>
implements Comparable {
String text;
T value;
public int compareTo(Object o) {
ResultField other = (ResultField) o;
return value.compareTo(other.value);
}
@Override
public String toString() {
return text;
}
}
/**
* The feed record for the run results.
*/
public static class FeedRecord {
/** The feed title. */
public String title;
/** The feed summary. */
public String summary;
/** The feed id. */
public String id;
/** Timestamp. */
long date;
/** The formatted timestamp. */
public String updated;
/** Resource URL. */
public String link;
/** List of tags on the resource. */
public String[] tags;
FeedRecord(RunId runId, RunResult result) {
StringBuilder b = new StringBuilder();
b.append(runId).append(" [").append(result.scale);
if (result.metric.value != null)
b.append(", ").append(result.metric.text);
// If result.result is valid, use it. Otherwise, use result.status.
if (result.result != null)
b.append(", ").append(result.result);
else if (result.status != null)
b.append(", ").append(result.status);
b.append(']');
title = b.toString();
summary = result.description;
id = runId.toString();
link = "/controller/results/location/" + runId;
date = result.dateTime.getTime();
if (result.tags == null)
tags = EMPTY_ARRAY;
else
tags = result.tags;
}
}
/**
* Obtains the list of feeds.
* @param user
* @return List<FeedRecord>.
*/
public static List<FeedRecord> getFeeds(Subject user) {
File[] dirs = new File(Config.OUT_DIR).listFiles();
ArrayList<FeedRecord> feedList = new ArrayList<FeedRecord>(dirs.length);
RunResult result0 = null;
for (File runDir : dirs) {
if (!runDir.isDirectory())
continue;
String runIdS = runDir.getName();
try {
RunId runId = new RunId(runIdS);
if (!AccessController.isViewAllowed(user, runIdS))
continue;
result0 = getInstance0(runId);
FeedRecord feedRecord = new FeedRecord(runId, result0);
feedList.add(feedRecord);
} catch (Exception e) {
logger.log(Level.WARNING, "Cannot read result dir " + runIdS,
e);
}
}
return sortAndLimit(feedList);
}
/**
* Obtains the list of feeds based on tags.
* @param user
* @param tags
* @return List<FeedRecord>
* @throws java.io.IOException
*/
public static List<FeedRecord> getFeeds(Subject user, String[] tags)
throws IOException {
TagEngine tagEngine;
try {
tagEngine = TagEngine.getInstance();
} catch (ClassNotFoundException ex) {
logger.log(Level.SEVERE, "Cannot find tag engine class", ex);
throw new IOException("Cannot find tag engine class", ex);
}
Set<String> runIds = tagEngine.search(tags);
ArrayList<FeedRecord> feedList =
new ArrayList<FeedRecord>(runIds.size());
RunResult res = null;
boolean runRemoved = false;
for (String runid : runIds) {
try {
RunId runId = new RunId(runid);
if (!AccessController.isViewAllowed(user, runid))
continue;
res = getInstance(runId);
if (res == null){
tagEngine.removeRun(runid);
runRemoved = true;
}
FeedRecord feedRecord = new FeedRecord(runId, res);
feedList.add(feedRecord);
} catch (Exception e) {
logger.log(Level.WARNING, "Cannot read result dir " + runid, e);
}
}
if (runRemoved)
tagEngine.save();
return sortAndLimit(feedList);
}
private static List<FeedRecord> sortAndLimit(List<FeedRecord> feedList) {
// Sort the list, newest first.
Collections.sort(feedList, new Comparator<FeedRecord>() {
public int compare(FeedRecord a, FeedRecord b) {
if (a.date > b.date)
return -1;
else if (a.date < b.date)
return 1;
else
return 0;
}
});
// Then limit to FEED_LIMIT (25) items.
if (feedList.size() > FEED_LIMIT)
return feedList.subList(0, FEED_LIMIT);
return feedList;
}
public static class Target implements Serializable {
public String name;
public String owner;
public String tags;
public String runs;
public String status;
public String metric;
public String metricunit;
public String achievedMetric;
public String achievedMetricunit;
public String red;
public String orange;
public String yellow;
}
}