Author: julien_viet
Date: 2010-10-18 09:40:27 -0400 (Mon, 18 Oct 2010)
New Revision: 4710
Added:
portal/trunk/component/common/src/main/java/org/exoplatform/commons/xml/DOMSerializer.java
portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml/
portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java
Removed:
portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java
Log:
GTNPORTAL-1569 : Performance problem with JSR286 header serialization in portal
Copied:
portal/trunk/component/common/src/main/java/org/exoplatform/commons/xml/DOMSerializer.java
(from rev 4415,
exo/portal/branches/3.1.4-PLF-perf/component/common/src/main/java/org/exoplatform/commons/xml/DOMSerializer.java)
===================================================================
---
portal/trunk/component/common/src/main/java/org/exoplatform/commons/xml/DOMSerializer.java
(rev 0)
+++
portal/trunk/component/common/src/main/java/org/exoplatform/commons/xml/DOMSerializer.java 2010-10-18
13:40:27 UTC (rev 4710)
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.xml;
+
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * An high performance and custom DOM serializer based on stax {@link XMLStreamWriter}.
+ *
+ * <p>The serializer takes care of correctly writing empty script elements with
their non empty form, because we want to ouput
+ * xhtml text that will still work on html browsers.</p>
+ *
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+public class DOMSerializer
+{
+
+ /** . */
+ private static final Logger log = LoggerFactory.getLogger(DOMSerializer.class);
+
+ /** Thread safe. */
+ private static final XMLOutputFactory outputFactory;
+
+ /** . */
+ private static final String DEFAULT_XML_OUTPUT_FACTORY =
"com.sun.xml.internal.stream.XMLOutputFactoryImpl";
+
+ static
+ {
+ XMLOutputFactory tmp;
+ try
+ {
+ tmp = XMLOutputFactory.newFactory(DEFAULT_XML_OUTPUT_FACTORY,
Thread.currentThread().getContextClassLoader());
+ }
+ catch (FactoryConfigurationError error)
+ {
+ tmp = XMLOutputFactory.newFactory();
+ log.warn("Could not use " + DEFAULT_XML_OUTPUT_FACTORY + " will
use default provided by runtime instead " +
+ tmp.getClass().getName());
+ }
+
+ //
+ outputFactory = tmp;
+ }
+
+ public static void serialize(Element element, Writer writer) throws IOException,
XMLStreamException
+ {
+ XMLStreamWriter xml = outputFactory.createXMLStreamWriter(writer);
+ serialize(element, xml);
+ xml.writeEndDocument();
+ xml.flush();
+ }
+
+ private static void serialize(Element element, XMLStreamWriter writer) throws
IOException, XMLStreamException
+ {
+ String tagName = element.getTagName();
+
+ // Determine if empty
+ // Note that we won't accumulate the elements that would be serialized for
performance reason
+ // we will just reiterate later before ending the element
+ boolean empty;
+ if (tagName.equalsIgnoreCase("script"))
+ {
+ empty = false;
+ }
+ else
+ {
+ empty = true;
+ NodeList children = element.getChildNodes();
+ int length = children.getLength();
+ for (int i = 0;i < length && empty;i++)
+ {
+ Node child = children.item(i);
+ if (child instanceof CharacterData)
+ {
+ empty = false;
+ }
+ else if (child instanceof Element)
+ {
+ empty = false;
+ }
+ }
+ }
+
+ //
+ if (empty)
+ {
+ writer.writeEmptyElement(tagName);
+ }
+ else
+ {
+ writer.writeStartElement(tagName);
+ }
+
+ // Write attributes
+ if (element.hasAttributes())
+ {
+ NamedNodeMap attrs = element.getAttributes();
+ int length = attrs.getLength();
+ for (int i = 0;i < length;i++)
+ {
+ Attr attr = (Attr)attrs.item(i);
+ writer.writeAttribute(attr.getName(), attr.getValue());
+ }
+ }
+
+ //
+ if (!empty)
+ {
+ // Serialize children that are worth to be
+ NodeList children = element.getChildNodes();
+ int length = children.getLength();
+ for (int i = 0;i < length;i++)
+ {
+ Node child = children.item(i);
+ if (child instanceof CharacterData)
+ {
+ writer.writeCData(((CharacterData)child).getData());
+ }
+ else if (child instanceof Element)
+ {
+ serialize((Element)child, writer);
+ }
+ }
+
+ // Close
+ writer.writeEndElement();
+ }
+ }
+}
Copied: portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml (from rev
4415,
exo/portal/branches/3.1.4-PLF-perf/component/common/src/test/java/org/exoplatform/commons/xml)
Deleted:
portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java
===================================================================
---
exo/portal/branches/3.1.4-PLF-perf/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java 2010-09-28
21:58:33 UTC (rev 4415)
+++
portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java 2010-10-18
13:40:27 UTC (rev 4710)
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010 eXo Platform SAS.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-
-package org.exoplatform.commons.xml;
-
-import junit.framework.TestCase;
-import org.w3c.dom.Element;
-import org.xml.sax.InputSource;
-
-import javax.xml.parsers.DocumentBuilderFactory;
-import java.io.StringReader;
-import java.io.StringWriter;
-
-/**
- * @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
- * @version $Revision$
- */
-public class TestDOMSerializer extends TestCase
-{
-
- @Override
- protected void setUp() throws Exception
- {
- }
-
- public void testScriptNoAttributes() throws Exception
- {
- assertSerialization("<script></script>",
"<script/>");
- }
-
- public void testScriptWithAttribute() throws Exception
- {
- assertSerialization("<script
type=\"text/javascript\"></script>", "<script
type='text/javascript'/>");
- }
-
- public void testMetaNoAttributes() throws Exception
- {
- assertSerialization("<meta/>", "<meta/>");
- }
-
- public void testMetaWithAttribute() throws Exception
- {
- assertSerialization("<meta
http-equiv=\"Content-Type\"/>", "<meta
http-equiv='Content-Type'></meta>");
- }
-
- private void assertSerialization(String expectedMarkup, String markup) throws
Exception
- {
- Element elt = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new
InputSource(new StringReader(markup))).getDocumentElement();
- StringWriter writer = new StringWriter();
- DOMSerializer.serialize(elt, writer);
- assertEquals(expectedMarkup, writer.toString());
- }
-}
Copied:
portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java
(from rev 4415,
exo/portal/branches/3.1.4-PLF-perf/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java)
===================================================================
---
portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java
(rev 0)
+++
portal/trunk/component/common/src/test/java/org/exoplatform/commons/xml/TestDOMSerializer.java 2010-10-18
13:40:27 UTC (rev 4710)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.exoplatform.commons.xml;
+
+import junit.framework.TestCase;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+public class TestDOMSerializer extends TestCase
+{
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ }
+
+ public void testScriptNoAttributes() throws Exception
+ {
+ assertSerialization("<script></script>",
"<script/>");
+ }
+
+ public void testScriptWithAttribute() throws Exception
+ {
+ assertSerialization("<script
type=\"text/javascript\"></script>", "<script
type='text/javascript'/>");
+ }
+
+ public void testMetaNoAttributes() throws Exception
+ {
+ assertSerialization("<meta/>", "<meta/>");
+ }
+
+ public void testMetaWithAttribute() throws Exception
+ {
+ assertSerialization("<meta
http-equiv=\"Content-Type\"/>", "<meta
http-equiv='Content-Type'></meta>");
+ }
+
+ private void assertSerialization(String expectedMarkup, String markup) throws
Exception
+ {
+ Element elt = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new
InputSource(new StringReader(markup))).getDocumentElement();
+ StringWriter writer = new StringWriter();
+ DOMSerializer.serialize(elt, writer);
+ assertEquals(expectedMarkup, writer.toString());
+ }
+}
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java 2010-10-18
12:09:28 UTC (rev 4709)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java 2010-10-18
13:40:27 UTC (rev 4710)
@@ -22,6 +22,7 @@
import org.exoplatform.Constants;
import org.exoplatform.commons.utils.ExpressionUtil;
import org.exoplatform.commons.utils.PortalPrinter;
+import org.exoplatform.commons.xml.DOMSerializer;
import org.exoplatform.container.ExoContainer;
import org.exoplatform.portal.config.UserPortalConfigService;
import org.exoplatform.portal.config.model.Page;
@@ -40,19 +41,12 @@
import org.gatein.common.http.QueryStringParser;
import org.w3c.dom.Element;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLDecoder;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -432,35 +426,16 @@
public List<String> getExtraMarkupHeadersAsStrings() throws Exception
{
List<String> markupHeaders = new ArrayList<String>();
-
if (extraMarkupHeaders != null && !extraMarkupHeaders.isEmpty())
{
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,
"yes");
-
+ StringWriter sw = new StringWriter();
for (Element element : extraMarkupHeaders)
{
- DOMSource source = new DOMSource(element);
- StreamResult result = new StreamResult(new StringWriter());
-
- // we want to ouput xhtml text that will still work on html browsers.
- // In order to do this we need to have the script tag be not self closing
- // which it will try and do with the xml or xhtml method. If we just use
- // the html method then the other tags will not be closed.
- if (element.getNodeName().equalsIgnoreCase("script"))
- {
- transformer.setOutputProperty(OutputKeys.METHOD, "html");
- }
- else
- {
- transformer.setOutputProperty(OutputKeys.METHOD, "xml");
- }
- transformer.transform(source, result);
- markupHeaders.add(result.getWriter().toString());
+ DOMSerializer.serialize(element, sw);
+ markupHeaders.add(sw.toString());
}
}
-
- return markupHeaders;
+ return markupHeaders;
}
/**