/* * Sun Public License * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is available at http://www.sun.com/ * * The Original Code is the SLAMD Distributed Load Generation Engine. * The Initial Developer of the Original Code is Neil A. Wilson. * Portions created by Neil A. Wilson are Copyright (C) 2004-2010. * Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): Neil A. Wilson */ package com.slamd.admin; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; import com.sleepycat.je.DatabaseException; import com.slamd.common.Constants; import com.slamd.common.DurationParser; import com.slamd.common.SLAMDException; import com.slamd.db.JobFolder; import com.slamd.job.Job; import com.slamd.job.JobClass; import com.slamd.job.OptimizationAlgorithm; import com.slamd.job.OptimizingJob; import com.slamd.job.SingleStatisticOptimizationAlgorithm; import com.slamd.jobgroup.JobGroup; import com.slamd.jobgroup.JobGroupItem; import com.slamd.jobgroup.JobGroupJob; import com.slamd.jobgroup.JobGroupOptimizingJob; import com.slamd.parameter.InvalidValueException; import com.slamd.parameter.LabelParameter; import com.slamd.parameter.Parameter; import com.slamd.parameter.ParameterList; import com.slamd.parameter.PlaceholderParameter; import com.slamd.server.SLAMDServerException; import static com.unboundid.util.StaticUtils.secondsToHumanReadableDuration; import static com.slamd.admin.AdminJob.*; import static com.slamd.admin.AdminServlet.*; import static com.slamd.admin.AdminUI.*; /** * This class provides a set of methods for providing logic for managing job * groups. */ public class AdminJobGroup { /** * Handles all processing related to viewing information about the job groups * defined in the SLAMD server. * * @param requestInfo The state information for this request. */ static void handleViewJobGroups(RequestInfo requestInfo) { logMessage(requestInfo, "In handleViewJobGroups()"); // Get the important state information for this request. String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to view job information to do anything here if (! requestInfo.mayViewJob) { logMessage(requestInfo, "No mayViewJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "view job group information"); return; } htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Manage Job Groups</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); // Get a list of the available job groups. JobGroup[] jobGroups; try { jobGroups = configDB.getSummaryJobGroups(); } catch (DatabaseException de) { infoMessage.append("ERROR -- Unable to retrieve the list of job groups " + "defined in the configuration: " + de.getMessage() + EOL); return; } if ((jobGroups == null) || (jobGroups.length == 0)) { htmlBody.append("No job groups have been defined in the SLAMD server." + EOL); htmlBody.append("<BR><BR>" + EOL); } else { htmlBody.append("The following job groups have been defined in the " + "SLAMD server:" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<UL>" + EOL); for (int i=0; i < jobGroups.length; i++) { String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroups[i].getName(), jobGroups[i].getName()); String description = jobGroups[i].getDescription(); htmlBody.append(" <LI>" + link); if ((description != null) && (description.length() > 0)) { htmlBody.append(" -- " + description); } htmlBody.append("</LI>" + EOL); } htmlBody.append("</UL>" + EOL); htmlBody.append("<BR><BR>" + EOL); } if (requestInfo.mayScheduleJob) { htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_ADD_GROUP) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Create a New Job " + "Group\">" + EOL); htmlBody.append("</FORM>" + EOL); } } /** * Handles all processing related to viewing information about a job group * defined in the SLAMD server. * * @param requestInfo The state information for this request. */ static void handleViewJobGroup(RequestInfo requestInfo) { logMessage(requestInfo, "In handleViewJobGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; // The user must be able to view job information to do anything here if (! requestInfo.mayViewJob) { logMessage(requestInfo, "No mayViewJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "view job group information"); return; } // Get the name of the job group to view. String groupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); handleViewJobGroup(requestInfo, groupName); } /** * Handles all processing related to viewing information about a job group * defined in the SLAMD server. * * @param requestInfo The state information for this request. * @param jobGroupName The name of the job group to view. */ static void handleViewJobGroup(RequestInfo requestInfo, String jobGroupName) { logMessage(requestInfo, "In handleViewJobGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to view job information to do anything here if (! requestInfo.mayViewJob) { logMessage(requestInfo, "No mayViewJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "view job group information"); return; } if ((jobGroupName == null) || (jobGroupName.length() == 0)) { infoMessage.append("ERROR: No job group name was specified.<BR>" + EOL); handleViewJobGroups(requestInfo); return; } // Get the requested job group from the configuration database. JobGroup jobGroup; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration database."); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not decode job group \"" + jobGroupName + "\": " + e.getMessage() + ".<BR>" + EOL); return; } // See if a particular job or optimizing job has been selected. If so, then // display information about it, but only for the "view job group" // subsection. if (requestInfo.subsection.equals(Constants.SERVLET_SECTION_JOB_VIEW_GROUP)) { String jobName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME); if (jobName != null) { handleViewJobGroupJob(requestInfo, jobGroup, jobName); return; } String optimizingJobName = request.getParameter( Constants.SERVLET_PARAM_JOB_GROUP_OPTIMIZING_JOB_NAME); if (optimizingJobName != null) { handleViewJobGroupOptimizingJob(requestInfo, jobGroup, optimizingJobName); return; } } htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">View Job Group " + jobGroupName + "</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); ArrayList jobList = jobGroup.getJobList(); if (requestInfo.mayScheduleJob) { htmlBody.append("<TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); if (! jobList.isEmpty()) { htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_SCHEDULE_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Schedule " + "This Job Group\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); } htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants. SERVLET_SECTION_JOB_CLONE_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Clone This " + "Job Group\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants. SERVLET_SECTION_JOB_REMOVE_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Delete This " + "Job Group\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append("</TABLE>" + EOL); htmlBody.append("<BR><BR>" + EOL); } // If there is a description, show it. String description = jobGroup.getDescription(); if ((description != null) && (description.length() > 0)) { htmlBody.append("<B>Job Group Description</B><BR>" + EOL); htmlBody.append(description + "<BR><BR>" + EOL); } if (requestInfo.mayScheduleJob) { htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_DESCRIPTION) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName()) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Edit Job Group " + "Name/Description\">" + EOL); htmlBody.append("</FORM>" + EOL); htmlBody.append("<BR><BR>" + EOL); } htmlBody.append("<TABLE BORDER=\"0\" CELLSPACING=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Jobs Contained in This " + "Group</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobList.isEmpty()) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">There are currently no jobs in " + "this job group.</TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (requestInfo.mayScheduleJob) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_ADD_JOB_TO_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Add a " + "Job\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants. SERVLET_SECTION_JOB_ADD_OPTIMIZING_JOB_TO_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Add an " + "Optimizing Job\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } else { String style = Constants.STYLE_JOB_SUMMARY_LINE_A; String lastName = null; for (int i=0; i < jobList.size(); i++) { style = ((i % 2) == 0) ? Constants.STYLE_JOB_SUMMARY_LINE_A : Constants.STYLE_JOB_SUMMARY_LINE_B; Object o = jobList.get(i); if (o instanceof JobGroupJob) { JobGroupJob job = (JobGroupJob) o; lastName = job.getName(); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName(), Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME, lastName, lastName); htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD>" + link + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + job.getJobClass().getJobName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } else if (o instanceof JobGroupOptimizingJob) { JobGroupOptimizingJob optimizingJob = (JobGroupOptimizingJob) o; lastName = optimizingJob.getName(); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName(), Constants.SERVLET_PARAM_JOB_GROUP_OPTIMIZING_JOB_NAME, lastName, lastName); htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD>" + link + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>Optimizing " + optimizingJob.getJobClass().getJobName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } if (requestInfo.mayScheduleJob) { htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_ADD_JOB_TO_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Add a " + "Job\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants. SERVLET_SECTION_JOB_ADD_OPTIMIZING_JOB_TO_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Add an " + "Optimizing Job\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_REMOVE_JOB_FROM_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName()) + EOL); htmlBody.append(" " + generateHidden( Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME, lastName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Remove " + "Last Job from Group\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Common Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); Parameter[] groupParameters = jobGroup.getParameters().getParameters(); if ((groupParameters == null) || (groupParameters.length == 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">No common parameters have been " + "defined.</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } else { for (int i=0; i < groupParameters.length; i++) { Parameter p = groupParameters[i]; String style = ((i % 2) == 0) ? Constants.STYLE_JOB_SUMMARY_LINE_A : Constants.STYLE_JOB_SUMMARY_LINE_B; String displayName = p.getDisplayName(); if (displayName == null) { displayName = p.getName(); } description = p.getDescription(); if (description == null) { description = ""; } htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD>" + displayName + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + description + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } if (requestInfo.mayScheduleJob) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName()) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Edit Job " + "Group Parameters\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append("</TABLE>" + EOL); } /** * Handles all processing related to viewing an individual job in a job group. * * @param requestInfo The state information for this request. * @param jobGroup The job group containing the job to view. * @param jobName The name of the job to view. */ static void handleViewJobGroupJob(RequestInfo requestInfo, JobGroup jobGroup, String jobName) { logMessage(requestInfo, "In handleViewJobGroupJob()"); // Get the important state information for this request. String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to view job information to do anything here if (! requestInfo.mayViewJob) { logMessage(requestInfo, "No mayViewJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "view job group information."); return; } // Get the job to view from the job group. JobGroupJob job = null; ArrayList<JobGroupItem> jobList = jobGroup.getJobList(); for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupJob) { if (((JobGroupJob) o).getName().equals(jobName)) { job = (JobGroupJob) o; break; } } } if (job == null) { infoMessage.append("ERROR: Job \"" + jobName + "\" does not exist in " + "job group \"" + jobGroup.getName() + "\".<BR>" + EOL); return; } htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">View Job Group Job \"" + jobName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); if (requestInfo.mayScheduleJob) { htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName()) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME, jobName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Edit Job\">" + EOL); htmlBody.append("</FORM>" + EOL); htmlBody.append("<BR>" + EOL); } htmlBody.append("<TABLE BORDER=\"0\" CELLSPACING=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>General Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Job Name</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + jobName + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName(), jobGroup.getName()); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Job Group</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + link + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Job Type</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + job.getJobClass().getJobName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_CLASSES, Constants.SERVLET_PARAM_JOB_CLASS, job.getJobClass().getClass().getName(), job.getJobClass().getClass().getName()); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Job Class</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + link + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); String durationStr; if (job.getDuration() > 0) { durationStr = secondsToHumanReadableDuration(job.getDuration()); } else { durationStr = ""; } htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + durationStr + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Number of Clients</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + job.getNumClients() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Threads per Client</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + job.getThreadsPerClient() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Thread Startup Delay (ms)</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + job.getThreadStartupDelay() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Statistics Collection Interval</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + secondsToHumanReadableDuration(job.getCollectionInterval()) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); ArrayList dependencies = job.getDependencies(); if ((dependencies != null) && (! dependencies.isEmpty())) { htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Job Dependencies</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); for (int i=0; i < dependencies.size(); i++) { htmlBody.append(" " + dependencies.get(i) + "<BR>" + EOL); } htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } LinkedHashMap mappedParameters = job.getMappedParameters(); if ((mappedParameters != null) && (! mappedParameters.isEmpty())) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Mapped Job " + "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); int i=0; Iterator iterator = mappedParameters.keySet().iterator(); while (iterator.hasNext()) { String jobParamName = (String) iterator.next(); String groupParamName = (String) mappedParameters.get(jobParamName); Parameter jobParam = job.getJobClass().getParameterStubs().getParameter(jobParamName); Parameter groupParam = jobGroup.getParameters().getParameter(groupParamName); String jobParamDisplayName; if ((jobParam == null) || (jobParam.getDisplayName() == null)) { jobParamDisplayName = jobParamName; } else { jobParamDisplayName = jobParam.getDisplayName(); } String groupParamDisplayName; if ((groupParam == null) || (groupParam.getDisplayName() == null)) { groupParamDisplayName = groupParamName; } else { groupParamDisplayName = groupParam.getDisplayName(); } String style = ((i++ % 2) == 0) ? Constants.STYLE_JOB_SUMMARY_LINE_A : Constants.STYLE_JOB_SUMMARY_LINE_B; htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD>" + jobParamDisplayName + "</TD>" + EOL); htmlBody.append(" <TD> --> </TD>" + EOL); htmlBody.append(" <TD>" + groupParamDisplayName + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } Parameter[] fixedParameters = job.getFixedParameters().getParameters(); if ((fixedParameters != null) && (fixedParameters.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Fixed Job Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); for (int i=0; i < fixedParameters.length; i++) { String style = ((i % 2) == 0) ? Constants.STYLE_JOB_SUMMARY_LINE_A : Constants.STYLE_JOB_SUMMARY_LINE_B; String displayName = fixedParameters[i].getDisplayName(); if (displayName == null) { displayName = fixedParameters[i].getName(); } htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD>" + displayName + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + fixedParameters[i].getHTMLDisplayValue() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append("</TABLE>" + EOL); } /** * Handles all processing related to viewing an individual optimizing job in a * job group. * * @param requestInfo The state information for this request. * @param jobGroup The job group containing the job to view. * @param optimizingJobName The name of the optimizing job to view. */ static void handleViewJobGroupOptimizingJob(RequestInfo requestInfo, JobGroup jobGroup, String optimizingJobName) { logMessage(requestInfo, "In handleViewJobGroupJob()"); // Get the important state information for this request. String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to view job information to do anything here if (! requestInfo.mayViewJob) { logMessage(requestInfo, "No mayViewJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "view job group information."); return; } // Get the optimizing job to view from the job group. JobGroupOptimizingJob optimizingJob = null; ArrayList<JobGroupItem> jobList = jobGroup.getJobList(); for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupOptimizingJob) { if (((JobGroupOptimizingJob) o).getName().equals(optimizingJobName)) { optimizingJob = (JobGroupOptimizingJob) o; break; } } } if (optimizingJob == null) { infoMessage.append("ERROR: Optimizing job \"" + optimizingJobName + "\" does not exist in job group \"" + jobGroup.getName() + "\".<BR>" + EOL); return; } htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">View Job Group Optimizing Job \"" + optimizingJobName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); if (requestInfo.mayScheduleJob) { htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_OPTIMIZING_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName()) + EOL); htmlBody.append(" " + generateHidden( Constants.SERVLET_PARAM_JOB_GROUP_OPTIMIZING_JOB_NAME, optimizingJobName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Edit Optimizing " + "Job\">" + EOL); htmlBody.append("</FORM>" + EOL); htmlBody.append("<BR>" + EOL); } htmlBody.append("<TABLE BORDER=\"0\" CELLSPACING=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>General Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Optimizing Job Name</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJobName + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName(), jobGroup.getName()); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Job Group</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + link + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Job Type</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJob.getJobClass().getJobName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_CLASSES, Constants.SERVLET_PARAM_JOB_CLASS, optimizingJob.getJobClass().getClass().getName(), optimizingJob.getJobClass().getClass().getName()); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Job Class</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + link + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); String durationStr; if (optimizingJob.getDuration() > 0) { durationStr = secondsToHumanReadableDuration(optimizingJob.getDuration()); } else { durationStr = ""; } htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + durationStr + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Delay Between Iterations</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJob.getDelayBetweenIterations() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Number of Clients</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJob.getNumClients() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Minimum Number of Threads</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJob.getMinThreads() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); String maxThreadsStr; if (optimizingJob.getMaxThreads() > 0) { maxThreadsStr = String.valueOf(optimizingJob.getMaxThreads()); } else { maxThreadsStr = "(not specified)"; } htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Maximum Number of Threads</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + maxThreadsStr + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Thread Increment Between Iterations</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJob.getThreadIncrement() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Thread Startup Delay (ms)</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJob.getThreadStartupDelay() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Statistics Collection Interval</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + secondsToHumanReadableDuration(optimizingJob.getCollectionInterval()) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Max. Consecutive Non-Improving Iterations</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJob.getMaxNonImprovingIterations() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Re-Run Best Iteration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizingJob.reRunBestIteration() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (optimizingJob.getReRunDuration() > 0) { durationStr = secondsToHumanReadableDuration( optimizingJob.getReRunDuration()); } else { durationStr = "(not specified)"; } htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_A + "\">" + EOL); htmlBody.append(" <TD>Re-Run Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + durationStr + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); ArrayList dependencies = optimizingJob.getDependencies(); if ((dependencies != null) && (! dependencies.isEmpty())) { htmlBody.append(" <TR CLASS=\"" + Constants.STYLE_JOB_SUMMARY_LINE_B + "\">" + EOL); htmlBody.append(" <TD>Job Dependencies</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); for (int i=0; i < dependencies.size(); i++) { htmlBody.append(" " + dependencies.get(i) + "<BR>" + EOL); } htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } Parameter[] optimizationParameters = optimizingJob.getOptimizationParameters().getParameters(); if ((optimizationParameters != null) && (optimizationParameters.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Optimization Algorithm "+ "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); for (int i=0; i < optimizationParameters.length; i++) { String style = ((i % 2) == 0) ? Constants.STYLE_JOB_SUMMARY_LINE_A : Constants.STYLE_JOB_SUMMARY_LINE_B; String displayName = optimizationParameters[i].getDisplayName(); if (displayName == null) { displayName = optimizationParameters[i].getName(); } htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD>" + displayName + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizationParameters[i].getHTMLDisplayValue() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } LinkedHashMap mappedParameters = optimizingJob.getMappedParameters(); if ((mappedParameters != null) && (! mappedParameters.isEmpty())) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Mapped Job " + "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); int i=0; Iterator iterator = mappedParameters.keySet().iterator(); while (iterator.hasNext()) { String jobParamName = (String) iterator.next(); String groupParamName = (String) mappedParameters.get(jobParamName); Parameter jobParam = optimizingJob.getJobClass().getParameterStubs().getParameter( jobParamName); Parameter groupParam = jobGroup.getParameters().getParameter(groupParamName); String jobParamDisplayName; if ((jobParam == null) || (jobParam.getDisplayName() == null)) { jobParamDisplayName = jobParamName; } else { jobParamDisplayName = jobParam.getDisplayName(); } String groupParamDisplayName; if ((groupParam == null) || (groupParam.getDisplayName() == null)) { groupParamDisplayName = groupParamName; } else { groupParamDisplayName = groupParam.getDisplayName(); } String style = ((i++ % 2) == 0) ? Constants.STYLE_JOB_SUMMARY_LINE_A : Constants.STYLE_JOB_SUMMARY_LINE_B; htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD>" + jobParamDisplayName + "</TD>" + EOL); htmlBody.append(" <TD> --> </TD>" + EOL); htmlBody.append(" <TD>" + groupParamDisplayName + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } Parameter[] fixedParameters = optimizingJob.getFixedParameters().getParameters(); if ((fixedParameters != null) && (fixedParameters.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Fixed Job Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); for (int i=0; i < fixedParameters.length; i++) { String style = ((i % 2) == 0) ? Constants.STYLE_JOB_SUMMARY_LINE_A : Constants.STYLE_JOB_SUMMARY_LINE_B; String displayName = fixedParameters[i].getDisplayName(); if (displayName == null) { displayName = fixedParameters[i].getName(); } htmlBody.append(" <TR CLASS=\"" + style + "\">" + EOL); htmlBody.append(" <TD>" + displayName + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + fixedParameters[i].getHTMLDisplayValue() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append("</TABLE>" + EOL); } /** * Handles all processing related to editing the name and/or description of a * job group. * * @param requestInfo The state information for this request */ static void handleEditJobGroupDescription(RequestInfo requestInfo) { logMessage(requestInfo, "In handleEditJobGroupDescription()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to schedule jobs to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "edit a job group."); return; } // Get the job group to edit. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if ((jobGroupName == null) || (jobGroupName.length() == 0)) { infoMessage.append("ERROR: No job group was specified for which to " + "edit the name and/or description.<BR>" + EOL); handleViewJobGroups(requestInfo); return; } JobGroup jobGroup = null; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration " + "database.<BR>" + EOL); handleViewJobGroups(requestInfo); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not retrieve job group \"" + jobGroupName + "\" from the configuration " + "database: " + e + ".<BR>" + EOL); handleViewJobGroups(requestInfo); return; } // See if the user submitted the form. If so, then set the corresponding // parameters. Otherwise, display the form to retrieve them. String confirmStr = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); if ((confirmStr != null) && (confirmStr.length() > 0)) { boolean jobValid = true; // There must be a name for the job group, and it must not conflict with // the name of any other job group. String newName = request.getParameter(Constants.SERVLET_PARAM_NEW_NAME); if ((newName == null) || (newName.length() == 0)) { infoMessage.append("ERROR: No new name was provided for the job " + "group.<BR>" + EOL); jobValid = false; } else if (! newName.equals(jobGroup.getName())) { try { JobGroup existingGroup = configDB.getJobGroup(newName); if (existingGroup != null) { infoMessage.append("ERROR: The new name provided for the job " + "group conflicts with the name of an existing " + "job group.<BR>" + EOL); jobValid = false; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not determine if the new name " + "conflicted with the name of any other job " + "groups in the configuration database: " + e + ".<BR>" + EOL); jobValid = false; } } // Get the new description for the job group. We don't care what it's // value is. String newDescription = request.getParameter(Constants.SERVLET_PARAM_JOB_DESCRIPTION); // If everything looks OK, then apply the update. if (jobValid) { jobGroup.setName(newName); jobGroup.setDescription(newDescription); try { configDB.writeJobGroup(jobGroup); // If the job group was renamed, then get rid of the record for the // old name. if (! jobGroupName.equals(newName)) { configDB.removeJobGroup(jobGroupName); } infoMessage.append("Successfully updated the name and/or " + "description for the job group.<BR>" + EOL); handleViewJobGroup(requestInfo, newName); return; } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not update the job group in the " + "configuration database: " + e + ".<BR>" + EOL); handleViewJobGroup(requestInfo); return; } } } // Display the form that allows the user to edit the job group name and/or // description. htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Edit Name/Description for Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Please provide the new name and/or description for the " + "job group:" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM CLASS=\"" + Constants.STYLE_MAIN_FORM + "\" METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_DESCRIPTION) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } String newName = request.getParameter(Constants.SERVLET_PARAM_NEW_NAME); if ((newName == null) || (newName.length() == 0)) { newName = jobGroup.getName(); } String newDescription = request.getParameter(Constants.SERVLET_PARAM_JOB_DESCRIPTION); if ((newDescription == null) || (newDescription.length() == 0)) { newDescription = jobGroup.getDescription(); } htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Group Name</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_NEW_NAME + "\" VALUE=\"" + newName + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Group Description</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_DESCRIPTION + "\" VALUE=\"" + newDescription + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"2\"> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Update " + "Name/Description\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append("</FORM>" + EOL); } /** * Handles all processing related to editing the parameters in a job group. * * @param requestInfo The state information for this request. */ static void handleEditJobGroupParams(RequestInfo requestInfo) { logMessage(requestInfo, "In handleEditJobGroupParams()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to schedule jobs to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "edit a job group."); return; } // Get the job group to edit. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if ((jobGroupName == null) || (jobGroupName.length() == 0)) { infoMessage.append("ERROR: No job group name was given for which to " + "edit the parameters."); handleViewJobGroups(requestInfo); return; } JobGroup jobGroup = null; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: No job group \"" + jobGroupName + "\" exists in the configuration database."); handleViewJobGroups(requestInfo); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not retrieve job group \"" + jobGroupName + "\" from the configuration database: " + e); handleViewJobGroups(requestInfo); return; } // Get the sets of jobs and optimizing jobs associated with this group. ArrayList<JobGroupItem> jobList = jobGroup.getJobList(); ArrayList<JobGroupJob> jobs = new ArrayList<JobGroupJob>(jobList.size()); ArrayList<JobGroupOptimizingJob> optimizingJobs = new ArrayList<JobGroupOptimizingJob>(jobList.size()); for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupJob) { jobs.add((JobGroupJob) o); } else if (o instanceof JobGroupOptimizingJob) { optimizingJobs.add((JobGroupOptimizingJob) o); } } // Get the parameters for this job group. Parameter[] params = jobGroup.getParameters().clone().getParameters(); // Get the index of the selected parameter, if there is one. int selectedIndex = -1; String indexStr = request.getParameter(Constants.SERVLET_PARAM_INDEX); if (indexStr != null) { try { selectedIndex = Integer.parseInt(indexStr); } catch (Exception e) {} } // See if the user submitted the form. If so, then figure out what to do // from there. String submitStr = request.getParameter(Constants.SERVLET_PARAM_SUBMIT); if ((submitStr == null) || (selectedIndex < 0)) { // We'll drop through to the form below. } else if (submitStr.equals(Constants.SUBMIT_STRING_MOVE_GROUP_PARAM)) { // Get the new index for the parameter and make the move. try { int newIndex = Integer.parseInt(request.getParameter( Constants.SERVLET_PARAM_NEW_INDEX)); ArrayList<Parameter> paramList = new ArrayList<Parameter>(params.length); for (int i=0; i < params.length; i++) { paramList.add(params[i]); } Parameter p = paramList.remove(selectedIndex); paramList.add(newIndex, p); paramList.toArray(params); jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully moved the parameter in the " + "parameter list.<BR>" + EOL); } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not move the parameter in the " + "parameter list: " + e + ".<BR>" + EOL); } } else if (submitStr.equals(Constants.SUBMIT_STRING_INSERT_PARAM_SPACER)) { // We want to insert a spacer before the selected element. Grow the // parameter array by one and insert a placeholder parameter in the new // location. try { Parameter[] newParams = new Parameter[params.length+1]; System.arraycopy(params, 0, newParams, 0, selectedIndex); System.arraycopy(params, selectedIndex, newParams, selectedIndex+1, (params.length-selectedIndex)); newParams[selectedIndex] = new PlaceholderParameter(); params = newParams; jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully inserted a spacer into the " + "parameter list.<BR>" + EOL); } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not insert a spacer into the " + "parameter list: " + e + ".<BR>" + EOL); } } else if (submitStr.equals(Constants.SUBMIT_STRING_REMOVE_PARAM_SPACER)) { // We want to remove the selected element if it is a spacer. try { Parameter p = params[selectedIndex]; if (p instanceof PlaceholderParameter) { Parameter[] newParams = new Parameter[params.length-1]; System.arraycopy(params, 0, newParams, 0, selectedIndex); System.arraycopy(params, selectedIndex+1, newParams, selectedIndex, (params.length-selectedIndex-1)); params = newParams; jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully removed the spacer from the " + "parameter list.<BR>" + EOL); } else { infoMessage.append("ERROR: The specified parameter was not " + "a spacer.<BR>" + EOL); } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not remove the spacer from the " + "parameter list: " + e + ".<BR>" + EOL); } } else if (submitStr.equals(Constants.SUBMIT_STRING_INSERT_PARAM_LABEL)) { // We want to insert a label before the selected element. First, see if // we have the text for the label. If so, then grow the parameter array // by one and insert a label parameter in the new location. Otherwise, // prompt the user for the new label. String label = request.getParameter(Constants.SERVLET_PARAM_LABEL_TEXT); if ((label == null) || (label.length() == 0)) { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Insert Label For Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Enter the text for the new label parameter:"); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBMIT, Constants.SUBMIT_STRING_INSERT_PARAM_LABEL) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(selectedIndex)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_LABEL_TEXT + "\" SIZE=\"40\">" + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Submit\">" + EOL); htmlBody.append("</FORM>" + EOL); return; } else { try { Parameter[] newParams = new Parameter[params.length+1]; System.arraycopy(params, 0, newParams, 0, selectedIndex); System.arraycopy(params, selectedIndex, newParams, selectedIndex+1, (params.length-selectedIndex)); newParams[selectedIndex] = new LabelParameter(label); params = newParams; jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully inserted a label into the " + "parameter list.<BR>" + EOL); } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not insert a label into the " + "parameter list: " + e + ".<BR>" + EOL); } } } else if (submitStr.equals(Constants.SUBMIT_STRING_REMOVE_PARAM_LABEL)) { // We want to remove the selected element if it is a label. try { Parameter p = params[selectedIndex]; if (p instanceof LabelParameter) { Parameter[] newParams = new Parameter[params.length-1]; System.arraycopy(params, 0, newParams, 0, selectedIndex); System.arraycopy(params, selectedIndex+1, newParams, selectedIndex, (params.length-selectedIndex-1)); params = newParams; jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully removed the label from the " + "parameter list.<BR>" + EOL); } else { infoMessage.append("ERROR: The specified parameter was not " + "a label.<BR>" + EOL); } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not remove the label from the " + "parameter list: " + e + ".<BR>" + EOL); } } else if (submitStr.equals(Constants.SUBMIT_STRING_EDIT_LABEL_TEXT)) { // Get the label text. String label = request.getParameter(Constants.SERVLET_PARAM_LABEL_TEXT); // See if the user submitted the form. If not, then show it to them to // let them edit the label. Otherwise, update the job group. String confirmStr = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); if ((confirmStr == null) || (confirmStr.length() == 0)) { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Edit Parameter Label For Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Enter the new text for the label parameter:"); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBMIT, Constants.SUBMIT_STRING_EDIT_LABEL_TEXT) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(selectedIndex)) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_LABEL_TEXT + "\" VALUE=\"" + label + "\" SIZE=\"40\">" + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Submit\">" + EOL); htmlBody.append("</FORM>" + EOL); return; } else { try { Parameter p = params[selectedIndex]; if (p instanceof LabelParameter) { params[selectedIndex] = new LabelParameter(label); jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully edited the label text.<BR>" + EOL); } else { infoMessage.append("ERROR: The specified parameter was not " + "a label.<BR>" + EOL); } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not edit the label text: " + e + ".<BR>" + EOL); } } } else if (submitStr.equals(Constants.SUBMIT_STRING_REMOVE_GROUP_PARAM)) { // We want to remove the selected parameter. try { Parameter p = params[selectedIndex]; Parameter[] newParams = new Parameter[params.length-1]; System.arraycopy(params, 0, newParams, 0, selectedIndex); System.arraycopy(params, selectedIndex+1, newParams, selectedIndex, (params.length-selectedIndex-1)); params = newParams; jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully removed parameter \"" + p.getDisplayName() + " from the parameter list.<BR>" + EOL); } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not remove the specified parameter " + "from the list: " + e + ".<BR>" + EOL); } } else if (submitStr.equals(Constants.SUBMIT_STRING_RENAME_GROUP_PARAM)) { // See if a new name was given. If so, then set it. If not, then prompt // the user for it. try { String newName = request.getParameter(Constants.SERVLET_PARAM_NEW_NAME); if ((newName == null) || (newName.length() == 0)) { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Edit Parameter Name for Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Enter the new display name for the \"" + params[selectedIndex].getDisplayName() + "\" parameter:"); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBMIT, Constants.SUBMIT_STRING_RENAME_GROUP_PARAM) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(selectedIndex)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_NEW_NAME + "\" SIZE=\"40\"" + " VALUE=\"" + params[selectedIndex].getDisplayName() + "\">" + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Submit\">" + EOL); htmlBody.append("</FORM>" + EOL); return; } // Make sure that the new name doesn't conflict with any other // parameters in the job group. boolean conflict = false; for (int i=0; i < params.length; i++) { if (i == selectedIndex) { continue; } else if (newName.equals(params[i].getDisplayName())) { infoMessage.append("ERROR: The new display name for the " + "parameter conflicts with the display name of " + "another parameter in the list.<BR>" + EOL); conflict = true; break; } } if (! conflict) { params[selectedIndex].setDisplayName(newName); jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully updated the display name of the " + "job group parameter.<BR>" + EOL); } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not rename the job parameter: " + e + ".<BR>" + EOL); } } else if (submitStr.equals(Constants.SUBMIT_STRING_SET_PARAM_DEFAULT)) { // See if the form was submitted. If so, then process it. Otherwise, // display it to the user. try { String confirmStr = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); if ((confirmStr == null) || (confirmStr.length() == 0)) { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Edit Default Value for Job Group \"" + jobGroupName + "\" Parameter \"" + params[selectedIndex].getDisplayName() + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Please choose the new default value for the \"" + params[selectedIndex].getDisplayName() + "\" parameter:"); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBMIT, Constants.SUBMIT_STRING_SET_PARAM_DEFAULT) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(selectedIndex)) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" " + params[selectedIndex].getHTMLInputForm( Constants.SERVLET_PARAM_JOB_PARAM_PREFIX) + EOL); htmlBody.append(" <BR><BR>" + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Submit\">" + EOL); htmlBody.append("</FORM>" + EOL); return; } // Try to set the new value for the parameter. params[selectedIndex].htmlInputFormToValue(request); jobGroup.setParameters(new ParameterList(params)); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully updated the default value for the " + "job group parameter.<BR>" + EOL); } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not update the default value: " + e + ".<BR>" + EOL); } } // Display the form allowing the user to edit the job group parameters. htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Edit Parameters for Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName, jobGroupName); htmlBody.append("Edit the parameter names, default values, ordering, and " + "spacing for mapped parameters in job group " + link + '.' + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<TABLE BORDER=\"0\">" + EOL); for (int i=0; i < params.length; i++) { if (i > 0) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><HR></TD>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" <TR>" + EOL); } if (params[i] instanceof PlaceholderParameter) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">----- Spacer -----</TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (params.length > 1) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_NEW_INDEX + "\">" + EOL); for (int j=0; j < params.length; j++) { String name; if (params[j] instanceof PlaceholderParameter) { name = "----- Spacer -----"; } else if (params[j] instanceof LabelParameter) { name = "----- Label: " + params[j].getDisplayValue() + "-----"; } else { name = params[j].getDisplayName(); } if (j < i) { htmlBody.append(" <OPTION VALUE=\"" + j + "\">Before " + name + EOL); } else if (j > i) { htmlBody.append(" <OPTION VALUE=\"" + j + "\">After " + name + EOL); } } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_MOVE_GROUP_PARAM + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_REMOVE_PARAM_SPACER + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } else if (params[i] instanceof LabelParameter) { String labelText = params[i].getDisplayValue(); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">----- Label: " + labelText + " -----</TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (params.length > 1) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_NEW_INDEX + "\">" + EOL); for (int j=0; j < params.length; j++) { String name; if (params[j] instanceof PlaceholderParameter) { name = "----- Spacer -----"; } else if (params[j] instanceof LabelParameter) { name = "----- Label: " + params[j].getDisplayValue() + "-----"; } else { name = params[j].getDisplayName(); } if (j < i) { htmlBody.append(" <OPTION VALUE=\"" + j + "\">Before " + name + EOL); } else if (j > i) { htmlBody.append(" <OPTION VALUE=\"" + j + "\">After " + name + EOL); } } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_MOVE_GROUP_PARAM + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_LABEL_TEXT, labelText) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_EDIT_LABEL_TEXT + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_REMOVE_PARAM_LABEL + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } else { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_INSERT_PARAM_SPACER + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_INSERT_PARAM_LABEL + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><B>Parameter Name</B></TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + params[i].getDisplayName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><B>Default Value</B></TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + params[i].getHTMLDisplayValue() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (params.length > 1) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_NEW_INDEX + "\">" + EOL); for (int j=0; j < params.length; j++) { String name; if (params[j] instanceof PlaceholderParameter) { name = "----- Spacer -----"; } else if (params[j] instanceof LabelParameter) { name = "----- Label: " + params[j].getDisplayValue() + "-----"; } else { name = params[j].getDisplayName(); } if (j < i) { htmlBody.append(" <OPTION VALUE=\"" + j + "\">Before " + name + EOL); } else if (j > i) { htmlBody.append(" <OPTION VALUE=\"" + j + "\">After " + name + EOL); } } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_MOVE_GROUP_PARAM + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + EOL); htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_RENAME_GROUP_PARAM + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_SET_PARAM_DEFAULT + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); boolean unused = true; for (int j=0; (unused && (j < jobs.size())); j++) { JobGroupJob job = jobs.get(j); Iterator iterator = job.getMappedParameters().values().iterator(); while (iterator.hasNext()) { if (params[i].getName().equals(iterator.next())) { unused = false; break; } } } for (int j=0; (unused && (j < optimizingJobs.size())); j++) { JobGroupOptimizingJob optimizingJob = optimizingJobs.get(j); Iterator iterator = optimizingJob.getMappedParameters().values().iterator(); while (iterator.hasNext()) { if (params[i].getName().equals(iterator.next())) { unused = false; break; } } } if (unused) { htmlBody.append(" <TD>" + EOL); htmlBody.append(" <FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_PARAMS) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_INDEX, String.valueOf(i)) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_SUBMIT + "\" VALUE=\"" + Constants.SUBMIT_STRING_REMOVE_GROUP_PARAM + "\">" + EOL); htmlBody.append(" </FORM>" + EOL); htmlBody.append(" </TD>" + EOL); } htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append("</TABLE>" + EOL); } /** * Handles all processing related to editing a job in a job group. * * @param requestInfo The state information for this request */ static void handleEditJobGroupJob(RequestInfo requestInfo) { logMessage(requestInfo, "In handleEditJobGroupJob()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to schedule jobs to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "edit a job group."); return; } // Get the job group to edit. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if ((jobGroupName == null) || (jobGroupName.length() == 0)) { infoMessage.append("ERROR: No job group was specified for which to " + "edit the job.<BR>" + EOL); handleViewJobGroups(requestInfo); return; } JobGroup jobGroup = null; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration " + "database.<BR>" + EOL); handleViewJobGroups(requestInfo); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not retrieve job group \"" + jobGroupName + "\" from the configuration " + "database: " + e + ".<BR>" + EOL); handleViewJobGroups(requestInfo); return; } // Get the job group job to edit. String jobName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME); if ((jobName == null) || (jobName.length() == 0)) { infoMessage.append("ERROR: No job was selected for editing in the " + "specified job group.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } JobGroupJob job = null; ArrayList jobList = jobGroup.getJobList(); for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupJob) { JobGroupJob currentJob = (JobGroupJob) o; if (currentJob.getName().equals(jobName)) { job = currentJob; break; } } } if (job == null) { infoMessage.append("ERROR: There is no job named \"" + jobName + "\" in job group \"" + jobGroupName + "\".<BR>" + EOL); handleViewJobGroup(requestInfo); return; } boolean submitted = false; String confirmStr = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); if ((confirmStr != null) && (confirmStr.length() > 0)) { boolean jobValid = true; submitted = true; String newName = request.getParameter(Constants.SERVLET_PARAM_NEW_NAME); if ((newName == null) || (newName.length() == 0)) { infoMessage.append("ERROR: The job must have a name.<BR>" + EOL); jobValid = false; } else if (! newName.equals(jobName)) { boolean conflict = false; for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupJob) { JobGroupJob j = (JobGroupJob) o; if (j.getName().equals(newName)) { conflict = true; break; } } else if (o instanceof JobGroupOptimizingJob) { JobGroupOptimizingJob oj = (JobGroupOptimizingJob) o; if (oj.getName().equals(newName)) { conflict = true; break; } } } if (conflict) { infoMessage.append("ERROR: The new name provided for the job " + "conflicts with the name of another job or " + "optimizing job in the job group.<BR>" + EOL); jobValid = false; } } int duration = -1; String durationStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DURATION); if ((durationStr != null) && (durationStr.length() > 0)) { try { duration = DurationParser.parse(durationStr); } catch (SLAMDException se) { infoMessage.append("ERROR: " + se.getMessage() + "<BR>" + EOL); jobValid = false; } } int numClients = -1; String numClientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS); if ((numClientsStr == null) || (numClientsStr.length() == 0)) { infoMessage.append("ERROR: No number of clients was provided.<BR>" + EOL); jobValid = false; } else { try { numClients = Integer.parseInt(numClientsStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided number of " + "clients as an integer.<BR>" + EOL); jobValid = false; } } int threadsPerClient = -1; String numThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_PER_CLIENT); if ((numThreadsStr == null) || (numThreadsStr.length() == 0)) { infoMessage.append("ERROR: No number of threads per client was " + "provided.<BR>" + EOL); jobValid = false; } else { try { threadsPerClient = Integer.parseInt(numThreadsStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided number of " + "threads per client as an integer.<BR>" + EOL); jobValid = false; } } int threadStartupDelay = 0; String delayStr = request.getParameter( Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY); if ((delayStr != null) && (delayStr.length() > 0)) { try { threadStartupDelay = Integer.parseInt(delayStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided thread " + "startup delay as an integer.<BR>" + EOL); jobValid = false; } } int collectionInterval = -1; String intervalStr = request.getParameter( Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL); if ((intervalStr == null) || (intervalStr.length() == 0)) { infoMessage.append("ERROR: No statistics collection interval was " + "provided.<BR>" + EOL); jobValid = false; } else { try { collectionInterval = DurationParser.parse(intervalStr); } catch (SLAMDException se) { infoMessage.append("ERROR: " + se.getMessage() + "<BR>" +EOL); jobValid = false; } } JobClass jobClass = job.getJobClass(); ParameterList newFixedParameters = new ParameterList(); ParameterList newJobGroupParameters = new ParameterList(); LinkedHashMap<String,String> newMappedParameters = new LinkedHashMap<String,String>(); ArrayList<String> removeMappedParameters = new ArrayList<String>(); ArrayList<String> removeFixedParameters = new ArrayList<String>(); Parameter[] stubs = jobClass.getParameterStubs().getParameters(); if ((stubs != null) && (stubs.length > 0)) { for (int i=0; i < stubs.length; i++) { if ((stubs[i] instanceof PlaceholderParameter) || (stubs[i] instanceof LabelParameter)) { continue; } // Determine how this parameter should be treated. String stubName = stubs[i].getName(); String pName = Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubName; String pValue = request.getParameter(pName); if (pValue == null) { // This is fine -- we'll just keep treating it like before. } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING)) { // Determine the parameter to which it should be mapped. String mapToName = Constants.SERVLET_PARAM_MAP_TO_NAME_PREFIX + stubName; String mapToValue = request.getParameter(mapToName); if ((mapToValue != null) && (mapToValue.length() > 0)) { removeFixedParameters.add(stubName); removeMappedParameters.add(stubName); newMappedParameters.put(stubName, mapToValue); } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW)) { String mapToName = Constants.SERVLET_PARAM_MAP_TO_DISPLAY_NAME_PREFIX + stubName; String mapToValue = request.getParameter(mapToName); if ((mapToValue != null) && (mapToValue.length() > 0)) { // Make sure that the new mapping doesn't conflict with an // existing one. boolean conflict = false; Parameter[] groupParams = jobGroup.getParameters().getParameters(); for (int j=0; j < groupParams.length; j++) { if (stubName.equals(groupParams[j].getName())) { // There is a conflict in the parameter names, which we can // work around by changing the name of the new parameter. conflict = true; int k = 1; String newStubName = stubName + k; while (conflict) { k++; conflict = false; newStubName = stubName + k; for (int l=0; l < groupParams.length; l++) { if (newStubName.equals(groupParams[l].getName())) { conflict = true; break; } } } } else if (stubs[i].getDisplayName().equalsIgnoreCase( groupParams[j].getDisplayName())) { conflict = true; infoMessage.append("ERROR: Job parameter \"" + stubs[i].getDisplayName() + "\" was configured to be a new mapped " + "parameter for the job group, but its " + "display name conflicts with that of " + "another parameter already in the " + "job group.<BR>" + EOL); break; } } if (conflict) { jobValid = false; } else { removeFixedParameters.add(stubName); removeMappedParameters.add(stubName); newMappedParameters.put(stubName, stubs[i].getName()); newJobGroupParameters.addParameter(stubs[i]); } } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_FIXED)) { try { stubs[i].htmlInputFormToValue(request); removeFixedParameters.add(stubName); removeMappedParameters.add(stubName); newFixedParameters.addParameter(stubs[i]); } catch (InvalidValueException ive) { infoMessage.append("ERROR: The specified fixed value for " + "parameter \"" + stubs[i].getDisplayName() + "\" is invalid: " + ive.getMessage() + ".<BR>" + EOL); jobValid = false; } } } } if (jobValid) { // Everything looks OK, so update the job and then write the job group // to the configuration database. job.setName(newName); job.setDuration(duration); job.setNumClients(numClients); job.setThreadsPerClient(threadsPerClient); job.setThreadStartupDelay(threadStartupDelay); job.setCollectionInterval(collectionInterval); for (int i=0; i < removeMappedParameters.size(); i++) { job.getMappedParameters().remove(removeMappedParameters.get(i)); } for (int i=0; i < removeFixedParameters.size(); i++) { job.getFixedParameters().removeParameter( removeFixedParameters.get(i)); } Iterator<String> iterator = newMappedParameters.keySet().iterator(); while (iterator.hasNext()) { String n = iterator.next(); String v = newMappedParameters.get(n); job.getMappedParameters().put(n, v); } Parameter[] newFixed = newFixedParameters.getParameters(); for (int i=0; i < newFixed.length; i++) { job.getFixedParameters().addParameter(newFixed[i]); } Parameter[] newGroup = newJobGroupParameters.getParameters(); for (int i=0; i < newGroup.length; i++) { jobGroup.getParameters().addParameter(newGroup[i]); } try { configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully updated the job group in the " + "configuration database.<BR>" + EOL); } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not update the job group in the " + "configuration database: " + e + ".<BR>" + EOL); } handleViewJobGroupJob(requestInfo, jobGroup, job.getName()); return; } } String star = "<SPAN CLASS=\"" + Constants.STYLE_WARNING_TEXT + "\">*</SPAN>"; htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Edit Job \"" + jobName + "\" in Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName, Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME, jobName, jobName); htmlBody.append("Update the following \"" + link + "\" job information." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Fields marked with an asterisk (" + star + ") are required to have a value."); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM CLASS=\"" + Constants.STYLE_MAIN_FORM + "\" METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME, jobName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); JobClass jobClass = job.getJobClass(); if (jobClass.overrideNumClients() > 0) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS, String.valueOf(jobClass.overrideNumClients())) + EOL); } if (jobClass.overrideThreadsPerClient() > 0) { htmlBody.append(" " + generateHidden( Constants.SERVLET_PARAM_JOB_THREADS_PER_CLIENT, String.valueOf(jobClass.overrideThreadsPerClient())) + EOL); } if (jobClass.overrideCollectionInterval() > 0) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL, secondsToHumanReadableDuration( jobClass.overrideCollectionInterval())) + EOL); } if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>General Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String newName = jobName; if (submitted) { newName = request.getParameter(Constants.SERVLET_PARAM_NEW_NAME); if ((newName == null) || (newName.length() == 0)) { newName = jobName; } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Name " + star +"</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_NEW_NAME + "\" VALUE=\"" + newName + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String durationStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DURATION); if ((durationStr == null) || (durationStr.length() == 0)) { if (submitted) { durationStr = ""; } else { if (job.getDuration() > 0) { durationStr = secondsToHumanReadableDuration(job.getDuration()); } else { durationStr = ""; } } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_DURATION + "\" VALUE=\"" + durationStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobClass.overrideNumClients() <= 0) { String numClientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS); if ((numClientsStr == null) || (numClientsStr.length() == 0)) { numClientsStr = String.valueOf(job.getNumClients()); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Number of Clients " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_NUM_CLIENTS + "\" VALUE=\"" + numClientsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } if (jobClass.overrideThreadsPerClient() <= 0) { String numThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_PER_CLIENT); if ((numThreadsStr == null) || (numThreadsStr.length() == 0)) { numThreadsStr = String.valueOf(job.getThreadsPerClient()); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Threads per Client " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREADS_PER_CLIENT + "\" VALUE=\"" + numThreadsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } String delayStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY); if ((delayStr == null) || (delayStr.length() == 0)) { if (submitted) { delayStr = "0"; } else { delayStr = String.valueOf(job.getThreadStartupDelay()); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Thread Startup Delay (ms)</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY + "\" VALUE=\"" + delayStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobClass.overrideCollectionInterval() <= 0) { String intervalStr = request.getParameter( Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL); if ((intervalStr == null) || (intervalStr.length() == 0)) { intervalStr = secondsToHumanReadableDuration(job.getCollectionInterval()); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Statistics Collection Interval " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL + "\" VALUE=\"" + intervalStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } Parameter[] stubs = jobClass.getParameterStubs().clone().getParameters(); Parameter[] groupParameters = jobGroup.getParameters().getParameters(); if ((stubs != null) && (stubs.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Job-Specific " + "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); boolean skippedFirstSpace = false; for (int i=0; i < stubs.length; i++) { if ((stubs[i] instanceof PlaceholderParameter) || (stubs[i] instanceof LabelParameter)) { continue; } if (! skippedFirstSpace) { skippedFirstSpace = true; } else { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + stubs[i].getDisplayName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); String mapParam = Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName(); String mapType = null; String mapToName = stubs[i].getName(); if (submitted) { mapType = request.getParameter(mapParam); try { stubs[i].htmlInputFormToValue(request); } catch (InvalidValueException ive) {} } if (mapType == null) { if (job.getMappedParameters().containsKey(stubs[i].getName())) { mapType = Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING; String mappedName = job.getMappedParameters().get(stubs[i].getName()); Parameter mappedParam = jobGroup.getParameters().getParameter(mappedName); if (mappedParam != null) { mapToName = mappedParam.getName(); stubs[i].setValueFrom(mappedParam); } } else if (job.getFixedParameters().hasParameter(stubs[i].getName())) { mapType = Constants.GROUP_PARAM_TYPE_FIXED; Parameter fixedParam = job.getFixedParameters().getParameter(stubs[i].getName()); if (fixedParam != null) { stubs[i].setValueFrom(fixedParam); } } else { mapType = Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW; } } htmlBody.append(" <TR>" + EOL); if (mapType.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING)) { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + mapParam + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING + "\" CHECKED>Map to Existing Job Group " + "Parameter</TD>" + EOL); } else { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + mapParam + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING + "\">Map to Existing Job Group Parameter</TD>" + EOL); } htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_MAP_TO_NAME_PREFIX + stubs[i].getName() + "\">" + EOL); for (int j=0; j < groupParameters.length; j++) { if ((groupParameters[j] instanceof PlaceholderParameter) || (groupParameters[j] instanceof LabelParameter)) { continue; } String selectedStr = ""; if (groupParameters[j].getName().equals(mapToName)) { selectedStr = " SELECTED"; } htmlBody.append(" <OPTION VALUE=\"" + groupParameters[j].getName() + '"' + selectedStr + '>' + groupParameters[j].getDisplayName() + EOL); } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); if (mapType.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW)) { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW + "\" CHECKED>Create a New Job Group Parameter</TD>" + EOL); } else { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW + "\">Create a New Job Group Parameter</TD>" + EOL); } htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_MAP_TO_DISPLAY_NAME_PREFIX + stubs[i].getName() + "\" VALUE=\"" + stubs[i].getDisplayName() + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); if (mapType.equals(Constants.GROUP_PARAM_TYPE_FIXED)) { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_FIXED + "\" CHECKED>Always Use a Fixed Value</TD>" + EOL); } else { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_FIXED + "\">Always Use a Fixed Value</TD>" + EOL); } htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + stubs[i].getHTMLInputForm( Constants.SERVLET_PARAM_JOB_PARAM_PREFIX) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"2\"> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Update " + "Job\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append("</FORM>" + EOL); } /** * Handles all processing related to editing an optimizing job in a job group. * * @param requestInfo The state information for this request */ static void handleEditJobGroupOptimizingJob(RequestInfo requestInfo) { logMessage(requestInfo, "In handleEditJobGroupOptimizingJob()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to schedule jobs to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "edit a job group."); return; } // Get the job group to edit. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if ((jobGroupName == null) || (jobGroupName.length() == 0)) { infoMessage.append("ERROR: No job group was specified for which to " + "edit the job.<BR>" + EOL); handleViewJobGroups(requestInfo); return; } JobGroup jobGroup = null; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration " + "database.<BR>" + EOL); handleViewJobGroups(requestInfo); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not retrieve job group \"" + jobGroupName + "\" from the configuration " + "database: " + e + ".<BR>" + EOL); handleViewJobGroups(requestInfo); return; } // Get the job group optimizing job to edit. String optimizingJobName = request.getParameter( Constants.SERVLET_PARAM_JOB_GROUP_OPTIMIZING_JOB_NAME); if ((optimizingJobName == null) || (optimizingJobName.length() == 0)) { infoMessage.append("ERROR: No optimizing job was selected for " + "editing in the specified job group.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } JobGroupOptimizingJob optimizingJob = null; ArrayList jobList = jobGroup.getJobList(); for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupOptimizingJob) { JobGroupOptimizingJob currentOptimizingJob = (JobGroupOptimizingJob) o; if (currentOptimizingJob.getName().equals(optimizingJobName)) { optimizingJob = currentOptimizingJob; break; } } } if (optimizingJob == null) { infoMessage.append("ERROR: There is no job named \"" + optimizingJobName + "\" in job group \"" + jobGroupName + "\".<BR>" + EOL); handleViewJobGroup(requestInfo); return; } boolean submitted = false; String confirmStr = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); if ((confirmStr != null) && (confirmStr.length() > 0)) { boolean jobValid = true; submitted = true; String newName = request.getParameter(Constants.SERVLET_PARAM_NEW_NAME); if ((newName == null) || (newName.length() == 0)) { infoMessage.append("ERROR: The optimizing job must have a name.<BR>" + EOL); jobValid = false; } else if (! newName.equals(optimizingJobName)) { boolean conflict = false; for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupJob) { JobGroupJob j = (JobGroupJob) o; if (j.getName().equals(newName)) { conflict = true; break; } } else if (o instanceof JobGroupOptimizingJob) { JobGroupOptimizingJob oj = (JobGroupOptimizingJob) o; if (oj.getName().equals(newName)) { conflict = true; break; } } } if (conflict) { infoMessage.append("ERROR: The new name provided for the " + "optimizing job conflicts with the name of " + "another job or optimizing job in the job " + "group.<BR>" + EOL); jobValid = false; } } int duration = -1; String durationStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DURATION); if ((durationStr != null) && (durationStr.length() > 0)) { try { duration = DurationParser.parse(durationStr); } catch (SLAMDException se) { infoMessage.append("ERROR: " + se.getMessage() + "<BR>" + EOL); jobValid = false; } } int numClients = -1; String numClientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS); if ((numClientsStr == null) || (numClientsStr.length() == 0)) { infoMessage.append("ERROR: No number of clients was provided.<BR>" + EOL); jobValid = false; } else { try { numClients = Integer.parseInt(numClientsStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided number of " + "clients as an integer.<BR>" + EOL); jobValid = false; } } int minThreads = -1; String minThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_MIN); if ((minThreadsStr == null) || (minThreadsStr.length() == 0)) { infoMessage.append("ERROR: No minimum number of threads per client " + "was provided.<BR>" + EOL); jobValid = false; } else { try { minThreads = Integer.parseInt(minThreadsStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided minimum " + "number of threads per client as an integer.<BR>" + EOL); jobValid = false; } } int maxThreads = -1; String maxThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_MAX); if ((maxThreadsStr != null) && (maxThreadsStr.length() > 0)) { try { maxThreads = Integer.parseInt(maxThreadsStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided maximum " + "number of threads per client as an integer.<BR>" + EOL); jobValid = false; } } int threadIncrement = -1; String incrementStr = request.getParameter(Constants.SERVLET_PARAM_THREAD_INCREMENT); if ((incrementStr == null) || (incrementStr.length() == 0)) { infoMessage.append("ERROR: No thread increment was provided.<BR>" + EOL); jobValid = false; } else { try { threadIncrement = Integer.parseInt(incrementStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided thread " + "increment as an integer.<BR>" + EOL); jobValid = false; } } int threadStartupDelay = 0; String delayStr = request.getParameter( Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY); if ((delayStr != null) && (delayStr.length() > 0)) { try { threadStartupDelay = Integer.parseInt(delayStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided thread " + "startup delay as an integer.<BR>" + EOL); jobValid = false; } } int collectionInterval = -1; String intervalStr = request.getParameter( Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL); if ((intervalStr == null) || (intervalStr.length() == 0)) { infoMessage.append("ERROR: No statistics collection interval was " + "provided.<BR>" + EOL); jobValid = false; } else { try { collectionInterval = DurationParser.parse(intervalStr); } catch (SLAMDException se) { infoMessage.append("ERROR: " + se.getMessage() + "<BR>" +EOL); jobValid = false; } } int maxNonImproving = -1; String nonImprovingStr = request.getParameter(Constants.SERVLET_PARAM_JOB_MAX_NON_IMPROVING); if ((nonImprovingStr == null) || (nonImprovingStr.length() == 0)) { infoMessage.append("ERROR: No maximum number of non-improving " + "iterations was provided.<BR>" + EOL); jobValid = false; } else { try { maxNonImproving = Integer.parseInt(nonImprovingStr); } catch (Exception e) { infoMessage.append("ERROR: Cannot parse the provided maximum " + "number of non-improving iterations as an " + "integer.<BR>" +EOL); jobValid = false; } } boolean reRunBestIteration = false; String reRunStr = request.getParameter(Constants.SERVLET_PARAM_RERUN_BEST_ITERATION); if ((reRunStr != null) && (reRunStr.length() > 0)) { reRunBestIteration = (reRunStr.equalsIgnoreCase("true") || reRunStr.equalsIgnoreCase("yes") || reRunStr.equalsIgnoreCase("on") || reRunStr.equalsIgnoreCase("1")); } int reRunDuration = -1; String reRunDurationStr = request.getParameter(Constants.SERVLET_PARAM_RERUN_DURATION); if ((reRunDurationStr != null) && (reRunDurationStr.length() > 0)) { try { reRunDuration = DurationParser.parse(reRunDurationStr); } catch (SLAMDException se) { infoMessage.append("ERROR: " + se.getMessage() + "<BR>" + EOL); jobValid = false; } } JobClass jobClass = optimizingJob.getJobClass(); OptimizationAlgorithm optimizationAlgorithm = optimizingJob.getOptimizationAlgorithm(); Parameter[] optimizationStubs = optimizationAlgorithm. getOptimizationAlgorithmParameterStubs(jobClass). getParameters().clone(); ParameterList optimizationParameters = new ParameterList(); for (int i=0; i < optimizationStubs.length; i++) { if ((optimizationStubs[i] instanceof PlaceholderParameter) || (optimizationStubs[i] instanceof LabelParameter)) { continue; } try { String paramName = Constants.SERVLET_PARAM_OPTIMIZATION_PARAM_PREFIX + optimizationStubs[i].getName(); String[] values = request.getParameterValues(paramName); optimizationStubs[i].htmlInputFormToValue(values); optimizationParameters.addParameter(optimizationStubs[i]); } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The provided value(s) for optimization " + "algorithm parameter \"" + optimizationStubs[i].getDisplayName() + "\" were invalid: " + e.getMessage() + ".<BR>" + EOL); } } ParameterList newFixedParameters = new ParameterList(); ParameterList newJobGroupParameters = new ParameterList(); LinkedHashMap<String,String> newMappedParameters = new LinkedHashMap<String,String>(); ArrayList<String> removeMappedParameters = new ArrayList<String>(); ArrayList<String> removeFixedParameters = new ArrayList<String>(); Parameter[] stubs = jobClass.getParameterStubs().clone().getParameters(); if ((stubs != null) && (stubs.length > 0)) { for (int i=0; i < stubs.length; i++) { if ((stubs[i] instanceof PlaceholderParameter) || (stubs[i] instanceof LabelParameter)) { continue; } // Determine how this parameter should be treated. String stubName = stubs[i].getName(); String pName = Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubName; String pValue = request.getParameter(pName); if (pValue == null) { // This is fine -- we'll just keep treating it like before. } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING)) { // Determine the parameter to which it should be mapped. String mapToName = Constants.SERVLET_PARAM_MAP_TO_NAME_PREFIX + stubName; String mapToValue = request.getParameter(mapToName); if ((mapToValue != null) && (mapToValue.length() > 0)) { removeFixedParameters.add(stubName); removeMappedParameters.add(stubName); newMappedParameters.put(stubName, mapToValue); } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW)) { String mapToName = Constants.SERVLET_PARAM_MAP_TO_DISPLAY_NAME_PREFIX + stubName; String mapToValue = request.getParameter(mapToName); if ((mapToValue != null) && (mapToValue.length() > 0)) { // Make sure that the new mapping doesn't conflict with an // existing one. boolean conflict = false; Parameter[] groupParams = jobGroup.getParameters().getParameters(); for (int j=0; j < groupParams.length; j++) { if (stubName.equals(groupParams[j].getName())) { // There is a conflict in the parameter names, which we can // work around by changing the name of the new parameter. conflict = true; int k = 1; String newStubName = stubName + k; while (conflict) { k++; conflict = false; newStubName = stubName + k; for (int l=0; l < groupParams.length; l++) { if (newStubName.equals(groupParams[l].getName())) { conflict = true; break; } } } } else if (stubs[i].getDisplayName().equalsIgnoreCase( groupParams[j].getDisplayName())) { conflict = true; infoMessage.append("ERROR: Job parameter \"" + stubs[i].getDisplayName() + "\" was configured to be a new mapped " + "parameter for the job group, but its " + "display name conflicts with that of " + "another parameter already in the " + "job group.<BR>" + EOL); break; } } if (conflict) { jobValid = false; } else { removeFixedParameters.add(stubName); removeMappedParameters.add(stubName); newMappedParameters.put(stubName, stubs[i].getName()); newJobGroupParameters.addParameter(stubs[i]); } } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_FIXED)) { try { stubs[i].htmlInputFormToValue(request); removeFixedParameters.add(stubName); removeMappedParameters.add(stubName); newFixedParameters.addParameter(stubs[i]); } catch (InvalidValueException ive) { infoMessage.append("ERROR: The specified fixed value for " + "parameter \"" + stubs[i].getDisplayName() + "\" is invalid: " + ive.getMessage() + ".<BR>" + EOL); jobValid = false; } } } } if (jobValid) { // Everything looks OK, so update the job and then write the job group // to the configuration database. optimizingJob.setName(newName); optimizingJob.setDuration(duration); optimizingJob.setNumClients(numClients); optimizingJob.setMinThreads(minThreads); optimizingJob.setMaxThreads(maxThreads); optimizingJob.setThreadIncrement(threadIncrement); optimizingJob.setThreadStartupDelay(threadStartupDelay); optimizingJob.setCollectionInterval(collectionInterval); optimizingJob.setMaxNonImprovingIterations(maxNonImproving); optimizingJob.setReRunBestIteration(reRunBestIteration); optimizingJob.setReRunDuration(reRunDuration); optimizingJob.setOptimizationParameters(optimizationParameters); for (int i=0; i < removeMappedParameters.size(); i++) { optimizingJob.getMappedParameters().remove( removeMappedParameters.get(i)); } for (int i=0; i < removeFixedParameters.size(); i++) { optimizingJob.getFixedParameters().removeParameter( removeFixedParameters.get(i)); } Iterator<String> iterator = newMappedParameters.keySet().iterator(); while (iterator.hasNext()) { String n = iterator.next(); String v = newMappedParameters.get(n); optimizingJob.getMappedParameters().put(n, v); } Parameter[] newFixed = newFixedParameters.getParameters(); for (int i=0; i < newFixed.length; i++) { optimizingJob.getFixedParameters().addParameter(newFixed[i]); } Parameter[] newGroup = newJobGroupParameters.getParameters(); for (int i=0; i < newGroup.length; i++) { jobGroup.getParameters().addParameter(newGroup[i]); } try { configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully updated the job group in the " + "configuration database.<BR>" + EOL); } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not update the job group in the " + "configuration database: " + e + ".<BR>" + EOL); } handleViewJobGroupOptimizingJob(requestInfo, jobGroup, optimizingJob.getName()); return; } } String star = "<SPAN CLASS=\"" + Constants.STYLE_WARNING_TEXT + "\">*</SPAN>"; htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Edit Optimizing Job \"" + optimizingJobName + "\" in Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName, Constants.SERVLET_PARAM_JOB_GROUP_OPTIMIZING_JOB_NAME, optimizingJobName, optimizingJobName); htmlBody.append("Update the following \"" + link + "\" optimizing job " + "information." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Fields marked with an asterisk (" + star + ") are required to have a value."); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM CLASS=\"" + Constants.STYLE_MAIN_FORM + "\" METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_EDIT_GROUP_OPTIMIZING_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden( Constants.SERVLET_PARAM_JOB_GROUP_OPTIMIZING_JOB_NAME, optimizingJobName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); JobClass jobClass = optimizingJob.getJobClass(); if (jobClass.overrideNumClients() > 0) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS, String.valueOf(jobClass.overrideNumClients())) + EOL); } if (jobClass.overrideCollectionInterval() > 0) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL, secondsToHumanReadableDuration( jobClass.overrideCollectionInterval())) + EOL); } if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>General Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String newName = optimizingJobName; if (submitted) { newName = request.getParameter(Constants.SERVLET_PARAM_NEW_NAME); if ((newName == null) || (newName.length() == 0)) { newName = optimizingJobName; } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Optimizing Job Name " + star +"</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_NEW_NAME + "\" VALUE=\"" + newName + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String durationStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DURATION); if ((durationStr == null) || (durationStr.length() == 0)) { if (submitted) { durationStr = ""; } else { if (optimizingJob.getDuration() > 0) { durationStr = secondsToHumanReadableDuration(optimizingJob.getDuration()); } else { durationStr = ""; } } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_DURATION + "\" VALUE=\"" + durationStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobClass.overrideNumClients() <= 0) { String numClientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS); if ((numClientsStr == null) || (numClientsStr.length() == 0)) { numClientsStr = String.valueOf(optimizingJob.getNumClients()); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Number of Clients " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_NUM_CLIENTS + "\" VALUE=\"" + numClientsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } String minThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_MIN); if ((minThreadsStr == null) || (minThreadsStr.length() == 0)) { minThreadsStr = String.valueOf(optimizingJob.getMinThreads()); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Minimum Number of Threads " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREADS_MIN + "\" VALUE=\"" + minThreadsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String maxThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_MAX); if ((maxThreadsStr == null) || (maxThreadsStr.length() == 0)) { if (optimizingJob.getMaxThreads() > 0) { maxThreadsStr = String.valueOf(optimizingJob.getMaxThreads()); } else { maxThreadsStr = ""; } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Maximum Number of Threads</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREADS_MAX + "\" VALUE=\"" + maxThreadsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String incrementStr = request.getParameter(Constants.SERVLET_PARAM_THREAD_INCREMENT); if ((incrementStr == null) || (incrementStr.length() == 0)) { incrementStr = String.valueOf(optimizingJob.getThreadIncrement()); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Thread Increment Between Iterations " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_THREAD_INCREMENT + "\" VALUE=\"" + incrementStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String delayStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY); if ((delayStr == null) || (delayStr.length() == 0)) { if (submitted) { delayStr = "0"; } else { delayStr = String.valueOf(optimizingJob.getThreadStartupDelay()); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Thread Startup Delay (ms)</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY + "\" VALUE=\"" + delayStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobClass.overrideCollectionInterval() <= 0) { String intervalStr = request.getParameter( Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL); if ((intervalStr == null) || (intervalStr.length() == 0)) { intervalStr = secondsToHumanReadableDuration( optimizingJob.getCollectionInterval()); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Statistics Collection Interval " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL + "\" VALUE=\"" + intervalStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } String nonImprovingStr = request.getParameter(Constants.SERVLET_PARAM_JOB_MAX_NON_IMPROVING); if ((nonImprovingStr == null) || (nonImprovingStr.length() == 0)) { nonImprovingStr = String.valueOf(optimizingJob.getMaxNonImprovingIterations()); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Max. Consecutive Non-Improving Iterations " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_MAX_NON_IMPROVING + "\" VALUE=\"" + nonImprovingStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); boolean reRunBestIteration; if (submitted) { reRunBestIteration = false; String reRunStr = request.getParameter(Constants.SERVLET_PARAM_RERUN_BEST_ITERATION); if (reRunStr != null) { reRunBestIteration = (reRunStr.equalsIgnoreCase("true") || reRunStr.equalsIgnoreCase("yes") || reRunStr.equalsIgnoreCase("on") || reRunStr.equalsIgnoreCase("1")); } } else { reRunBestIteration = optimizingJob.reRunBestIteration(); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Re-Run Best Iteration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"CHECKBOX\" NAME=\"" + Constants.SERVLET_PARAM_RERUN_BEST_ITERATION + '"' + (reRunBestIteration ? " CHECKED" : "") + "></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String reRunDurationStr = request.getParameter(Constants.SERVLET_PARAM_RERUN_DURATION); if ((reRunDurationStr == null) || (reRunDurationStr.length() == 0)) { if (submitted) { reRunDurationStr = ""; } else { if (optimizingJob.getReRunDuration() > 0) { reRunDurationStr = secondsToHumanReadableDuration( optimizingJob.getReRunDuration()); } else { reRunDurationStr = ""; } } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Re-Run Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_RERUN_DURATION + "\" VALUE=\"" + reRunDurationStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); Parameter[] optimizationStubs = optimizingJob.getOptimizationAlgorithm(). getOptimizationAlgorithmParameterStubs(jobClass).clone(). getParameters(); if ((optimizationStubs != null) && (optimizationStubs.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Optimization Algorithm " + "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); for (int i=0; i < optimizationStubs.length; i++) { if ((optimizationStubs[i] instanceof PlaceholderParameter) || (optimizationStubs[i] instanceof LabelParameter)) { continue; } if (submitted) { try { optimizationStubs[i].htmlInputFormToValue(request); } catch (InvalidValueException ive) {} } else { Parameter p = optimizingJob.getOptimizationParameters().getParameter( optimizationStubs[i].getName()); if (p != null) { optimizationStubs[i].setValueFrom(p); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>" + optimizationStubs[i].getDisplayName() + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizationStubs[i].getHTMLInputForm( Constants.SERVLET_PARAM_OPTIMIZATION_PARAM_PREFIX) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } Parameter[] stubs = jobClass.getParameterStubs().clone().getParameters(); Parameter[] groupParameters = jobGroup.getParameters().getParameters(); if ((stubs != null) && (stubs.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Job-Specific " + "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); boolean skippedFirstSpace = false; for (int i=0; i < stubs.length; i++) { if ((stubs[i] instanceof PlaceholderParameter) || (stubs[i] instanceof LabelParameter)) { continue; } if (! skippedFirstSpace) { skippedFirstSpace = true; } else { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + stubs[i].getDisplayName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); String mapParam = Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName(); String mapType = null; String mapToName = stubs[i].getName(); if (submitted) { mapType = request.getParameter(mapParam); try { stubs[i].htmlInputFormToValue(request); } catch (InvalidValueException ive) {} } if (mapType == null) { if (optimizingJob.getMappedParameters().containsKey( stubs[i].getName())) { mapType = Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING; String mappedName = optimizingJob.getMappedParameters().get(stubs[i].getName()); Parameter mappedParam = jobGroup.getParameters().getParameter(mappedName); if (mappedParam != null) { mapToName = mappedParam.getName(); stubs[i].setValueFrom(mappedParam); } } else if (optimizingJob.getFixedParameters().hasParameter( stubs[i].getName())) { mapType = Constants.GROUP_PARAM_TYPE_FIXED; Parameter fixedParam = optimizingJob.getFixedParameters().getParameter( stubs[i].getName()); if (fixedParam != null) { stubs[i].setValueFrom(fixedParam); } } else { mapType = Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW; } } htmlBody.append(" <TR>" + EOL); if (mapType.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING)) { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + mapParam + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING + "\" CHECKED>Map to Existing Job Group " + "Parameter</TD>" + EOL); } else { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + mapParam + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING + "\">Map to Existing Job Group Parameter</TD>" + EOL); } htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_MAP_TO_NAME_PREFIX + stubs[i].getName() + "\">" + EOL); for (int j=0; j < groupParameters.length; j++) { if ((groupParameters[j] instanceof PlaceholderParameter) || (groupParameters[j] instanceof LabelParameter)) { continue; } String selectedStr = ""; if (groupParameters[j].getName().equals(mapToName)) { selectedStr = " SELECTED"; } htmlBody.append(" <OPTION VALUE=\"" + groupParameters[j].getName() + '"' + selectedStr + '>' + groupParameters[j].getDisplayName() + EOL); } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); if (mapType.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW)) { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW + "\" CHECKED>Create a New Job Group Parameter</TD>" + EOL); } else { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW + "\">Create a New Job Group Parameter</TD>" + EOL); } htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_MAP_TO_DISPLAY_NAME_PREFIX + stubs[i].getName() + "\" VALUE=\"" + stubs[i].getDisplayName() + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); if (mapType.equals(Constants.GROUP_PARAM_TYPE_FIXED)) { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_FIXED + "\" CHECKED>Always Use a Fixed Value</TD>" + EOL); } else { htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_FIXED + "\">Always Use a Fixed Value</TD>" + EOL); } htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + stubs[i].getHTMLInputForm( Constants.SERVLET_PARAM_JOB_PARAM_PREFIX) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"2\"> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Update " + "Optimizing Job\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append("</FORM>" + EOL); } /** * Handles all processing related to creating a new job group in the SLAMD * server. * * @param requestInfo The state information for this request. */ static void handleAddJobGroup(RequestInfo requestInfo) { logMessage(requestInfo, "In handleAddJobGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to schedule jobs to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "create a job group."); return; } // Get any parameters that may have been specified. String name = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); String description = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_DESCRIPTION); // If a job group name was specified, then create the job group. if (name != null) { // Make sure that the specified name isn't already taken. JobGroup jobGroup; try { jobGroup = configDB.getJobGroup(name); } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Unable to determine whether the job " + "group already exists " + e.getMessage() + "<BR>" + EOL); return; } if (jobGroup == null) { try { jobGroup = new JobGroup(name, description); configDB.writeJobGroup(jobGroup); handleViewJobGroup(requestInfo); return; } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Unable to add the job group to the " + "configuration database: " + e.getMessage() + "<BR>" + EOL); return; } } else { infoMessage.append("ERROR: A job group already exists with the " + "name \"" + name + "\".<BR>" + EOL); } } htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Create a New Job Group</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM CLASS=\"" + Constants.STYLE_MAIN_FORM + "\" METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_ADD_GROUP) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } if (name == null) { name = ""; } if (description == null) { description = ""; } htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><SPAN CLASS=\"" + Constants.STYLE_FORM_CAPTION + "\">Job Group Name</SPAN></TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_GROUP_NAME + "\" VALUE=\"" + name + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><SPAN CLASS=\"" + Constants.STYLE_FORM_CAPTION + "\">Job Group Description</SPAN></TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_GROUP_DESCRIPTION + "\" VALUE=\"" + description + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Create Job " + "Group\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append("</FORM>" + EOL); } /** * Handles all processing related to adding a job to a job group. * * @param requestInfo The state information for this request. */ static void handleAddJobToGroup(RequestInfo requestInfo) { logMessage(requestInfo, "In handleAddJobToJobGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to view job information to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "update a job group."); return; } // Get the job group to which a new job should be added. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if (jobGroupName == null) { infoMessage.append("ERROR: No job group specified.<BR>" + EOL); return; } JobGroup jobGroup; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration database." + "<BR>" + EOL); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Cannot retrieve job group \"" + jobGroupName + "\": " + e.getMessage() + "<BR>" + EOL); return; } ArrayList jobList = jobGroup.getJobList(); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName, jobGroupName); // See if the user has specified the job type. If not, then display a form // to allow the user to select it. JobClass jobClass = null; String jobClassName = request.getParameter(Constants.SERVLET_PARAM_JOB_CLASS); if (jobClassName != null) { jobClass = slamdServer.getJobClass(jobClassName); if (jobClass == null) { infoMessage.append("WARNING: Job class \"" + jobClassName + "\" is not defined in the SLAMD server."); } else { StringBuilder deprecatedMessage = new StringBuilder(); if (jobClass.isDeprecated(deprecatedMessage)) { infoMessage.append("WARNING: This job class has been deprecated."); if (deprecatedMessage.length() > 0) { infoMessage.append(" "); infoMessage.append(deprecatedMessage); } infoMessage.append("<BR><BR>" + EOL); } } } if (jobClass == null) { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Add a New Job to Job Group " + jobGroupName + "</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Choose the type of job to add to the \"" + link + "\" job group:" + EOL); htmlBody.append("<BR><BR>"); htmlBody.append("<FORM METHOD=\"SUBMIT\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_ADD_JOB_TO_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_JOB_CLASS + "\">"); String[] jobCategories = slamdServer.getJobClassCategories(); Arrays.sort(jobCategories); for (int i=0; i < jobCategories.length; i++) { JobClass[] jobClasses = slamdServer.getJobClasses(jobCategories[i]); for (int j=0; ((jobClasses != null) && (j < jobClasses.length)); j++) { htmlBody.append(" <OPTION VALUE=\"" + jobClasses[j].getClass().getName() + "\">" + jobCategories[i] + " -- " + jobClasses[j].getJobName() + EOL); } } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" <BR><BR>"); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Continue\">" + EOL); htmlBody.append("</FORM>" + EOL); return; } // See if the user submitted the form. If so, then make sure that the // provided values are acceptable and add the job to the group. String confirmed = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); boolean submitted = ((confirmed != null) && (confirmed.length() > 0)); if (submitted) { boolean jobValid = true; // Get the job name. It is required, and it must not duplicate the name // of any existing job or optimizing job in the group. String jobName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME); if ((jobName == null) || (jobName.length() == 0)) { jobValid = false; infoMessage.append("ERROR: No job name was given. This is a " + "required parameter.<BR>" + EOL); } else { for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupJob) { if (((JobGroupJob) o).getName().equalsIgnoreCase(jobName)) { jobValid = false; infoMessage.append("ERROR: Job name \"" + jobName + "\" is already in use by another job in the " + "job group.<BR>" + EOL); } } else if (o instanceof JobGroupOptimizingJob) { if (((JobGroupOptimizingJob) o).getName().equalsIgnoreCase(jobName)) { jobValid = false; infoMessage.append("ERROR: Job name \"" + jobName + "\" is already in use by an optimizing job " + "in the job group.<BR>" + EOL); } } } } // Get the duration. It is optional. int duration = -1; String durationStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DURATION); if ((durationStr != null) && (durationStr.length() > 0)) { try { duration = DurationParser.parse(durationStr); } catch (SLAMDException se) { jobValid = false; infoMessage.append("ERROR: " + se.getMessage() + "<BR>" + EOL); } } // Get the number of clients. It is required. int numClients = -1; String clientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS); if ((clientsStr == null) || (clientsStr.length() == 0)) { jobValid = false; infoMessage.append("ERROR: The number of clients was not provided. " + "This is a required parameter.<BR>" + EOL); } else { try { numClients = Integer.parseInt(clientsStr); if (numClients < 1) { jobValid = false; infoMessage.append("ERROR: The number of clients must be " + "greater than or equal to 1.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The number of clients must be an " + "integer.<BR>" + EOL); } } // Get the number of threads per client. It is required. int threadsPerClient = -1; String threadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_PER_CLIENT); if ((threadsStr == null) || (threadsStr.length() == 0)) { jobValid = false; infoMessage.append("ERROR: The number of threads per client was not " + "provided. This is a required parameter.<BR>" + EOL); } else { try { threadsPerClient = Integer.parseInt(threadsStr); if (threadsPerClient < 1) { jobValid = false; infoMessage.append("ERROR: The number of threads per client " + "must be greater than or equal to 1.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The number of threads per client must " + "be an integer.<BR>" + EOL); } } // Get the thread startup delay. It is optional. int threadStartupDelay = 0; String delayStr = request.getParameter( Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY); if ((delayStr != null) && (delayStr.length() > 0)) { try { threadStartupDelay = Integer.parseInt(delayStr); if (threadStartupDelay < 0) { jobValid = false; infoMessage.append("ERROR: The thread startup delay must be " + "greater than or equal to 0.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The thread startup delay must be an " + "integer.<BR>" + EOL); } } // Get the statistics collection interval. It is required. int collectionInterval = -1; String intervalStr = request.getParameter( Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL); if ((intervalStr == null) || (intervalStr.length() == 0)) { jobValid = false; infoMessage.append("ERROR: The statistics collection interval was " + "not provided. This is a required parameter.<BR>" + EOL); } else { try { collectionInterval = DurationParser.parse(intervalStr); if (collectionInterval <= 0) { jobValid = false; infoMessage.append("ERROR: The statistics collection interval " + "must be greater than zero.<BR>" + EOL); } else if ((duration > 0) && (collectionInterval >= duration)) { jobValid = false; infoMessage.append("ERROR: The statistics collection interval " + "must be less than the job duration.<BR>" + EOL); } } catch (SLAMDException se) { jobValid = false; infoMessage.append("ERROR: " + se.getMessage() + "<BR>" + EOL); } } // Get the set of dependencies. It is optional. ArrayList<String> dependencies = new ArrayList<String>(); String[] dependencyStrs = request.getParameterValues(Constants.SERVLET_PARAM_JOB_DEPENDENCY); if ((dependencyStrs != null) && (dependencyStrs.length > 0)) { for (int i=0; i < dependencyStrs.length; i++) { boolean found = false; for (int j=0; j < jobList.size(); j++) { Object o = jobList.get(j); if (o instanceof JobGroupJob) { if (((JobGroupJob) o).getName().equals(dependencyStrs[i])) { found = true; break; } } else if (o instanceof JobGroupOptimizingJob) { if (((JobGroupOptimizingJob) o).getName().equals(dependencyStrs[i])) { found = true; break; } } } if (found) { dependencies.add(dependencyStrs[i]); } else { jobValid = false; infoMessage.append("ERROR: A dependency was defined for job \"" + dependencyStrs[i] + "\" but no such job was " + "found in the job group.<BR>" + EOL); } } } // Process all of the job-specific parameters. LinkedHashMap<String,String> mappedParameters = new LinkedHashMap<String,String>(); ParameterList newMappedParameters = new ParameterList(); ParameterList fixedParameters = new ParameterList(); ParameterList jobGroupParameters = jobGroup.getParameters(); Parameter[] stubs = jobClass.getParameterStubs().clone().getParameters(); for (int i=0; i < stubs.length; i++) { // Determine whether this parameter should be mapped to an existing // parameter, mapped as a new parameter, or hold a fixed value. String pName = Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName(); String pValue = request.getParameter(pName); if ((pValue == null) || (pValue.length() == 0)) { // This shouldn't happen, but we'll let it slide if it's not a // required parameter. if (stubs[i].isRequired()) { jobValid = false; infoMessage.append("ERROR: Unable to determine how job " + "parameter \"" + stubs[i].getDisplayName() + "\" should be handled.<BR>" + EOL); } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING)) { // Determine which existing parameter it should be mapped to. String mapToName = Constants.SERVLET_PARAM_MAP_TO_NAME_PREFIX + stubs[i].getName(); String mapToValue = request.getParameter(mapToName); if ((mapToValue == null) || (mapToValue.length() == 0)) { jobValid = false; infoMessage.append("ERROR: Job parameter \"" + stubs[i].getDisplayName() + " was configured " + "to be mapped to a job group parameter, but " + "no target parameter was specified.<BR>" + EOL); } else { Parameter p = jobGroupParameters.getParameter(mapToValue); if (p == null) { jobValid = false; infoMessage.append("ERROR: Job parameter \"" + stubs[i].getDisplayName() + "\" was " + "configured to be mapped to job group " + "parameter \"" + mapToValue + "\" but no " + "such parameter is defined in the job " + "group.<BR>" + EOL); } else { mappedParameters.put(stubs[i].getName(), mapToValue); } } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW)) { // Determine the display name to use for the new mapped parameter. String mapToName = Constants.SERVLET_PARAM_MAP_TO_DISPLAY_NAME_PREFIX + stubs[i].getName(); String mapToValue = request.getParameter(mapToName); if ((mapToValue != null) && (mapToValue.length() > 0)) { stubs[i].setDisplayName(mapToValue); } // Make sure that the new parameter doesn't conflict with an // existing job group parameter. boolean conflict = false; Parameter[] groupParams = jobGroupParameters.getParameters(); String originalName = stubs[i].getName(); for (int j=0; j < groupParams.length; j++) { if (stubs[i].getName().equals(groupParams[j].getName())) { // There is a conflict in the parameter names, which we can work // around by changing the name of the new parameter. conflict = true; int k = 1; String baseName = stubs[i].getName(); String newName = baseName + k; while (conflict) { k++; conflict = false; newName = baseName + k; for (int l=0; l < groupParams.length; l++) { if (newName.equals(groupParams[l].getName())) { conflict = true; break; } } } stubs[i].setName(newName); } else if (stubs[i].getDisplayName().equalsIgnoreCase( groupParams[j].getDisplayName())) { // There is a conflict in the display names, which we can't work // around and will therefore propagate back to the user. conflict = true; infoMessage.append("ERROR: Job parameter \"" + stubs[i].getDisplayName() + "\" was " + "configured to be a new mapped parameter " + "for the job group, but its display name " + "conflicts with the display name of another " + "parameter already in the job group.<BR>" + EOL); break; } } if (conflict) { jobValid = false; } else { mappedParameters.put(originalName, stubs[i].getName()); newMappedParameters.addParameter(stubs[i]); } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_FIXED)) { // Determine the fixed value to use for the parameter. try { stubs[i].htmlInputFormToValue(request); fixedParameters.addParameter(stubs[i]); } catch (InvalidValueException ive) { jobValid = false; infoMessage.append("ERROR: The specified fixed value for " + "parameter \"" + stubs[i].getDisplayName() + "\" is invalid: " + ive.getMessage() + "<BR>" + EOL); } } else { jobValid = false; infoMessage.append("ERROR: Unable to determine how job " + "parameter \"" + stubs[i].getDisplayName() + "\" should be handled.<BR>" + EOL); } } // If everything looks good, then create the job and add it to the group. // Also, if there are any new mapped parameters, then add them to the job // group. if (jobValid) { JobGroupJob job = new JobGroupJob(jobGroup, jobName, jobClass, duration, collectionInterval, numClients, threadsPerClient, threadStartupDelay, dependencies, mappedParameters, fixedParameters); jobGroup.getJobList().add(job); Parameter[] newMapped = newMappedParameters.getParameters(); for (int i=0; i < newMapped.length; i++) { jobGroupParameters.addParameter(newMapped[i]); } // Write the updated job group to the configuration database. try { configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully added job \"" + jobName + "\" to the job group.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not update the job group in the " + "configuration database: " + e.getMessage() + ".<BR>" + EOL); } } } String star = "<SPAN CLASS=\"" + Constants.STYLE_WARNING_TEXT + "\">*</SPAN>"; htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Add a New \"" + jobClass.getJobName() + "\" Job to Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Enter the following information about the " + jobClass.getJobName() + " job to add to the \"" + link + "\" job group." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("For the job-specific parameters, you may either " + "specify hard-coded values or allow the user to " + "specify the value as part of the job group parameters." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Fields marked with an asterisk (" + star + ") are required to have a value."); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM CLASS=\"" + Constants.STYLE_MAIN_FORM + "\" METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_ADD_JOB_TO_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_CLASS, jobClass.getClass().getName()) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); if (jobClass.overrideNumClients() > 0) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS, String.valueOf(jobClass.overrideNumClients())) + EOL); } if (jobClass.overrideThreadsPerClient() > 0) { htmlBody.append(" " + generateHidden( Constants.SERVLET_PARAM_JOB_THREADS_PER_CLIENT, String.valueOf(jobClass.overrideThreadsPerClient())) + EOL); } if (jobClass.overrideCollectionInterval() > 0) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL, secondsToHumanReadableDuration( jobClass.overrideCollectionInterval())) + EOL); } if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>General Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String jobName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME); if (jobName == null) { jobName = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Name " + star +"</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME + "\" VALUE=\"" + jobName + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String durationStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DURATION); if (durationStr == null) { durationStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_DURATION + "\" VALUE=\"" + durationStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobClass.overrideNumClients() <= 0) { String numClientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS); if (numClientsStr == null) { numClientsStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Number of Clients " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_NUM_CLIENTS + "\" VALUE=\"" + numClientsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } if (jobClass.overrideThreadsPerClient() <= 0) { String numThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_PER_CLIENT); if (numThreadsStr == null) { numThreadsStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Threads per Client " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREADS_PER_CLIENT + "\" VALUE=\"" + numThreadsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } String delayStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY); if (delayStr == null) { delayStr = "0"; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Thread Startup Delay (ms)</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY + "\" VALUE=\"" + delayStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobClass.overrideCollectionInterval() <= 0) { String intervalStr = request.getParameter( Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL); if (intervalStr == null) { intervalStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Statistics Collection Interval " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL + "\" VALUE=\"" + intervalStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } if (! jobList.isEmpty()) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Dependencies</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); for (int i=0; i < jobList.size(); i++) { String depName; Object o = jobList.get(i); if (o instanceof JobGroupJob) { depName = ((JobGroupJob) o).getName(); } else if (o instanceof JobGroupOptimizingJob) { depName = ((JobGroupOptimizingJob) o).getName(); } else { continue; } String checkedStr = ""; String[] depValues = request.getParameterValues(Constants.SERVLET_PARAM_JOB_DEPENDENCY); for (int j=0; ((depValues != null) && (j < depValues.length)); j++) { if (depValues[j].equals(depName)) { checkedStr = " CHECKED"; break; } } if ((! submitted) && (i == (jobList.size() - 1))) { checkedStr = " CHECKED"; } htmlBody.append(" <INPUT TYPE=\"CHECKBOX\" NAME=\"" + Constants.SERVLET_PARAM_JOB_DEPENDENCY + "\" VALUE=\"" + depName + '"' + checkedStr + '>' + depName + "<BR>" + EOL); } htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } Parameter[] stubs = jobClass.getParameterStubs().clone().getParameters(); Parameter[] groupParameters = jobGroup.getParameters().getParameters(); if ((stubs != null) && (stubs.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Job-Specific " + "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); boolean skippedFirstSpace = false; for (int i=0; i < stubs.length; i++) { if ((stubs[i] instanceof PlaceholderParameter) || (stubs[i] instanceof LabelParameter)) { continue; } if (! skippedFirstSpace) { skippedFirstSpace = true; } else { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + stubs[i].getDisplayName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (submitted) { try { stubs[i].htmlInputFormToValue(request); } catch (InvalidValueException ive) {} } boolean selected = false; if (groupParameters.length > 0) { int selectedIndex = -1; for (int j=0; ((! selected) && (j < groupParameters.length)); j++) { if ((groupParameters[j] instanceof PlaceholderParameter) || (groupParameters[j] instanceof LabelParameter)) { continue; } if (stubs[i].getName().equalsIgnoreCase( groupParameters[j].getName()) || stubs[i].getDisplayName().equalsIgnoreCase( groupParameters[j].getDisplayName())) { selected = true; selectedIndex = j; } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING + '"'); if (selected) { htmlBody.append(" CHECKED"); } htmlBody.append(">Map to Existing Job Group Parameter</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_MAP_TO_NAME_PREFIX + stubs[i].getName() + "\">" + EOL); for (int j=0; j < groupParameters.length; j++) { if ((groupParameters[j] instanceof PlaceholderParameter) || (groupParameters[j] instanceof LabelParameter)) { continue; } htmlBody.append(" <OPTION VALUE=\"" + groupParameters[j].getName()); if (j == selectedIndex) { htmlBody.append("\" SELECTED>"); } else { htmlBody.append("\">"); } String displayName = groupParameters[j].getDisplayName(); if (displayName == null) { displayName = groupParameters[j].getName(); } htmlBody.append(displayName + EOL); } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW + '"'); if (! selected) { htmlBody.append(" CHECKED"); selected = true; } htmlBody.append(">Create a New Job Group Parameter</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_MAP_TO_DISPLAY_NAME_PREFIX + stubs[i].getName() + "\" VALUE=\"" + stubs[i].getDisplayName() + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_FIXED + "\">Always Use a " + "Fixed Value</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + stubs[i].getHTMLInputForm( Constants.SERVLET_PARAM_JOB_PARAM_PREFIX) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"2\"> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Add Job to Job " + "Group\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append("</FORM>" + EOL); } /** * Handles all processing related to adding an optimizing job to a job group. * * @param requestInfo The state information for this request. */ static void handleAddOptimizingJobToGroup(RequestInfo requestInfo) { logMessage(requestInfo, "In handleAddOptimizingJobToJobGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to view job information to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "update a job group."); return; } // Get the job group to which a new job should be added. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if (jobGroupName == null) { infoMessage.append("ERROR: No job group specified.<BR>" + EOL); return; } JobGroup jobGroup; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration database." + "<BR>" + EOL); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Cannot retrieve job group \"" + jobGroupName + "\": " + e.getMessage() + "<BR>" + EOL); return; } ArrayList jobList = jobGroup.getJobList(); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName, jobGroupName); // See if the user has specified the job type. If not, then display a form // to allow the user to select it. JobClass jobClass = null; String jobClassName = request.getParameter(Constants.SERVLET_PARAM_JOB_CLASS); if (jobClassName != null) { jobClass = slamdServer.getJobClass(jobClassName); if (jobClass == null) { infoMessage.append("WARNING: Job class \"" + jobClassName + "\" is not defined in the SLAMD server."); } else { StringBuilder deprecatedMessage = new StringBuilder(); if (jobClass.isDeprecated(deprecatedMessage)) { infoMessage.append("WARNING: This job class has been deprecated."); if (deprecatedMessage.length() > 0) { infoMessage.append(" "); infoMessage.append(deprecatedMessage); } infoMessage.append("<BR><BR>" + EOL); } } } if (jobClass == null) { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Add a New Optimizing Job to Job Group " + jobGroupName + "</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Choose the type of optimizing job to add to the \"" + link + "\" job group:" + EOL); htmlBody.append("<BR><BR>"); htmlBody.append("<FORM METHOD=\"SUBMIT\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_ADD_OPTIMIZING_JOB_TO_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_JOB_CLASS + "\">"); String[] jobCategories = slamdServer.getJobClassCategories(); Arrays.sort(jobCategories); for (int i=0; i < jobCategories.length; i++) { JobClass[] jobClasses = slamdServer.getJobClasses(jobCategories[i]); for (int j=0; ((jobClasses != null) && (j < jobClasses.length)); j++) { if (jobClasses[j].overrideThreadsPerClient() < 0) { htmlBody.append(" <OPTION VALUE=\"" + jobClasses[j].getClass().getName() + "\">" + jobCategories[i] + " -- " + jobClasses[j].getJobName() + EOL); } } } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" <BR><BR>"); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Continue\">" + EOL); htmlBody.append("</FORM>" + EOL); return; } // Figure out which optimization algorithm should be used. If one was // specified in the request, then assume it has already been provided. // Otherwise, show the user a set of the options available to them. OptimizationAlgorithm optimizationAlgorithm; String optimizationAlgorithmClass = request.getParameter(Constants.SERVLET_PARAM_OPTIMIZATION_ALGORITHM); if ((optimizationAlgorithmClass == null) || (optimizationAlgorithmClass.length() == 0)) { // Get a list of the available optimization algorithms that can be used // for this job and allow the user to choose which one he/she wants. // If none are available, display an error message. ArrayList<OptimizationAlgorithm> availableAlgorithmList = new ArrayList<OptimizationAlgorithm>(); OptimizationAlgorithm[] algorithms = slamdServer.getOptimizationAlgorithms(); if ((algorithms == null) || (algorithms.length == 0)) { infoMessage.append("WARNING: No optimization algorithms have been " + "configured in the server. Using the default.<BR>" + EOL); algorithms = new OptimizationAlgorithm[] { new SingleStatisticOptimizationAlgorithm() }; } for (int i=0; i < algorithms.length; i++) { if (algorithms[i].availableWithJobClass(jobClass)) { availableAlgorithmList.add(algorithms[i]); } } if (availableAlgorithmList.isEmpty()) { infoMessage.append("ERROR: There are no optimization algorithms " + "configured in the server that may be used with " + jobClass.getJobName() + " jobs.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } else if (availableAlgorithmList.size() == 1) { optimizationAlgorithm = availableAlgorithmList.get(0); } else { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Add an Optimizing Job to Job Group " + jobGroupName + "</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Select the optimization algorithm that you wish to " + "use for this optimizing " + jobClass.getJobName() + " job." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + requestInfo.servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, requestInfo.section) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, requestInfo.subsection) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroup.getName()) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_CLASS, jobClass.getClass().getName()) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_OPTIMIZATION_ALGORITHM + "\">" + EOL); for (int i=0; i < availableAlgorithmList.size(); i++) { OptimizationAlgorithm algorithm = availableAlgorithmList.get(i); htmlBody.append(" <OPTION VALUE=\"" + algorithm.getClass().getName() + "\">" + algorithm.getOptimizationAlgorithmName() + EOL); } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" <BR><BR>" + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" VALUE=\"Continue\">" + EOL); htmlBody.append("</FORM>" + EOL); return; } } else { optimizationAlgorithm = slamdServer.getOptimizationAlgorithm(optimizationAlgorithmClass); if (optimizationAlgorithm == null) { infoMessage.append("ERROR: Undefined optimization algorithm class \"" + optimizationAlgorithmClass + "\" specified for the optimizing job.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } } // See if the user submitted the form. If so, then make sure that the // provided values are acceptable and add the job to the group. String confirmed = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); boolean submitted = ((confirmed != null) && (confirmed.length() > 0)); if (submitted) { boolean jobValid = true; // Get the optimizing job name. It is required, and it must not duplicate // the name of any existing job or optimizing job in the group. String jobName = request.getParameter( Constants.SERVLET_PARAM_JOB_GROUP_OPTIMIZING_JOB_NAME); if ((jobName == null) || (jobName.length() == 0)) { jobValid = false; infoMessage.append("ERROR: No optimizing job name was given. This " + "is a required parameter.<BR>" + EOL); } else { for (int i=0; i < jobList.size(); i++) { Object o = jobList.get(i); if (o instanceof JobGroupJob) { if (((JobGroupJob) o).getName().equalsIgnoreCase(jobName)) { jobValid = false; infoMessage.append("ERROR: Job name \"" + jobName + "\" is already in use by a job in the job " + "group.<BR>" + EOL); } } else if (o instanceof JobGroupOptimizingJob) { if (((JobGroupOptimizingJob) o).getName().equalsIgnoreCase(jobName)) { jobValid = false; infoMessage.append("ERROR: Job name \"" + jobName + "\" is already in use by another optimizing " + "job in the job group.<BR>" + EOL); } } } } // Get the duration. It is optional. int duration = -1; String durationStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DURATION); if ((durationStr != null) && (durationStr.length() > 0)) { try { duration = DurationParser.parse(durationStr); } catch (SLAMDException se) { jobValid = false; infoMessage.append("ERROR: " + se.getMessage() + "<BR>" + EOL); } } // Get the delay between iterations. It is optional. int delayBetweenIterations = 0; String delayStr = request.getParameter(Constants.SERVLET_PARAM_TIME_BETWEEN_STARTUPS); if ((delayStr != null) && (delayStr.length() > 0)) { try { delayBetweenIterations = Integer.parseInt(delayStr); if (delayBetweenIterations < 0) { jobValid = false; infoMessage.append("ERROR: The delay between iterations must " + "be greater than or equal to 0.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The delay between iterations must be " + "an integer.<BR>" + EOL); } } // Get the number of clients. It is required. int numClients = -1; String clientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS); if ((clientsStr == null) || (clientsStr.length() == 0)) { jobValid = false; infoMessage.append("ERROR: The number of clients was not provided. " + "This is a required parameter.<BR>" + EOL); } else { try { numClients = Integer.parseInt(clientsStr); if (numClients < 1) { jobValid = false; infoMessage.append("ERROR: The number of clients must be " + "greater than or equal to 1.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The number of clients must be an " + "integer.<BR>" + EOL); } } // Get the minimum number of threads per client. It is required. int minThreads = 1; String minThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_MIN); if ((minThreadsStr == null) || (minThreadsStr.length() == 0)) { jobValid = false; infoMessage.append("ERROR: The minimum number of threads per client " + "was not provided. This is a required parameter." + "<BR>" + EOL); } else { try { minThreads = Integer.parseInt(minThreadsStr); if (minThreads < 1) { jobValid = false; infoMessage.append("ERROR: The minimum number of threads per " + "client must be greater than or equal to " + "1.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The minimum number of threads per " + "client must be an integer.<BR>" + EOL); } } // Get the maximum number of threads per client. It is optional. int maxThreads = -1; String maxThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_MAX); if ((maxThreadsStr != null) && (maxThreadsStr.length() > 0)) { try { maxThreads = Integer.parseInt(maxThreadsStr); if ((maxThreads > 0) && (maxThreads < minThreads)) { jobValid = false; infoMessage.append("ERROR: The maximum number of threads per " + "client must be greater than or equal to the " + "minimum number of threads per client.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The maximum number of threads per " + "client must be an integer.<BR>" + EOL); } } // Get the thread increment between iterations. It is required. int threadIncrement = 1; String incrementStr = request.getParameter(Constants.SERVLET_PARAM_THREAD_INCREMENT); if ((incrementStr == null) || (incrementStr.length() == 0)) { jobValid = false; infoMessage.append("ERROR: The thread increment between iterations " + "was not provided. It is a required " + "parameter.<BR>" + EOL); } else { try { threadIncrement = Integer.parseInt(incrementStr); if (threadIncrement < 1) { jobValid = false; infoMessage.append("ERROR: The thread increment between " + "iterations must be greater than or equal to " + "1.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The thread increment between " + "iterations must be an integer.<BR>" + EOL); } } // Get the thread startup delay. It is optional. int threadStartupDelay = 0; delayStr = request.getParameter( Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY); if ((delayStr != null) && (delayStr.length() > 0)) { try { threadStartupDelay = Integer.parseInt(delayStr); if (threadStartupDelay < 0) { jobValid = false; infoMessage.append("ERROR: The thread startup delay must be " + "greater than or equal to 0.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The thread startup delay must be an " + "integer.<BR>" + EOL); } } // Get the statistics collection interval. It is required. int collectionInterval = -1; String intervalStr = request.getParameter( Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL); if ((intervalStr == null) || (intervalStr.length() == 0)) { jobValid = false; infoMessage.append("ERROR: The statistics collection interval was " + "not provided. This is a required parameter.<BR>" + EOL); } else { try { collectionInterval = DurationParser.parse(intervalStr); if (collectionInterval <= 0) { jobValid = false; infoMessage.append("ERROR: The statistics collection interval " + "must be greater than zero.<BR>" + EOL); } else if ((duration > 0) && (collectionInterval >= duration)) { jobValid = false; infoMessage.append("ERROR: The statistics collection interval " + "must be less than the job duration.<BR>" + EOL); } } catch (SLAMDException se) { jobValid = false; infoMessage.append("ERROR: " + se.getMessage() + "<BR>" + EOL); } } // Get the maximum number of non-improving iterations. It is required. int maxNonImproving = 1; String maxNonImprovingStr = request.getParameter(Constants.SERVLET_PARAM_JOB_MAX_NON_IMPROVING); if ((maxNonImprovingStr == null) || (maxNonImprovingStr.length() == 0)) { jobValid = false; infoMessage.append("ERROR: The maximum number of consecutive " + "non-improving iterations was not provided. This " + "a required parameter.<BR>" + EOL); } else { try { maxNonImproving = Integer.parseInt(maxNonImprovingStr); if (maxNonImproving < 1) { jobValid = false; infoMessage.append("ERROR: The maximum number of consecutive " + "non-improving iterations must be greater " + "than or equal to 1.<BR>" + EOL); } } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The maximum number of consecutive " + "non-improving iterations must be an " + "integer.<BR>" + EOL); } } // Get the flag indicating whether to re-run the best iteration. boolean reRunBestIteration = false; String reRunStr = request.getParameter(Constants.SERVLET_PARAM_RERUN_BEST_ITERATION); if (reRunStr != null) { reRunBestIteration = (reRunStr.equalsIgnoreCase("true") || reRunStr.equalsIgnoreCase("yes") || reRunStr.equalsIgnoreCase("on") || reRunStr.equalsIgnoreCase("1")); } // Get the re-run duration. int reRunDuration = -1; String reRunDurationStr = request.getParameter(Constants.SERVLET_PARAM_RERUN_DURATION); if ((reRunDurationStr != null) && (reRunDurationStr.length() > 0)) { try { reRunDuration = DurationParser.parse(reRunDurationStr); } catch (SLAMDException se) { jobValid = false; infoMessage.append("ERROR: " + se.getMessage() + "<BR>" + EOL); } } // Get the set of dependencies. It is optional. ArrayList<String> dependencies = new ArrayList<String>(); String[] dependencyStrs = request.getParameterValues(Constants.SERVLET_PARAM_JOB_DEPENDENCY); if ((dependencyStrs != null) && (dependencyStrs.length > 0)) { for (int i=0; i < dependencyStrs.length; i++) { boolean found = false; for (int j=0; j < jobList.size(); j++) { Object o = jobList.get(j); if (o instanceof JobGroupJob) { if (((JobGroupJob) o).getName().equals(dependencyStrs[i])) { found = true; break; } } else if (o instanceof JobGroupOptimizingJob) { if (((JobGroupOptimizingJob) o).getName().equals(dependencyStrs[i])) { found = true; break; } } } if (found) { dependencies.add(dependencyStrs[i]); } else { jobValid = false; infoMessage.append("ERROR: A dependency was defined for " + "optimizing job \"" + dependencyStrs[i] + "\" but no such job or optimizing job was " + "found in the job group.<BR>" + EOL); } } } // Process all of the optimization algorithm parameters. Parameter[] optimizationStubs = optimizationAlgorithm.getOptimizationAlgorithmParameterStubs( jobClass).clone().getParameters(); ParameterList optimizationParameters = new ParameterList(); for (int i=0; i < optimizationStubs.length; i++) { if ((optimizationStubs[i] instanceof PlaceholderParameter) || (optimizationStubs[i] instanceof LabelParameter)) { continue; } try { String paramName = Constants.SERVLET_PARAM_OPTIMIZATION_PARAM_PREFIX + optimizationStubs[i].getName(); String[] values = request.getParameterValues(paramName); optimizationStubs[i].htmlInputFormToValue(values); optimizationParameters.addParameter(optimizationStubs[i]); } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: The provided value(s) for optimization " + "algorithm parameter \"" + optimizationStubs[i].getDisplayName() + "\" were invalid: " + e.getMessage() + ".<BR>" + EOL); } } // Process all of the job-specific parameters. LinkedHashMap<String,String> mappedParameters = new LinkedHashMap<String,String>(); ParameterList newMappedParameters = new ParameterList(); ParameterList fixedParameters = new ParameterList(); ParameterList jobGroupParameters = jobGroup.getParameters(); Parameter[] stubs = jobClass.getParameterStubs().clone().getParameters(); for (int i=0; i < stubs.length; i++) { // Determine whether this parameter should be mapped to an existing // parameter, mapped as a new parameter, or hold a fixed value. String pName = Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName(); String pValue = request.getParameter(pName); if ((pValue == null) || (pValue.length() == 0)) { // This shouldn't happen, but we'll let it slide if it's not a // required parameter. if (stubs[i].isRequired()) { jobValid = false; infoMessage.append("ERROR: Unable to determine how optimizing " + "job parameter \"" + stubs[i].getDisplayName() + "\" should be handled.<BR>" + EOL); } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING)) { // Determine which existing parameter it should be mapped to. String mapToName = Constants.SERVLET_PARAM_MAP_TO_NAME_PREFIX + stubs[i].getName(); String mapToValue = request.getParameter(mapToName); if ((mapToValue == null) || (mapToValue.length() == 0)) { jobValid = false; infoMessage.append("ERROR: Optimizing job ob parameter \"" + stubs[i].getDisplayName() + " was configured " + "to be mapped to a job group parameter, but " + "no target parameter was specified.<BR>" + EOL); } else { Parameter p = jobGroupParameters.getParameter(mapToValue); if (p == null) { jobValid = false; infoMessage.append("ERROR: Optimizing job parameter \"" + stubs[i].getDisplayName() + "\" was " + "configured to be mapped to job group " + "parameter \"" + mapToValue + "\" but no " + "such parameter is defined in the job " + "group.<BR>" + EOL); } else { mappedParameters.put(stubs[i].getName(), mapToValue); } } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW)) { // Determine the display name to use for the new mapped parameter. String mapToName = Constants.SERVLET_PARAM_MAP_TO_DISPLAY_NAME_PREFIX + stubs[i].getName(); String mapToValue = request.getParameter(mapToName); if ((mapToValue != null) && (mapToValue.length() > 0)) { stubs[i].setDisplayName(mapToValue); } // Make sure that the new parameter doesn't conflict with an // existing job group parameter. boolean conflict = false; String originalName = stubs[i].getName(); Parameter[] groupParams = jobGroupParameters.getParameters(); for (int j=0; j < groupParams.length; j++) { if (stubs[i].getName().equals(groupParams[j].getName())) { // There is a conflict in the parameter names, which we can work // around by changing the name of the new parameter. conflict = true; int k = 1; String baseName = stubs[i].getName(); String newName = baseName + k; while (conflict) { k++; conflict = false; newName = baseName + k; for (int l=0; l < groupParams.length; l++) { if (newName.equals(groupParams[l].getName())) { conflict = true; break; } } } stubs[i].setName(newName); } else if (stubs[i].getDisplayName().equalsIgnoreCase( groupParams[j].getDisplayName())) { conflict = true; infoMessage.append("ERROR: Optimizing job parameter \"" + stubs[i].getDisplayName() + "\" was " + "configured to be a new mapped parameter " + "for the job group, but its display name " + "conflicts with the display name of another " + "parameter already in the job group.<BR>" + EOL); break; } } if (conflict) { jobValid = false; } else { mappedParameters.put(originalName, stubs[i].getName()); newMappedParameters.addParameter(stubs[i]); } } else if (pValue.equals(Constants.GROUP_PARAM_TYPE_FIXED)) { // Determine the fixed value to use for the parameter. try { stubs[i].htmlInputFormToValue(request); fixedParameters.addParameter(stubs[i]); } catch (InvalidValueException ive) { jobValid = false; infoMessage.append("ERROR: The specified fixed value for " + "parameter \"" + stubs[i].getDisplayName() + "\" is invalid: " + ive.getMessage() + "<BR>" + EOL); } } else { jobValid = false; infoMessage.append("ERROR: Unable to determine how optimizing job " + "parameter \"" + stubs[i].getDisplayName() + "\" should be handled.<BR>" + EOL); } } // If everything looks good, then create the job and add it to the group. // Also, if there are any new mapped parameters, then add them to the job // group. if (jobValid) { JobGroupOptimizingJob optimizingJob = new JobGroupOptimizingJob(jobName, jobGroup, jobClass, duration, delayBetweenIterations, numClients, minThreads, maxThreads, threadIncrement, collectionInterval, maxNonImproving, threadStartupDelay, reRunBestIteration, reRunDuration, dependencies, optimizationAlgorithm, optimizationParameters, mappedParameters, fixedParameters); jobGroup.getJobList().add(optimizingJob); Parameter[] newMapped = newMappedParameters.getParameters(); for (int i=0; i < newMapped.length; i++) { jobGroupParameters.addParameter(newMapped[i]); } // Write the updated job group to the configuration database. try { configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully added optimizing job \"" + jobName + "\" to the job group.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not update the job group in the " + "configuration database: " + e.getMessage() + ".<BR>" + EOL); } } } String star = "<SPAN CLASS=\"" + Constants.STYLE_WARNING_TEXT + "\">*</SPAN>"; htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Add a New Optimizing \"" + jobClass.getJobName() + "\" Job to Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Enter the following information about the optimizing " + jobClass.getJobName() + " job to add to the \"" + link + "\" job group." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("The optimization parameters must be given hard-coded " + "values." + EOL); htmlBody.append("For the job-specific parameters, you may either " + "specify hard-coded values or allow the user to " + "specify the value as part of the job group parameters." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Fields marked with an asterisk (" + star + ") are required to have a value."); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM CLASS=\"" + Constants.STYLE_MAIN_FORM + "\" METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_ADD_OPTIMIZING_JOB_TO_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_CLASS, jobClass.getClass().getName()) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_OPTIMIZATION_ALGORITHM, optimizationAlgorithm.getClass().getName()) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); if (jobClass.overrideNumClients() > 0) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS, String.valueOf(jobClass.overrideNumClients())) + EOL); } if (jobClass.overrideCollectionInterval() > 0) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL, secondsToHumanReadableDuration( jobClass.overrideCollectionInterval())) + EOL); } if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>General Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String jobName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME); if (jobName == null) { jobName = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Name " + star +"</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_GROUP_OPTIMIZING_JOB_NAME + "\" VALUE=\"" + jobName + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String durationStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DURATION); if (durationStr == null) { durationStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_DURATION + "\" VALUE=\"" + durationStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String delayStr = request.getParameter(Constants.SERVLET_PARAM_TIME_BETWEEN_STARTUPS); if (delayStr == null) { delayStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Delay Between Iterations</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_TIME_BETWEEN_STARTUPS + "\" VALUE=\"" + delayStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobClass.overrideNumClients() <= 0) { String numClientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_NUM_CLIENTS); if (numClientsStr == null) { numClientsStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Number of Clients " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_NUM_CLIENTS + "\" VALUE=\"" + numClientsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } String minThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_MIN); if (minThreadsStr == null) { minThreadsStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Minimum Number of Threads " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREADS_MIN + "\" VALUE=\"" + minThreadsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String maxThreadsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREADS_MAX); if (maxThreadsStr == null) { maxThreadsStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Maximum Number of Threads</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREADS_MAX + "\" VALUE=\"" + maxThreadsStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String incrementStr = request.getParameter(Constants.SERVLET_PARAM_THREAD_INCREMENT); if (incrementStr == null) { incrementStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Thread Increment Between Iterations " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_THREAD_INCREMENT + "\" VALUE=\"" + incrementStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); delayStr = request.getParameter(Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY); if (delayStr == null) { delayStr = "0"; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Thread Startup Delay (ms)</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_THREAD_STARTUP_DELAY + "\" VALUE=\"" + delayStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (jobClass.overrideCollectionInterval() <= 0) { String intervalStr = request.getParameter( Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL); if (intervalStr == null) { intervalStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Statistics Collection Interval " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_COLLECTION_INTERVAL + "\" VALUE=\"" + intervalStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); } String maxNonImprovingStr = request.getParameter(Constants.SERVLET_PARAM_JOB_MAX_NON_IMPROVING); if (maxNonImprovingStr == null) { maxNonImprovingStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Max. Consecutive Non-Improving Iterations " + star + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_MAX_NON_IMPROVING + "\" VALUE=\"" + maxNonImprovingStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); boolean reRunBestIteration = false; String reRunStr = request.getParameter(Constants.SERVLET_PARAM_RERUN_BEST_ITERATION); if (reRunStr != null) { reRunBestIteration = (reRunStr.equalsIgnoreCase("true") || reRunStr.equalsIgnoreCase("yes") || reRunStr.equalsIgnoreCase("on") || reRunStr.equalsIgnoreCase("1")); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Re-Run Best Iteration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"CHECKBOX\" NAME=\"" + Constants.SERVLET_PARAM_RERUN_BEST_ITERATION + '"' + (reRunBestIteration ? " CHECKED" : "") + "></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String reRunDurationStr = request.getParameter(Constants.SERVLET_PARAM_RERUN_DURATION); if (reRunDurationStr == null) { reRunDurationStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Re-Run Duration</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_RERUN_DURATION + "\" VALUE=\"" + reRunDurationStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (! jobList.isEmpty()) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Dependencies</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); for (int i=0; i < jobList.size(); i++) { String depName; Object o = jobList.get(i); if (o instanceof JobGroupJob) { depName = ((JobGroupJob) o).getName(); } else if (o instanceof JobGroupOptimizingJob) { depName = ((JobGroupOptimizingJob) o).getName(); } else { continue; } String checkedStr = ""; String[] depValues = request.getParameterValues(Constants.SERVLET_PARAM_JOB_DEPENDENCY); for (int j=0; ((depValues != null) && (j < depValues.length)); j++) { if (depValues[j].equals(depName)) { checkedStr = " CHECKED"; break; } } if ((! submitted) && (i == (jobList.size() - 1))) { checkedStr = " CHECKED"; } htmlBody.append(" <INPUT TYPE=\"CHECKBOX\" NAME=\"" + Constants.SERVLET_PARAM_JOB_DEPENDENCY + "\" VALUE=\"" + depName + '"' + checkedStr + '>' + depName + "<BR>" + EOL); } htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } Parameter[] optimizationStubs = optimizationAlgorithm. getOptimizationAlgorithmParameterStubs(jobClass).clone(). getParameters(); if ((optimizationStubs != null) && (optimizationStubs.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Optimization Algorithm " + "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); for (int i=0; i < optimizationStubs.length; i++) { if ((optimizationStubs[i] instanceof PlaceholderParameter) || (optimizationStubs[i] instanceof LabelParameter)) { continue; } if (submitted) { try { optimizationStubs[i].htmlInputFormToValue(request); } catch (InvalidValueException ive) {} } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>" + optimizationStubs[i].getDisplayName() + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + optimizationStubs[i].getHTMLInputForm( Constants.SERVLET_PARAM_OPTIMIZATION_PARAM_PREFIX) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } Parameter[] stubs = jobClass.getParameterStubs().clone().getParameters(); Parameter[] groupParameters = jobGroup.getParameters().getParameters(); if ((stubs != null) && (stubs.length > 0)) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"><B>Job-Specific " + "Parameters</B></TD>" + EOL); htmlBody.append(" </TR>" + EOL); boolean skippedFirstSpace = false; for (int i=0; i < stubs.length; i++) { if ((stubs[i] instanceof PlaceholderParameter) || (stubs[i] instanceof LabelParameter)) { continue; } if (! skippedFirstSpace) { skippedFirstSpace = true; } else { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\">" + stubs[i].getDisplayName() + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); if (submitted) { try { stubs[i].htmlInputFormToValue(request); } catch (InvalidValueException ive) {} } boolean selected = false; if (groupParameters.length > 0) { int selectedIndex = -1; for (int j=0; ((! selected) && (j < groupParameters.length)); j++) { if ((groupParameters[j] instanceof PlaceholderParameter) || (groupParameters[j] instanceof LabelParameter)) { continue; } if (stubs[i].getName().equalsIgnoreCase( groupParameters[j].getName()) || stubs[i].getDisplayName().equalsIgnoreCase( groupParameters[j].getDisplayName())) { selected = true; selectedIndex = j; } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_EXISTING + '"'); if (selected) { htmlBody.append(" CHECKED"); } htmlBody.append(">Map to Existing Job Group Parameter</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_MAP_TO_NAME_PREFIX + stubs[i].getName() + "\">" + EOL); for (int j=0; j < groupParameters.length; j++) { if ((groupParameters[j] instanceof PlaceholderParameter) || (groupParameters[j] instanceof LabelParameter)) { continue; } htmlBody.append(" <OPTION VALUE=\"" + groupParameters[j].getName()); if (j == selectedIndex) { htmlBody.append("\" SELECTED>"); } else { htmlBody.append("\">"); } String displayName = groupParameters[j].getDisplayName(); if (displayName == null) { displayName = groupParameters[j].getName(); } htmlBody.append(displayName + EOL); } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_MAPPED_TO_NEW + '"'); if (! selected) { htmlBody.append(" CHECKED"); selected = true; } htmlBody.append(">Create a New Job Group Parameter</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_MAP_TO_DISPLAY_NAME_PREFIX + stubs[i].getName() + "\" VALUE=\"" + stubs[i].getDisplayName() + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"RADIO\" NAME=\"" + Constants.SERVLET_PARAM_GROUP_PARAM_TYPE_PREFIX + stubs[i].getName() + "\" VALUE=\"" + Constants.GROUP_PARAM_TYPE_FIXED + "\">Always Use a " + "Fixed Value</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + stubs[i].getHTMLInputForm( Constants.SERVLET_PARAM_JOB_PARAM_PREFIX) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"2\"> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Add Optimizing " + "Job to Job Group\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append("</FORM>" + EOL); } /** * Handles all processing related to removing a job from a job group. * * @param requestInfo The state information for this request. */ static void handleRemoveJobFromGroup(RequestInfo requestInfo) { logMessage(requestInfo, "In handleRemoveJobFromGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to view job information to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "update a job group."); return; } // Get the job group from which the job should be removed. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if (jobGroupName == null) { infoMessage.append("ERROR: No job group specified.<BR>" + EOL); return; } JobGroup jobGroup; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration database." + "<BR>" + EOL); handleViewJobGroups(requestInfo); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); handleViewJobGroups(requestInfo); infoMessage.append("ERROR: Cannot retrieve job group \"" + jobGroupName + "\": " + e.getMessage() + "<BR>" + EOL); return; } // Get the name of the job to remove from the job group (it may be a normal // job or an optimizing job). String jobName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME); if ((jobName == null) || (jobName.length() == 0)) { infoMessage.append("ERROR: No job was specified to remove from the " + "job group."); handleViewJobGroup(requestInfo); return; } // Right now, we only support removing the last job in the group so that we // don't cause problems with dependencies. Make sure the specified job is // the last one. ArrayList jobList = jobGroup.getJobList(); if (jobList.isEmpty()) { infoMessage.append("ERROR: There are no jobs or optimizing jobs " + "defined in job group " + jobGroupName + ".<BR>" + EOL); handleViewJobGroup(requestInfo); return; } Object o = jobList.get(jobList.size() - 1); if (o instanceof JobGroupJob) { if (! ((JobGroupJob) o).getName().equals(jobName)) { infoMessage.append("ERROR: The specified job is not the last job " + "in the list. Only the last job in a job group " + "may be removed to ensure that dependencies are " + "properly maintained.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } } else if (o instanceof JobGroupOptimizingJob) { if (! ((JobGroupOptimizingJob) o).getName().equals(jobName)) { infoMessage.append("ERROR: The specified job is not the last job " + "in the list. Only the last job in a job group " + "may be removed to ensure that dependencies are " + "properly maintained.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } } else { infoMessage.append("ERROR: Unrecognized object \"" + String.valueOf(o) + "\" as the last element of the job group. It must " + "be either a job or an optimizing job.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } // See if the user provided confirmation that the group should be updated. // If so, then remove the job and update the list. Otherwise, display the // form to request confirmation. String confirmStr = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); if ((confirmStr != null) && (confirmStr.equalsIgnoreCase("yes"))) { try { jobList.remove(o); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully updated job group \"" + jobGroupName + "\" in the configuration database.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not update job group\"" + jobGroupName + "\" in the configuration " + "database: " + e.getMessage() + ".<BR>" + EOL); handleViewJobGroup(requestInfo); return; } } else if ((confirmStr != null) && (confirmStr.equalsIgnoreCase("no"))) { infoMessage.append("Job Group \"" + jobGroupName + "\" was not " + "updated.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } else { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Update Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); if (o instanceof JobGroupJob) { htmlBody.append("Are you sure that you want to remove job \"" + jobName + "\" from job group \"" + jobGroupName + "\"?" + EOL); } else if (o instanceof JobGroupOptimizingJob) { htmlBody.append("Are you sure that you want to remove optimizing " + "job \"" + jobName + "\" from job group \"" + jobGroupName + "\"?" + EOL); } htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_REMOVE_JOB_FROM_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_JOB_NAME, jobName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_CONFIRMED + "\" VALUE=\"Yes\">" + EOL); htmlBody.append("   " + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_CONFIRMED + "\" VALUE=\"No\">" + EOL); htmlBody.append("</FORM>" + EOL); } } /** * Handles all processing related to removing a job group from the SLAMD * server. * * @param requestInfo The state information for this request. */ static void handleRemoveJobGroup(RequestInfo requestInfo) { logMessage(requestInfo, "In handleRemoveJobGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to view job information to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "remove a job group."); return; } // Get the job group that should be removed. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if (jobGroupName == null) { infoMessage.append("ERROR: No job group specified.<BR>" + EOL); return; } JobGroup jobGroup; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration database." + "<BR>" + EOL); handleViewJobGroups(requestInfo); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Cannot retrieve job group \"" + jobGroupName + "\": " + e.getMessage() + "<BR>" + EOL); return; } // See if the user provided confirmation. If so, then remove the job // group. If not, then get it. String confirmStr = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); if ((confirmStr != null) && (confirmStr.equalsIgnoreCase("yes"))) { try { configDB.removeJobGroup(jobGroupName); infoMessage.append("Successfully removed job group \"" + jobGroupName + "\" from the configuration database.<BR>" + EOL); handleViewJobGroups(requestInfo); return; } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Could not remove job group\"" + jobGroupName + "\" from the configuration " + "database: " + e.getMessage() + ".<BR>" + EOL); return; } } else if ((confirmStr != null) && (confirmStr.equalsIgnoreCase("no"))) { infoMessage.append("Job Group \"" + jobGroupName + "\" was not removed " + "from the configuration database.<BR>" + EOL); handleViewJobGroup(requestInfo); return; } else { htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Remove Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Are you sure that you want to remove this job group?" + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants. SERVLET_SECTION_JOB_REMOVE_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_CONFIRMED + "\" VALUE=\"Yes\">" + EOL); htmlBody.append("   " + EOL); htmlBody.append(" <INPUT TYPE=\"SUBMIT\" NAME=\"" + Constants.SERVLET_PARAM_CONFIRMED + "\" VALUE=\"No\">" + EOL); htmlBody.append("</FORM>" + EOL); } } /** * Handles all processing related to scheduling a job group. * * @param requestInfo The state information for this request. */ static void handleScheduleJobGroup(RequestInfo requestInfo) { logMessage(requestInfo, "In handleScheduleJobGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to schedule a job to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "schedule a job group."); return; } // Get the job group that should be scheduled. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if (jobGroupName == null) { infoMessage.append("ERROR: No job group specified.<BR>" + EOL); return; } JobGroup jobGroup; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration database." + "<BR>" + EOL); handleViewJobGroups(requestInfo); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Cannot retrieve job group \"" + jobGroupName + "\": " + e.getMessage() + "<BR>" + EOL); return; } // See if the user has submitted the form and wants to schedule the job. String confirmed = request.getParameter(Constants.SERVLET_PARAM_CONFIRMED); boolean submitted = ((confirmed != null) && (confirmed.length() > 0)); if (submitted) { boolean jobValid = true; String folderName = request.getParameter(Constants.SERVLET_PARAM_JOB_FOLDER); if ((folderName == null) || (folderName.length() == 0)) { jobValid = false; infoMessage.append("ERROR: No job folder name was provided.<BR>" + EOL); } else { try { JobFolder folder = configDB.getFolder(folderName); if (folder == null) { jobValid = false; infoMessage.append("ERROR: Job folder \"" + folderName + "\" does not exist in the configuration " + "database.<BR>" + EOL); } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); jobValid = false; infoMessage.append("ERROR: Could not retrieve job folder \"" + folderName + "\": " + e.getMessage() + ".<BR>" + EOL); } } Date startTime; String startTimeStr = request.getParameter(Constants.SERVLET_PARAM_JOB_START_TIME); if ((startTimeStr == null) || (startTimeStr.length() == 0)) { startTime = new Date(); } else { try { startTime = dateFormat.parse(startTimeStr); } catch (Exception e) { startTime = new Date(); jobValid = false; infoMessage.append("ERROR: Could not parse the job start time " + "value \"" + startTimeStr + "\" as a valid " + "timestamp in the form YYYYMMDDhhmmss.<BR>" + EOL); } } String[] requestedClients = new String[0]; String requestedClientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_CLIENTS); if ((requestedClientsStr != null) && (requestedClientsStr.length() > 0)) { ArrayList<String> clientList = new ArrayList<String>(); StringTokenizer tokenizer = new StringTokenizer(requestedClientsStr); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); try { InetAddress clientAddress = InetAddress.getByName(token); clientList.add(clientAddress.getHostAddress()); } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: Could not resolve client address \"" + token + "\" to an IP address.<BR>" + EOL); } } if (! clientList.isEmpty()) { requestedClients = new String[clientList.size()]; clientList.toArray(requestedClients); } } String[] requestedMonitorClients = new String[0]; String requestedMonitorClientsStr = request.getParameter(Constants.SERVLET_PARAM_JOB_MONITOR_CLIENTS); if ((requestedMonitorClientsStr != null) && (requestedMonitorClientsStr.length() > 0)) { ArrayList<String> monitorClientList = new ArrayList<String>(); StringTokenizer tokenizer = new StringTokenizer(requestedMonitorClientsStr); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); try { InetAddress clientAddress = InetAddress.getByName(token); monitorClientList.add(clientAddress.getHostAddress()); } catch (Exception e) { jobValid = false; infoMessage.append("ERROR: Could not resolve monitor client " + "address \"" + token + "\" to an IP address.<BR>" + EOL); } } if (! monitorClientList.isEmpty()) { requestedMonitorClients = new String[monitorClientList.size()]; monitorClientList.toArray(requestedMonitorClients); } } // Monitor Clients if Available boolean monitorClientsIfAvailable = false; String monitorIfAvailableStr = request.getParameter( Constants.SERVLET_PARAM_JOB_MONITOR_CLIENTS_IF_AVAILABLE); if (monitorIfAvailableStr != null) { monitorClientsIfAvailable = (monitorIfAvailableStr.equalsIgnoreCase("true") || monitorIfAvailableStr.equalsIgnoreCase("yes") || monitorIfAvailableStr.equalsIgnoreCase("on") || monitorIfAvailableStr.equalsIgnoreCase("1")); } // See if a dependency was specified. String[] dependencies; String dependency = request.getParameter(Constants.SERVLET_PARAM_JOB_DEPENDENCY); if ((dependency == null) || (dependency.length() == 0)) { dependencies = new String[0]; } else { dependencies = new String[] { dependency }; } Parameter[] groupParams = jobGroup.getParameters().clone().getParameters(); for (int i=0; i < groupParams.length; i++) { try { groupParams[i].htmlInputFormToValue(request); } catch (InvalidValueException ive) { jobValid = false; infoMessage.append("ERROR: The provided value for job parameter " + groupParams[i].getDisplayName() + " is invalid: " + ive.getMessage() + ".<BR>" + EOL); } } ParameterList parameters = new ParameterList(groupParams); if (jobValid) { try { ArrayList<String> messages = new ArrayList<String>(); jobGroup.schedule(slamdServer, startTime, folderName, requestedClients, requestedMonitorClients, monitorClientsIfAvailable, dependencies, parameters, messages); for (int i=0; i < messages.size(); i++) { infoMessage.append(messages.get(i) + "<BR>" + EOL); } infoMessage.append("Successfully scheduled all jobs in job group " + jobGroup.getName() + ".<BR>" + EOL); handleViewJob(requestInfo, Constants.SERVLET_SECTION_JOB_VIEW_PENDING, null, null); return; } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: An error occurred while attepting to " + "schedule one of the jobs in job group " + jobGroup.getName() + ": " + e.getMessage() + ". Only some of the jobs may have been " + "scheduled.<BR>" + EOL); handleViewJob(requestInfo, Constants.SERVLET_SECTION_JOB_VIEW_PENDING, null, null); return; } } } // Generate the form that allows the user to schedule the job group. String star = "<SPAN CLASS=\"" + Constants.STYLE_WARNING_TEXT + "\">*</SPAN>"; htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Schedule the \"" + jobGroupName + "\" Job Group</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName, jobGroupName); htmlBody.append("Enter the following information to use to schedule " + "the \"" + link + "\" job group." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("Fields marked with an asterisk (" + star + ") are required to have a value."); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM CLASS=\"" + Constants.STYLE_MAIN_FORM + "\" METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_SCHEDULE_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); String folderName = request.getParameter(Constants.SERVLET_PARAM_JOB_FOLDER); JobFolder[] folders = null; try { folders = configDB.getFolders(); } catch (DatabaseException de) {} if ((folders != null) && (folders.length > 0)) { if (folderName == null) { folderName = request.getParameter(Constants.SERVLET_PARAM_JOB_FOLDER); } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Place in Folder</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_JOB_FOLDER + "\">" + EOL); for (int i=0; i < folders.length; i++) { if ((folderName != null) && folderName.equalsIgnoreCase(folders[i].getFolderName())) { htmlBody.append(" <OPTION VALUE=\"" + folders[i].getFolderName() + "\" SELECTED>" + folders[i].getFolderName() + EOL); } else { htmlBody.append(" <OPTION VALUE=\"" + folders[i].getFolderName() + "\">" + folders[i].getFolderName() + EOL); } } htmlBody.append(" </SELECT>"); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } String startTimeStr = request.getParameter(Constants.SERVLET_PARAM_JOB_START_TIME); if (startTimeStr == null) { if (populateStartTime) { startTimeStr = dateFormat.format(new Date()); } else { startTimeStr = ""; } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Start Time <FONT SIZE=\"-1\">(YYYYMMDDhhmmss)" + "</FONT></TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_START_TIME + "\" VALUE=\"" + startTimeStr + "\" SIZE=\"40\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String[] requestedClients = request.getParameterValues(Constants.SERVLET_PARAM_JOB_CLIENTS); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Use Specific Clients</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><TEXTAREA NAME=\"" + Constants.SERVLET_PARAM_JOB_CLIENTS + "\" ROWS=\"5\"" + " COLS=\"40\">"); String separator = ""; for (int i=0; ((requestedClients != null) && (i < requestedClients.length)); i++) { htmlBody.append(separator); htmlBody.append(requestedClients[i]); separator = EOL; } htmlBody.append("</TEXTAREA></TD>" + EOL); htmlBody.append(" </TR>" + EOL); String[] monitorClients = request.getParameterValues( Constants.SERVLET_PARAM_JOB_MONITOR_CLIENTS); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Resource Monitor Clients</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><TEXTAREA NAME=\"" + Constants.SERVLET_PARAM_JOB_MONITOR_CLIENTS + "\" ROWS=\"5\"" + " COLS=\"40\">"); separator = ""; for (int i=0; ((monitorClients != null) && (i < monitorClients.length)); i++) { htmlBody.append(separator); htmlBody.append(monitorClients[i]); separator = EOL; } htmlBody.append("</TEXTAREA></TD>" + EOL); htmlBody.append(" </TR>" + EOL); boolean monitorClientsIfAvailable; String monitorStr = request.getParameter( Constants.SERVLET_PARAM_JOB_MONITOR_CLIENTS_IF_AVAILABLE); if ((monitorStr != null) && (monitorStr.equalsIgnoreCase("true") || monitorStr.equalsIgnoreCase("yes") || monitorStr.equalsIgnoreCase("on") || monitorStr.equalsIgnoreCase("1"))) { monitorClientsIfAvailable = true; } else { monitorClientsIfAvailable = false; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Monitor Clients if Available</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"CHECKBOX\" NAME=\"" + Constants.SERVLET_PARAM_JOB_MONITOR_CLIENTS_IF_AVAILABLE + '"' + (monitorClientsIfAvailable ? " CHECKED" : "") + "></TD>" + EOL); htmlBody.append(" </TR>" + EOL); Job[] pendingJobs = scheduler.getPendingJobs(); Job[] runningJobs = scheduler.getRunningJobs(); OptimizingJob[] optimizingJobs = new OptimizingJob[0]; try { optimizingJobs = scheduler.getUncompletedOptimizingJobs(); } catch (SLAMDServerException sse) { requestInfo.infoMessage.append("ERROR: Unable to retrieve the list " + "of uncompleted optimizing jobs -- " + sse + "<BR>" + EOL); } if ((pendingJobs.length > 0) || (runningJobs.length > 0) || (optimizingJobs.length > 0)) { String dependencyStr = request.getParameter(Constants.SERVLET_PARAM_JOB_DEPENDENCY); if (dependencyStr == null) { dependencyStr = ""; } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Group Dependency</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + EOL); htmlBody.append(" <SELECT NAME=\"" + Constants.SERVLET_PARAM_JOB_DEPENDENCY + "\">" + EOL); htmlBody.append(" <OPTION VALUE=\"\">No Dependency" + EOL); for (int i=0; i < pendingJobs.length; i++) { String description = pendingJobs[i].getJobDescription(); if (description == null) { description = ""; } else if (description.length() > 0) { description = " -- " + description; } String selectedStr; if (pendingJobs[i].getJobID().equals(dependencyStr)) { selectedStr = "\" SELECTED>"; } else { selectedStr = "\">"; } htmlBody.append(" <OPTION VALUE=\"" + pendingJobs[i].getJobID() + selectedStr + pendingJobs[i].getJobID() + " -- Pending " + pendingJobs[i].getJobName() + description + EOL); } for (int i=0; i < runningJobs.length; i++) { String description = runningJobs[i].getJobDescription(); if (description == null) { description = ""; } else if (description.length() > 0) { description = " -- " + description; } String selectedStr; if (runningJobs[i].getJobID().equals(dependencyStr)) { selectedStr = "\" SELECTED>"; } else { selectedStr = "\">"; } htmlBody.append(" <OPTION VALUE=\"" + runningJobs[i].getJobID() + selectedStr + runningJobs[i].getJobID() + " -- Running " + runningJobs[i].getJobName() + description + EOL); } for (int i=0; i < optimizingJobs.length; i++) { String description = optimizingJobs[i].getDescription(); if (description == null) { description = ""; } else { description = " -- " + description; } String selectedStr; if (optimizingJobs[i].getOptimizingJobID().equals(dependencyStr)) { selectedStr = "\" SELECTED>"; } else { selectedStr = "\">"; } htmlBody.append(" <OPTION VALUE=\"" + optimizingJobs[i].getOptimizingJobID() + selectedStr + optimizingJobs[i].getOptimizingJobID() + " -- Optimizing " + optimizingJobs[i].getJobClass().getJobName() + description + EOL); } htmlBody.append(" </SELECT>" + EOL); htmlBody.append(" </TD>" + EOL); htmlBody.append(" </TR>" + EOL); } Parameter[] stubs = jobGroup.getParameters().clone().getParameters(); if (stubs.length > 0) { htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); for (int i=0; i < stubs.length; i++) { String displayName = stubs[i].getDisplayName(); if (displayName == null) { displayName = stubs[i].getName(); } if (stubs[i].isRequired()) { displayName += ' ' + star; } if (submitted) { try { stubs[i].htmlInputFormToValue(request); } catch (Exception e) {} } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>" + displayName + "</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD>" + stubs[i].getHTMLInputForm( Constants.SERVLET_PARAM_JOB_PARAM_PREFIX) + "</TD>" + EOL); htmlBody.append(" </TR>" + EOL); } } htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"2\"> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Schedule Job " + "Group\"></TD>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append("</FORM>" + EOL); } /** * Handles the work of cloning an existing job group. * * @param requestInfo The state information for this request. */ static void handleCloneJobGroup(RequestInfo requestInfo) { logMessage(requestInfo, "In handleScheduleJobGroup()"); // Get the important state information for this request. HttpServletRequest request = requestInfo.request; String servletBaseURI = requestInfo.servletBaseURI; StringBuilder htmlBody = requestInfo.htmlBody; StringBuilder infoMessage = requestInfo.infoMessage; // The user must be able to schedule a job to do anything here if (! requestInfo.mayScheduleJob) { logMessage(requestInfo, "No mayScheduleJob permission granted"); generateAccessDeniedBody(requestInfo, "You do not have permission to " + "clone a job group."); return; } // Get the job group that should be cloned. String jobGroupName = request.getParameter(Constants.SERVLET_PARAM_JOB_GROUP_NAME); if (jobGroupName == null) { infoMessage.append("ERROR: No job group specified.<BR>" + EOL); return; } JobGroup jobGroup; try { jobGroup = configDB.getJobGroup(jobGroupName); if (jobGroup == null) { infoMessage.append("ERROR: Job group \"" + jobGroupName + "\" does not exist in the configuration database." + "<BR>" + EOL); handleViewJobGroups(requestInfo); return; } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Cannot retrieve job group \"" + jobGroupName + "\": " + e.getMessage() + "<BR>" + EOL); return; } // See if a new name has been specified. If so, then perform the clone. // Otherwise, show the form allowing the user to choose the name. String cloneName = request.getParameter(Constants.SERVLET_PARAM_NEW_NAME); if ((cloneName != null) && (cloneName.length() > 0) && (! cloneName.equalsIgnoreCase(jobGroupName))) { try { String description = request.getParameter(Constants.SERVLET_PARAM_JOB_DESCRIPTION); // Make sure that the new name does not conflict with the name of an // existing job group. if (configDB.getJobGroup(cloneName) == null) { jobGroup.setName(cloneName); jobGroup.setDescription(description); configDB.writeJobGroup(jobGroup); infoMessage.append("Successfully cloned job group \"" + jobGroupName + "\" as \"" + cloneName + "\".<BR>" + EOL); handleViewJobGroup(requestInfo, cloneName); return; } else { infoMessage.append("ERROR: A job group already exists with the " + "specified name.<BR>" + EOL); } } catch (Exception e) { slamdServer.logMessage(Constants.LOG_LEVEL_EXCEPTION_DEBUG, JobClass.stackTraceToString(e)); infoMessage.append("ERROR: Unable to clone the job: " + e + ".<BR>" + EOL); handleViewJobGroup(requestInfo); return; } } htmlBody.append("<SPAN CLASS=\"" + Constants.STYLE_MAIN_HEADER + "\">Clone Job Group \"" + jobGroupName + "\"</SPAN>" + EOL); htmlBody.append("<BR><BR>" + EOL); String link = generateLink(requestInfo, Constants.SERVLET_SECTION_JOB, Constants.SERVLET_SECTION_JOB_VIEW_GROUP, Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName, jobGroupName); htmlBody.append("Enter the following information to use to schedule " + "the \"" + link + "\" job group." + EOL); htmlBody.append("<BR><BR>" + EOL); htmlBody.append("<FORM CLASS=\"" + Constants.STYLE_MAIN_FORM + "\" METHOD=\"POST\" ACTION=\"" + servletBaseURI + "\">" + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SECTION, Constants.SERVLET_SECTION_JOB) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_SUBSECTION, Constants.SERVLET_SECTION_JOB_CLONE_GROUP) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_JOB_GROUP_NAME, jobGroupName) + EOL); htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_CONFIRMED, "1") + EOL); if (requestInfo.debugHTML) { htmlBody.append(" " + generateHidden(Constants.SERVLET_PARAM_HTML_DEBUG, "1") + EOL); } if ((cloneName == null) || (cloneName.length() == 0)) { cloneName = jobGroup.getName(); } String description = request.getParameter(Constants.SERVLET_PARAM_JOB_DESCRIPTION); if ((description == null) || (description.length() == 0)) { description = jobGroup.getDescription(); if (description == null) { description = ""; } } htmlBody.append(" <TABLE BORDER=\"0\">" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>New Job Group Name:</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_NEW_NAME + "\" VALUE=\"" + cloneName + "\" SIZE=\"40\">" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD>Job Group Description:</TD>" + EOL); htmlBody.append(" <TD> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"TEXT\" NAME=\"" + Constants.SERVLET_PARAM_JOB_DESCRIPTION + "\" VALUE=\"" + description + "\" SIZE=\"40\">" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"3\"> </TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" <TR>" + EOL); htmlBody.append(" <TD COLSPAN=\"2\"> </TD>" + EOL); htmlBody.append(" <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Submit\"></TD>" + EOL); htmlBody.append(" </TR>" + EOL); htmlBody.append(" </TABLE>" + EOL); htmlBody.append("</FORM>" + EOL); } }