--- /dev/null
+package ibex.xt;
+
+import ibex.util.XML;
+import org.ibex.js.JS;
+import org.ibex.js.JSScope;
+
+import ibex.collection.*;
+import java.util.*;
+
+import java.io.StringReader;
+import java.io.Writer;
+import java.io.IOException;
+
+public class JSElement extends JSScope implements XML.Element {
+ protected XML.Element wrapped;
+
+ /** Creates an Element around <tt>wrapped</tt>, replacing
+ * references to it in its parent and children with this object. */
+ public JSElement(XML.Element wrapped) {
+ super(findScope(wrapped));
+ this.wrapped = wrapped;
+
+ // remap parent and children
+ if (wrapped.getParent() != null) {
+ List c = wrapped.getParent().getChildren();
+ c.remove(wrapped); c.add(this);
+ }
+ List c = wrapped.getChildren();
+ for (int i=c.size(); i >= 0; i--) ((XML.Block)c.get(i)).setParent(this);
+ }
+
+ public void toXML(Writer w) throws IOException {
+ // grab all related attributes
+ try {
+ XML.Attributes a = getAttributes();
+ for(int i=0; i < a.attrSize(); i++) {
+ if (!"http://xt.ibex.org/".equals(a.getUri(i))) continue;
+ declare(a.getKey(i));
+ put(a.getKey(i), eval(a.getVal(i)));
+ }
+ } catch (Exception e) { throw new RuntimeException(e); }
+ }
+
+ private Object eval(String s) {
+ if (s == null) return null;
+ StringBuffer ret = new StringBuffer();
+ while (s.indexOf("${") != -1) {
+ ret.append(s.substring(0, s.indexOf("${")));
+ String s2 = s.substring(s.indexOf("${")+2);
+ Object app = exec("return (" + s2.substring(0, s2.indexOf('}')) + ");\n");
+ s = s.substring(s.indexOf('}') + 1);
+
+ if (!(app == null ||
+ app instanceof String ||
+ app instanceof Number ||
+ app instanceof Boolean))
+ throw new RuntimeException("javascripts within ${...} can only return " +
+ "strings, numbers, and booleans; not a " +
+ app.getClass().getName());
+
+ ret.append(app == null ? "null" : app.toString());
+ }
+ ret.append(s);
+ return ret.toString();
+ }
+
+ public Object exec(String s) {
+ try {
+ return JS.eval(JS.cloneWithNewParentScope(
+ JS.fromReader("input", 0, new StringReader(s)), this));
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ // Pass Through ///////////////////////////////////////////////////////////
+
+ public void setParent(XML.Element p) { wrapped.setParent(p); }
+ public XML.Element getParent() { return wrapped.getParent(); }
+ public XML.Attributes getAttributes() { return wrapped.getAttributes(); }
+ public XML.Prefixes getPrefixes() { return wrapped.getPrefixes(); }
+ public List getChildren() { return wrapped.getChildren(); }
+ public String getQName() { return wrapped.getQName(); }
+ public String getLocalName() { return wrapped.getLocalName(); }
+ public String getPrefix() { return wrapped.getPrefix(); }
+ public String getUri() { return wrapped.getUri(); }
+
+ /** Works up the Element object model until an instance of a JSScope is found. */
+ private static JSScope findScope(XML.Element e) {
+ while (e != null && !(e instanceof JSScope)) e = e.getParent();
+ return (JSScope)e;
+ }
+
+ /** A JSElement with the element attributes merged with a second
+ * element.
+ *
+ * All functions of the XML.Element interface are mapped onto the
+ * primary element, except <tt>getAttributes()</tt>. This function
+ * returns a MergedAttr instance with the <b>secondary</b> element
+ * acting as the primary attribute source.
+ */
+ public static class Merge extends JSElement {
+ private final XML.Attributes a;
+ public Merge(XML.Element wrapped, XML.Element merge) {
+ super(wrapped);
+ a = new MergeAttr(merge.getAttributes(), wrapped.getAttributes());
+ }
+ public XML.Attributes getAttributes() { return a; }
+ }
+
+ /** Creates a single view onto two sets of Attributes, first
+ * checking the <tt>primary</tt> array for an entry, or
+ * otherwise returning any matching entry in the
+ * <tt>secondary</tt> Attributes object.
+ *
+ * FIXME: toXML() produces invalid XML if qname in both a and b.
+ */
+ public static final class MergeAttr implements XML.Attributes {
+ private final XML.Attributes a, b;
+ public MergeAttr(XML.Attributes primary, XML.Attributes secondary) {
+ a = primary; b = secondary;
+ }
+ public int getIndex(String qname) {
+ int i = a.getIndex(qname); if (i >= 0) return i;
+ i = b.getIndex(qname); if (i >= 0) return i + a.attrSize();
+ return -1;
+ }
+ public int getIndex(String uri, String key) {
+ int i = a.getIndex(uri, key); if (i >= 0) return i;
+ i = b.getIndex(uri, key); if (i >= 0) return i + b.attrSize();
+ return -1;
+ }
+ public String getKey(int i) {
+ return i >= a.attrSize() ? b.getKey(i-a.attrSize()) : a.getKey(i); }
+ public String getVal(int i) {
+ return i >= a.attrSize() ? b.getVal(i-a.attrSize()) : a.getVal(i); }
+ public String getUri(int i) {
+ return i >= a.attrSize() ? b.getUri(i-a.attrSize()) : a.getUri(i); }
+ public String getPrefix(int i) {
+ return i >= a.attrSize() ? b.getUri(i-a.attrSize()) : a.getUri(i); }
+ public String getQName(int i) {
+ return i >= a.attrSize() ? b.getUri(i-a.attrSize()) : a.getUri(i); }
+ public int attrSize() { return a.attrSize() + b.attrSize(); }
+ }
+}
-package org.ibex.xt;
+package ibex.xt;
+
import org.ibex.js.*;
-import org.ibex.util.*;
-import org.ibex.io.*;
+import ibex.util.*;
+//import org.ibex.io.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
-import com.thoughtworks.xstream.*;
+//import com.thoughtworks.xstream.*;
import org.prevayler.*;
import org.prevayler.implementation.snapshot.*;
String base = cx.getRealPath("/") + "WEB-INF" + File.separatorChar + "prevalent";
System.err.println("prevayling to " + base);
pf.configurePrevalenceBase(base);
+ /*
XStreamSnapshotManager manager = new XStreamSnapshotManager(new JS(), base, null) {
protected XStream createXStream() {
XStream xstream = new XStream();
};
System.err.println("configuring with " + manager);
pf.configureSnapshotManager(manager);
- //pf.configureSnapshotManager(new SnapshotManager(new JS(), base));
+ */
+ pf.configureSnapshotManager(new SnapshotManager(new JS(), base));
//pf.configureClassLoader(JSTransaction.class.getClassLoader());
prevayler = pf.create();
prevaylers.put(cx, prevayler);
-package org.ibex.xt;
-import org.ibex.js.*;
-import org.ibex.util.*;
-import org.ibex.io.*;
+package ibex.xt;
+
+import ibex.util.XML;
+import org.ibex.js.JS;
+import org.ibex.js.JSArray;
+import org.ibex.js.JSDate;
+import org.ibex.js.JSExn;
+
import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
-import com.thoughtworks.xstream.*;
+
import org.prevayler.*;
import org.prevayler.implementation.snapshot.*;
public class Servlet extends HttpServlet {
- private ServletScope servletscope = null;
private String path;
private Prevayler prevayler;
private JS prevalent;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { doGet(request, response); }
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
- servletscope = new ServletScope(request, response, cx);
- path = cx.getRealPath(((HttpServletRequest)request).getServletPath());
- Reader xmlreader = new InputStreamReader(new FileInputStream(path));
- new Template(servletscope, new JSScope(servletscope), xmlreader).wrap(null).toXML(response.getWriter());
+ public void doGet(HttpServletRequest rq, HttpServletResponse rs) throws IOException {
+ String path = cx.getRealPath(rq.getServletPath());
+ Servlet.Scope scope = new Servlet.Scope(cx, rq, rs, prevayler);
+ try { Template.wrap(Template.parse(path, scope), scope).toXML(rs.getWriter()); }
+ catch (Exception e) { e.printStackTrace(); System.out.println("e = "+e); }
}
- public class ServletScope extends JSScope {
- HttpServletRequest request;
- HttpServletResponse response;
- ServletContext cx;
- public String getRealPath(String s) { return cx.getRealPath(s); }
- public ServletScope(ServletRequest request, ServletResponse response, ServletContext cx) {
- super(null);
- this.request = (HttpServletRequest)request;
- this.response = (HttpServletResponse)response;
- this.cx = cx;
+ public static class Scope extends Template.Scope {
+ private final ServletContext cx;
+ private final HttpServletRequest request;
+ private final HttpServletResponse response;
+ private final Prevayler prevayler;
+
+ public Scope(ServletContext cx, HttpServletRequest rq, HttpServletResponse rs, Prevayler p) {
+ super(null); this.cx = cx; request = rq; response = rs; prevayler = p;
+ }
+
+ public String getLocalPath() { return cx.getRealPath("/") + "/WEB-INF/"; }
+ public void transaction(JS t) {
+ try { prevayler.execute(new Prevalence.JSTransaction(t)); }
+ catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }
}
+
private JS params = new JS() {
- public Object get(Object key) { return request.getParameter(JS.toString(key)); }
- public Enumeration keys() { return request.getParameterNames(); }
- };
+ public Object get(Object key) { return request.getParameter(JS.toString(key)); }
+ public Enumeration keys() { return request.getParameterNames(); }
+ };
private JS cookies = new JS() {
/*
public Object get(Object key) { return request.getCookie(JS.toString(key)); }
*/
};
private JS sessionAttributes = new JS() {
- public Object get(Object key) { return request.getSession(true).getAttribute(JS.toString(key)); }
- public void put(Object key, Object val) {
- if (val == null) request.getSession(true).removeAttribute(JS.toString(key));
- else request.setAttribute(JS.toString(key), val); }
- public Enumeration keys() { return request.getSession(true).getAttributeNames(); }
- };
+ public Object get(Object key) {
+ return request.getSession(true).getAttribute(JS.toString(key)); }
+ public void put(Object key, Object val) {
+ if (val == null) request.getSession(true).removeAttribute(JS.toString(key));
+ else request.setAttribute(JS.toString(key), val); }
+ public Enumeration keys() { return request.getSession(true).getAttributeNames(); }
+ };
private JS requestHeader = new JS() {
- public Object get(Object key) { return request.getHeader(JS.toString(key)); }
- public Enumeration keys() { return request.getHeaderNames(); }
- };
+ public Object get(Object key) { return request.getHeader(JS.toString(key)); }
+ public Enumeration keys() { return request.getHeaderNames(); }
+ };
private JS responseHeader = new JS() {
- public void put(Object key, Object val) { response.setHeader(JS.toString(key), JS.toString(val)); }
- };
+ public void put(Object key, Object val) {
+ response.setHeader(JS.toString(key), JS.toString(val)); }
+ };
/** lets us put multi-level get/put/call keys all in the same method */
Object key;
Sub(Object key) { this.key = key; }
public void put(Object key, Object val) throws JSExn {
- ServletScope.this.put(JS.toString(this.key) + "." + JS.toString(key), val); }
+ Scope.this.put(JS.toString(this.key) + "." + JS.toString(key), val); }
public Object get(Object key) throws JSExn {
- return ServletScope.this.get(JS.toString(this.key) + "." + JS.toString(key)); }
+ return Scope.this.get(JS.toString(this.key) + "." + JS.toString(key)); }
public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
- return ServletScope.this.callMethod(this.key, a0, a1, a2, rest, nargs);
+ return Scope.this.callMethod(this.key, a0, a1, a2, rest, nargs);
}
public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
- return ServletScope.this.callMethod(JS.toString(this.key) + "."
+ return Scope.this.callMethod(JS.toString(this.key) + "."
+ JS.toString(method), a0, a1, a2, rest, nargs);
}
}
case "request.remote": return getSub("request.remote");
case "request.remote.ip": return request.getRemoteAddr();
case "request.remote.host": return request.getRemoteHost();
- case "request.ssl": return request.isSecure();
+ case "request.ssl": return new Boolean(request.isSecure());
case "request.path": return request.getPathInfo();
case "response": return getSub("response");
case "response.header": return responseHeader;
case "session.accessed": return new JSDate(request.getSession(true).getLastAccessedTime());
case "session.invalidate": return METHOD;
case "page": return getSub("page");
- case "page.lastmodified": return new JSDate(new File(path).lastModified());
+ //case "page.lastmodified": return new JSDate(new File(path).lastModified()); FIXME
case "context": return getSub("context");
case "context.list": return METHOD;
case "params": return params;
case "cookie": return cookies;
+ case "xt.date": return new JSDate(); // TODO: discuss
//#end
return null;
}
public void put(Object key, Object val) throws JSExn {
try {
//#switch(JS.toString(key))
- case "transaction":
- try { prevayler.execute(new Prevalence.JSTransaction((JS)val));
- } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }
+ case "transaction": transaction((JS)val);
case "response.code": response.setStatus(JS.toInt(val));
case "response.redirect": response.sendRedirect(JS.toString(val));
case "response.contentType": response.setContentType(JS.toString(val));
--- /dev/null
+package ibex.xt;
+
+import ibex.util.XML;
+import ibex.util.Vec; //FIXME remove
+
+import org.ibex.js.JS;
+import org.ibex.js.JSScope;
+import org.ibex.js.JSArray;
+import org.ibex.js.JSExn;
+
+import ibex.collection.*;
+import java.util.*;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.io.IOException;
+
+
+public class Template extends JSElement {
+ public static Template parse(String path, Template.Scope s) throws IOException, XML.Exn {
+ Reader xmlreader = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
+ XML.Document doc = new XML.Document();
+ doc.parse(xmlreader);
+ return new Template(doc.getRoot(), s);
+ }
+
+ public static XML.Element wrap(XML.Element e, Template.Scope s) throws IOException, XML.Exn {
+ final String uri = e.getUri();
+
+ if (uri.equals("http://xt.ibex.org/")) {
+ //#switch(e.getLocalName())
+ case "if": e = new Template.If(e); break;
+ case "js": e = new Template.JSTag(e); break;
+ case "foreach": e = new Template.ForEach(e); break;
+ case "children": e = new Template.Children(e); break;
+ case "transaction": e = new Template.Transaction(e, s); break;
+ //#end
+
+ } else if (uri.startsWith("http://xt.ibex.org/")) {
+ //#switch(uri.substring(19))
+ case "io": System.out.println("ibex.xt.io not yet implemented"); // TODO
+ //#end
+ throw new RuntimeException("Unknown XT library: "+uri);
+
+ } else if (uri.startsWith("local:")) {
+ Template t = parse(s.getLocalPath() + uri.substring(6), s);
+
+ List c = e.getChildren();
+ if (c.size() > 0) {
+ // move all children from e to placeholder
+ XML.Element placeholder = findPlaceholder(t);
+ if (placeholder == null) throw new RuntimeException(
+ "<"+e.getQName()+"> attempted to include children into a " +
+ "template which does not contain an <xt:children /> tag.");
+
+ placeholder.getChildren().addAll(e.getChildren());
+ e.getChildren().clear();
+ }
+
+ // merge original attributes with replacement template
+ e = new JSElement.Merge(t, e);
+
+ } else if (uri.startsWith("java:")) {
+ e = new Java(e);
+ }
+
+ // wrap children
+ List c = e.getChildren();
+ for (int i=0; i < c.size(); i++)
+ if (c.get(i) instanceof XML.Element) wrap((XML.Element)c.get(i), s);
+
+ return e;
+ }
+
+ /** Returns the first Template.Children child found. */
+ private static Template.Children findPlaceholder(XML.Element e) {
+ if (e instanceof Template.Children) return (Template.Children)e;
+ List c = e.getChildren();
+ for (int i=0; i < c.size(); i++) {
+ if (!(c.get(i) instanceof XML.Element)) continue;
+ Template.Children ret = findPlaceholder((XML.Element)c.get(i));
+ if (ret != null) return ret;
+ }
+ return null;
+ }
+
+ private Template.Scope tscope;
+
+ public Template(XML.Element w, Template.Scope t) { super(w); tscope = t; }
+
+ public JSScope getParentScope() { return tscope; }
+
+
+ public static final class If extends JSElement {
+ public If(XML.Element e) { super(e); }
+
+ public void toXML(Writer w) throws IOException {
+ super.toXML(w);
+
+ try {
+ Object varIf = get("if"); if (varIf != null) undeclare("if");
+ if (varIf != null && !Boolean.getBoolean((String)varIf)) return;
+ } catch (JSExn e) { throw new RuntimeException(e); }
+
+ List c = getChildren();
+ for (int i=0; i < c.size(); i++) ((XML.Block)c.get(i)).toXML(w);
+ }
+ }
+
+ public static final class JSTag extends JSElement {
+ public JSTag(XML.Element e) {
+ super(e);
+ List c = getChildren();
+ for (int i=0; i < c.size(); i++)
+ if (c.get(i) instanceof XML.Element) throw new RuntimeException(
+ "<"+getPrefix()+":js> tags may not have child elements");
+ }
+
+ public void toXML(Writer w) throws IOException {
+ super.toXML(w);
+
+ try {
+ Object varIf = get("if"); if (varIf != null) undeclare("if");
+ if (varIf != null && !Boolean.getBoolean((String)varIf)) return;
+
+ List c = getChildren();
+ StringWriter s = new StringWriter();
+ for (int i=0; i < c.size(); i++) ((XML.Block)c.get(i)).toXML(s);
+ exec(s.toString());
+ } catch (JSExn e) { throw new RuntimeException(e); }
+ }
+ }
+
+ public static final class ForEach extends JSElement {
+ public ForEach(XML.Element e) { super(e); }
+
+ public void toXML(Writer w) throws IOException {
+ super.toXML(w);
+
+ try {
+ Object varIn = get("in"); if (varIn != null) undeclare("in");
+ Object varPut = get("put"); if (varPut != null) undeclare("put");
+ Object varIf = get("if"); if (varIf != null) undeclare("if");
+ if (varIf != null && !Boolean.getBoolean((String)varIf)) return;
+
+ varIn = exec("return (" + varIn + ");");
+ if (varIn == null || (varIn instanceof JSArray)) throw new RuntimeException(
+ "<"+getPrefix()+":foreach> requires attribute 'in' to specify " +
+ "the name of a valid js array in the current scope, not in='"+varIn+"'.");
+
+ if (varPut == null) varPut = "x";
+ else if (!(varPut instanceof String) || get(varPut) != null)
+ throw new RuntimeException(
+ "<"+getPrefix()+":foreach> 'put' attribute requires the name of "+
+ "an undeclared variable, not put='"+varPut+"'.");
+ if (get(varPut) != null) throw new RuntimeException(
+ "<"+getPrefix()+":foreach> has no 'put' attribute defined and the "+
+ "default variable 'x' already exists in the current scope.");
+
+ List c = getChildren();
+
+ declare((String)varPut);
+ Vec v = ((JSArray)varIn).toVec();
+ for (int j=0; j < v.size(); j++) {
+ put(varPut, v.elementAt(j));
+ for (int i=0; i < c.size(); i++) ((XML.Block)c.get(i)).toXML(w);
+ }
+ } catch (JSExn e) { throw new RuntimeException(e); }
+ }
+ }
+
+ public static final class Children extends JSElement {
+ public Children(XML.Element e) { super(e); }
+ }
+
+ public static final class Transaction extends JSElement {
+ private final Template.Scope scope; // FIXME: HACK. unstatisise all tags, or do this to all
+ public Transaction(XML.Element e, Template.Scope s) { super(e); scope = s;} // TODO: check kids
+
+ public void toXML(Writer w) throws IOException {
+ super.toXML(w);
+
+ // FIXME: what about scope import? <xt:use /> children?
+ List c = getChildren();
+ StringWriter sw = new StringWriter();
+ for (int i=0; i < c.size(); i++) ((XML.Block)c.get(i)).toXML(sw);
+ JS t = JS.fromReader("input", 0, new StringReader(sw.toString()));
+ t = JS.cloneWithNewParentScope(t, new JSScope(null));
+ scope.transaction(t);
+ }
+ }
+
+ public static final class Java extends JSElement {
+ // TODO what exactly?
+ public Java(XML.Element w) { super(w); }
+ }
+
+ public abstract static class Scope extends JSScope {
+ public Scope(JSScope j) { super(j); }
+
+ /** Returns the template path for local:/ namespace. */
+ public abstract String getLocalPath();
+
+ /** Registers a new Prevayler transaction. */
+ public abstract void transaction(JS t);
+ }
+
+}
+++ /dev/null
-package org.ibex.xt;
-import org.ibex.js.*;
-import org.ibex.util.*;
-import org.ibex.io.*;
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-public class Node {
-
- public String name = null;
- public String cdata = null;
- public int numattrs = 0;
- public String[] attrs = null;
- public String uri = null;
- private int delta = 0;
-
- public Node() { }
- public Node(Node n) { copyFrom(n); }
- public final void clear() { name = null; cdata = null; numattrs = 0; delta = 0; uri = null; }
- public final void copyFrom(Node n) {
- name=n.name; cdata=n.cdata; numattrs=n.numattrs; delta=n.delta; uri=n.uri;
- if (n.attrs == null) { attrs = null; return; }
- attrs = new String[n.attrs.length]; System.arraycopy(n.attrs, 0, attrs, 0, attrs.length); }
- public final String attr(String key) {
- for(int i=0; i<numattrs; i++) if (key.equals(attrs[i*2])) return attrs[i*2+1]; return null; }
-
- public static abstract class Stream {
- public static final Stream NULL = new Stream() { public boolean _read(Node n) { return false; } };
- public static interface Functor { public Node.Stream wrap(Node.Stream in); }
- public static class ConstantFunctor implements Functor {
- private final Node.Stream stream;
- public ConstantFunctor(Node.Stream stream) { this.stream = stream; }
- public Node.Stream wrap(Node.Stream in) { return stream; }
- }
- public static abstract class Filter extends Stream {
- Stream upstream;
- Filter() { }
- public Filter(Stream upstream) { this.upstream = upstream; }
- public boolean upstreamRead(Node n) { upstream = upstream.simplify(); return upstream.read(n); }
- public void wrapUpstream(Functor f) { upstream = f.wrap(upstream); }
- public Filter graft(Functor f, Node n) {
- upstream = new Graft((upstream instanceof Peekable) ? (Peekable)upstream : new Peekable(upstream), n, f);
- return this;
- }
- }
-
- public Stream simplify() { return this; }
- protected abstract boolean _read(Node n);
- public final boolean read(Node n) { n.clear(); if (!_read(n)) { n.clear(); return false; } return true; }
-
- public static class Peekable extends Filter {
- public Peekable(Stream s) { super(s); }
- private Node pending = null;
- public boolean peek(Node n) {
- if (pending == null) {
- Node n2 = new Node();
- if (!upstreamRead(n2)) return false;
- pending = n2;
- }
- n.copyFrom(pending);
- return true;
- }
- public boolean _read(Node n) {
- if (pending != null) { n.copyFrom(pending); pending = null; return true; }
- return upstreamRead(n);
- }
- }
-
- private static class Graft extends Filter {
- private Stream inner2;
- private Peekable a;
- int total = 0;
- int net = 0;
- boolean simple = false;
- private Node pending = new Node();
- public Graft(final Peekable a, final Node n, final Functor f) {
- this.a = a;
- upstream = inner2 = new Stream() {
- public boolean _read(Node n) {
- if (!Graft.this.a.peek(n)) return false;
- if (net + n.delta <= 0) return false;
- Graft.this.a.read(n);
- net += n.delta;
- return true;
- } };
- wrapUpstream(f);
- if (__read(pending)) pending.delta = n.delta;
- total = n.delta;
- }
- public boolean _read(Node n) {
- if (pending != null) { n.copyFrom(pending); pending = null; return true; }
- boolean ret = __read(n);
- if (ret) total += n.delta;
- return ret;
- }
- public boolean __read(Node n) {
- if (simple) return a.read(n);
- if (upstreamRead(n)) return true;
- while(inner2.read(n));
- if (!a.read(n)) return false;
- n.delta += net - total;
- simple = true;
- return true;
- }
- }
-
- public static class FromXML extends Node.Stream {
- private final XML.Pull xml;
- private XML.Element parent = null;
- private XML.Element e;
- private int currentdelta = 0;
- public FromXML(Reader r) { this.xml = new XML.Pull(r); }
- protected boolean _read(Node n) { try {
- Object ret = xml.read();
- if (ret == null) return false;
- if (ret instanceof String) {
- n.cdata = (String)ret;
- n.delta = xml.level - currentdelta;
- currentdelta = xml.level;
- return true;
- }
- XML.Element e = (XML.Element)ret;
- n.name = e.getLocalName();
- n.uri = e.getUri();
- n.numattrs = e.getAttrLen();
- n.delta = e.level - currentdelta;
- currentdelta = e.level;
- if (n.attrs == null || n.attrs.length < n.numattrs*2) n.attrs = new String[n.numattrs*4];
- for(int i=0; i<n.numattrs; i++) { n.attrs[i*2] = e.getAttrKey(i); n.attrs[i*2+1] = e.getAttrVal(i); }
- return true;
- } catch (Exception e) { throw new RuntimeException(e); } }
- }
-
- public void toXML(Writer writer) throws IOException { Node n = new Node(); if (read(n)) toXML(writer, n); }
- private Node toXML(Writer w, Node n) throws IOException {
- final String name = n.name;
- if (n.cdata != null) {
- w.write(n.cdata);
- if (!read(n)) n = null;
- } else {
- w.write("<");
- w.write(name);
- for(int i=0; i < n.numattrs * 2; i+=2) {
- w.write(" ");
- w.write(n.attrs[i]);
- w.write("=\"");
- w.write(n.attrs[i+1]);
- w.write("\"");
- }
- if (!read(n)) n = null;
- if (n == null || n.delta <= 0) {
- w.write("/>");
- } else {
- w.write(">");
- while(n != null && n.delta > 0) n = toXML(w, n);
- w.write("</");
- w.write(name);
- w.write(">");
- }
- }
- if (n != null) n.delta++;
- return n;
- }
- }
-}
+++ /dev/null
-package org.ibex.xt;
-import org.ibex.js.*;
-import org.ibex.util.*;
-import org.ibex.io.*;
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-public class Template extends Node.Stream.Filter implements Node.Stream.Functor {
-
- static Template newTemplate(Servlet.ServletScope servletscope, JSScope scope, String str) {
- try {
- File f = new File(str);
- if (!f.exists()) f = new File(str + ".xt");
- if (!f.exists()) f = new File(str + ".xml");
- return new Template(servletscope, scope, new InputStreamReader(new FileInputStream(f)));
- } catch (Exception e) { throw new RuntimeException(e); }
- }
-
- static JSScope copyNodeToScope(Node n, JSScope scope) {
- try {
- for(int i=0; i<n.numattrs; i++) {
- scope.declare(n.attrs[i*2]);
- scope.put(n.attrs[i*2], n.attrs[i*2+1]);
- }
- return scope;
- } catch (Exception e) { throw new RuntimeException(e); }
- }
-
- private class JSRewriter extends Node.Stream {
- private Node.Stream in;
- private JSScope scope;
- public JSRewriter(Node.Stream in, JSScope scope) { this.in = in; this.scope = scope; }
- protected boolean _read(Node n) { if (!in.read(n)) return false; transform(n, scope); return true; }
- }
-
- public static Node transform(Node n, JSScope scope) {
- if (n.cdata != null) n.cdata = eval(n.cdata, scope).toString();
- else for(int i=1; i<n.numattrs*2; i+=2) n.attrs[i] = eval(n.attrs[i], scope).toString();
- return n;
- }
-
- private static Object eval(String s, JSScope scope) {
- if (s == null) return null;
- StringBuffer ret = new StringBuffer();
- for(boolean first = true; s.indexOf("${") != -1; first = false) {
- ret.append(s.substring(0, s.indexOf("${")));
- String s2 = s.substring(s.indexOf("${")+2);
- Object app = exec("return (" + s2.substring(0, s2.indexOf('}')) + ");\n", scope);
- s = s.substring(s.indexOf('}') + 1);
- //if (first && s.trim().length() == 0) return app;
- if (!(app == null || app instanceof String || app instanceof Number || app instanceof Boolean))
- throw new RuntimeException("javascripts within ${...} can only return strings, numbers, and booleans; not a " +
- app.getClass().getName());
- ret.append(app == null ? "null" : app.toString());
- }
- ret.append(s);
- return ret.toString();
- }
-
- public static Object exec(String s, JSScope scope) {
- try {
- return JS.eval(JS.cloneWithNewParentScope(JS.fromReader("input", 0, new StringReader(s)), scope));
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
-
- private JSScope scope;
- private Servlet.ServletScope servletscope;
- private Node.Stream children;
- public Node.Stream wrap(Node.Stream children) { this.children = children; return this; }
- public Template(Servlet.ServletScope servletscope, JSScope scope, Reader template) {
- super(new Node.Stream.FromXML(template));
- this.scope = scope;
- this.servletscope = servletscope;
- }
- public boolean _read(Node n) { boolean ret = __read(n); if (ret) transform(n, scope); return ret; }
- public boolean __read(final Node n) {
- if (!upstreamRead(n)) return false;
- if (n.cdata != null) return true;
- final String uri = n.uri;
- final String name = n.name;
- if (uri.indexOf(':') == -1)
- throw new RuntimeException("uri does not contain a colon: " + uri + " (tag name " + name + ")");
- final String method = uri.substring(0, uri.indexOf(':'));
- final String rest = uri.substring(uri.indexOf(':')+1);
- if (uri.equals("http://www.w3.org/1999/xhtml")) { return true;
- } else if (method.equals("webinf")) {
- return graft(newTemplate(servletscope, copyNodeToScope(transform(n, scope), new JSScope(servletscope)),
- servletscope.getRealPath("/") + "/WEB-INF/" + rest + name), n).upstreamRead(n);
- } else if (uri.equals("http://xt.ibex.org/")) {
- //#switch(name)
- case "if":
- transform(n, scope);
- return graft("true".equals(n.attr("if")) ? new DropTag() : new DropAll(), n).upstreamRead(n);
- case "js": return graft(new JsTag(scope), n).upstreamRead(n);
- case "foreach": return graft(new ForEach(n, scope), n).upstreamRead(n);
- case "children":
- if (children == null) return true;
- graft(new Node.Stream.ConstantFunctor(children), n);
- children = null;
- return upstreamRead(n);
- //#end
- return true;
- } else if (method.equals("java")) {
- try { return graft((Node.Stream.Functor)Class.forName(rest).newInstance(), n).upstreamRead(n); }
- catch (Exception e) { throw new RuntimeException(e); }
- }
- throw new RuntimeException("Unknown namespace URI " + uri);
- }
-
- private class ForEach extends Node.Stream.Filter implements Node.Stream.Functor {
- private Node[] nodes = null;
- private Vec array = new Vec();
- private JSScope scope;
- public ForEach(Node n, JSScope s) {
- super(Node.Stream.NULL);
- Vec v = ((JSArray)exec("return (" + n.attr("in").toString() + ");", this.scope = s)).toVec();
- while(true) { Object o = v.pop(); if (o == null) break; array.push(o); }
- }
- public Node.Stream wrap(Node.Stream kids) {
- Vec nodes = new Vec();
- Node n2 = new Node();
- while(kids.read(n2)) nodes.addElement(new Node(n2));
- nodes.copyInto(this.nodes = new Node[nodes.size()]);
- return this;
- }
- protected boolean _read(Node n) {
- if (upstreamRead(n)) return true;
- if (array.size() == 0) return false;
- JSScope scope2 = new JSScope(scope);
- try { scope2.declare("x"); scope2.put("x", array.pop()); } catch (JSExn e) { throw new RuntimeException(e); }
- return graft(new ConstantFunctor(new JSRewriter(new Node.Stream() {
- private int i = 0;
- protected boolean _read(Node n) {
- if (i>=nodes.length) return false;
- n.copyFrom(nodes[i++]);
- return true;
- } }, scope2)), n).upstreamRead(n);
- }
- }
-
- private class DropTag implements Node.Stream.Functor {
- public Node.Stream wrap(Node.Stream kids) {
- return kids;
- } }
-
- private class DropAll implements Node.Stream.Functor {
- public Node.Stream wrap(Node.Stream kids) {
- return new Node.Stream() { public boolean _read(Node n) { return false; } };
- } }
-
- private class JsTag implements Node.Stream.Functor {
- JSScope scope;
- public JsTag(JSScope scope) { this.scope = scope; }
- public Node.Stream wrap(final Node.Stream s) {
- return new Node.Stream() {
- protected boolean _read(Node n) {
- boolean ret = s.read(n);
- if (ret && n.cdata != null) {
- System.err.println("exec("+n.cdata+")");
- exec(n.cdata, scope);
- return _read(n);
- }
- return ret;
- }
- };
- }
- }
-}