/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.web.demo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxCallListener;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resources;
import org.geoserver.platform.resource.Resource.Type;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.web.GeoServerBasePage;
import org.geoserver.web.wicket.CodeMirrorEditor;
import org.geotools.util.logging.Logging;
import org.vfny.geoserver.global.ConfigurationException;
import org.geoserver.config.GeoServer;
/**
*
* @author Gabriel Roldan
* @since 1.8.x
* @version $Id$
*/
@SuppressWarnings("serial")
public class DemoRequestsPage extends GeoServerBasePage {
private static final Logger LOGGER = Logging.getLogger("org.geoserver.web.demo");
final Resource demoDir;
private TextField urlTextField;
private CodeMirrorEditor body;
private TextField username;
private PasswordTextField password;
public DemoRequestsPage() {
try {
GeoServerResourceLoader loader = this.getGeoServer().getCatalog().getResourceLoader();
demoDir = Resources.serializable(loader.get("demo"));
} catch (Exception e) {
throw new WicketRuntimeException("Can't access demo requests directory: "
+ e.getMessage());
}
DemoRequest model = new DemoRequest(demoDir.path());
setDefaultModel(new Model(model));
setUpDemoRequestsForm(demoDir);
}
/**
* Package visible constructor aimed to help in setting up unit tests for this class
*
* @param demoDir
*/
DemoRequestsPage(final Resource demoDir) {
this.demoDir = Resources.serializable(demoDir);
DemoRequest model = new DemoRequest(demoDir.path());
setDefaultModel(new Model(model));
setUpDemoRequestsForm(demoDir);
}
/**
* Loads the contents of the demo request file named {@code reqFileName} and located in the
* demo directory.
*
* @param reqFileName
* the file name to load the contents for
* @return the file contents
* @throws IOException
* if an io exception occurs opening or loading the file
*/
private String getFileContents(final String reqFileName) throws IOException {
final Resource file = demoDir.get(reqFileName);
final StringBuilder sb = new StringBuilder();
final BufferedReader reader = new BufferedReader(new InputStreamReader(file.in()));
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
} finally {
reader.close();
}
return sb.toString();
}
private void setUpDemoRequestsForm(final Resource demoDir) {
final IModel requestModel = getDefaultModel();
final Form demoRequestsForm;
demoRequestsForm = new Form("demoRequestsForm");
demoRequestsForm.setOutputMarkupId(true);
demoRequestsForm.setModel(requestModel);
add(demoRequestsForm);
final List<String> demoList = getDemoList(demoDir);
final DropDownChoice demoRequestsList;
final IModel reqFileNameModel = new PropertyModel(requestModel, "requestFileName");
demoRequestsList = new DropDownChoice("demoRequestsList", reqFileNameModel, demoList,
new ChoiceRenderer() {
public String getIdValue(Object obj, int index) {
return String.valueOf(obj);
}
public Object getDisplayValue(Object obj) {
return obj;
}
});
demoRequestsForm.add(demoRequestsList);
/*
* Wanted to use a simpler OnChangeAjaxBehavior but target.add(body) does not make
* the EditAreaBehavior to update the body contents inside it, but instead puts the plain
* TextArea contents above the empty xml editor
*/
demoRequestsList.add(new AjaxFormSubmitBehavior(demoRequestsForm, "change") {
@Override
protected void onSubmit(AjaxRequestTarget target) {
final String reqFileName = demoRequestsList.getModelValue();
final String contents;
String proxyBaseUrl;
final String baseUrl;
{
HttpServletRequest httpServletRequest =
getGeoServerApplication().servletRequest(DemoRequestsPage.this.getRequest());
proxyBaseUrl = GeoServerExtensions.getProperty("PROXY_BASE_URL");
if (StringUtils.isEmpty(proxyBaseUrl)) {
GeoServer gs = getGeoServer();
proxyBaseUrl = gs.getGlobal().getSettings().getProxyBaseUrl();
if (StringUtils.isEmpty(proxyBaseUrl)) {
baseUrl = ResponseUtils.baseURL(httpServletRequest);
} else {
baseUrl = proxyBaseUrl;
}
} else {
baseUrl = proxyBaseUrl;
}
}
try {
contents = getFileContents(reqFileName);
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Can't load demo file " + reqFileName, e);
throw new WicketRuntimeException("Can't load demo file " + reqFileName, e);
}
boolean demoRequestIsHttpGet = reqFileName.endsWith(".url");
final String service = reqFileName.substring(0, reqFileName.indexOf('_'))
.toLowerCase();
if (demoRequestIsHttpGet) {
String url = ResponseUtils.appendPath(baseUrl, contents);
urlTextField.setModelObject(url);
body.setModelObject("");
} else {
String serviceUrl = ResponseUtils.appendPath(baseUrl, service);
urlTextField.setModelObject(serviceUrl);
body.setModelObject(contents);
}
// target.add(urlTextField);
// target.add(body);
/*
* Need to setResponsePage, addComponent causes the EditAreaBehavior to sometimes
* not updating properly
*/
setResponsePage(DemoRequestsPage.this);
}
@Override
protected void onError(AjaxRequestTarget target) {
// nothing to do
}
});
urlTextField = new TextField("url", new PropertyModel(requestModel, "requestUrl"));
urlTextField.setMarkupId("requestUrl");
urlTextField.setOutputMarkupId(true);
demoRequestsForm.add(urlTextField);
body = new CodeMirrorEditor("body", new PropertyModel(requestModel, "requestBody"));
// force the id otherwise this blasted thing won't be usable from other forms
// body.setMarkupId("requestBody");
// body.setOutputMarkupId(true);
body.setTextAreaMarkupId("requestBody");
//body.add(new EditAreaBehavior());
demoRequestsForm.add(body);
username = new TextField("username", new PropertyModel(requestModel, "userName"));
demoRequestsForm.add(username);
password = new PasswordTextField("password", new PropertyModel(requestModel, "password"));
password.setRequired(false);
demoRequestsForm.add(password);
final ModalWindow responseWindow;
responseWindow = new ModalWindow("responseWindow");
add(responseWindow);
//responseWindow.setPageMapName("demoResponse");
responseWindow.setCookieName("demoResponse");
responseWindow.setPageCreator(new ModalWindow.PageCreator() {
public Page createPage() {
return new DemoRequestResponse(requestModel);
}
});
demoRequestsForm.add(new AjaxSubmitLink("submit", demoRequestsForm) {
@Override
public void onSubmit(AjaxRequestTarget target, Form testWfsPostForm) {
responseWindow.show(target);
}
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
// we need to force EditArea to update the textarea contents (which it hides)
// before submitting the form, otherwise the contents won't be the ones the user
// edited
attributes.getAjaxCallListeners().add(new AjaxCallListener() {
@Override
public CharSequence getBeforeHandler(Component component) {
return "document.getElementById('requestBody').value = document.gsEditors.requestBody.getValue();";
}
});
}
});
}
private List<String> getDemoList(final Resource demoDir) {
final List<String> demoList = new ArrayList<String>();
for (Resource file : demoDir.list()) {
if (file.getType() != Type.DIRECTORY) {
final String name = file.name();
if (name.endsWith(".url") || name.endsWith(".xml")) {
demoList.add(name);
} else {
LOGGER.warning("Ignoring file " + name
+ " in demo requests directory, only .url and .xml files allowed");
}
}
}
Collections.sort(demoList);
return demoList;
}
}