123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668 |
- /* *************************************************************************
-
- IT Mill Toolkit
-
- Development of Browser User Intarfaces 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/license.txt. Use of this product might
- require purchasing a commercial license from IT Mill Ltd. For guidelines
- on usage, see license/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.Stack;
-
- /**
- * User Interface Description Language Target.
- *
- * @author IT Mill Ltd.
- * @version
- * @VERSION@
- * @since 3.1
- */
- public class AjaxPaintTarget implements PaintTarget {
-
- /* Document type declarations */
- private final static String UIDL_XML_DECL = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
-
- 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 boolean mTagArgumentListOpen;
-
- private PrintWriter uidlBuffer;
-
- private AjaxVariableMap variableMap;
-
- private boolean closed = false;
-
- private AjaxApplicationManager manager;
-
- private boolean trackPaints = false;
-
- private int numberOfPaints = 0;
-
- /**
- * Create a new XMLPrintWriter, without automatic line flushing.
- *
- *
- * @param out
- * A character-output stream.
- */
- public AjaxPaintTarget(AjaxVariableMap variableMap, AjaxApplicationManager manager,
- OutputStream output) throws PaintException {
-
- // Set the cache
- this.manager = manager;
-
- // Set the variable map
- this.variableMap = variableMap;
-
- // Set 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();
- mTagArgumentListOpen = false;
-
- //Add document declaration
- this.print(UIDL_XML_DECL + "\n\n");
-
- // Add UIDL start tag and its attributes
- this.startTag("changes");
-
- }
-
- /**
- * Ensures that the currently open element tag is closed.
- */
- private void ensureClosedTag() {
- if (mTagArgumentListOpen) {
- append(">");
- mTagArgumentListOpen = false;
- }
- }
-
- /**
- * Method append.
- *
- * @param string
- */
- private void append(String string) {
- uidlBuffer.print(string);
- }
-
- /**
- * Print element start tag.
- *
- * <pre>
- * Todo:
- * Checking of input values
- *
- * </pre>
- *
- * @param tagName
- * The name of the start tag
- *
- */
- public void startTag(String tagName) throws PaintException {
- // In case of null data output nothing:
- if (tagName == null)
- throw new NullPointerException();
-
- // Incerement paint tracker
- if (this.isTrackPaints()) {
- this.numberOfPaints++;
- }
-
- //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.
- ensureClosedTag();
-
- // Check tagName and attributes here
- mOpenTags.push(tagName);
-
- // Print the tag with attributes
- append("\n<" + tagName);
-
- mTagArgumentListOpen = true;
- }
-
- /**
- * Print 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
- */
- 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.");
-
- String lastTag = "";
-
- lastTag = (String) mOpenTags.pop();
- if (!tagName.equalsIgnoreCase(lastTag))
- throw new PaintException("Invalid UIDL: wrong ending tag: '"
- + tagName + "' expected: '" + lastTag + "'.");
-
- // Make sure that the open start tag is closed before
- // anything is written.
- if (mTagArgumentListOpen) {
- append(">");
- mTagArgumentListOpen = false;
- }
-
- //Write the end (closing) tag
- append("</" + lastTag + ">\n");
- flush();
- }
-
- /**
- * Substitute the XML sensitive characters with predefined XML entities.
- *
- * @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();
- }
-
- /**
- * Substitute 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;
- }
-
- /**
- * Substitute a XML sensitive character with predefined XML entity.
- *
- * @param c
- * 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;
- }
- }
-
- /**
- * Print XML.
- *
- * Writes pre-formatted XML to stream. Well-formness of XML is checked.
- *
- * <pre>
- *
- * TODO: XML checking should be made
- *
- * </pre>
- */
- private void print(String str) {
- // In case of null data output nothing:
- if (str == null)
- return;
-
- // Make sure that the open start tag is closed before
- // anything is written.
- ensureClosedTag();
-
- // Write what was given
- append(str);
- }
-
- /**
- * Print XML-escaped text.
- *
- */
- 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
- * Attribute name
- * @param value
- * Attribute value
- */
- 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
- * Attribute name
- * @param value
- * Attribute value
- */
- 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
- * Attribute name
- * @param value
- * Attribute value
- * @return this object
- */
- 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
- * Attribute name
- * @param value
- * Attribute value
- * @return this object
- */
- 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
- * Boolean attribute name
- * @param value
- * Boolean attribute value
- * @return this object
- */
- 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");
-
- //Ensure that the target is open
- if (this.closed)
- throw new PaintException(
- "Attempted to write to a closed PaintTarget.");
-
- // Check that argument list is writable.
- if (!mTagArgumentListOpen)
- throw new PaintException("XML argument list not open.");
-
- append(" " + name + "=\"" + escapeXML(value) + "\"");
- }
-
- /**
- * Add a string type variable.
- *
- * @param owner
- * Listener for variable changes
- * @param name
- * Variable name
- * @param value
- * Variable initial value
- * @return Reference to this.
- */
- public void addVariable(VariableOwner owner, String name, String value)
- throws PaintException {
- String code = variableMap.registerVariable(name, String.class, value,
- owner);
- startTag("string");
- addAttribute(UIDL_ARG_ID, code);
- addAttribute(UIDL_ARG_NAME, name);
- addText(value);
- endTag("string");
- }
-
- /**
- * Add a int type variable.
- *
- * @param owner
- * Listener for variable changes
- * @param name
- * Variable name
- * @param value
- * Variable initial value
- * @return Reference to this.
- */
- public void addVariable(VariableOwner owner, String name, int value)
- throws PaintException {
- String code = variableMap.registerVariable(name, Integer.class,
- new Integer(value), owner);
- startTag("integer");
- addAttribute(UIDL_ARG_ID, code);
- addAttribute(UIDL_ARG_NAME, name);
- addAttribute(UIDL_ARG_VALUE, String.valueOf(value));
- endTag("integer");
- }
-
- /**
- * Add a boolean type variable.
- *
- * @param owner
- * Listener for variable changes
- * @param name
- * Variable name
- * @param value
- * Variable initial value
- * @return Reference to this.
- */
- public void addVariable(VariableOwner owner, String name, boolean value)
- throws PaintException {
- String code = variableMap.registerVariable(name, Boolean.class,
- new Boolean(value), owner);
- startTag("boolean");
- addAttribute(UIDL_ARG_ID, code);
- addAttribute(UIDL_ARG_NAME, name);
- addAttribute(UIDL_ARG_VALUE, String.valueOf(value));
- endTag("boolean");
- }
-
- /**
- * Add a string array type variable.
- *
- * @param owner
- * Listener for variable changes
- * @param name
- * Variable name
- * @param value
- * Variable initial value
- * @return Reference to this.
- */
- public void addVariable(VariableOwner owner, String name, String[] value)
- throws PaintException {
- String code = variableMap.registerVariable(name, String[].class, value,
- owner);
- startTag("array");
- addAttribute(UIDL_ARG_ID, code);
- addAttribute(UIDL_ARG_NAME, name);
- for (int i = 0; i < value.length; i++)
- addSection("ai", value[i]);
- endTag("array");
- }
-
- /**
- * Add a upload stream type variable.
- *
- * @param owner
- * Listener for variable changes
- * @param name
- * Variable name
- * @param value
- * Variable initial value
- * @return Reference to this.
- */
- 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");
- }
-
- /**
- * Print single text section.
- *
- * Prints full text section. The section data is escaped from XML tags and
- * surrounded by XML start and end-tags.
- */
- public void addSection(String sectionTagName, String sectionData)
- throws PaintException {
- startTag(sectionTagName);
- addText(sectionData);
- endTag(sectionTagName);
- }
-
- /** Add XML dirctly to UIDL */
- 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.
- ensureClosedTag();
-
- // Escape and write what was given
- if (xml != null)
- append(xml);
-
- }
-
- /**
- * Add XML section with namespace
- *
- * @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);
- append(">");
- mTagArgumentListOpen = false;
-
- if (sectionData != null)
- append(sectionData);
- endTag(sectionTagName);
- }
-
- /**
- * Get the UIDL already printed to stream. Paint target must be closed
- * before the getUIDL() cn be called.
- */
- public String getUIDL() {
- if (this.closed) {
- return uidlBuffer.toString();
- }
- throw new IllegalStateException(
- "Tried to read UIDL from open PaintTarget");
- }
-
- /**
- * Close the paint target. Paint target must be closed before the getUIDL()
- * cn 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.
- */
- public void close() throws PaintException {
- if (!this.closed) {
- this.endTag("changes");
- 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 tag)
- throws PaintException {
- startTag(tag);
- String id = manager.getPaintableId(paintable);
- paintable.addListener(manager);
- addAttribute("id", id);
- return false;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.itmill.toolkit.terminal.PaintTarget#addCharacterData(java.lang.String)
- */
- public void addCharacterData(String text) throws PaintException {
- // TODO: This should check the validity of characters
- ensureClosedTag();
- append(escapeXML(text));
- }
-
- public boolean isTrackPaints() {
- return trackPaints;
- }
-
- /** Get number of paints.
- *
- * @return
- */
- public int getNumberOfPaints() {
- return numberOfPaints;
- }
-
- /** Set tracking to true or false.
- *
- * This also resets the number of paints.
- * @param trackPaints
- * @see #getNumberOfPaints()
- */
- public void setTrackPaints(boolean enabled) {
- this.trackPaints = enabled;
- this.numberOfPaints = 0;
- }
-
- }
|