diff --git a/.idea/dictionaries/jhyde.xml b/.idea/dictionaries/jhyde.xml new file mode 100644 index 0000000..613f73d --- /dev/null +++ b/.idea/dictionaries/jhyde.xml @@ -0,0 +1,9 @@ + + + + appendable + escaper + iterables + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__xml_apis_xml_apis_1_0_b2.xml b/.idea/libraries/Maven__xml_apis_xml_apis_1_0_b2.xml new file mode 100644 index 0000000..c36e717 --- /dev/null +++ b/.idea/libraries/Maven__xml_apis_xml_apis_1_0_b2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__xml_apis_xml_apis_2_0_2.xml b/.idea/libraries/Maven__xml_apis_xml_apis_2_0_2.xml deleted file mode 100644 index dcb2e9e..0000000 --- a/.idea/libraries/Maven__xml_apis_xml_apis_2_0_2.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index e1cbc70..79a37df 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -34,35 +34,8 @@ http://www.w3.org/1999/xhtml - + - - - - - - - - - - - - 1.6 - - - - - - - diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..83290e4 --- /dev/null +++ b/NOTICE @@ -0,0 +1,12 @@ +olap4j-xmlaserver + +=============================================================================== +This product includes software from the Mondrian project. + +Copyright (C) 2001-2005 Julian Hyde +Copyright (C) 2005-2012 Pentaho and others + +=============================================================================== +The StringEscaper class comes from the eigenbase-xom project. + +Copyright (C) 2005 Dynamo BI Corporation diff --git a/src/main/java/mondrian/xmla/XmlaConstants.java b/src/main/java/mondrian/xmla/XmlaConstants.java index 298cefe..565ecab 100644 --- a/src/main/java/mondrian/xmla/XmlaConstants.java +++ b/src/main/java/mondrian/xmla/XmlaConstants.java @@ -50,12 +50,12 @@ public interface XmlaConstants { public static final String SOAP_PREFIX = "SOAP-ENV"; - /* + /** * Soap Header mustUnderstand attribute name. */ public static final String SOAP_MUST_UNDERSTAND_ATTR = "mustUnderstand"; - /* + /** * Soap XMLA Header elements and attribute names. */ public static final String XMLA_BEGIN_SESSION = "BeginSession"; @@ -64,9 +64,8 @@ public interface XmlaConstants { public static final String XMLA_SESSION_ID = "SessionId"; public static final String XMLA_SECURITY = "Security"; - /* - * Names of context keys known by both callbacks and Mondrian code. - */ + // Names of context keys known by both callbacks and Mondrian code. + // context key for role name storage public static final String CONTEXT_ROLE_NAME = "role_name"; // context key for language (SOAP or JSON) diff --git a/src/main/java/mondrian/xmla/XmlaRequestCallback.java b/src/main/java/mondrian/xmla/XmlaRequestCallback.java index 756f3e8..9bb7e3b 100644 --- a/src/main/java/mondrian/xmla/XmlaRequestCallback.java +++ b/src/main/java/mondrian/xmla/XmlaRequestCallback.java @@ -40,12 +40,11 @@ public static XmlaException authorizationException(Exception ex) { ex); } - /* - HTTP/1.1 100 Continue - Server: Microsoft-IIS/5.0 - Date: Tue, 21 Feb 2006 21:07:57 GMT - X-Powered-By: ASP.NET - */ + + // HTTP/1.1 100 Continue + // Server: Microsoft-IIS/5.0 + // Date: Tue, 21 Feb 2006 21:07:57 GMT + // X-Powered-By: ASP.NET public static void generatedExpectResponse( HttpServletRequest request, HttpServletResponse response, diff --git a/src/main/java/mondrian/xmla/impl/AuthenticatingXmlaRequestCallback.java b/src/main/java/mondrian/xmla/impl/AuthenticatingXmlaRequestCallback.java index f684c2a..7dcbd70 100644 --- a/src/main/java/mondrian/xmla/impl/AuthenticatingXmlaRequestCallback.java +++ b/src/main/java/mondrian/xmla/impl/AuthenticatingXmlaRequestCallback.java @@ -58,11 +58,9 @@ public void preAction( Map context) throws Exception { - /* - * This is where the magic happens. At this stage, we have - * the username/password known. We will delegate the authentication - * process down to the subclass. - */ + // This is where the magic happens. At this stage, we have + // the username/password known. We will delegate the authentication + // process down to the subclass. final String roleNames = authenticate( (String) context.get(XmlaConstants.CONTEXT_XMLA_USERNAME), diff --git a/src/main/java/mondrian/xmla/impl/DefaultSaxWriter.java b/src/main/java/mondrian/xmla/impl/DefaultSaxWriter.java index 53b0579..73b9942 100644 --- a/src/main/java/mondrian/xmla/impl/DefaultSaxWriter.java +++ b/src/main/java/mondrian/xmla/impl/DefaultSaxWriter.java @@ -11,9 +11,7 @@ import mondrian.xmla.SaxWriter; -import org.olap4j.xmla.server.impl.ArrayStack; -import org.olap4j.xmla.server.impl.Util; -import org.olap4j.xmla.server.impl.XmlUtil; +import org.olap4j.xmla.server.impl.*; import org.xml.sax.Attributes; @@ -36,9 +34,9 @@ public class DefaultSaxWriter implements SaxWriter { /** After a burst of character data. */ private static final int STATE_CHARACTERS = 3; - private final PrintWriter writer; + private final Appendable buf; private int indent; - private String indentStr = " "; + private final String indentStr = " "; private final ArrayStack stack = new ArrayStack(); private int state = STATE_END_ELEMENT; @@ -47,33 +45,32 @@ public class DefaultSaxWriter implements SaxWriter { * Creates a DefaultSaxWriter writing to an {@link java.io.OutputStream}. */ public DefaultSaxWriter(OutputStream stream) { - this(new OutputStreamWriter(stream)); + this(new BufferedWriter(new OutputStreamWriter(stream))); } public DefaultSaxWriter(OutputStream stream, String xmlEncoding) throws UnsupportedEncodingException { - this(new OutputStreamWriter(stream, xmlEncoding)); + this(new BufferedWriter(new OutputStreamWriter(stream, xmlEncoding))); } /** - * Creates a SAXWriter writing to a {@link java.io.Writer}. + * Creates a DefaultSaxWriter without indentation. * - *

If writer is a {@link java.io.PrintWriter}, - * {@link #DefaultSaxWriter(java.io.OutputStream)} is preferred. + * @param buf String builder to write to */ - public DefaultSaxWriter(Writer writer) { - this(new PrintWriter(writer), 0); + public DefaultSaxWriter(Appendable buf) { + this(buf, 0); } /** - * Creates a DefaultSaxWriter writing to a {@link java.io.PrintWriter}. + * Creates a DefaultSaxWriter. * - * @param writer - * @param initialIndent + * @param buf String builder to write to + * @param initialIndent Initial indent (0 to write on single line) */ - public DefaultSaxWriter(PrintWriter writer, int initialIndent) { - this.writer = writer; + public DefaultSaxWriter(Appendable buf, int initialIndent) { + this.buf = buf; this.indent = initialIndent; } @@ -81,84 +78,76 @@ private void _startElement( String namespaceURI, String localName, String qName, - Attributes atts) + Attributes atts) throws IOException { _checkTag(); if (indent > 0) { - writer.println(); + buf.append(Util.nl); } for (int i = 0; i < indent; i++) { - writer.write(indentStr); + buf.append(indentStr); } indent++; - writer.write('<'); - writer.write(qName); - for (int i = 0; i < atts.getLength(); i++) { - XmlUtil.printAtt(writer, atts.getQName(i), atts.getValue(i)); + buf.append('<'); + buf.append(qName); + final int length = atts.getLength(); + for (int i = 0; i < length; i++) { + String val = atts.getValue(i); + if (val != null) { + buf.append(' '); + buf.append(atts.getQName(i)); + buf.append("=\""); + StringEscaper.XML_NUMERIC_ESCAPER.appendEscapedString(val, buf); + buf.append("\""); + } } state = STATE_IN_TAG; + assert qName != null; + stack.add(qName); } - private void _checkTag() { + private void _checkTag() throws IOException { if (state == STATE_IN_TAG) { state = STATE_AFTER_TAG; - writer.print(">"); + buf.append('>'); } } - private void _endElement( - String namespaceURI, - String localName, - String qName) + private void _endElement() throws IOException { + String qName = stack.pop(); indent--; if (state == STATE_IN_TAG) { - writer.write("/>"); + buf.append("/>"); } else { if (state != STATE_CHARACTERS) { - writer.println(); + buf.append(Util.nl); for (int i = 0; i < indent; i++) { - writer.write(indentStr); + buf.append(indentStr); } } - writer.write("'); + buf.append("'); } state = STATE_END_ELEMENT; } - private void _characters(char ch[], int start, int length) { + private void _characters(String s) throws IOException + { _checkTag(); - - // Display the string, quoting in if necessary, - // or using XML escapes as a last result. - String s = new String(ch, start, length); - if (XmlUtil.stringHasXmlSpecials(s)) { - XmlUtil.stringEncodeXml(s, writer); -/* - if (s.indexOf("]]>") < 0) { - writer.print(""); - } else { - XMLUtil.stringEncodeXml(s, writer); - } -*/ - } else { - writer.print(s); - } - + StringEscaper.XML_NUMERIC_ESCAPER.appendEscapedString(s, buf); state = STATE_CHARACTERS; } - // // Simplifying methods public void characters(String s) { - if (s != null && s.length() > 0) { - _characters(s.toCharArray(), 0, s.length()); + try { + _characters(s); + } catch (IOException e) { + throw new RuntimeException("Error while appending XML", e); } } @@ -179,18 +168,24 @@ public void endSequence() { } public final void textElement(String name, Object data) { - startElement(name); - String s = data.toString(); - - // Replace line endings with spaces. IBM's DOM implementation keeps - // line endings, whereas Sun's does not. For consistency, always strip - // them. - // - // REVIEW: It would be better to enclose in CDATA, but some clients - // might not be expecting this. - s = Util.replace(s, Util.nl, " "); - characters(s); - endElement(); + try { + _startElement(null, null, name, EmptyAttributes); + String s = data.toString(); + + // Replace line endings with spaces. IBM's DOM implementation keeps + // line endings, whereas Sun's does not. For consistency, always + // strip them. + // + // REVIEW: It would be better to enclose in CDATA, but some clients + // might not be expecting this. + if (s != null && s.length() > 0) { + s = Util.replace(s, Util.nl, " "); + _characters(s); + } + _endElement(); + } catch (IOException e) { + throw new RuntimeException("Error while appending XML", e); + } } public void element(String tagName, Object... attributes) { @@ -199,19 +194,28 @@ public void element(String tagName, Object... attributes) { } public void startElement(String tagName) { - _startElement(null, null, tagName, EmptyAttributes); - stack.add(tagName); + try { + _startElement(null, null, tagName, EmptyAttributes); + } catch (IOException e) { + throw new RuntimeException("Error while appending XML", e); + } } public void startElement(String tagName, Object... attributes) { - _startElement(null, null, tagName, new StringAttributes(attributes)); - assert tagName != null; - stack.add(tagName); + try { + _startElement( + null, null, tagName, new StringAttributes(attributes)); + } catch (IOException e) { + throw new RuntimeException("Error while appending XML", e); + } } public void endElement() { - String tagName = stack.pop(); - _endElement(null, null, tagName); + try { + _endElement(); + } catch (IOException e) { + throw new RuntimeException("Error while appending XML", e); + } } public void startDocument() { @@ -225,7 +229,7 @@ public void endDocument() { throw new IllegalStateException( "Document may have unbalanced elements"); } - writer.flush(); + flush(); } public void completeBeforeElement(String tagName) { @@ -235,19 +239,32 @@ public void completeBeforeElement(String tagName) { String currentTagName = stack.peek(); while (!tagName.equals(currentTagName)) { - _endElement(null, null, currentTagName); - stack.pop(); + try { + _endElement(); + } catch (IOException e) { + throw new RuntimeException("Error while appending XML", e); + } currentTagName = stack.peek(); } } public void verbatim(String text) { - _checkTag(); - writer.print(text); + try { + _checkTag(); + buf.append(text); + } catch (IOException e) { + throw new RuntimeException("Error while appending XML", e); + } } public void flush() { - writer.flush(); + if (buf instanceof Writer) { + try { + ((Writer) buf).flush(); + } catch (IOException e) { + throw new RuntimeException("Error while flushing XML", e); + } + } } private static final Attributes EmptyAttributes = new Attributes() { diff --git a/src/main/java/mondrian/xmla/impl/DefaultXmlaServlet.java b/src/main/java/mondrian/xmla/impl/DefaultXmlaServlet.java index 07cade1..9a42d60 100644 --- a/src/main/java/mondrian/xmla/impl/DefaultXmlaServlet.java +++ b/src/main/java/mondrian/xmla/impl/DefaultXmlaServlet.java @@ -555,13 +555,11 @@ protected void marshallSoapMessage( break; } - /* - * The setCharacterEncoding, setContentType, or setLocale method - * must be called BEFORE getWriter or getOutputStream and before - * committing the response for the character encoding to be used. - * - * @see javax.servlet.ServletResponse - */ + // The setCharacterEncoding, setContentType, or setLocale method + // must be called BEFORE getWriter or getOutputStream and before + // committing the response for the character encoding to be used. + // + // See javax.servlet.ServletResponse OutputStream outputStream = response.getOutputStream(); diff --git a/src/main/java/org/olap4j/xmla/server/impl/Composite.java b/src/main/java/org/olap4j/xmla/server/impl/Composite.java index 1ecdea0..6616dee 100644 --- a/src/main/java/org/olap4j/xmla/server/impl/Composite.java +++ b/src/main/java/org/olap4j/xmla/server/impl/Composite.java @@ -28,7 +28,7 @@ public abstract class Composite { public static List of( List... lists) { - return CompositeList.of(lists); + return CompositeList.of(lists); } /** @@ -55,19 +55,20 @@ public static Iterable of( public static Iterator of( Iterator... iterators) { - final Iterator[] iterators1 = (Iterator[]) iterators; - return new CompositeIterator(iterators1); + //noinspection unchecked + return new CompositeIterator((Iterator[]) iterators); } private static class CompositeIterable implements Iterable { - private final Iterable[] iterables; + private final Iterable[] iterables; - public CompositeIterable(Iterable[] iterables) { + private CompositeIterable(Iterable[] iterables) { this.iterables = iterables; } public Iterator iterator() { - return new CompositeIterator(iterables); + //noinspection unchecked + return new CompositeIterator(iterables); } } @@ -79,16 +80,14 @@ private static class CompositeIterator implements Iterator { public CompositeIterator(Iterator[] iterables) { this.iteratorIterator = Arrays.asList(iterables).iterator(); - this.iterator = Collections.emptyList().iterator(); + this.iterator = EmptyIterator.instance(); this.hasNext = true; advance(); } - public CompositeIterator(final Iterable[] iterables) { - this.iteratorIterator = - new IterableIterator(iterables); - Arrays.asList(iterables).iterator(); - this.iterator = Collections.emptyList().iterator(); + public CompositeIterator(Iterable[] iterables) { + this.iteratorIterator = new IterableIterator(iterables); + this.iterator = EmptyIterator.instance(); this.hasNext = true; advance(); } @@ -145,6 +144,27 @@ public void remove() { throw new UnsupportedOperationException(); } } + + private static class EmptyIterator implements Iterator { + private static final Iterator INSTANCE = new EmptyIterator(); + + private static Iterator instance() { + //noinspection unchecked + return INSTANCE; + } + + public boolean hasNext() { + return false; + } + + public Object next() { + throw new NoSuchElementException(); + } + + public void remove() { + throw new IllegalStateException(); + } + } } // End Composite.java diff --git a/src/main/java/org/olap4j/xmla/server/impl/StringEscaper.java b/src/main/java/org/olap4j/xmla/server/impl/StringEscaper.java index aec2a87..3b63752 100644 --- a/src/main/java/org/olap4j/xmla/server/impl/StringEscaper.java +++ b/src/main/java/org/olap4j/xmla/server/impl/StringEscaper.java @@ -17,70 +17,85 @@ */ package org.olap4j.xmla.server.impl; +import java.io.IOException; import java.util.*; /** * Utility for replacing special characters * with escape sequences in strings. * - *

Initially, a StringEscaper starts out as - * an identity transform in the "mutable" state. Call defineEscape as many - * times as necessary to set up mappings, and then call makeImmutable() before - * using appendEscapedString to actually apply the defined transform. Or, use - * one of the global mappings pre-defined here.

+ *

To create a StringEscaper, create a builder. + * Initially it is the identity transform (it leaves every character unchanged). + * Call {@link Builder#defineEscape} as many + * times as necessary to set up mappings, and then call {@link Builder#build} + * to create a StringEscaper.

+ * + *

StringEscaper is immutable, but you can call {@link #toBuilder()} to + * get a builder back.

+ * + *

Several escapers are pre-defined:

+ * + *
+ *
{@link #HTML_ESCAPER}
+ *
HTML (using &amp;, &<, etc.)
+ *
{@link #XML_ESCAPER}
+ *
XML (same as HTML escaper)
+ *
{@link #XML_NUMERIC_ESCAPER}
+ *
Uses numeric codes, e.g. &#38; for &.
+ *
{@link #URL_ARG_ESCAPER}
+ *
Converts '?' and '&' in URL arguments into URL format
+ *
{@link #URL_ESCAPER}
+ *
Converts to URL format
+ *
*/ -public class StringEscaper implements Cloneable +public class StringEscaper { - private ArrayList translationVector; - private String [] translationTable; - - public static StringEscaper xmlEscaper; - public static StringEscaper xmlNumericEscaper; - public static StringEscaper htmlEscaper; - public static StringEscaper urlArgEscaper; - public static StringEscaper urlEscaper; - - /** - * Identity transform - */ - public StringEscaper() - { - translationVector = new ArrayList(); - } - - /** - * Map character "from" to escape sequence "to" - */ - public void defineEscape(char from,String to) - { - int i = (int) from; - if (i >= translationVector.size()) { - // Extend list by adding the requisite number of nulls. - final int count = i + 1 - translationVector.size(); - translationVector.addAll( - new AbstractList() { - public Object get(int index) { - return null; - } - - public int size() { - return count; - } - }); - } - translationVector.set(i, to); - } + private final String [] translationTable; + + public static final StringEscaper HTML_ESCAPER = + new Builder() + .defineEscape('&', "&") + .defineEscape('"', """) + .defineEscape('\'', "'") // not "'" + .defineEscape('<', "<") + .defineEscape('>', ">") + .build(); + + public static final StringEscaper XML_ESCAPER = HTML_ESCAPER; + + public static final StringEscaper XML_NUMERIC_ESCAPER = + new Builder() + .defineEscape('&',"&") + .defineEscape('"',""") + .defineEscape('\'',"'") + .defineEscape('<',"<") + .defineEscape('>',">") + .defineEscape('\t'," ") + .defineEscape('\n'," ") + .defineEscape('\r'," ") + .build(); + + public static final StringEscaper URL_ARG_ESCAPER = + new Builder() + .defineEscape('?', "%3f") + .defineEscape('&', "%26") + .build(); + + public static final StringEscaper URL_ESCAPER = + URL_ARG_ESCAPER.toBuilder() + .defineEscape('%', "%%") + .defineEscape('"', "%22") + .defineEscape('\r', "+") + .defineEscape('\n', "+") + .defineEscape(' ', "+") + .defineEscape('#', "%23") + .build(); /** - * Call this before attempting to escape strings; after this, - * defineEscape may not be called again. + * Creates a StringEscaper. Only called from Builder. */ - public void makeImmutable() - { - translationTable = - (String[]) translationVector.toArray( - new String[translationVector.size()]); - translationVector = null; + private StringEscaper(String[] translationTable) { + this.translationTable = translationTable; } /** @@ -88,7 +103,7 @@ public void makeImmutable() */ public String escapeString(String s) { - StringBuffer sb = null; + StringBuilder sb = null; int n = s.length(); for (int i = 0; i < n; i++) { char c = s.charAt(i); @@ -107,7 +122,7 @@ public String escapeString(String s) } } else { if (sb == null) { - sb = new StringBuffer(n * 2); + sb = new StringBuilder(n * 2); sb.append(s.substring(0, i)); } sb.append(escape); @@ -122,7 +137,7 @@ public String escapeString(String s) } /** - * Apply an immutable transformation to the given string, writing the + * Applies an immutable transformation to the given string, writing the * results to a string buffer. */ public void appendEscapedString(String s, StringBuffer sb) @@ -144,68 +159,79 @@ public void appendEscapedString(String s, StringBuffer sb) } } - protected Object clone() + /** + * Applies an immutable transformation to the given string, writing the + * results to an {@link Appendable} (such as a {@link StringBuilder}). + */ + public void appendEscapedString(String s, Appendable sb) throws IOException { - StringEscaper clone = new StringEscaper(); - if (translationVector != null) { - clone.translationVector = new ArrayList(translationVector); - } - if (translationTable != null) { - clone.translationTable = (String[]) translationTable.clone(); + int n = s.length(); + for (int i = 0; i < n; i++) { + char c = s.charAt(i); + String escape; + if (c >= translationTable.length) { + escape = null; + } else { + escape = translationTable[c]; + } + if (escape == null) { + sb.append(c); + } else { + sb.append(escape); + } } - return clone; } /** - * Create a mutable escaper from an existing escaper, which may - * already be immutable. + * Creates a builder from an existing escaper. */ - public StringEscaper getMutableClone() + public Builder toBuilder() { - StringEscaper clone = (StringEscaper) clone(); - if (clone.translationVector == null) { - clone.translationVector = - new ArrayList(Arrays.asList(clone.translationTable)); - clone.translationTable = null; - } - return clone; + return new Builder( + new ArrayList(Arrays.asList(translationTable))); } - static - { - htmlEscaper = new StringEscaper(); - htmlEscaper.defineEscape('&', "&"); - htmlEscaper.defineEscape('"', """); -// htmlEscaper.defineEscape('\'',"'"); - htmlEscaper.defineEscape('\'', "'"); - htmlEscaper.defineEscape('<', "<"); - htmlEscaper.defineEscape('>', ">"); - - xmlNumericEscaper = new StringEscaper(); - xmlNumericEscaper.defineEscape('&',"&"); - xmlNumericEscaper.defineEscape('"',"""); - xmlNumericEscaper.defineEscape('\'',"'"); - xmlNumericEscaper.defineEscape('<',"<"); - xmlNumericEscaper.defineEscape('>',">"); - - urlArgEscaper = new StringEscaper(); - urlArgEscaper.defineEscape('?', "%3f"); - urlArgEscaper.defineEscape('&', "%26"); - urlEscaper = urlArgEscaper.getMutableClone(); - urlEscaper.defineEscape('%', "%%"); - urlEscaper.defineEscape('"', "%22"); - urlEscaper.defineEscape('\r', "+"); - urlEscaper.defineEscape('\n', "+"); - urlEscaper.defineEscape(' ', "+"); - urlEscaper.defineEscape('#', "%23"); - - htmlEscaper.makeImmutable(); - xmlEscaper = htmlEscaper; - xmlNumericEscaper.makeImmutable(); - urlArgEscaper.makeImmutable(); - urlEscaper.makeImmutable(); - } + /** + * Builder for {@link StringEscaper} instances. + */ + public static class Builder { + private final List translationVector; + + public Builder() { + this(new ArrayList()); + } + + private Builder(List translationVector) { + this.translationVector = translationVector; + } + /** + * Creates an escaper with the current state of the translation + * table. + * + * @return A string escaper + */ + public StringEscaper build() { + return new StringEscaper( + translationVector.toArray( + new String[translationVector.size()])); + } + + /** + * Map character "from" to escape sequence "to" + */ + public Builder defineEscape(char from, String to) { + int i = (int) from; + if (i >= translationVector.size()) { + // Extend list by adding the requisite number of nulls. + translationVector.addAll( + Collections.nCopies( + i + 1 - translationVector.size(), null)); + } + translationVector.set(i, to); + return this; + } + } } // End StringEscaper.java diff --git a/src/main/java/org/olap4j/xmla/server/impl/XmlUtil.java b/src/main/java/org/olap4j/xmla/server/impl/XmlUtil.java deleted file mode 100644 index da69430..0000000 --- a/src/main/java/org/olap4j/xmla/server/impl/XmlUtil.java +++ /dev/null @@ -1,106 +0,0 @@ -/* -// Licensed to Julian Hyde under one or more contributor license -// agreements. See the NOTICE file distributed with this work for -// additional information regarding copyright ownership. -// -// Julian Hyde licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -*/ -package org.olap4j.xmla.server.impl; - -import java.io.PrintWriter; - -/** - * XML utilities. - * - * @author jhyde - */ -public abstract class XmlUtil { - private XmlUtil() { - throw new RuntimeException("eek!"); - } - - /** - * Determine if a String contains any XML special characters, return true - * if it does. If this function returns true, the string will need to be - * encoded either using the stringEncodeXml function above or using a - * CDATA section. Note that MSXML has a nasty bug whereby whitespace - * characters outside of a CDATA section are lost when parsing. To - * avoid hitting this bug, this method treats many whitespace characters - * as "special". - * - * @param input the String to scan for XML special characters. - * @return true if the String contains any such characters. - */ - public static boolean stringHasXmlSpecials(String input) { - for (int i = 0; i < input.length(); i++) { - char c = input.charAt(i); - switch (c) { - case '<': - case '>': - case '"': - case '\'': - case '&': - case '\t': - case '\n': - case '\r': - return true; - } - } - return false; - } - - /** - * Encodes a String for XML output, displaying it to a PrintWriter. - * The String to be encoded is displayed, except that - * special characters are converted into entities. - * - * @param input a String to convert. - * @param out a PrintWriter to which to write the results. - */ - public static void stringEncodeXml(String input, PrintWriter out) { - for (int i = 0; i < input.length(); i++) { - char c = input.charAt(i); - switch (c) { - case '<': - case '>': - case '"': - case '\'': - case '&': - case '\t': - case '\n': - case '\r': - out.print("&#" + (int)c + ";"); - break; - default: - out.print(c); - } - } - } - - /** Prints an XML attribute name and value for string val. */ - public static void printAtt(PrintWriter pw, String name, String val) { - if (val != null /* && !val.equals("") */) { - pw.print(" "); - pw.print(name); - pw.print("=\""); - pw.print(escapeForQuoting(val)); - pw.print("\""); - } - } - - private static String escapeForQuoting(String val) { - return StringEscaper.xmlNumericEscaper.escapeString(val); - } -} - -// End XmlUtil.java diff --git a/xmlaserver.iml b/xmlaserver.iml index 05dbd41..bd689a0 100644 --- a/xmlaserver.iml +++ b/xmlaserver.iml @@ -13,7 +13,7 @@ - +