package com.intuit.tank.script;
/*
* #%L
* JSF Support Beans
* %%
* Copyright (C) 2011 - 2015 Intuit Inc.
* %%
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* #L%
*/
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import com.intuit.tank.util.Messages;
import org.picketlink.Identity;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.model.basic.User;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.intuit.tank.ModifiedScriptMessage;
import com.intuit.tank.PreferencesBean;
import com.intuit.tank.auth.Security;
import com.intuit.tank.common.ScriptUtil;
import com.intuit.tank.converter.ScriptStepHolder;
import com.intuit.tank.dao.ScriptDao;
import com.intuit.tank.filter.FilterBean;
import com.intuit.tank.prefs.TablePreferences;
import com.intuit.tank.prefs.TableViewState;
import com.intuit.tank.project.JobDetailFormatter;
import com.intuit.tank.project.JobValidator;
import com.intuit.tank.project.Script;
import com.intuit.tank.project.ScriptStep;
import com.intuit.tank.qualifier.Modified;
import com.intuit.tank.script.ScriptConstants;
import com.intuit.tank.script.util.ScriptFilterUtil;
import com.intuit.tank.vm.settings.AccessRight;
@Named
@ConversationScoped
public class ScriptEditor implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger LOG = LogManager.getLogger(ScriptEditor.class);
private Script script;
private String variableKey;
private String variableValue;
private String minThinkTime;
private String maxThinkTime;
private String jobDetails;
private String sleepTime;
private List<String> gotoGroupList = new ArrayList<String>();
@Inject
private VariableEditor variableEditor;
@Inject
private ClearCookiesEditor clearCookiesEditor;
@Inject
private CookieStepEditor cookieStepEditor;
@Inject
private AuthenticationEditor authenticationEditor;
@Inject
private ThinkTimeEditor thinkTimeEditor;
@Inject
private SleepTimeEditor sleepTimeEditor;
@Inject
private ScriptRequestEditor requestEditor;
@Inject
private ScriptSearchBean searchBean;
@Inject
private FilterBean filterBean;
@Inject
private AggregatorEditor aggregatorEditor;
@Inject
private LogicStepEditor logicStepEditor;
@Inject
private Identity identity;
@Inject
private IdentityManager identityManager;
@Inject
private Security security;
@Inject
private Conversation conversation;
@Inject
@Modified
private Event<ModifiedScriptMessage> scriptEvent;
@Inject
private CopyBuffer copyBuffer;
@Inject
private Messages messages;
private int currentPage = 0;
private int numRowsVisible = 20;
private String saveAsName;
private List<ScriptStep> selectedSteps = new ArrayList<ScriptStep>();
private ScriptStep[] selectedStepsArr;
private List<ScriptStep> steps;
private List<ScriptStepHolder> orderList;
private ScriptStep currentStep;
@Inject
private PreferencesBean userPrefs;
protected TablePreferences tablePrefs;
protected TableViewState tableState = new TableViewState();
@PostConstruct
public void init() {
tablePrefs = new TablePreferences(userPrefs.getPreferences().getScriptStepTableColumns());
tablePrefs.registerListener(userPrefs);
}
/**
* @return the tablePrefs
*/
public TablePreferences getTablePrefs() {
return tablePrefs;
}
/**
* @return the tableState
*/
public TableViewState getTableState() {
return tableState;
}
public List<ScriptStepHolder> getOrderList() {
if (orderList == null) {
orderList = new ArrayList<ScriptStepHolder>(steps.size());
for (int i = 0; i < steps.size(); i++) {
ScriptStep step = steps.get(i);
orderList.add(new ScriptStepHolder(i + 1, step.getUuid(), step
.getLabel()));
}
}
return orderList;
}
public void clearOrderList() {
orderList = null;
}
public void createScriptDetails() {
JobValidator validator = new JobValidator(script);
jobDetails = JobDetailFormatter.createJobDetails(validator, script.getName());
}
public String getScriptDetails() {
return jobDetails;
}
/**
* @return the saveAsName
*/
public String getSaveAsName() {
return saveAsName;
}
/**
* @param saveAsName
* the saveAsName to set
*/
public void setSaveAsName(String saveAsName) {
this.saveAsName = saveAsName;
}
public void setOrderList(List<ScriptStepHolder> list) {
Map<String, ScriptStep> map = new HashMap<String, ScriptStep>();
for (ScriptStep step : steps) {
map.put(step.getUuid(), step);
}
steps.clear();
for (ScriptStepHolder h : list) {
steps.add(map.get(h.getUuid()));
}
clearOrderList();
}
public String getPrettyString(String s, String mimetype) {
if (StringUtils.isNotBlank(s)) {
if (StringUtils.containsIgnoreCase(mimetype, "json")) {
try {
JsonParser parser = new JsonParser();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonElement el = parser.parse(s);
s = gson.toJson(el); // done
} catch (JsonSyntaxException e) {
LOG.warn("Cannot format json string: " + e);
}
} else if (StringUtils.containsIgnoreCase(mimetype, "xml")) {
try {
StringWriter sw;
final OutputFormat format = OutputFormat.createPrettyPrint();
final org.dom4j.Document document = DocumentHelper.parseText(s);
sw = new StringWriter();
final XMLWriter writer = new XMLWriter(sw, format);
writer.write(document);
s = sw.toString();
} catch (Exception e) {
LOG.warn("Cannot format xml string: " + e);
}
}
s = s.trim();
}
return s;
}
/**
* @return the currentStep
*/
public ScriptStep getCurrentStep() {
return currentStep;
}
/**
* @param currentStep
* the currentStep to set
*/
public void setCurrentStep(ScriptStep currentStep) {
this.currentStep = currentStep;
}
/**
* Sets the current editing script to the passed in parameter script.
*
* @param script
*/
public String editScript(Script s) {
conversation.begin();
this.script = new ScriptDao().findById(s.getId());
ScriptUtil.setScriptStepLabels(script);
steps = script.getScriptSteps();
saveAsName = script.getName();
if (!canEditScript()) {
messages.warn("You do not have permission to edit this script.");
}
return "success";
}
public String cancel() {
conversation.end();
this.script = null;
return "success";
}
public void enterFilterMode() {
}
/**
* applies all selected filters to the script currently being edited
*
* @return
*/
public String reapplyFilters() {
List<Integer> selectedFilterIds = filterBean.getSelectedFilterIds();
try {
ScriptFilterUtil.applyFilters(selectedFilterIds, script);
ScriptUtil.setScriptStepLabels(script);
messages.info("Applied " + selectedFilterIds.size()
+ " filter(s) to \"" + script.getName() + "\".");
return "success";
} catch (Exception e) {
e.printStackTrace();
}
messages.error("Error applying filters to \"" + script.getName()
+ "\".");
return "failure";
}
public void selectAll() {
this.selectedSteps.clear();
selectedSteps.addAll(steps);
setSelectedStepsArr(steps.toArray(new ScriptStep[0]));
}
public void deselectAll() {
this.selectedSteps.clear();
setSelectedStepsArr(new ScriptStep[0]);
}
/**
* @return the numRowsVisible
*/
public int getNumRowsVisible() {
return numRowsVisible;
}
/**
* @param numRowsVisible
* the numRowsVisible to set
*/
public void setNumRowsVisible(int numRowsVisible) {
this.numRowsVisible = numRowsVisible;
}
/**
* @return the gotoGroupList
*/
public List<String> getGotoGroupList() {
return gotoGroupList;
}
public List<String> complete(String query) {
List<String> suggestions = null;
if (StringUtils.isEmpty(query)) {
suggestions = gotoGroupList;
} else {
suggestions = new ArrayList<String>();
for (String s : gotoGroupList) {
if (s.startsWith(query)) {
suggestions.add(s);
}
}
}
return suggestions;
}
public void populateGroupList() {
gotoGroupList.clear();
for (ScriptStep step : script.getScriptSteps()) {
if ((!StringUtils.isEmpty(step.getScriptGroupName()))
&& (!gotoGroupList.contains(step.getScriptGroupName()))) {
gotoGroupList.add(step.getScriptGroupName());
}
}
// selectedSteps.clear();
}
/**
* @return the selectedSteps
*/
public List<ScriptStep> getSelectedSteps() {
return selectedSteps;
}
/**
* @param selectedSteps
* the selectedSteps to set
*/
public void setSelectedSteps(List<ScriptStep> selectedSteps) {
this.selectedSteps = selectedSteps;
}
/**
* @return the script
*/
public Script getScript() {
return script;
}
/**
* @param script
* the script to set
*/
public void setScript(Script script) {
this.script = script;
this.saveAsName = script.getName();
}
/**
* @return the script
*/
public String getScriptName() {
return script.getName();
}
/**
* @param script
* the script to set
*/
public void setScriptName(String name) {
this.script.setName(name);
}
/**
* @return the variableKey
*/
public String getVariableKey() {
return variableKey;
}
/**
* @param variableKey
* the variableKey to set
*/
public void setVariableKey(String variableKey) {
this.variableKey = variableKey;
}
/**
* @return the variableValue
*/
public String getVariableValue() {
return variableValue;
}
/**
* @param variableValue
* the variableValue to set
*/
public void setVariableValue(String variableValue) {
this.variableValue = variableValue;
}
/**
* @return the minThinkTime
*/
public String getMinThinkTime() {
return minThinkTime;
}
/**
* @param minThinkTime
* the minThinkTime to set
*/
public void setMinThinkTime(String minThinkTime) {
this.minThinkTime = minThinkTime;
}
/**
* @return the maxThinkTime
*/
public String getMaxThinkTime() {
return maxThinkTime;
}
/**
* @param maxThinkTime
* the maxThinkTime to set
*/
public void setMaxThinkTime(String maxThinkTime) {
this.maxThinkTime = maxThinkTime;
}
/**
* @return the sleepTime
*/
public String getSleepTime() {
return sleepTime;
}
/**
* @param sleepTime
* the sleepTime to set
*/
public void setSleepTime(String sleepTime) {
this.sleepTime = sleepTime;
}
/**
* Saves the script to persistent storage
*/
public void save() {
new ScriptDao().saveOrUpdate(script);
// ScriptSearchService s3 = new ScriptSearchService();
// s3.saveScript(script);
scriptEvent.fire(new ModifiedScriptMessage(script, this));
messages.info("Script " + script.getName() + " has been saved.");
}
public void saveAs() {
if (StringUtils.isEmpty(saveAsName)) {
messages.error("You must give the script a name.");
return;
}
try {
String originalName = script.getName();
if (originalName.equals(saveAsName)) {
save();
} else {
Script copyScript = ScriptUtil.copyScript(
identityManager.lookupById(User.class, identity.getAccount().getId()).getLoginName()
, saveAsName, script);
copyScript = new ScriptDao().saveOrUpdate(copyScript);
scriptEvent.fire(new ModifiedScriptMessage(copyScript, this));
messages.info("Script " + originalName + " has been saved as "
+ copyScript.getName() + ".");
editScript(copyScript);
}
} catch (Exception e) {
messages.error(e.getMessage());
}
}
/**
* Does something to insert think time into the script.
*/
public void insertThinkTime() {
ScriptStep thinkTimeScriptStep = ScriptStepFactory.createThinkTime(
getMinThinkTime(), getMaxThinkTime());
steps.add(getInsertIndex(), thinkTimeScriptStep);
minThinkTime = "";
maxThinkTime = "";
reindexScriptSteps();
}
/**
* Does something to insert a sleep time into the script.
*/
public void insertSleepTime() {
ScriptStep sleepTimeScriptStep = ScriptStepFactory
.createSleepTime(getSleepTime());
steps.add(getInsertIndex(), sleepTimeScriptStep);
sleepTime = "";
reindexScriptSteps();
}
/**
* Does something to insert a variable request into the script.
*/
public void insertVariable() {
ScriptStep variableStep = ScriptStepFactory.createVariable(
getVariableKey(), getVariableValue());
steps.add(getInsertIndex(), variableStep);
variableKey = "";
variableValue = "";
reindexScriptSteps();
}
/**
* Deletes a request from the script.
*
* @param request
*/
public void deleteRequest(ScriptStep step) {
doDelete(step);
messages.info("Script Step " + step.getLabel() + " has been deleted.");
}
/**
* Deletes a request from the script.
*
* @param request
*/
private void doDelete(ScriptStep step) {
if (aggregatorEditor.isAggregator(step)) {
ScriptStep stepPair = aggregatorEditor.getAggregatorPair(step);
steps.remove(stepPair);
searchBean.removeFromSearchMatch(stepPair);
}
steps.remove(step);
searchBean.removeFromSearchMatch(step);
reindexScriptSteps();
}
/**
*
* @return
*/
public List<ScriptStep> getSteps() {
return steps;
}
/**
* @param steps
* the steps to set
*/
public void setSteps(List<ScriptStep> steps) {
this.steps = steps;
}
/**
*
* @param scriptStep
*/
public boolean isVariable(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.VARIABLE);
}
/**
*
* @param scriptStep
*/
public boolean isClearVariable(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.CLEAR);
}
/**
*
* @param scriptStep
*/
public boolean isThinkTime(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.THINK_TIME);
}
/**
*
* @param scriptStep
*/
public boolean isLogicStep(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.LOGIC);
}
/**
*
* @param scriptStep
*/
public boolean isCookieStep(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.COOKIE);
}
/**
*
* @param scriptStep
*/
public boolean isAuthStep(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.AUTHENTICATION);
}
/**
*
* @param scriptStep
*/
public boolean isSleepTime(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.SLEEP);
}
/**
*
* @param scriptStep
*/
public boolean isRequest(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.REQUEST);
}
/**
* @param scriptStep
* @return
*/
public boolean isAggregator(ScriptStep scriptStep) {
return scriptStep.getType().equals(ScriptConstants.TIMER);
}
/**
*
* @param scriptStep
*/
public void editVariable(ScriptStep scriptStep) {
variableEditor.editVariable(scriptStep);
clearOrderList();
}
/**
*
* @param scriptStep
*/
public void editThinkTime(ScriptStep scriptStep) {
thinkTimeEditor.editThinkTime(scriptStep);
clearOrderList();
}
/**
*
* @param scriptStep
*/
public void editCookieStep(ScriptStep scriptStep) {
cookieStepEditor.editCookieStep(scriptStep);
clearOrderList();
}
/**
*
* @param scriptStep
*/
public void editAuthStep(ScriptStep scriptStep) {
authenticationEditor.editAuthentication(scriptStep);
clearOrderList();
}
/**
*
* @param scriptStep
*/
public void editSleepTime(ScriptStep scriptStep) {
sleepTimeEditor.editSleepTime(scriptStep);
clearOrderList();
}
/**
*
* @param scriptStep
*/
public void editLogicStep(ScriptStep scriptStep) {
logicStepEditor.editLogicStep(scriptStep);
clearOrderList();
}
public void editAggregator(ScriptStep step) {
aggregatorEditor.editAggregator(step);
clearOrderList();
}
public void addTimerGroup() {
aggregatorEditor.insertAggregator();
clearOrderList();
}
/**
*
* @param scriptStep
*/
public void editRequest(ScriptStep scriptStep) {
requestEditor.editRequest(scriptStep);
clearOrderList();
}
public void paste() {
int insertIndex = getInsertIndex();
for (ScriptStep step : copyBuffer.getBuffer()) {
ScriptStep copy = ScriptUtil.copyScriptStep(step);
this.steps.add(insertIndex, copy);
insertIndex++;
}
clearOrderList();
reIndexAndCheck();
}
public void insert(ScriptStep step) {
ScriptUtil.updateStepLabel(step);
this.steps.add(getInsertIndex(), step);
clearOrderList();
reindexScriptSteps();
}
private int getInsertIndex() {
int ret = steps.size();
if (!selectedSteps.isEmpty()) {
for (ScriptStep s : selectedSteps) {
ret = Math.min(ret, steps.indexOf(s));
}
}
return ret;
}
public void insert(ScriptStep step, int index) {
ScriptUtil.updateStepLabel(step);
steps.add(index, step);
clearOrderList();
reindexScriptSteps();
}
/**
* @return the currentPage
*/
public int getCurrentPage() {
return currentPage;
}
/**
* @param currentPage
* the currentPage to set
*/
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
/**
* @return the selectedStepsArr
*/
public ScriptStep[] getSelectedStepsArr() {
return selectedStepsArr;
}
public void deleteSelected() {
for (ScriptStep step : selectedSteps) {
doDelete(step);
}
messages.info("Deleted " + selectedSteps.size()
+ " selected Script Steps.");
selectedSteps.clear();
setSelectedStepsArr(new ScriptStep[0]);
}
public void copySelected() {
copyBuffer.clear();
copyBuffer.getBuffer().addAll(selectedSteps);
}
public boolean isCopyEnabled() {
return !selectedSteps.isEmpty();
}
public boolean isDeleteEnabled() {
return !selectedSteps.isEmpty();
}
/**
* @param selectedStepsArr
* the selectedStepsArr to set
*/
public void setSelectedStepsArr(ScriptStep[] selectedStepsArr) {
this.selectedStepsArr = selectedStepsArr;
if (selectedStepsArr != null) {
selectedSteps.clear();
selectedSteps.addAll(Arrays.asList(selectedStepsArr));
}
}
/**
* Reindexes the script steps.
*/
public void reindexScriptSteps() {
int index = 1;
for (ScriptStep step : steps) {
step.setStepIndex(index);
index++;
}
}
public void reIndexAndCheck() {
reindexScriptSteps();
for (ScriptStep step : steps) {
if (isAggregator(step)) {
aggregatorEditor.checkFixOrder(step);
}
}
Collections.sort(steps);
}
public boolean canEditScript() {
return security.hasRight(AccessRight.EDIT_SCRIPT)
|| security.isOwner(script);
}
public ScriptStep getPreviousRequest(ScriptStep step) {
ScriptStep ret = null;
int index = getInsertIndex();
if (step != null) {
index = step.getStepIndex();
}
for (int i = index; --i >= 0;) {
ScriptStep candidate = getSteps().get(i);
if (ScriptConstants.REQUEST.equals(candidate.getType())) {
ret = candidate;
break;
}
}
return ret;
}
}