Author: rwatler
Date: Wed Dec 16 20:19:02 2009
New Revision: 891414
URL: http://svn.apache.org/viewvc?rev=891414&view=rev
Log:
Jetspeed DynamicPage Support - WebContent Maintenance
-----------------------------------------------------------
- extended WebContentPortlet to support derived implementations with custom
rewriters
- implemented locking on stateful WebContentPortlet rewriter to prevent unsafe
parallel access
- extend rewriter protocols to support url rewriting of tag text
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/WebContentPortlet.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/AbstractRewriter.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/BasicRewriter.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/Rewriter.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RulesetRewriterImpl.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/SwingParserAdaptor.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/neko/CallbackElementRemover.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/xml/SaxParserAdaptor.java
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/WebContentPortlet.java
URL:
http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/WebContentPortlet.java?rev=891414&r1=891413&r2=891414&view=diff
==============================================================================
---
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/WebContentPortlet.java
(original)
+++
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/WebContentPortlet.java
Wed Dec 16 20:19:02 2009
@@ -36,6 +36,8 @@
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
@@ -67,6 +69,7 @@
import
org.apache.portals.applications.webcontent.rewriter.xml.SaxParserAdaptor;
import org.apache.portals.bridges.velocity.GenericVelocityPortlet;
import org.apache.portals.messaging.PortletMessaging;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -102,7 +105,8 @@
protected final static Logger log =
LoggerFactory.getLogger(WebContentPortlet.class);
public final static String defaultEncoding = "UTF-8";
- // Data Members
+ // Data Members
+ private Lock rewriterLock = new ReentrantLock();
private RulesetRewriter rewriter = null;
private RewriterController rewriteController = null;
@@ -181,7 +185,8 @@
}
}
return ; // proceed to doView() with adjusted history
- }
+ }
+
// Check if an action parameter was defined
String webContentURL =
actionRequest.getParameter(WebContentRewriter.ACTION_PARAMETER_URL);
String webContentMethod =
actionRequest.getParameter(WebContentRewriter.ACTION_PARAMETER_METHOD);
@@ -247,38 +252,32 @@
currentPage = new WebContentHistoryPage(sourceURL);
}
- // Initialize the controller if it's not already done
- if (rewriteController == null)
+ byte[] content = null;
+ try
{
- PortletContext portletApplication = getPortletContext();
- String path = portletApplication.getRealPath("/WEB-INF");
- String contextPath = path + "/";
+ // initialize the controller if it's not already done
+ // and lock stateful rewriter
+ initializeRewriter();
+
+ // get content from current page
+ response.setContentType("text/html");
try
{
- // Create rewriter adaptor
- rewriteController = getController(contextPath);
+ content = doWebContent(currentPage.getUrl(),
currentPage.getParams(), currentPage.isPost(), request, response);
}
- catch (Exception e)
+ catch (Throwable t)
{
- response.getWriter().print("<p>WebContentPortlet failed to
create rewriter controller.</p>");
+ PrintWriter writer = response.getWriter();
+ writer.print("Error retrieveing web content:" +
t.getMessage());
return;
}
+ // System.out.println("Rewritten content is\n..."+new
String(content));
}
-
- // get content from current page
- response.setContentType("text/html");
- byte[] content = null;
- try
- {
- content = doWebContent(currentPage.getUrl(),
currentPage.getParams(), currentPage.isPost(), request, response);
- }
- catch (Throwable t)
+ finally
{
- PrintWriter writer = response.getWriter();
- writer.print("Error retrieveing web content:" + t.getMessage());
- return;
+ // unlock stateful rewriter
+ freeRewriter();
}
- // System.out.println("Rewritten content is\n..."+new String(content));
// write the meta-control navigation header
PrintWriter writer = response.getWriter();
@@ -317,8 +316,34 @@
}
/*
- * Privaye helpers for generating WebContent
+ * Protected helpers for generating WebContent
*/
+
+ protected void initializeRewriter() throws PortletException
+ {
+ initializeRewriter(WebContentRewriter.class);
+ }
+
+ protected void initializeRewriter(Class rewriterClass) throws
PortletException
+ {
+ rewriterLock.lock();
+ if (rewriteController == null)
+ {
+ PortletContext portletApplication = getPortletContext();
+ String path = portletApplication.getRealPath("/WEB-INF");
+ String contextPath = path + "/";
+ try
+ {
+ // Create rewriter adaptor
+ rewriteController = getController(contextPath, rewriterClass);
+ }
+ catch (Exception e)
+ {
+ throw new PortletException("WebContentPortlet failed to create
rewriter controller: "+e, e);
+ }
+ }
+ }
+
protected byte[] doWebContent(String sourceAttr, Map sourceParams, boolean
isPost, RenderRequest request, RenderResponse response)
throws PortletException
{
@@ -506,13 +531,10 @@
/*
* Generate a rewrite controller using the basic rules file
*/
- private RewriterController getController(String contextPath) throws
Exception
+ protected RewriterController getController(String contextPath, Class
rewriterClass) throws Exception
{
- Class[] rewriterClasses = new Class[]
- { WebContentRewriter.class, WebContentRewriter.class};
-
- Class[] adaptorClasses = new Class[]
- { NekoParserAdaptor.class, SaxParserAdaptor.class};
+ Class[] rewriterClasses = new Class[] { rewriterClass, rewriterClass};
+ Class[] adaptorClasses = new Class[] { NekoParserAdaptor.class,
SaxParserAdaptor.class};
RewriterController rwc = new MappingRewriterController(contextPath +
"conf/rewriter-rules-mapping.xml", Arrays
.asList(rewriterClasses), Arrays.asList(adaptorClasses));
@@ -523,6 +545,16 @@
rewriter = rwc.createRewriter(ruleset);
return rwc;
}
+
+ protected RulesetRewriter getRewriter()
+ {
+ return rewriter;
+ }
+
+ protected void freeRewriter()
+ {
+ rewriterLock.unlock();
+ }
protected HttpClient getHttpClient(RenderRequest request) throws
IOException
{
@@ -661,7 +693,7 @@
static final int BLOCK_SIZE = 4096;
- private void drain(Reader r, Writer w) throws IOException
+ protected void drain(Reader r, Writer w) throws IOException
{
char[] bytes = new char[BLOCK_SIZE];
try
@@ -683,7 +715,7 @@
}
- private String getContentCharSet(InputStream is) throws IOException
+ protected String getContentCharSet(InputStream is) throws IOException
{
if (!is.markSupported())
{
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/AbstractRewriter.java
URL:
http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/AbstractRewriter.java?rev=891414&r1=891413&r2=891414&view=diff
==============================================================================
---
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/AbstractRewriter.java
(original)
+++
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/AbstractRewriter.java
Wed Dec 16 20:19:02 2009
@@ -123,4 +123,9 @@
public void enterConvertTagEvent(String tag, MutableAttributes attrs)
{
}
+
+ public String enterConvertTextEvent(String tag, String text)
+ {
+ return null;
+ }
}
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/BasicRewriter.java
URL:
http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/BasicRewriter.java?rev=891414&r1=891413&r2=891414&view=diff
==============================================================================
---
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/BasicRewriter.java
(original)
+++
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/BasicRewriter.java
Wed Dec 16 20:19:02 2009
@@ -38,6 +38,19 @@
return getBaseRelativeUrl(url);
}
+ /*
+ * This callback is called by the ParserAdaptor implementation to write
+ * back all rewritten text to point to the proxy server.
+ * Given the original text, rewrites links as a link back to the proxy
server.
+ *
+ * @return the rewritten text that points to the proxy server or null to
leave unchanged.
+ *
+ */
+ public String rewriteText(String tag, String text)
+ {
+ return null;
+ }
+
public boolean shouldRemoveTag(String tag)
{
if (tag.equalsIgnoreCase("html"))
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/Rewriter.java
URL:
http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/Rewriter.java?rev=891414&r1=891413&r2=891414&view=diff
==============================================================================
---
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/Rewriter.java
(original)
+++
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/Rewriter.java
Wed Dec 16 20:19:02 2009
@@ -66,6 +66,16 @@
*/
String rewriteUrl(String url, String tag, String attribute);
+ /**
+ * This event is the inteface between the Rewriter and ParserAdaptor for
rewriting text.
+ * The ParserAdaptor calls back the Rewriter when it finds text that is a
candidate to be
+ * rewritten. The Rewriter rewrites the text and returns it as the result
of this function.
+ *
+ * @param tag The tag being processed
+ * @param text The current text being processsed
+ */
+ String rewriteText(String tag, String text);
+
/**
* Returns true if the tag should be removed, otherwise false.
* Removing a tag only removes the tag but not the contents in
@@ -207,4 +217,11 @@
*/
void enterConvertTagEvent(String tag, MutableAttributes attrs);
+ /**
+ * Rewriter event called back for text conversion by the ParserAdaptor.
+ *
+ * @param tag The name of the tag being processed.
+ * @param text the text to be converted.
+ */
+ String enterConvertTextEvent(String tag, String text);
}
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RulesetRewriterImpl.java
URL:
http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RulesetRewriterImpl.java?rev=891414&r1=891413&r2=891414&view=diff
==============================================================================
---
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RulesetRewriterImpl.java
(original)
+++
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RulesetRewriterImpl.java
Wed Dec 16 20:19:02 2009
@@ -157,4 +157,9 @@
{
return getBaseRelativeUrl(url);
}
+
+ public String enterConvertTextEvent(String tagid, String text)
+ {
+ return rewriteText(tagid, text);
+ }
}
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/SwingParserAdaptor.java
URL:
http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/SwingParserAdaptor.java?rev=891414&r1=891413&r2=891414&view=diff
==============================================================================
---
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/SwingParserAdaptor.java
(original)
+++
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/SwingParserAdaptor.java
Wed Dec 16 20:19:02 2009
@@ -20,6 +20,7 @@
import java.io.Reader;
import java.io.Writer;
import java.util.Enumeration;
+import java.util.Stack;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
@@ -130,6 +131,7 @@
private boolean simpleTag = false;
private String stripTag = null;
private Writer writer = null;
+ private Stack tagStack = new Stack();
private Callback (Writer writer)
{
@@ -160,6 +162,16 @@
return;
}
+ if (!tagStack.isEmpty())
+ {
+ String tag = (String)tagStack.peek();
+ String convertedValues = convertText(tag, new String(values));
+ if (convertedValues != null)
+ {
+ values = convertedValues.toCharArray();
+ }
+ }
+
addToResult(values);
}
@@ -241,6 +253,7 @@
public void handleStartTag(HTML.Tag htmlTag, MutableAttributeSet
attrs, int position)
{
String tag = htmlTag.toString();
+ tagStack.push(tag);
if (false == rewriter.enterStartTagEvent(tag, new
SwingAttributes(attrs)))
{
@@ -293,6 +306,10 @@
public void handleEndTag(HTML.Tag htmlTag, int position)
{
String tag = htmlTag.toString();
+ if (!tagStack.isEmpty() && tag.equals(tagStack.peek()))
+ {
+ tagStack.pop();
+ }
if (false == rewriter.enterEndTagEvent(tag.toString()))
{
return;
@@ -538,7 +555,19 @@
*/
}
+ /*
+ * Determines which HTML Tag/Element is being inspected, and calls the
+ * appropriate converter for that context. This method contains all
the
+ * logic for determining how text is rewritten.
+ *
+ * @param tag TAG from the Callback-Interface.
+ * @param text The text for the current HTML element.
+ */
+ private String convertText(String tag, String text)
+ {
+ return rewriter.enterConvertTextEvent(tag.toString(), text);
+ }
}
}
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/neko/CallbackElementRemover.java
URL:
http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/neko/CallbackElementRemover.java?rev=891414&r1=891413&r2=891414&view=diff
==============================================================================
---
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/neko/CallbackElementRemover.java
(original)
+++
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/html/neko/CallbackElementRemover.java
Wed Dec 16 20:19:02 2009
@@ -16,6 +16,8 @@
*/
package org.apache.portals.applications.webcontent.rewriter.html.neko;
+import java.util.Stack;
+
import org.apache.portals.applications.webcontent.rewriter.Rewriter;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.QName;
@@ -41,6 +43,7 @@
{
private Rewriter rewriter;
+ private Stack tagStack = new Stack();
/**
* Construct with reference to the rewriter context to consult for
rewriting advice
@@ -48,7 +51,6 @@
public CallbackElementRemover( Rewriter rewriter )
{
super();
-
this.rewriter = rewriter;
}
@@ -57,6 +59,26 @@
/**
* <p>
+ * characters
+ * </p>
+ *
+ * @see
org.apache.xerces.xni.XMLDocumentHandler#characters(org.apache.xerces.xni.XMLString
text, org.apache.xerces.xni.Augmentations augs)
+ * @param text
+ * @param augs
+ * @throws org.apache.xerces.xni.XNIException
+ */
+ public void characters(XMLString text,Augmentations augs) throws
XNIException
+ {
+ if (!tagStack.isEmpty())
+ {
+ String tag = (String)tagStack.peek();
+ processText(tag, text);
+ }
+ super.characters(text, augs);
+ }
+
+ /**
+ * <p>
* comment
* </p>
*
@@ -87,7 +109,8 @@
*/
public void emptyElement( QName element, XMLAttributes attrs,
Augmentations arg2 ) throws XNIException
{
- processTag(element,attrs) ;
+ String tag = element.rawname.toLowerCase();
+ processTag(tag,attrs) ;
super.emptyElement(element, attrs, arg2);
}
@@ -106,10 +129,32 @@
*/
public void startElement( QName element, XMLAttributes attrs,
Augmentations arg2 ) throws XNIException
{
- processTag(element,attrs);
+ String tag = element.rawname.toLowerCase();
+ tagStack.push(tag);
+ processTag(tag,attrs);
super.startElement(element, attrs, arg2);
}
+ /**
+ * <p>
+ * endElement
+ * </p>
+ *
+ * @see
org.apache.xerces.xni.XMLDocumentHandler#endElement(org.apache.xerces.xni.QName,
+ * org.apache.xerces.xni.Augmentations)
+ * @param element
+ * @param arg1
+ * @throws org.apache.xerces.xni.XNIException
+ */
+ public void endElement( QName element, Augmentations arg1 ) throws
XNIException
+ {
+ String tag = element.rawname.toLowerCase();
+ if (!tagStack.isEmpty() && tag.equals(tagStack.peek()))
+ {
+ tagStack.pop();
+ }
+ super.endElement(element, arg1);
+ }
// Support Methods
@@ -119,13 +164,13 @@
* </p>
*
* @param tag
+ * @param attrs
*/
- protected void processTag(QName element, XMLAttributes attrs)
+ protected void processTag(String tag, XMLAttributes attrs)
{
- String tag = element.rawname.toLowerCase();
if (fRemovedElements.contains(tag))
{
- // alread removed
+ // already removed
return ;
}
else if (rewriter.shouldStripTag(tag))
@@ -137,7 +182,7 @@
}
else if (rewriter.shouldRemoveTag(tag))
{
- // BOZO - block intentially left EMPTY
+ // BOZO - block intentionally left EMPTY
// first time for this tag...
// remove - no directive necessary, the default behavior of
ElementRemover is to drop tags that it does not know about (but the assocated
text will remain)
@@ -160,4 +205,22 @@
}
return names ;
}
+
+ /**
+ * <p>
+ * processText
+ * </p>
+ *
+ * @param tag
+ * @param text
+ */
+ protected void processText(String tag, XMLString text)
+ {
+ String convertedText = rewriter.enterConvertTextEvent(tag, new
String(text.ch, text.offset, text.length));
+ if (convertedText != null)
+ {
+ char [] convertedTextChars = convertedText.toCharArray();
+ text.setValues(convertedTextChars, 0, convertedTextChars.length);
+ }
+ }
}
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/xml/SaxParserAdaptor.java
URL:
http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/xml/SaxParserAdaptor.java?rev=891414&r1=891413&r2=891414&view=diff
==============================================================================
---
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/xml/SaxParserAdaptor.java
(original)
+++
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/xml/SaxParserAdaptor.java
Wed Dec 16 20:19:02 2009
@@ -24,6 +24,7 @@
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
+import java.util.Stack;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
@@ -106,6 +107,7 @@
private int elementCount = 0;
private boolean emit = true;
private Writer writer = null;
+ private Stack tagStack = new Stack();
public SaxFormatHandler(Writer writer)
{
@@ -128,7 +130,17 @@
return;
if (false == rewriter.enterText(values, start))
- return;
+ return;
+
+ if (!tagStack.isEmpty())
+ {
+ String tag = (String)tagStack.peek();
+ String convertedValues = convertText(tag, new String(values,
start, length));
+ if (convertedValues != null)
+ {
+ values = convertedValues.toCharArray();
+ }
+ }
if (writer != null)
{
@@ -149,6 +161,7 @@
// System.out.println("localName = " + localName);
// System.out.println("uri = " + uri);
String tag = qName;
+ tagStack.push(tag);
if (false == rewriter.enterStartTagEvent(tag.toString(),
attributes))
return;
@@ -173,6 +186,10 @@
throws SAXException
{
String tag = qName;
+ if (!tagStack.isEmpty() && tag.equals(tagStack.peek()))
+ {
+ tagStack.pop();
+ }
elementCount++;
if (false == rewriter.enterEndTagEvent(tag.toString()))
return;
@@ -257,6 +274,20 @@
rewriter.enterConvertTagEvent(tag.toString(), attrs);
}
+ /*
+ * Determines which HTML Tag/Element is being inspected, and calls the
+ * appropriate converter for that context. This method contains all
the
+ * logic for determining how text is rewritten.
+ *
+ * @param tag TAG from the Callback-Interface.
+ * @param text The text for the current HTML element.
+ */
+
+ private String convertText(String tag, String text)
+ {
+ return rewriter.enterConvertTextEvent(tag.toString(), text);
+ }
+
public InputSource resolveEntity (String publicId, String systemId)
{