Merge pull request #424 from internetarchive/ui-cleanup

UI: Refactor duplicate template rendering code
This commit is contained in:
Alex Osborne
2021-08-09 14:41:28 +09:00
committed by GitHub
7 changed files with 97 additions and 245 deletions
@@ -19,16 +19,69 @@
package org.archive.crawler.restlet;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.archive.crawler.framework.Engine;
import org.archive.crawler.restlet.models.ViewModel;
import org.restlet.data.MediaType;
import org.restlet.representation.Representation;
import org.restlet.representation.WriterRepresentation;
import org.restlet.resource.ServerResource;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Writer;
/**
* Abstract {@code Resource} with common shared functionality.
*
* @author nlevitt
*/
public abstract class BaseResource extends ServerResource {
@Override
public EngineApplication getApplication() {
return (EngineApplication) super.getApplication();
}
protected Engine getEngine() {
return getApplication().getEngine();
}
protected String getStaticRef(String resource) {
String rootRef = getRequest().getRootRef().toString();
return rootRef + "/engine/static/" + resource;
}
protected Representation render(String templateName, ViewModel viewModel) {
return render(templateName, viewModel, null);
}
protected Representation render(String templateName, ViewModel viewModel, ObjectWrapper objectWrapper) {
String baseRef = getRequest().getResourceRef().getBaseRef().toString();
if(!baseRef.endsWith("/")) {
baseRef += "/";
}
viewModel.put("baseRef", baseRef);
viewModel.setFlashes(Flash.getFlashes(getRequest()));
Template template;
try {
template = getApplication().getTemplateConfiguration().getTemplate(templateName);
} catch (IOException e) {
throw new UncheckedIOException("Error reading template " + templateName, e);
}
return new WriterRepresentation(MediaType.TEXT_HTML) {
@Override
public void write(Writer writer) throws IOException {
try {
template.process(viewModel, writer, objectWrapper);
} catch (TemplateException e) {
throw new RuntimeException(e);
}
writer.flush();
}
};
}
}
@@ -33,7 +33,6 @@ import org.archive.crawler.restlet.models.BeansModel;
import org.archive.crawler.restlet.models.ViewModel;
import org.archive.spring.PathSharingContext;
import org.restlet.Context;
import org.restlet.data.CharacterSet;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Reference;
@@ -47,11 +46,6 @@ import org.restlet.representation.Variant;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* Restlet Resource which allows browsing the constructed beans in
* a hierarchical fashion.
@@ -63,8 +57,7 @@ import freemarker.template.TemplateException;
*/
public class BeanBrowseResource extends JobRelatedResource {
protected PathSharingContext appCtx;
protected String beanPath;
private Configuration _templateConfiguration;
protected String beanPath;
@Override
public void init(Context ctx, Request req, Response res) throws ResourceException {
@@ -82,17 +75,6 @@ public class BeanBrowseResource extends JobRelatedResource {
} else {
beanPath = "";
}
Configuration tmpltCfg = new Configuration();
tmpltCfg.setClassForTemplateLoading(this.getClass(),"");
tmpltCfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
setTemplateConfiguration(tmpltCfg);
}
public void setTemplateConfiguration(Configuration tmpltCfg) {
_templateConfiguration=tmpltCfg;
}
public Configuration getTemplateConfiguration(){
return _templateConfiguration;
}
@Override
@@ -141,24 +123,17 @@ public class BeanBrowseResource extends JobRelatedResource {
throw new ResourceException(404);
}
Representation representation;
if (variant.getMediaType() == MediaType.APPLICATION_XML) {
representation = new WriterRepresentation(MediaType.APPLICATION_XML) {
return new WriterRepresentation(MediaType.APPLICATION_XML) {
public void write(Writer writer) throws IOException {
XmlMarshaller.marshalDocument(writer, "beans", makeDataModel());
}
};
} else {
representation = new WriterRepresentation(
MediaType.TEXT_HTML) {
public void write(Writer writer) throws IOException {
BeanBrowseResource.this.writeHtml(writer);
}
};
ViewModel viewModel = new ViewModel();
viewModel.put("model", makeDataModel());
return render("Beans.ftl", viewModel);
}
// TODO: remove if not necessary in future?
representation.setCharacterSet(CharacterSet.UTF_8);
return representation;
}
/**
@@ -219,28 +194,4 @@ public class BeanBrowseResource extends JobRelatedResource {
nestedNames);
}
protected void writeHtml(Writer writer) {
String baseRef = getRequest().getResourceRef().getBaseRef().toString();
if(!baseRef.endsWith("/")) {
baseRef += "/";
}
Configuration tmpltCfg = getTemplateConfiguration();
ViewModel viewModel = new ViewModel();
viewModel.setFlashes(Flash.getFlashes(getRequest()));
viewModel.put("baseRef",baseRef);
viewModel.put("model",makeDataModel());
try {
Template template = tmpltCfg.getTemplate("Beans.ftl");
template.process(viewModel, writer);
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TemplateException e) {
throw new RuntimeException(e);
}
}
}
@@ -23,6 +23,8 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import org.archive.crawler.framework.Engine;
import org.archive.util.TextUtils;
import org.restlet.Application;
@@ -48,12 +50,17 @@ import org.restlet.service.StatusService;
* @author gojomo
*/
public class EngineApplication extends Application {
protected Engine engine;
protected Engine engine;
private final Configuration templateConfiguration;
public EngineApplication(Engine engine) {
this.engine = engine;
getMetadataService().addExtension("log", MediaType.TEXT_PLAIN );
getMetadataService().addExtension("cxml", MediaType.APPLICATION_XML );
setStatusService(new EngineStatusService());
templateConfiguration = new Configuration();
templateConfiguration.setClassForTemplateLoading(getClass(), "");
templateConfiguration.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
}
@Override
@@ -159,4 +166,7 @@ public class EngineApplication extends Application {
}
public Configuration getTemplateConfiguration() {
return templateConfiguration;
}
}
@@ -25,14 +25,13 @@ import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.ObjectWrapper;
import org.archive.crawler.framework.CrawlJob;
import org.archive.crawler.framework.Engine;
import org.archive.crawler.restlet.models.EngineModel;
import org.archive.crawler.restlet.models.ViewModel;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.CharacterSet;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.representation.EmptyRepresentation;
@@ -41,11 +40,6 @@ import org.restlet.representation.WriterRepresentation;
import org.restlet.resource.ResourceException;
import org.restlet.representation.Variant;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import static org.restlet.data.MediaType.APPLICATION_XML;
/**
@@ -58,46 +52,27 @@ import static org.restlet.data.MediaType.APPLICATION_XML;
*/
public class EngineResource extends BaseResource {
private Configuration _templateConfiguration;
@Override
public void init(Context ctx, Request req, Response res) {
super.init(ctx, req, res);
getVariants().add(new Variant(MediaType.TEXT_HTML));
getVariants().add(new Variant(APPLICATION_XML));
Configuration tmpltCfg = new Configuration();
tmpltCfg.setClassForTemplateLoading(this.getClass(),"");
tmpltCfg.setObjectWrapper(new DefaultObjectWrapper());
setTemplateConfiguration(tmpltCfg);
}
public void setTemplateConfiguration(Configuration tmpltCfg) {
_templateConfiguration=tmpltCfg;
}
public Configuration getTemplateConfiguration(){
return _templateConfiguration;
}
@Override
protected Representation get(Variant variant) throws ResourceException {
Representation representation;
if (variant.getMediaType() == APPLICATION_XML) {
representation = new WriterRepresentation(APPLICATION_XML) {
return new WriterRepresentation(APPLICATION_XML) {
public void write(Writer writer) throws IOException {
XmlMarshaller.marshalDocument(writer, "engine", makeDataModel());
}
};
} else {
representation = new WriterRepresentation(MediaType.TEXT_HTML) {
public void write(Writer writer) throws IOException {
EngineResource.this.writeHtml(writer);
}
};
ViewModel viewModel = new ViewModel();
viewModel.put("fileSeparator", File.separator);
viewModel.put("engine", makeDataModel());
return render("Engine.ftl", viewModel, ObjectWrapper.DEFAULT_WRAPPER);
}
// TODO: remove if not necessary in future?
representation.setCharacterSet(CharacterSet.UTF_8);
return representation;
}
@Override
@@ -226,33 +201,4 @@ public class EngineResource extends BaseResource {
return new EngineModel(getEngine(), baseRef);
}
protected void writeHtml(Writer writer) {
EngineModel model = makeDataModel();
String baseRef = getRequest().getResourceRef().getBaseRef().toString();
if(!baseRef.endsWith("/")) {
baseRef += "/";
}
Configuration tmpltCfg = getTemplateConfiguration();
ViewModel viewModel = new ViewModel();
viewModel.setFlashes(Flash.getFlashes(getRequest()));
viewModel.put("baseRef",baseRef);
viewModel.put("fileSeparator", File.separator);
viewModel.put("engine", model);
try {
Template template = tmpltCfg.getTemplate("Engine.ftl");
template.process(viewModel, writer);
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TemplateException e) {
throw new RuntimeException(e);
}
}
protected Engine getEngine() {
return ((EngineApplication)getApplication()).getEngine();
}
}
@@ -72,10 +72,6 @@ public abstract class JobRelatedResource extends BaseResource {
}
}
protected Engine getEngine() {
return ((EngineApplication)getApplication()).getEngine();
}
/**
* Starting at (and including) the given object, adds nested Map
* representations of named beans to the {@code namedBeans} Collection. The
@@ -61,7 +61,6 @@ import freemarker.template.TemplateException;
public class JobResource extends BaseResource {
public static final IOFileFilter EDIT_FILTER = FileUtils
.getRegexFileFilter(".*\\.((c?xml)|(txt))$");
private Configuration _templateConfiguration;
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(JobResource.class
@@ -77,17 +76,6 @@ public class JobResource extends BaseResource {
getVariants().add(new Variant(MediaType.APPLICATION_XML));
cj = getEngine().getJob(
TextUtils.urlUnescape((String) req.getAttributes().get("job")));
Configuration tmpltCfg = new Configuration();
tmpltCfg.setClassForTemplateLoading(this.getClass(),"");
tmpltCfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
setTemplateConfiguration(tmpltCfg);
}
public void setTemplateConfiguration(Configuration tmpltCfg) {
_templateConfiguration=tmpltCfg;
}
public Configuration getTemplateConfiguration(){
return _templateConfiguration;
}
@Override
@@ -96,9 +84,8 @@ public class JobResource extends BaseResource {
throw new ResourceException(404);
}
Representation representation = null;
if (variant.getMediaType() == MediaType.APPLICATION_XML) {
representation = new WriterRepresentation(MediaType.APPLICATION_XML) {
return new WriterRepresentation(MediaType.APPLICATION_XML) {
public void write(Writer writer) throws IOException {
CrawlJobModel model = makeDataModel();
model.put("heapReport", getEngine().heapReportData());
@@ -106,17 +93,11 @@ public class JobResource extends BaseResource {
}
};
} else {
representation = new WriterRepresentation(MediaType.TEXT_HTML) {
public void write(Writer writer) throws IOException {
JobResource.this.writeHtml(writer);
}
};
ViewModel viewModel = new ViewModel();
viewModel.put("heapReport", getEngine().heapReportData());
viewModel.put("job", makeDataModel());
return render("Job.ftl", viewModel);
}
// TODO: remove if not necessary in future?
// honor requested charset?
representation.setCharacterSet(CharacterSet.UTF_8);
return representation;
}
/**
@@ -134,31 +115,6 @@ public class JobResource extends BaseResource {
return new CrawlJobModel(cj,baseRef);
}
protected void writeHtml(Writer writer) {
String baseRef = getRequest().getResourceRef().getBaseRef().toString();
if(!baseRef.endsWith("/")) {
baseRef += "/";
}
Configuration tmpltCfg = getTemplateConfiguration();
ViewModel viewModel = new ViewModel();
viewModel.setFlashes(Flash.getFlashes(getRequest()));
viewModel.put("baseRef",baseRef);
viewModel.put("job", makeDataModel());
viewModel.put("heapReport", getEngine().heapReportData());
try {
Template template = tmpltCfg.getTemplate("Job.ftl");
template.process(viewModel, writer);
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TemplateException e) {
throw new RuntimeException(e);
}
}
/**
* Get a usable HrefPath, relative to the JobResource, for the given file.
* Assumes usual helper resources ('jobdir/', 'anypath/') at the usual
@@ -182,10 +138,6 @@ public class JobResource extends BaseResource {
return "../../anypath/" + fullPath;
}
protected Engine getEngine() {
return ((EngineApplication) getApplication()).getEngine();
}
@Override
public Representation post(Representation entity, Variant variant)
throws ResourceException {
@@ -19,39 +19,26 @@
package org.archive.crawler.restlet;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import org.apache.commons.lang.StringUtils;
import org.archive.crawler.restlet.models.ScriptModel;
import org.archive.crawler.restlet.models.ViewModel;
import org.restlet.Context;
import org.restlet.data.CharacterSet;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Reference;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.representation.Representation;
import org.restlet.representation.Variant;
import org.restlet.representation.WriterRepresentation;
import org.restlet.resource.ResourceException;
import org.restlet.representation.Variant;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import java.io.IOException;
import java.io.Writer;
import java.util.*;
/**
* Restlet Resource which runs an arbitrary script, which is supplied
@@ -80,28 +67,16 @@ public class ScriptResource extends JobRelatedResource {
}
protected String chosenEngine = FACTORIES.isEmpty() ? "" : FACTORIES.getFirst().getNames().get(0);
private Configuration _templateConfiguration;
@Override
public void init(Context ctx, Request req, Response res) throws ResourceException {
super.init(ctx, req, res);
getVariants().add(new Variant(MediaType.TEXT_HTML));
getVariants().add(new Variant(MediaType.APPLICATION_XML));
Configuration tmpltCfg = new Configuration();
tmpltCfg.setClassForTemplateLoading(this.getClass(),"");
tmpltCfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
setTemplateConfiguration(tmpltCfg);
scriptingConsole = new ScriptingConsole(cj);
}
public void setTemplateConfiguration(Configuration tmpltCfg) {
_templateConfiguration=tmpltCfg;
}
public Configuration getTemplateConfiguration(){
return _templateConfiguration;
}
private ScriptingConsole scriptingConsole;
@Override
@@ -126,23 +101,20 @@ public class ScriptResource extends JobRelatedResource {
@Override
public Representation get(Variant variant) throws ResourceException {
Representation representation;
if (variant.getMediaType() == MediaType.APPLICATION_XML) {
representation = new WriterRepresentation(MediaType.APPLICATION_XML) {
return new WriterRepresentation(MediaType.APPLICATION_XML) {
public void write(Writer writer) throws IOException {
XmlMarshaller.marshalDocument(writer,"script", makeDataModel());
}
};
} else {
representation = new WriterRepresentation(MediaType.TEXT_HTML) {
public void write(Writer writer) throws IOException {
ScriptResource.this.writeHtml(writer);
}
};
ViewModel viewModel = new ViewModel();
viewModel.put("baseResourceRef", getRequest().getRootRef().toString() + "/engine/static/");
viewModel.put("model", makeDataModel());
viewModel.put("selectedEngine", chosenEngine);
viewModel.put("staticRef", getStaticRef(""));
return render("Script.ftl", viewModel);
}
// TODO: remove if not necessary in future?
representation.setCharacterSet(CharacterSet.UTF_8);
return representation;
}
protected Collection<Map<String,String>> getAvailableScriptEngines() {
@@ -177,32 +149,4 @@ public class ScriptResource extends JobRelatedResource {
return model;
}
protected void writeHtml(Writer writer) {
String baseRef = getRequest().getResourceRef().getBaseRef().toString();
if(!baseRef.endsWith("/")) {
baseRef += "/";
}
Configuration tmpltCfg = getTemplateConfiguration();
ViewModel viewModel = new ViewModel();
viewModel.setFlashes(Flash.getFlashes(getRequest()));
viewModel.put("baseRef",baseRef);
viewModel.put("staticRef", getStaticRef(""));
viewModel.put("baseResourceRef",getRequest().getRootRef().toString()+"/engine/static/");
viewModel.put("model", makeDataModel());
viewModel.put("selectedEngine", chosenEngine);
try {
Template template = tmpltCfg.getTemplate("Script.ftl");
template.process(viewModel, writer);
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TemplateException e) {
throw new RuntimeException(e);
}
}
}