/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.atomojo.server.xproc;
import com.xmlcalabash.io.ReadablePipe;
import com.xmlcalabash.io.WritableDocument;
import com.xmlcalabash.model.RuntimeValue;
import com.xmlcalabash.model.Serialization;
import com.xmlcalabash.runtime.XPipeline;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import net.sf.saxon.s9api.QName;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.OutputRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.ServerResource;
/**
*
* @author alex
*/
public class XProcResource extends ServerResource {
public static final String CONTEXT_ATTR = "xproc.load.context";
public static final String HREF_PARAM = "xproc.href";
public static final String LOAD_TYPE_PARAM = "xproc.load.type";
public static final String OPTION_NAMES_PARAM = "xproc.option.names";
XProcCache cache;
URI pipelineRef;
List<QName> options;
public XProcResource() {
setNegotiated(false);
cache = null;
pipelineRef = null;
options = null;
}
protected String getOptionValue(QName name)
{
String key = name.getLocalName();
if (name.getNamespaceURI()!=null) {
key = name.getClarkName();
}
Object o = getRequest().getAttributes().get(key);
if (o!=null) {
return o.toString();
}
o = getContext().getAttributes().get(key);
if (o!=null) {
return o.toString();
}
return getContext().getParameters().getFirstValue(key);
}
protected void doInit() {
try {
cache = (XProcCache)getContext().getAttributes().get(XProcCache.ATTR);
if (cache==null) {
getLogger().warning("No cache "+XProcCache.ATTR+" attribute was found for caching xproc pipeline instances.");
}
} catch (Exception ex) {
getLogger().log(Level.SEVERE,"Cannot retrieve cache from context.",ex);
}
String href = getContext().getParameters().getFirstValue(HREF_PARAM);
if (href!=null) {
try {
if ("context".equals(getContext().getParameters().getFirstValue(LOAD_TYPE_PARAM))) {
Object contextObj = getContext().getAttributes().get(CONTEXT_ATTR);
if (contextObj!=null) {
URL pipelineURL = contextObj.getClass().getResource(href);
if (pipelineURL!=null) {
pipelineRef = pipelineURL.toURI();
} else {
getLogger().info("Cannot find resource via context: "+href);
}
} else {
getLogger().info("No context object specified for attribute "+CONTEXT_ATTR);
}
} else {
pipelineRef = new URI(href);
}
getLogger().info("Pipeline: "+pipelineRef);
} catch (URISyntaxException ex) {
getLogger().log(Level.SEVERE,"Cannot instantiate pipeline URI reference: "+href,ex);
}
} else {
getLogger().warning("No xproc.href parameter was specified.");
}
String optionNames = getContext().getParameters().getFirstValue(OPTION_NAMES_PARAM);
if (optionNames!=null) {
String [] names = optionNames.split(",");
for (int i=0; i<names.length; i++) {
QName name = QName.fromClarkName(names[i].trim());
if (options==null) {
options = new ArrayList<QName>();
}
options.add(name);
}
}
}
protected Representation get() {
if (cache==null) {
getResponse().setStatus(Status.SERVER_ERROR_SERVICE_UNAVAILABLE);
return null;
}
if (pipelineRef==null) {
getResponse().setStatus(Status.SERVER_ERROR_SERVICE_UNAVAILABLE);
return null;
}
try {
final XPipelineContext xproc = cache.get(pipelineRef);
XPipeline pipeline = xproc.getPipeline();
if (pipeline.getInputs().size()>0) {
// unsupported
getLogger().severe("Inputs on GET methods are not supported: "+xproc.getPipeline().getInputs());
getResponse().setStatus(Status.SERVER_ERROR_SERVICE_UNAVAILABLE);
cache.release(xproc);
return null;
}
if (pipeline.getOutputs().size()!=1) {
// unsupported
getLogger().severe("Multiple outputs are not supported.");
getResponse().setStatus(Status.SERVER_ERROR_SERVICE_UNAVAILABLE);
cache.release(xproc);
return null;
}
//for (QName optionName : pipeline.getOptions()) {
if (options!=null) {
for (QName optionName : options) {
getLogger().fine("Setting option: "+optionName);
String value = getOptionValue(optionName);
if (value!=null) {
getLogger().fine("Option: "+optionName+"="+value);
pipeline.passOption(optionName, new RuntimeValue(value));
}
}
}
final String outputPort = xproc.getPipeline().getOutputs().iterator().next();
return new OutputRepresentation(MediaType.APPLICATION_XML) {
public void write(OutputStream out) {
try {
xproc.getPipeline().run();
Serialization serial = xproc.getPipeline().getSerialization(outputPort);
WritableDocument doc = new WritableDocument(cache.getRuntime(),null,serial,out);
ReadablePipe rpipe = xproc.getPipeline().readFrom(outputPort);
while (rpipe.moreDocuments()) {
doc.write(rpipe.read());
}
out.flush();
} catch (Exception ex) {
getLogger().log(Level.SEVERE,"Exception while running pipeline.",ex);
}
}
public void release() {
cache.release(xproc);
}
};
} catch (Exception ex) {
getLogger().log(Level.SEVERE,"Cannot load pipeline.",ex);
return null;
} finally {
}
}
}