From c8f24647121cb45e09430ddbe3d85395403368b8 Mon Sep 17 00:00:00 2001 From: Matti Tahvonen Date: Tue, 5 Jun 2007 11:38:41 +0000 Subject: [PATCH] now from app/UIDL feeds JSON svn changeset:1582/svn branch:trunk --- .../terminal/web/AjaxApplicationManager.java | 149 +-- .../terminal/web/AjaxJsonPaintTarget.java | 993 ++++++++++++++++++ ...intTarget.java => AjaxXmlPaintTarget.java} | 271 +---- .../terminal/web/ApplicationServlet.java | 2 +- 4 files changed, 1130 insertions(+), 285 deletions(-) create mode 100644 src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java rename src/com/itmill/toolkit/terminal/web/{AjaxPaintTarget.java => AjaxXmlPaintTarget.java} (70%) diff --git a/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java b/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java index 298b95d2ca..11b2ea7c16 100644 --- a/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java @@ -54,6 +54,7 @@ import com.itmill.toolkit.Application; import com.itmill.toolkit.Application.WindowAttachEvent; import com.itmill.toolkit.Application.WindowDetachEvent; import com.itmill.toolkit.terminal.DownloadStream; +import com.itmill.toolkit.terminal.PaintTarget; import com.itmill.toolkit.terminal.Paintable; import com.itmill.toolkit.terminal.URIHandler; import com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent; @@ -92,7 +93,7 @@ public class AjaxApplicationManager implements private Set removedWindows = new HashSet(); - private AjaxPaintTarget paintTarget; + private PaintTarget paintTarget; public AjaxApplicationManager(Application application) { this.application = application; @@ -131,6 +132,15 @@ public class AjaxApplicationManager implements application.removeListener((Application.WindowDetachListener) this); } + + public void handleUidlRequest(HttpServletRequest request, + HttpServletResponse response, ThemeSource themeSource) throws IOException { + handleUidlRequest(request, + response, themeSource, false); + + } + + /** * * @param request @@ -141,8 +151,8 @@ public class AjaxApplicationManager implements * if the writing failed due to input/output error. */ public void handleUidlRequest(HttpServletRequest request, - HttpServletResponse response, ThemeSource themeSource) - throws IOException { + HttpServletResponse response, ThemeSource themeSource, boolean isJson) + throws IOException { // repaint requested or sesssion has timed out and new one is created boolean repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null) @@ -191,11 +201,16 @@ public class AjaxApplicationManager implements if (window == null) return; - // Sets the response type - response.setContentType("application/xml; charset=UTF-8"); - - paintTarget = new AjaxPaintTarget(getVariableMap(), this, - out); + if(isJson) { + // Sets the response type + response.setContentType("application/json; charset=UTF-8"); + paintTarget = new AjaxJsonPaintTarget(getVariableMap(), + this, out); + } else { + response.setContentType("application/xml; charset=UTF-8"); + paintTarget = new AjaxXmlPaintTarget(getVariableMap(), + this, out); + } // Render the removed windows Set removed = new HashSet(getRemovedWindows()); @@ -294,11 +309,11 @@ public class AjaxApplicationManager implements paintTarget.addAttribute("pid", pid); // Track paints to identify empty paints - paintTarget.setTrackPaints(true); + ((AjaxPaintTarget) paintTarget).setTrackPaints(true); p.paint(paintTarget); // If no paints add attribute empty - if (paintTarget.getNumberOfPaints() <= 0) { + if (((AjaxPaintTarget) paintTarget).getNumberOfPaints() <= 0) { paintTarget.addAttribute("visible", false); } paintTarget.endTag("change"); @@ -306,64 +321,56 @@ public class AjaxApplicationManager implements } } - // add meta instruction for client to set focus if it is set - Paintable f = (Paintable) application.consumeFocus(); - // .. or initializion (first uidl-request) - boolean init = application.ajaxInit(); - if (init || f != null) { - paintTarget.startTag("meta"); - if (init) - paintTarget.addAttribute("appInit", true); - if (f != null) { - paintTarget.startTag("focus"); - paintTarget.addAttribute("pid", getPaintableId(f)); - paintTarget.endTag("focus"); - } - paintTarget.endTag("meta"); - } - - // Precache custom layouts - // TODO Does not support theme-get param or different themes - // in different windows -> Allways preload layouts with the - // theme specified by the applications - String themeName = application.getTheme() != null ? application - .getTheme() - : ApplicationServlet.DEFAULT_THEME; - // TODO We should only precache the layouts that are not - // cached already - for (Iterator i = paintTarget.preCachedResources.iterator(); i - .hasNext();) { - String resource = (String) i.next(); - InputStream is = null; - try { - is = themeSource.getResource(themeName + "/" - + resource); - } catch (ThemeSource.ThemeException e) { - Log.info(e.getMessage()); - } - if (is != null) { - paintTarget.startTag("precache"); - paintTarget.addAttribute("resource", resource); - StringBuffer layout = new StringBuffer(); - - try { - InputStreamReader r = new InputStreamReader(is); - char[] buffer = new char[20000]; - int charsRead = 0; - while ((charsRead = r.read(buffer)) > 0) - layout.append(buffer, 0, charsRead); - r.close(); - } catch (java.io.IOException e) { - Log.info("Resource transfer failed: " - + request.getRequestURI() + ". (" - + e.getMessage() + ")"); - } - paintTarget.addCharacterData(layout.toString()); - paintTarget.endTag("precache"); - } - } - - paintTarget.close(); + // add meta instruction for client to set focus if it is set + Paintable f = (Paintable) application.consumeFocus(); + // .. or initializion (first uidl-request) + boolean init = application.ajaxInit(); + if(init || f != null) { + paintTarget.startTag("meta"); + if(init) + paintTarget.addAttribute("appInit", true); + if(f != null) { + paintTarget.startTag("focus"); + paintTarget.addAttribute("pid", getPaintableId(f)); + paintTarget.endTag("focus"); + } + paintTarget.endTag("meta"); + } + + // Precache custom layouts + // TODO Does not support theme-get param or different themes in different windows -> Allways preload layouts with the theme specified by the applications + String themeName = application.getTheme() != null ? application.getTheme() : ApplicationServlet.DEFAULT_THEME; + // TODO We should only precache the layouts that are not cached already + for (Iterator i=((AjaxPaintTarget) paintTarget).getPreCachedResources().iterator(); i.hasNext();) { + String resource = (String) i.next(); + InputStream is = null; + try { + is = themeSource.getResource(themeName + "/" + resource); + } catch (ThemeSource.ThemeException e) { + Log.info(e.getMessage()); + } + if (is != null) { + paintTarget.startTag("precache"); + paintTarget.addAttribute("resource", resource); + StringBuffer layout = new StringBuffer(); + + try { + InputStreamReader r = new InputStreamReader(is); + char[] buffer = new char[20000]; + int charsRead = 0; + while ((charsRead = r.read(buffer)) > 0) + layout.append(buffer, 0, charsRead); + r.close(); + } catch (java.io.IOException e) { + Log.info("Resource transfer failed: " + request.getRequestURI() + + ". (" + e.getMessage() + ")"); + } + paintTarget.addCharacterData(layout.toString()); + paintTarget.endTag("precache"); + } + } + + ((AjaxPaintTarget) paintTarget).close(); out.flush(); } else { @@ -591,10 +598,10 @@ public class AjaxApplicationManager implements public synchronized String getPaintableId(Paintable paintable) { String id = (String) paintableIdMap.get(paintable); - if (id == null) - // get PID using growing sequence number + if (id == null) { id = "PID" + Integer.toString(idSequence++); - paintableIdMap.put(paintable, id); + paintableIdMap.put(paintable, id); + } return id; } diff --git a/src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java b/src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java new file mode 100644 index 0000000000..fb0a45f4d0 --- /dev/null +++ b/src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java @@ -0,0 +1,993 @@ +/* ************************************************************************* + + IT Mill Toolkit + + Development of Browser User Interfaces Made Easy + + Copyright (C) 2000-2006 IT Mill Ltd + + ************************************************************************* + + This product is distributed under commercial license that can be found + from the product package on license.pdf. Use of this product might + require purchasing a commercial license from IT Mill Ltd. For guidelines + on usage, see licensing-guidelines.html + + ************************************************************************* + + For more information, contact: + + IT Mill Ltd phone: +358 2 4802 7180 + Ruukinkatu 2-4 fax: +358 2 4802 7181 + 20540, Turku email: info@itmill.com + Finland company www: www.itmill.com + + Primary source for information and releases: www.itmill.com + + ********************************************************************** */ + +package com.itmill.toolkit.terminal.web; + +import com.itmill.toolkit.Application; +import com.itmill.toolkit.terminal.ApplicationResource; +import com.itmill.toolkit.terminal.ExternalResource; +import com.itmill.toolkit.terminal.PaintException; +import com.itmill.toolkit.terminal.PaintTarget; +import com.itmill.toolkit.terminal.Paintable; +import com.itmill.toolkit.terminal.Resource; +import com.itmill.toolkit.terminal.ThemeResource; +import com.itmill.toolkit.terminal.UploadStream; +import com.itmill.toolkit.terminal.VariableOwner; + +import java.io.BufferedWriter; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Set; +import java.util.Stack; +import java.util.Vector; + +/** + * User Interface Description Language Target. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.1 + */ +public class AjaxJsonPaintTarget implements PaintTarget, AjaxPaintTarget { + + /* Document type declarations */ + + private final static String UIDL_ARG_NAME = "name"; + + private final static String UIDL_ARG_VALUE = "value"; + + private final static String UIDL_ARG_ID = "id"; + + private Stack mOpenTags; + + private Stack openJsonTags; + + private boolean mTagArgumentListOpen; + + private PrintWriter uidlBuffer; + + private AjaxVariableMap variableMap; + + private boolean closed = false; + + private AjaxApplicationManager manager; + + private boolean trackPaints = false; + + private int numberOfPaints = 0; + + private int changes = 0; + + Set preCachedResources = new HashSet(); + private boolean customLayoutArgumentsOpen = false; + + private JsonTag tag; + + /** + * Creates a new XMLPrintWriter, without automatic line flushing. + * + * @param variableMap + * @param manager + * @param output + * A character-output stream. + * @throws PaintException + * if the paint operation failed. + */ + public AjaxJsonPaintTarget(AjaxVariableMap variableMap, + AjaxApplicationManager manager, OutputStream output) + throws PaintException { + + this.manager = manager; + // Sets the variable map + this.variableMap = variableMap; + + + // Sets the target for UIDL writing + try { + this.uidlBuffer = new PrintWriter(new BufferedWriter( + new OutputStreamWriter(output, "UTF-8"))); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("Internal error"); + } + + // Initialize tag-writing + mOpenTags = new Stack(); + openJsonTags = new Stack(); + mTagArgumentListOpen = false; + + // Adds document declaration + + // Adds UIDL start tag and its attributes + tag = new JsonTag(); + openJsonTags.push(tag); + append("{"); + + } + + /** + * Method append.This method is thread safe. + * + * @param string + * the text to insert. + */ + private void append(String string) { + uidlBuffer.print(string); + } + + + public void startTag(String tagName) throws PaintException { + startTag(tagName, false); + } + + /** + * Prints the element start tag. + * + *
+	 * Todo:
+	 *  Checking of input values
+	 *  
+	 * 
+ * + * @param tagName + * the name of the start tag. + * @throws PaintException + * if the paint operation failed. + * + */ + public void startTag(String tagName, boolean isChildNode) throws PaintException { + // In case of null data output nothing: + if (tagName == null) + throw new NullPointerException(); + + // Increments paint tracker + if (this.isTrackPaints()) { + this.numberOfPaints++; + } + + // Ensures that the target is open + if (this.closed) + throw new PaintException( + "Attempted to write to a closed PaintTarget."); + + tagName = tag.postfixChildtag(tagName, true); + + // Checks tagName and attributes here + mOpenTags.push(tagName); + openJsonTags.push(tag); + + + if(isChildNode && !tag.childrenArrayOpen) { + append(tag.startField()); + tag.openChildrenArray(); + } + if(!isChildNode && tag.childrenArrayOpen) + tag.closeChildrenArray(); + + append(tag.startField()); + tag = new JsonTag(); + if(isChildNode) { + append("{"); + tag.setChildNode(true); + } else { + // Prints the tag with attributes + append("" + tagName +": {"); + } + + mTagArgumentListOpen = true; + + if ("customlayout".equals(tagName)) + customLayoutArgumentsOpen = true; + } + + /** + * Prints the element end tag. + * + * If the parent tag is closed before every child tag is closed an + * PaintException is raised. + * + * @param tag + * the name of the end tag. + * @throws Paintexception + * if the paint operation failed. + */ + public void endTag(String tagName) throws PaintException { + // In case of null data output nothing: + if (tagName == null) + throw new NullPointerException(); + + // Ensure that the target is open + if (this.closed) + throw new PaintException( + "Attempted to write to a closed PaintTarget."); + + JsonTag parent = (JsonTag) openJsonTags.pop(); + if(parent != null) + tagName = parent.postfixChildtag(tagName, false); + + String lastTag = ""; + + lastTag = (String) mOpenTags.pop(); + if (!tagName.equalsIgnoreCase(lastTag)) + throw new PaintException("Invalid UIDL: wrong ending tag: '" + + tagName + "' expected: '" + lastTag + "'."); + + if(tag.childrenArrayOpen) + tag.closeChildrenArray(); + append(tag.getData()); + append(tag.attributesAsJsonObject()); + append(tag.variablesAsJsonObject()); + // Writes the end (closing) tag + append("}"); + tag = parent; + flush(); + } + + /** + * Substitutes the XML sensitive characters with predefined XML entities. + * + * @param xml + * the String to be substituted. + * @return A new string instance where all occurrences of XML sensitive + * characters are substituted with entities. + */ + static public String escapeXML(String xml) { + if (xml == null || xml.length() <= 0) + return ""; + return escapeXML(new StringBuffer(xml)).toString(); + } + + /** + * Substitutes the XML sensitive characters with predefined XML entities. + * + * @param xml + * the String to be substituted. + * @return A new StringBuffer instance where all occurrences of XML + * sensitive characters are substituted with entities. + * + */ + static public StringBuffer escapeXML(StringBuffer xml) { + if (xml == null || xml.length() <= 0) + return new StringBuffer(""); + + StringBuffer result = new StringBuffer(xml.length() * 2); + + for (int i = 0; i < xml.length(); i++) { + char c = xml.charAt(i); + String s = toXmlChar(c); + if (s != null) { + result.append(s); + } else { + result.append(c); + } + } + return result; + } + + static public String escapeJSON(String s) { + if(s==null) + return ""; + StringBuffer sb=new StringBuffer(); + for(int i=0;i='\u0000' && ch<='\u001F'){ + String ss=Integer.toHexString(ch); + sb.append("\\u"); + for(int k=0;k<4-ss.length();k++){ + sb.append('0'); + } + sb.append(ss.toUpperCase()); + } + else{ + sb.append(ch); + } + } + } + return sb.toString(); + } + + /** + * Substitutes a XML sensitive character with predefined XML entity. + * + * @param c + * the Character to be replaced with an entity. + * @return String of the entity or null if character is not to be replaced + * with an entity. + */ + private static String toXmlChar(char c) { + switch (c) { + case '&': + return "&"; // & => & + case '>': + return ">"; // > => > + case '<': + return "<"; // < => < + case '"': + return """; // " => " + case '\'': + return "'"; // ' => ' + default: + return null; + } + } + + /** + * Prints XML-escaped text. + * + * @param str + * @throws PaintException + * if the paint operation failed. + * + */ + public void addText(String str) throws PaintException { + tag.addData(escapeJSON(str)); + } + + /** + * Adds a boolean attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, boolean value) throws PaintException { + tag.addAttribute( name + ":" + (value ? "true" : "false")); + } + + /** + * Adds a resource attribute to component. Atributes must be added before + * any content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, Resource value) throws PaintException { + + if (value instanceof ExternalResource) { + addAttribute(name, ((ExternalResource) value).getURL()); + + } else if (value instanceof ApplicationResource) { + ApplicationResource r = (ApplicationResource) value; + Application a = r.getApplication(); + if (a == null) + throw new PaintException( + "Application not specified for resorce " + + value.getClass().getName()); + String uri = a.getURL().getPath(); + if (uri.charAt(uri.length() - 1) != '/') + uri += "/"; + uri += a.getRelativeLocation(r); + addAttribute(name, uri); + + } else if (value instanceof ThemeResource) { + String uri = "theme://" + ((ThemeResource) value).getResourceId(); + addAttribute(name, uri); + } else + throw new PaintException("Ajax adapter does not " + + "support resources of type: " + + value.getClass().getName()); + + } + + /** + * Adds a integer attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, int value) throws PaintException { + tag.addAttribute(name + ":" + String.valueOf(value)); + } + + /** + * Adds a long attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, long value) throws PaintException { + tag.addAttribute(name + ":" + String.valueOf(value)); + } + + /** + * Adds a string attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Boolean attribute name. + * @param value + * the Boolean attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, String value) throws PaintException { + // In case of null data output nothing: + if ((value == null) || (name == null)) + throw new NullPointerException( + "Parameters must be non-null strings"); + + + tag.addAttribute( name + ": \"" + escapeJSON(value) + "\""); + + } + + /** + * Adds a string type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, String value) + throws PaintException { + tag.addVariable(new StringVariable(owner,name,value)); + } + + /** + * Adds a int type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, int value) + throws PaintException { + tag.addVariable(new IntVariable(owner,name,value)); + } + + /** + * Adds a boolean type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, boolean value) + throws PaintException { + tag.addVariable(new BooleanVariable(owner,name,value)); + } + + /** + * Adds a string array type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, String[] value) + throws PaintException { + tag.addVariable(new ArrayVariable(owner,name,value)); + } + + /** + * Adds a upload stream type variable. + * + * TODO not converted for JSON + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addUploadStreamVariable(VariableOwner owner, String name) + throws PaintException { + String code = variableMap.registerVariable(name, UploadStream.class, + null, owner); + startTag("uploadstream"); + addAttribute(UIDL_ARG_ID, code); + addAttribute(UIDL_ARG_NAME, name); + endTag("uploadstream"); + } + + /** + * Prints the single text section. + * + * Prints full text section. The section data is escaped from XML tags and + * surrounded by XML start and end-tags. + * + * @param sectionTagName + * the name of the tag. + * @param sectionData + * the section data to be printed. + * @throws PaintException + * if the paint operation failed. + */ + public void addSection(String sectionTagName, String sectionData) + throws PaintException { + startTag(sectionTagName); + addText(sectionData); + endTag(sectionTagName); + } + + /** + * Adds XML directly to UIDL. + * + * @param xml + * the Xml to be added. + * @throws PaintException + * if the paint operation failed. + */ + public void addUIDL(String xml) throws PaintException { + + // Ensure that the target is open + if (this.closed) + throw new PaintException( + "Attempted to write to a closed PaintTarget."); + + // Make sure that the open start tag is closed before + // anything is written. + + // Escape and write what was given + if (xml != null) + tag.addData(xml); + + } + + /** + * Adds XML section with namespace. + * + * @param sectionTagName + * the name of the tag. + * @param sectionData + * the section data. + * @param namespace + * the namespace to be added. + * @throws PaintException + * if the paint operation failed. + * + * @see com.itmill.toolkit.terminal.PaintTarget#addXMLSection(String, + * String, String) + */ + public void addXMLSection(String sectionTagName, String sectionData, + String namespace) throws PaintException { + + // Ensure that the target is open + if (this.closed) + throw new PaintException( + "Attempted to write to a closed PaintTarget."); + + startTag(sectionTagName); + if (namespace != null) + addAttribute("xmlns", namespace); + mTagArgumentListOpen = false; + + if (sectionData != null) + tag.addData(sectionData); + endTag(sectionTagName); + } + + /** + * Gets the UIDL already printed to stream. Paint target must be closed + * before the getUIDL can be called. + * + * @return the UIDL. + */ + public String getUIDL() { + if (this.closed) { + return uidlBuffer.toString(); + } + throw new IllegalStateException( + "Tried to read UIDL from open PaintTarget"); + } + + /** + * Closes the paint target. Paint target must be closed before the + * getUIDL can be called. Subsequent attempts to write to + * paint target. If the target was already closed, call to this function is + * ignored. will generate an exception. + * + * @throws PaintException + * if the paint operation failed. + */ + public void close() throws PaintException { + append("}"); + if (!this.closed) { + flush(); + + // Close all + this.uidlBuffer.close(); + this.closed = true; + } + } + + /** + * Method flush. + */ + private void flush() { + this.uidlBuffer.flush(); + } + + /** + * @see com.itmill.toolkit.terminal.PaintTarget#startTag(com.itmill.toolkit.terminal.Paintable, + * java.lang.String) + */ + public boolean startTag(Paintable paintable, String tagName) + throws PaintException { + startTag(tagName, true); + String id = manager.getPaintableId(paintable); + paintable.addListener(manager); + addAttribute("id", id); + addAttribute("type", tagName); + return false; + } + + /** + * @see com.itmill.toolkit.terminal.PaintTarget#addCharacterData(java.lang.String) + */ + public void addCharacterData(String text) throws PaintException { + if (text != null) + tag.addData(text); + } + + /** + * + * @return + */ + public boolean isTrackPaints() { + return trackPaints; + } + + /** + * Gets the number of paints. + * + * @return the number of paints. + */ + public int getNumberOfPaints() { + return numberOfPaints; + } + + /** + * Sets the tracking to true or false. + * + * This also resets the number of paints. + * + * @param enabled + * is the tracking is enabled or not. + * @see #getNumberOfPaints() + */ + public void setTrackPaints(boolean enabled) { + this.trackPaints = enabled; + this.numberOfPaints = 0; + } + + /** + * This is basically a container for UI components variables, that will be + * added at the end of JSON object. + * @author mattitahvonen + * + */ + class JsonTag { + boolean firstField = true; + + Vector variables = new Vector(); + + Vector attr = new Vector(); + + private HashMap childTagCounters = new HashMap(); + + StringBuffer data = new StringBuffer(); + + public boolean childrenArrayOpen = false; + + private boolean childNode = false; + + public JsonTag() { + + } + + public void openChildrenArray() { + if(!childrenArrayOpen) { + append("children : ["); + childrenArrayOpen = true; + firstField = true; + } + } + + /** + * This is used to prevent possible collapses on tag names + * @param tagName + * @param start + * @return + */ + public String postfixChildtag(String tagName, boolean start) { + TagCounter i = (TagCounter) childTagCounters.get(tagName); + if(i == null) { + i = new TagCounter(); + childTagCounters.put(tagName, i); + } + tagName = i.postfix(tagName); + if(!start) + i.increment(); + return tagName; + } + + public void closeChildrenArray() { + append("]"); + firstField = false; + } + + public void setChildNode(boolean b) { + this.childNode = b; + } + + public boolean isChildNode(){ + return childNode; + } + + public String startField() { + if(firstField) { + firstField = false; + return ""; + } else { + return ","; + } + } + + public void addData(String s) { + data.append(s); + } + + public String getData() { + if(data.length() == 0) + return ""; + return startField() + "data:\"" + escapeJSON(data.toString()) +"\""; + } + + public void addAttribute(String jsonNode) { + attr.add(jsonNode); + } + + public String attributesAsJsonObject() { + if(attr.size() == 0) + return ""; + StringBuffer buf = new StringBuffer(); + buf.append(startField()); + buf.append("attr:{"); + for (Iterator iter = attr.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + buf.append(element); + if(iter.hasNext()) + buf.append(","); + } + buf.append("}"); + return buf.toString(); + } + + public void addVariable(Variable v) { + variables.add(v); + } + + public String variablesAsJsonObject() { + if(variables.size() == 0) + return ""; + StringBuffer buf = new StringBuffer(); + buf.append(startField()); + buf.append("variables:{"); + for (Iterator iter = variables.iterator(); iter.hasNext();) { + Variable element = (Variable) iter.next(); + buf.append(element.getJsonPresentation()); + if(iter.hasNext()) + buf.append(","); + } + buf.append("}"); + return buf.toString(); + } + + class TagCounter { + int count; + public TagCounter() { + count = 0; + } + public void increment() { + count++; + } + public String postfix(String s) { + if(count > 0) { + return s + count; + } + return s; + } + } + } + + abstract class Variable { + String code; + String name; + public abstract String getJsonPresentation(); + } + + class BooleanVariable extends Variable { + boolean value; + + public BooleanVariable(VariableOwner owner, String name, boolean v) { + value = v; + this.name = name; + code = variableMap.registerVariable(name, Boolean.class, + new Boolean(value), owner); + } + + public String getJsonPresentation() { + return name +":{name:\""+name+"\",id:\"" + + code+"\",type:\"boolean\", value : " + + (value == true ? "true}" : "false}"); + } + + } + + class StringVariable extends Variable { + String value; + + public StringVariable(VariableOwner owner, String name, String v) { + value = v; + this.name = name; + code = variableMap.registerVariable(name, String.class, + value, owner); + } + + public String getJsonPresentation() { + return name +":{name:\""+name+"\",id:\"" + + code+"\",type:\"string\", value : \"" + + value + "\"}"; + } + + } + + class IntVariable extends Variable { + int value; + + public IntVariable(VariableOwner owner, String name, int v) { + value = v; + this.name = name; + code = variableMap.registerVariable(name, Boolean.class, + new Integer(value), owner); + } + + public String getJsonPresentation() { + return name +":{name:\""+name+"\",id:\"" + + code+"\",type:\"int\", value : " + + value + "}"; + } + } + + class ArrayVariable extends Variable { + String[] value; + + public ArrayVariable(VariableOwner owner, String name, String[] v) { + value = v; + this.name = name; + code = variableMap.registerVariable(name, String[].class, + value, owner); + } + + public String getJsonPresentation() { + String pres = name +":{name:\""+name+"\",id:\"" + + code+"\",type:\"array\", value : ["; + for (int i = 0; i < value.length;) { + pres += value[i]; + i++; + if(i < value.length) + pres += ","; + } + pres += "]}"; + + return pres; + } + } + + public Set getPreCachedResources() { + return new HashSet(); + } + + public void setPreCachedResources(Set preCachedResources) { + // TODO Auto-generated method stub + + } + + +} diff --git a/src/com/itmill/toolkit/terminal/web/AjaxPaintTarget.java b/src/com/itmill/toolkit/terminal/web/AjaxXmlPaintTarget.java similarity index 70% rename from src/com/itmill/toolkit/terminal/web/AjaxPaintTarget.java rename to src/com/itmill/toolkit/terminal/web/AjaxXmlPaintTarget.java index 70ece88985..26dd13d9e2 100644 --- a/src/com/itmill/toolkit/terminal/web/AjaxPaintTarget.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxXmlPaintTarget.java @@ -56,7 +56,7 @@ import java.util.Stack; * @VERSION@ * @since 3.1 */ -public class AjaxPaintTarget implements PaintTarget { +public class AjaxXmlPaintTarget implements PaintTarget, AjaxPaintTarget { /* Document type declarations */ private final static String UIDL_XML_DECL = ""; @@ -83,7 +83,7 @@ public class AjaxPaintTarget implements PaintTarget { private int numberOfPaints = 0; - Set preCachedResources = new HashSet(); + private Set preCachedResources = new HashSet(); private boolean customLayoutArgumentsOpen = false; /** @@ -96,7 +96,7 @@ public class AjaxPaintTarget implements PaintTarget { * @throws PaintException * if the paint operation failed. */ - public AjaxPaintTarget(AjaxVariableMap variableMap, + public AjaxXmlPaintTarget(AjaxVariableMap variableMap, AjaxApplicationManager manager, OutputStream output) throws PaintException { @@ -147,20 +147,8 @@ public class AjaxPaintTarget implements PaintTarget { uidlBuffer.print(string); } - /** - * Prints the element start tag. - * - *
-	 * Todo:
-	 *  Checking of input values
-	 *  
-	 * 
- * - * @param tagName - * the name of the start tag. - * @throws PaintException - * if the paint operation failed. - * + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#startTag(java.lang.String) */ public void startTag(String tagName) throws PaintException { // In case of null data output nothing: @@ -193,16 +181,8 @@ public class AjaxPaintTarget implements PaintTarget { customLayoutArgumentsOpen = true; } - /** - * Prints the element end tag. - * - * If the parent tag is closed before every child tag is closed an - * PaintException is raised. - * - * @param tag - * the name of the end tag. - * @throws Paintexception - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#endTag(java.lang.String) */ public void endTag(String tagName) throws PaintException { // In case of null data output nothing: @@ -327,44 +307,22 @@ public class AjaxPaintTarget implements PaintTarget { append(str); } - /** - * Prints XML-escaped text. - * - * @param str - * @throws PaintException - * if the paint operation failed. - * + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addText(java.lang.String) */ public void addText(String str) throws PaintException { addUIDL(escapeXML(str)); } - /** - * Adds a boolean attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addAttribute(java.lang.String, boolean) */ public void addAttribute(String name, boolean value) throws PaintException { addAttribute(name, String.valueOf(value)); } - /** - * Adds a resource attribute to component. Atributes must be added before - * any content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addAttribute(java.lang.String, com.itmill.toolkit.terminal.Resource) */ public void addAttribute(String name, Resource value) throws PaintException { @@ -394,49 +352,22 @@ public class AjaxPaintTarget implements PaintTarget { } - /** - * Adds a integer attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addAttribute(java.lang.String, int) */ public void addAttribute(String name, int value) throws PaintException { addAttribute(name, String.valueOf(value)); } - /** - * Adds a long attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addAttribute(java.lang.String, long) */ public void addAttribute(String name, long value) throws PaintException { addAttribute(name, String.valueOf(value)); } - /** - * Adds a string attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Boolean attribute name. - * @param value - * the Boolean attribute value. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addAttribute(java.lang.String, java.lang.String) */ public void addAttribute(String name, String value) throws PaintException { // In case of null data output nothing: @@ -456,21 +387,11 @@ public class AjaxPaintTarget implements PaintTarget { append(" " + name + "=\"" + escapeXML(value) + "\""); if (customLayoutArgumentsOpen && "style".equals(name)) - preCachedResources.add("layout/" + value + ".html"); + getPreCachedResources().add("layout/" + value + ".html"); } - /** - * Adds a string type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addVariable(com.itmill.toolkit.terminal.VariableOwner, java.lang.String, java.lang.String) */ public void addVariable(VariableOwner owner, String name, String value) throws PaintException { @@ -483,18 +404,8 @@ public class AjaxPaintTarget implements PaintTarget { endTag("string"); } - /** - * Adds a int type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addVariable(com.itmill.toolkit.terminal.VariableOwner, java.lang.String, int) */ public void addVariable(VariableOwner owner, String name, int value) throws PaintException { @@ -507,18 +418,8 @@ public class AjaxPaintTarget implements PaintTarget { endTag("integer"); } - /** - * Adds a boolean type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addVariable(com.itmill.toolkit.terminal.VariableOwner, java.lang.String, boolean) */ public void addVariable(VariableOwner owner, String name, boolean value) throws PaintException { @@ -531,18 +432,8 @@ public class AjaxPaintTarget implements PaintTarget { endTag("boolean"); } - /** - * Adds a string array type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addVariable(com.itmill.toolkit.terminal.VariableOwner, java.lang.String, java.lang.String[]) */ public void addVariable(VariableOwner owner, String name, String[] value) throws PaintException { @@ -556,16 +447,8 @@ public class AjaxPaintTarget implements PaintTarget { endTag("array"); } - /** - * Adds a upload stream type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addUploadStreamVariable(com.itmill.toolkit.terminal.VariableOwner, java.lang.String) */ public void addUploadStreamVariable(VariableOwner owner, String name) throws PaintException { @@ -577,18 +460,8 @@ public class AjaxPaintTarget implements PaintTarget { endTag("uploadstream"); } - /** - * Prints the single text section. - * - * Prints full text section. The section data is escaped from XML tags and - * surrounded by XML start and end-tags. - * - * @param sectionTagName - * the name of the tag. - * @param sectionData - * the section data to be printed. - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addSection(java.lang.String, java.lang.String) */ public void addSection(String sectionTagName, String sectionData) throws PaintException { @@ -597,13 +470,8 @@ public class AjaxPaintTarget implements PaintTarget { endTag(sectionTagName); } - /** - * Adds XML directly to UIDL. - * - * @param xml - * the Xml to be added. - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addUIDL(java.lang.String) */ public void addUIDL(String xml) throws PaintException { @@ -622,20 +490,8 @@ public class AjaxPaintTarget implements PaintTarget { } - /** - * Adds XML section with namespace. - * - * @param sectionTagName - * the name of the tag. - * @param sectionData - * the section data. - * @param namespace - * the namespace to be added. - * @throws PaintException - * if the paint operation failed. - * - * @see com.itmill.toolkit.terminal.PaintTarget#addXMLSection(String, - * String, String) + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addXMLSection(java.lang.String, java.lang.String, java.lang.String) */ public void addXMLSection(String sectionTagName, String sectionData, String namespace) throws PaintException { @@ -656,11 +512,8 @@ public class AjaxPaintTarget implements PaintTarget { endTag(sectionTagName); } - /** - * Gets the UIDL already printed to stream. Paint target must be closed - * before the getUIDL can be called. - * - * @return the UIDL. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#getUIDL() */ public String getUIDL() { if (this.closed) { @@ -670,14 +523,8 @@ public class AjaxPaintTarget implements PaintTarget { "Tried to read UIDL from open PaintTarget"); } - /** - * Closes the paint target. Paint target must be closed before the - * getUIDL can be called. Subsequent attempts to write to - * paint target. If the target was already closed, call to this function is - * ignored. will generate an exception. - * - * @throws PaintException - * if the paint operation failed. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#close() */ public void close() throws PaintException { if (!this.closed) { @@ -697,9 +544,8 @@ public class AjaxPaintTarget implements PaintTarget { this.uidlBuffer.flush(); } - /** - * @see com.itmill.toolkit.terminal.PaintTarget#startTag(com.itmill.toolkit.terminal.Paintable, - * java.lang.String) + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#startTag(com.itmill.toolkit.terminal.Paintable, java.lang.String) */ public boolean startTag(Paintable paintable, String tag) throws PaintException { @@ -710,8 +556,8 @@ public class AjaxPaintTarget implements PaintTarget { return false; } - /** - * @see com.itmill.toolkit.terminal.PaintTarget#addCharacterData(java.lang.String) + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#addCharacterData(java.lang.String) */ public void addCharacterData(String text) throws PaintException { ensureClosedTag(); @@ -719,35 +565,34 @@ public class AjaxPaintTarget implements PaintTarget { append(""); } - /** - * - * @return + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#isTrackPaints() */ public boolean isTrackPaints() { return trackPaints; } - /** - * Gets the number of paints. - * - * @return the number of paints. + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#getNumberOfPaints() */ public int getNumberOfPaints() { return numberOfPaints; } - /** - * Sets the tracking to true or false. - * - * This also resets the number of paints. - * - * @param enabled - * is the tracking is enabled or not. - * @see #getNumberOfPaints() + /* (non-Javadoc) + * @see com.itmill.toolkit.terminal.web.AjaxPaintTarget#setTrackPaints(boolean) */ public void setTrackPaints(boolean enabled) { this.trackPaints = enabled; this.numberOfPaints = 0; } + public void setPreCachedResources(Set preCachedResources) { + this.preCachedResources = preCachedResources; + } + + public Set getPreCachedResources() { + return preCachedResources; + } + } diff --git a/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java b/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java index 625684244e..fb7d7399b3 100644 --- a/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java +++ b/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java @@ -566,7 +566,7 @@ public class ApplicationServlet extends HttpServlet implements String resourceId = request.getPathInfo(); if (resourceId != null && resourceId.startsWith(AJAX_UIDL_URI)) { getApplicationManager(application).handleUidlRequest( - request, response, themeSource); + request, response, themeSource, true); return; } -- 2.39.5