/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////
package org.projectforge.web.scripting;
import java.io.ByteArrayOutputStream;
import java.util.Date;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.projectforge.calendar.TimePeriod;
import org.projectforge.common.DateHelper;
import org.projectforge.common.DateHolder;
import org.projectforge.common.NumberHelper;
import org.projectforge.core.UserException;
import org.projectforge.excel.ExportWorkbook;
import org.projectforge.export.ExportJFreeChart;
import org.projectforge.export.ExportJson;
import org.projectforge.export.ExportZipArchive;
import org.projectforge.scripting.GroovyResult;
import org.projectforge.scripting.ScriptDO;
import org.projectforge.scripting.ScriptDao;
import org.projectforge.scripting.ScriptParameter;
import org.projectforge.task.TaskDO;
import org.projectforge.task.TaskDao;
import org.projectforge.user.PFUserDO;
import org.projectforge.user.UserDao;
import org.projectforge.web.fibu.ISelectCallerPage;
import org.projectforge.web.wicket.AbstractEditPage;
import org.projectforge.web.wicket.AbstractListPage;
import org.projectforge.web.wicket.AbstractStandardFormPage;
import org.projectforge.web.wicket.DownloadUtils;
import org.projectforge.web.wicket.WicketUtils;
import org.projectforge.web.wicket.bootstrap.GridBuilder;
import org.projectforge.web.wicket.components.ContentMenuEntryPanel;
import org.projectforge.web.wicket.flowlayout.DivTextPanel;
import org.projectforge.web.wicket.flowlayout.FieldsetPanel;
public class ScriptExecutePage extends AbstractScriptingPage implements ISelectCallerPage
{
private static final long serialVersionUID = -183858142939207911L;
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(ScriptExecutePage.class);
@SpringBean(name = "scriptDao")
private ScriptDao scriptDao;
@SpringBean(name = "taskDao")
private TaskDao taskDao;
@SpringBean(name = "userDao")
private UserDao userDao;
private ScriptExecuteForm form;
private Integer id;
protected FieldsetPanel scriptResultFieldsetPanel;
private GridBuilder resultGridBuilder;
@SuppressWarnings("serial")
public ScriptExecutePage(final PageParameters parameters)
{
super(parameters);
id = WicketUtils.getAsInteger(parameters, AbstractEditPage.PARAMETER_KEY_ID);
final ContentMenuEntryPanel editMenuEntryPanel = new ContentMenuEntryPanel(getNewContentMenuChildId(), new Link<Object>("link") {
@Override
public void onClick()
{
storeRecentScriptCalls();
final PageParameters params = new PageParameters();
params.add(AbstractEditPage.PARAMETER_KEY_ID, String.valueOf(id));
final ScriptEditPage editPage = new ScriptEditPage(params);
editPage.setReturnToPage(ScriptExecutePage.this);
form.refresh = true; // Force reload of parameter settings.
setResponsePage(editPage);
};
}, getString("edit"));
addContentMenuEntry(editMenuEntryPanel);
form = new ScriptExecuteForm(this, loadScript());
body.add(form);
form.init();
resultGridBuilder = form.newGridBuilder(body, "results");
resultGridBuilder.newGridPanel();
{
scriptResultFieldsetPanel = new FieldsetPanel(resultGridBuilder.getPanel(), getString("scripting.script.result")) {
/**
* @see org.apache.wicket.Component#isVisible()
*/
@Override
public boolean isVisible()
{
return groovyResult != null;
}
}.suppressLabelForWarning();
final DivTextPanel resultPanel = new DivTextPanel(scriptResultFieldsetPanel.newChildId(), new Model<String>() {
@Override
public String getObject()
{
return groovyResult != null ? groovyResult.getResultAsHtmlString() : "";
}
});
resultPanel.getLabel().setEscapeModelStrings(false);
scriptResultFieldsetPanel.add(resultPanel);
}
}
protected ScriptDO loadScript()
{
final ScriptDO script = scriptDao.getById(id);
if (script == null) {
log.error("Script with id '" + id + "' not found");
throw new UserException("scripting.script.error.notFound");
}
return script;
}
@Override
protected String getTitle()
{
return getString("scripting.script.execute");
}
protected void cancel()
{
final PageParameters params = new PageParameters();
params.add(AbstractListPage.PARAMETER_HIGHLIGHTED_ROW, id);
setResponsePage(ScriptListPage.class, params);
}
protected void execute()
{
final StringBuffer buf = new StringBuffer();
buf.append("Execute script '").append(getScript().getName()).append("': ");
if (form.scriptParameters != null) {
boolean first = true;
for (final ScriptParameter parameter : form.scriptParameters) {
if (first == true) {
first = false;
} else {
buf.append(',');
}
buf.append(parameter.getAsString());
}
}
log.info(buf.toString());
storeRecentScriptCalls();
groovyResult = scriptDao.execute(getScript(), form.scriptParameters);
if (groovyResult.hasException() == true) {
form.error(getLocalizedMessage("exception.groovyError", String.valueOf(groovyResult.getException())));
return;
}
if (groovyResult.hasResult() == true) {
// TODO maybe a good point to generalize to AbstractScriptingPage?
final Object obj = groovyResult.getResult();
if (obj instanceof ExportWorkbook == true) {
exportExcel((ExportWorkbook) obj);
} else if (obj instanceof ExportJFreeChart == true) {
exportJFreeChart((ExportJFreeChart) obj);
} else if (obj instanceof ExportZipArchive == true) {
exportZipArchive((ExportZipArchive) obj);
} else if (obj instanceof ExportJson) {
jsonExport();
}
}
}
private void exportExcel(final ExportWorkbook workbook)
{
final StringBuffer buf = new StringBuffer();
if (workbook.getFilename() != null) {
buf.append(workbook.getFilename()).append("_");
} else {
buf.append("pf_scriptresult_");
}
buf.append(DateHelper.getTimestampAsFilenameSuffix(new Date())).append(".xls");
final String filename = buf.toString();
final byte[] xls = workbook.getAsByteArray();
if (xls == null || xls.length == 0) {
log.error("Oups, xls has zero size. Filename: " + filename);
return;
}
DownloadUtils.setDownloadTarget(xls, filename);
}
private void exportJFreeChart(final ExportJFreeChart exportJFreeChart)
{
final StringBuilder sb = new StringBuilder();
sb.append("pf_chart_");
sb.append(DateHelper.getTimestampAsFilenameSuffix(new Date()));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final String extension = exportJFreeChart.write(out);
sb.append('.').append(extension);
DownloadUtils.setDownloadTarget(out.toByteArray(), sb.toString());
}
private void exportZipArchive(final ExportZipArchive exportZipArchive)
{
try {
final StringBuilder sb = new StringBuilder();
sb.append(exportZipArchive.getFilename()).append("_");
sb.append(DateHelper.getTimestampAsFilenameSuffix(new Date())).append(".zip");
final String filename = sb.toString();
DownloadUtils.setDownloadTarget(filename, exportZipArchive.createResourceStreamWriter());
} catch (final Exception ex) {
error(getLocalizedMessage("error", ex.getMessage()));
log.error(ex.getMessage(), ex);
}
}
protected void storeRecentScriptCalls()
{
final RecentScriptCalls recents = getRecentScriptCalls();
final ScriptCallData scriptCallData = new ScriptCallData(getScript().getName(), form.scriptParameters);
recents.append(scriptCallData);
}
protected RecentScriptCalls getRecentScriptCalls()
{
RecentScriptCalls recentScriptCalls = (RecentScriptCalls) getUserPrefEntry(ScriptExecutePage.class.getName());
if (recentScriptCalls == null) {
recentScriptCalls = new RecentScriptCalls();
putUserPrefEntry(ScriptExecutePage.class.getName(), recentScriptCalls, true);
}
return recentScriptCalls;
}
protected ScriptDO getScript()
{
return form.data;
}
public void cancelSelection(final String property)
{
// Do nothing.
}
public void select(final String property, final Object selectedValue)
{
if (property == null) {
log.error("Oups, null property not supported for selection.");
return;
}
final int colonPos = property.indexOf(':'); // For date:idx e. g. date:3 for 3rd parameter.
final int dotPos = property.lastIndexOf('.'); // For quick select e. g. quickSelect:3.month
String indexString = null;
if (dotPos > 0) {
indexString = property.substring(colonPos + 1, dotPos);
} else {
indexString = colonPos > 0 ? property.substring(colonPos + 1) : null;
}
final Integer idx = NumberHelper.parseInteger(indexString);
if (property.startsWith("quickSelect:") == true) {
final Date date = (Date) selectedValue;
TimePeriod timePeriod = form.scriptParameters.get(idx).getTimePeriodValue();
if (timePeriod == null) {
timePeriod = new TimePeriod();
}
timePeriod.setFromDate(date);
final DateHolder dateHolder = new DateHolder(date);
if (property.endsWith(".month") == true) {
dateHolder.setEndOfMonth();
} else if (property.endsWith(".week") == true) {
dateHolder.setEndOfWeek();
} else {
log.error("Property '" + property + "' not supported for selection.");
}
timePeriod.setToDate(dateHolder.getDate());
form.scriptParameters.get(idx).setTimePeriodValue(timePeriod);
form.datePanel1[idx].markModelAsChanged();
form.datePanel2[idx].markModelAsChanged();
} else if (property.startsWith("taskId:") == true) {
final TaskDO task = taskDao.getById((Integer) selectedValue);
form.scriptParameters.get(idx).setTask(task);
} else if (property.startsWith("userId:") == true) {
final PFUserDO user = userDao.getById((Integer) selectedValue);
form.scriptParameters.get(idx).setUser(user);
} else {
log.error("Property '" + property + "' not supported for selection.");
}
}
public void unselect(final String property)
{
// Do nothing.
}
}