From 15224c4f3f0841f6ac64252c2d6575445e8d61bb Mon Sep 17 00:00:00 2001 From: "Eric J. Bowersox" Date: Tue, 27 Jul 2004 08:54:48 +0000 Subject: [PATCH] added the ability for the HTML checker to recognize "emoticon" character sequences and replace them with special tags, which the post-formatting task will in turn replace with real emoticons (GIFs). --- etc/emoticon.xml | 2 +- etc/venice-config.xml | 6 + .../venice/core/internals/GlobalSiteImpl.java | 172 ++--- .../venice/htmlcheck/HTMLChecker.java | 22 +- .../venice/htmlcheck/MarkupData.java | 66 +- .../venice/htmlcheck/Rewriter.java | 10 +- .../htmlcheck/filters/EmoticonRewriter.java | 89 ++- .../htmlcheck/filters/EmoticonTagHandler.java | 105 +++ .../htmlcheck/impl/HTMLCheckerImpl.java | 616 ++++++++++-------- .../venice/ui/conf/jsp/PostRewriteTag.java | 9 +- .../venice/ui/config/EmoticonManager.java | 76 +++ .../venice/ui/servlet/BaseServlet.java | 6 + .../venice/ui/servlet/RequestImpl.java | 9 +- 13 files changed, 783 insertions(+), 405 deletions(-) create mode 100644 src/com/silverwrist/venice/htmlcheck/filters/EmoticonTagHandler.java diff --git a/etc/emoticon.xml b/etc/emoticon.xml index e23edf2..dc28317 100644 --- a/etc/emoticon.xml +++ b/etc/emoticon.xml @@ -25,7 +25,7 @@ Smile! - :( + emote/ei_frown.gif frown... diff --git a/etc/venice-config.xml b/etc/venice-config.xml index 3b2f45b..9e2e1a3 100644 --- a/etc/venice-config.xml +++ b/etc/venice-config.xml @@ -328,8 +328,10 @@ + + @@ -345,9 +347,11 @@ + + @@ -367,8 +371,10 @@ + + diff --git a/src/com/silverwrist/venice/core/internals/GlobalSiteImpl.java b/src/com/silverwrist/venice/core/internals/GlobalSiteImpl.java index 00f0e1e..8896e57 100644 --- a/src/com/silverwrist/venice/core/internals/GlobalSiteImpl.java +++ b/src/com/silverwrist/venice/core/internals/GlobalSiteImpl.java @@ -65,8 +65,8 @@ public class GlobalSiteImpl implements GlobalSite Runnable task = getNextTaskToRun(quitting); while (task!=null) { // null task indicates we are shutting down - if (my_logger.isDebugEnabled()) - my_logger.debug("Servicing task of class " + task.getClass().getName()); + if (s_thread_logger.isDebugEnabled()) + s_thread_logger.debug("Servicing task of class " + task.getClass().getName()); try { // run the background task @@ -75,7 +75,7 @@ public class GlobalSiteImpl implements GlobalSite } // end try catch (Exception e) { // log the exception and continue - my_logger.error("Background thread caught exception in task",e); + s_thread_logger.error("Background thread caught exception in task",e); } // end catch @@ -92,11 +92,11 @@ public class GlobalSiteImpl implements GlobalSite public void run() { - my_logger.info("Background thread starting"); + s_thread_logger.info("Background thread starting"); doRunLoop(false); - my_logger.info("Background thread quitting"); + s_thread_logger.info("Background thread quitting"); doRunLoop(true); - my_logger.info("Background thread finished"); + s_thread_logger.info("Background thread finished"); } // end run @@ -107,8 +107,8 @@ public class GlobalSiteImpl implements GlobalSite *-------------------------------------------------------------------------------- */ - private static Category logger = Category.getInstance(GlobalSiteImpl.class); - private static Category my_logger = Category.getInstance(BackgroundThread.class); + private static Logger logger = Logger.getLogger(GlobalSiteImpl.class); + private static Logger s_thread_logger = Logger.getLogger(BackgroundThread.class); private static final int NUM_TASK_THREADS = 4; // TODO: make this configurable @@ -117,18 +117,18 @@ public class GlobalSiteImpl implements GlobalSite *-------------------------------------------------------------------------------- */ - private ServiceProvider engine_svc = null; // ServiceProvider for the VeniceEngine + private ServiceProvider m_engine_svc = null; // ServiceProvider for the VeniceEngine private Set m_privileged_addrs = Collections.EMPTY_SET; // privileged addresses - private DataPool datapool = null; // the database pool - private Properties email_props = null; // email properties - private javax.mail.Session mailsession = null; // email session object - private StockMessages stock_messages = null; // stock messages holder - private HashMap html_checkers = new HashMap(); // HTML checkers - private SecurityMonitorEnvironment sm_env; // security monitor environment - private volatile boolean task_running = true; // running tasks flag - private Object task_semaphore = new Object(); // semaphore used for tasks - private LinkedList[] task_queues; // the task queues - private Thread[] task_threads; // the task threads + private DataPool m_datapool = null; // the database pool + private Properties m_email_props = null; // email properties + private javax.mail.Session m_mailsession = null; // email session object + private StockMessages m_stock_messages = null; // stock messages holder + private HashMap m_html_checkers = new HashMap(); // HTML checkers + private SecurityMonitorEnvironment m_sm_env; // security monitor environment + private volatile boolean m_task_running = true; // running tasks flag + private Object m_task_semaphore = new Object(); // semaphore used for tasks + private LinkedList[] m_task_queues; // the task queues + private Thread[] m_task_threads; // the task threads /*-------------------------------------------------------------------------------- * Constructor @@ -138,7 +138,7 @@ public class GlobalSiteImpl implements GlobalSite public GlobalSiteImpl(ServiceProvider engine_svc, Element config, String application_root) throws ConfigException { - this.engine_svc = engine_svc; + m_engine_svc = engine_svc; XMLLoader loader = XMLLoader.get(); // Get the section. @@ -168,7 +168,7 @@ public class GlobalSiteImpl implements GlobalSite try { // allocate the data pool object - datapool = new DataPool(sect); + m_datapool = new DataPool(sect); } // end try catch (SQLException e) @@ -183,31 +183,31 @@ public class GlobalSiteImpl implements GlobalSite sect_h = new DOMElementHelper(sect); // initialize the email properties and get a mail session object - email_props = new Properties(); - email_props.put("mail.transport.protocol","smtp"); - email_props.put("mail.smtp.host",sect_h.getSubElementText("smtp-host")); - email_props.put("mail.from",sect_h.getSubElementText("mail-from-addr")); - email_props.put("com.silverwrist.venice.email.mailer",sect_h.getSubElementText("mailer")); - mailsession = javax.mail.Session.getInstance(email_props,null); + m_email_props = new Properties(); + m_email_props.put("mail.transport.protocol","smtp"); + m_email_props.put("mail.smtp.host",sect_h.getSubElementText("smtp-host")); + m_email_props.put("mail.from",sect_h.getSubElementText("mail-from-addr")); + m_email_props.put("com.silverwrist.venice.email.mailer",sect_h.getSubElementText("mailer")); + m_mailsession = javax.mail.Session.getInstance(m_email_props,null); // Get the section. sect = loader.configGetSubSection(config_h,"messages"); // Initialize the stock messages list. - stock_messages = new StockMessages(sect); + m_stock_messages = new StockMessages(sect); // Initialize the task queues. int i; - task_queues = new LinkedList[TASK_PRIO_MAX + 1]; - for (i=0; i section. sect = loader.configGetSubSection(config_h,"html-checker"); @@ -257,14 +263,14 @@ public class GlobalSiteImpl implements GlobalSite sect = loader.configGetSubSection(config_h,"security"); // Load the security monitors. - sm_env = new SecurityMonitorEnvironment(); + m_sm_env = new SecurityMonitorEnvironment(); nl = sect.getChildNodes(); for (i=0; i=TASK_PRIO_MIN; i--) - if (!(task_queues[i].isEmpty())) // select a task from highest possible priority queue - return (Runnable)(task_queues[i].removeFirst()); + if (!(m_task_queues[i].isEmpty())) // select a task from highest possible priority queue + return (Runnable)(m_task_queues[i].removeFirst()); } // end if else { // work it normally - while (task_running) + while (m_task_running) { // look for a task we can do for (i=TASK_PRIO_MAX; i>=TASK_PRIO_MIN; i--) - if (!(task_queues[i].isEmpty())) // select a task from highest possible priority queue - return (Runnable)(task_queues[i].removeFirst()); + if (!(m_task_queues[i].isEmpty())) // select a task from highest possible priority queue + return (Runnable)(m_task_queues[i].removeFirst()); try { // wait for something to happen - task_semaphore.wait(); + m_task_semaphore.wait(); } // end try catch (InterruptedException e) @@ -525,7 +531,7 @@ public class GlobalSiteImpl implements GlobalSite } // end synchronized block - return null; // if get here, task_running is false and we are quitting + return null; // if get here, m_task_running is false and we are quitting // (or the task queue is empty, if quitting is true) } // end getNextTaskToRun @@ -538,15 +544,15 @@ public class GlobalSiteImpl implements GlobalSite public Object queryService(Class klass) { if (klass==DataPool.class) - return datapool; + return m_datapool; if (klass==MailSend.class) - return new BaseMailSend(this,email_props,mailsession); + return new BaseMailSend(this,m_email_props,m_mailsession); if (klass==SecurityMonitorEnvironment.class) - return sm_env; + return m_sm_env; if (klass==SecurityMonitor.class) - return sm_env.getMonitor("Global"); + return m_sm_env.getMonitor("Global"); if (klass==VeniceEngine.class) - return engine_svc.queryService(klass); + return m_engine_svc.queryService(klass); throw new NoSuchServiceException("GlobalSite",klass); } // end queryService @@ -570,7 +576,7 @@ public class GlobalSiteImpl implements GlobalSite if (klass==HTMLCheckerConfig.class) { // get the HTML Checker config - Object rc = html_checkers.get(serviceid); + Object rc = m_html_checkers.get(serviceid); if (rc==null) throw new NoSuchServiceException("GlobalSite",klass,serviceid); return rc; @@ -579,7 +585,7 @@ public class GlobalSiteImpl implements GlobalSite if (klass==HTMLChecker.class) { // create an HTML Checker using the specified HTML Checker config - HTMLCheckerConfig fact = (HTMLCheckerConfig)(html_checkers.get(serviceid)); + HTMLCheckerConfig fact = (HTMLCheckerConfig)(m_html_checkers.get(serviceid)); if (fact==null) throw new NoSuchServiceException("GlobalSite",klass,serviceid); return fact.createHTMLChecker(); @@ -588,7 +594,7 @@ public class GlobalSiteImpl implements GlobalSite if (klass==SecurityMonitor.class) { // get a security monitor from the environment - SecurityMonitor rc = sm_env.getMonitor(serviceid); + SecurityMonitor rc = m_sm_env.getMonitor(serviceid); if (rc==null) throw new NoSuchServiceException("GlobalSite",klass,serviceid); return rc; @@ -613,13 +619,13 @@ public class GlobalSiteImpl implements GlobalSite public Connection getConnection(String db_selector) throws SQLException { // db_selector is ignored for now - return datapool.getConnection(); + return m_datapool.getConnection(); } // end getConnection public String getStockMessage(String key) { - return stock_messages.get(key); + return m_stock_messages.get(key); } // end getStockMessage @@ -632,13 +638,13 @@ public class GlobalSiteImpl implements GlobalSite if (task instanceof AcceptGlobalSite) ((AcceptGlobalSite)task).setGlobalSite(this); - synchronized (task_semaphore) + synchronized (m_task_semaphore) { // make sure we are running // If the running flag is off, only the background tasks themselves may queue new tasks. - if (task_running || Thread.currentThread().getName().startsWith("GlobalSite_bkgd")); + if (m_task_running || Thread.currentThread().getName().startsWith("GlobalSite_bkgd")); { // add the task to a queue and notify a thread to take it - task_queues[priority].addLast(task); - task_semaphore.notify(); + m_task_queues[priority].addLast(task); + m_task_semaphore.notify(); } // end if @@ -659,20 +665,20 @@ public class GlobalSiteImpl implements GlobalSite public void shutdown() { - synchronized (task_semaphore) + synchronized (m_task_semaphore) { // notify the task threads that we're quitting - task_running = false; - task_semaphore.notifyAll(); + m_task_running = false; + m_task_semaphore.notifyAll(); } // end synchronized block int i = 0; - while (i, + * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -19,22 +19,22 @@ package com.silverwrist.venice.htmlcheck; public interface HTMLChecker { - public abstract void append(String str) throws AlreadyFinishedException; + public void append(String str) throws AlreadyFinishedException; - public abstract void finish() throws AlreadyFinishedException; + public void finish() throws AlreadyFinishedException; - public abstract void reset(); + public void reset(); - public abstract String getValue() throws NotYetFinishedException; + public String getValue() throws NotYetFinishedException; - public abstract int getLength() throws NotYetFinishedException; + public int getLength() throws NotYetFinishedException; - public abstract int getLines() throws NotYetFinishedException; + public int getLines() throws NotYetFinishedException; - public abstract int getCounter(String name) throws NotYetFinishedException; + public int getCounter(String name) throws NotYetFinishedException; - public abstract Object getContextValue(String name); + public Object getContextValue(String name); - public abstract void setContextValue(String name, Object val); + public void setContextValue(String name, Object val); } // end interface HTMLChecker diff --git a/src/com/silverwrist/venice/htmlcheck/MarkupData.java b/src/com/silverwrist/venice/htmlcheck/MarkupData.java index c6a6376..cac3c09 100644 --- a/src/com/silverwrist/venice/htmlcheck/MarkupData.java +++ b/src/com/silverwrist/venice/htmlcheck/MarkupData.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Community System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -24,20 +24,31 @@ public class MarkupData *-------------------------------------------------------------------------------- */ - private String begin_markup; - private String text; - private String end_markup; + private String m_begin_markup; + private String m_text; + private String m_end_markup; + private boolean m_rescan; /*-------------------------------------------------------------------------------- - * Constructor + * Constructors *-------------------------------------------------------------------------------- */ public MarkupData(String begin_markup, String text, String end_markup) { - this.begin_markup = begin_markup; - this.text = text; - this.end_markup = end_markup; + m_begin_markup = begin_markup; + m_text = text; + m_end_markup = end_markup; + m_rescan = false; + + } // end constructor + + public MarkupData(String begin_markup, String text, String end_markup, boolean rescan) + { + m_begin_markup = begin_markup; + m_text = text; + m_end_markup = end_markup; + m_rescan = rescan; } // end constructor @@ -48,20 +59,51 @@ public class MarkupData public String getBeginMarkup() { - return begin_markup; + return m_begin_markup; } // end getBeginMarkup public String getText() { - return text; + return m_text; } // end getText + public boolean hasText() + { + return (m_text!=null) && (m_text.length()>0); + + } // end hasText + + public int getTextLength() + { + return (m_text==null) ? 0 : m_text.length(); + + } // end getTextLength + public String getEndMarkup() { - return end_markup; + return m_end_markup; } // end getEndMarkup + public String getAll() + { + StringBuffer buf = new StringBuffer(); + if (m_begin_markup!=null) + buf.append(m_begin_markup); + if (m_text!=null) + buf.append(m_text); + if (m_end_markup!=null) + buf.append(m_end_markup); + return buf.toString(); + + } // end getAll + + public boolean getRescan() + { + return m_rescan; + + } // end getRescan + } // end class MarkupData diff --git a/src/com/silverwrist/venice/htmlcheck/Rewriter.java b/src/com/silverwrist/venice/htmlcheck/Rewriter.java index 79ba103..de3c9a7 100644 --- a/src/com/silverwrist/venice/htmlcheck/Rewriter.java +++ b/src/com/silverwrist/venice/htmlcheck/Rewriter.java @@ -7,11 +7,11 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -19,8 +19,8 @@ package com.silverwrist.venice.htmlcheck; public interface Rewriter { - public abstract String getName(); + public String getName(); - public abstract MarkupData rewrite(String data, RewriterServices svc); + public MarkupData rewrite(String data, RewriterServices svc); } // end interface Rewriter diff --git a/src/com/silverwrist/venice/htmlcheck/filters/EmoticonRewriter.java b/src/com/silverwrist/venice/htmlcheck/filters/EmoticonRewriter.java index 132856a..402bcbd 100644 --- a/src/com/silverwrist/venice/htmlcheck/filters/EmoticonRewriter.java +++ b/src/com/silverwrist/venice/htmlcheck/filters/EmoticonRewriter.java @@ -33,25 +33,25 @@ public class EmoticonRewriter implements Rewriter *-------------------------------------------------------------------------------- */ - private String m_prefixchars; + private char[] m_prefixchars; private Map m_patmap; + private int m_minlength; /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ - public EmoticonRewriter(String config_file) throws ConfigException + public EmoticonRewriter(Element root) throws ConfigException { - // Load the configuration file. XMLLoader loader = XMLLoader.get(); - Document config = loader.loadConfigDocument(config_file); - Element root = loader.configGetRootElement(config,"emoticon-config"); // Get the set of prefix characters. - m_prefixchars = loader.configGetSubElementText(root,"prefix-chars"); + String pfxchar = loader.configGetSubElementText(root,"prefix-chars"); + m_prefixchars = pfxchar.toCharArray(); HashMap tmp = new HashMap(); + m_minlength = Integer.MAX_VALUE; // Look for all associated icons. NodeList nl = root.getChildNodes(); @@ -66,13 +66,17 @@ public class EmoticonRewriter implements Rewriter NodeList nl2 = n.getChildNodes(); for (int j=0; j elements - Node n2 = nl2.item(i); + Node n2 = nl2.item(j); if ((n2.getNodeType()==Node.ELEMENT_NODE) && n2.getNodeName().equals("pattern")) { // get the element text DOMElementHelper h = new DOMElementHelper((Element)n2); String pattern = h.getElementText(); - if (m_prefixchars.indexOf(pattern.charAt(0))>=0) + if (pfxchar.indexOf(pattern.charAt(0))>=0) + { // add pattern and recompute minimum length tmp.put(pattern,icon_name); + m_minlength = Math.min(m_minlength,pattern.length()); + + } // end if } // end if // else skip this element @@ -104,7 +108,74 @@ public class EmoticonRewriter implements Rewriter public MarkupData rewrite(String data, RewriterServices svc) { - return null; + int pos = Integer.MAX_VALUE; + for (int i=0; i=0) + pos = Math.min(pos,foo); + + } // end for + + if (pos==Integer.MAX_VALUE) + return null; // none present - we can short-circuit matters + + boolean did_replace = false; + StringBuffer output = new StringBuffer(); + String work = data; + do + { // break off the front part of the string + if (pos>0) + { // append it and make it work + output.append(work.substring(0,pos)); + work = work.substring(pos); + + } // end if + + boolean looking = true; + if (work.length()>=m_minlength) + { // there's a chance we have a pattern + for (Iterator it=m_patmap.entrySet().iterator(); looking && it.hasNext(); ) + { // hunt through all the smiley entries + Map.Entry ntry = (Map.Entry)(it.next()); + String match = ntry.getKey().toString(); + if (work.startsWith(match)) + { // found the right smiley + looking = false; + output.append(""); + work = work.substring(match.length()); + did_replace = true; + + } // end if + + } // end for + + } // end if + + if (looking) + { // no such luck - shift the triggering character over + output.append(work.charAt(0)); + work = work.substring(1); + + } // end if + + // now look for the next triggering character + pos = Integer.MAX_VALUE; + for (int i=0; i=0) + pos = Math.min(pos,foo); + + } // end for + + } while (pos!=Integer.MAX_VALUE); // end do + + if (!did_replace) + return null; // no replacements done, so what's the point? + + output.append(work); // tack this onto the end + return new MarkupData(null,output.toString(),null,true); } // end rewrite diff --git a/src/com/silverwrist/venice/htmlcheck/filters/EmoticonTagHandler.java b/src/com/silverwrist/venice/htmlcheck/filters/EmoticonTagHandler.java new file mode 100644 index 0000000..633edbb --- /dev/null +++ b/src/com/silverwrist/venice/htmlcheck/filters/EmoticonTagHandler.java @@ -0,0 +1,105 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Community System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.htmlcheck.filters; + +import java.util.*; +import org.apache.log4j.*; +import org.apache.regexp.*; +import org.w3c.dom.*; +import com.silverwrist.venice.except.*; +import com.silverwrist.venice.htmlcheck.Rewriter; +import com.silverwrist.venice.htmlcheck.RewriterServices; +import com.silverwrist.venice.htmlcheck.MarkupData; +import com.silverwrist.venice.util.XMLLoader; + +public class EmoticonTagHandler implements Rewriter +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(EmoticonTagHandler.class); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private Set m_valid_icons; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public EmoticonTagHandler(Element root) throws ConfigException + { + XMLLoader loader = XMLLoader.get(); + HashSet tmp = new HashSet(); + + // Look for all associated icons. + NodeList nl = root.getChildNodes(); + for (int i=0; i",null,null); + + } // end rewrite + +} // end class EmoticonTagHandler diff --git a/src/com/silverwrist/venice/htmlcheck/impl/HTMLCheckerImpl.java b/src/com/silverwrist/venice/htmlcheck/impl/HTMLCheckerImpl.java index d763f6f..a2687a9 100644 --- a/src/com/silverwrist/venice/htmlcheck/impl/HTMLCheckerImpl.java +++ b/src/com/silverwrist/venice/htmlcheck/impl/HTMLCheckerImpl.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -30,39 +30,59 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic static class CountingRewriter implements Rewriter { - private Rewriter inner; - private int count = 0; + /*==================================================================== + * Attributes + *==================================================================== + */ + + private Rewriter m_inner; + private int m_count = 0; + + /*==================================================================== + * Constructor + *==================================================================== + */ public CountingRewriter(Rewriter inner) { - this.inner = inner; + m_inner = inner; } // end constructor + /*==================================================================== + * Implementations from interface Rewriter + *==================================================================== + */ + public String getName() { - return inner.getName(); + return m_inner.getName(); } // end getName public MarkupData rewrite(String data, RewriterServices svc) { - MarkupData rc = inner.rewrite(data,svc); - if (rc!=null) - count++; + MarkupData rc = m_inner.rewrite(data,svc); + if ((rc!=null) && !(rc.getRescan())) + m_count++; return rc; } // end rewrite - public int getCount() + /*==================================================================== + * External operations + *==================================================================== + */ + + int getCount() { - return count; + return m_count; } // end getCount - public void reset() + void reset() { - count = 0; + m_count = 0; } // end reset @@ -93,32 +113,32 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic *-------------------------------------------------------------------------------- */ - private static Category logger = Category.getInstance(HTMLCheckerImpl.class); + private static Logger logger = Logger.getLogger(HTMLCheckerImpl.class); /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ - private HTMLCheckerConfigImpl config; // the configuration we're working from - private boolean started = false; // have we started parsing? - private boolean finished = false; // have we finished parsing? - private short state = ST_WHITESPACE; // current parser state - private char quote_char; // quote character to match - private int paren_level = 0; // parenthesization level - private short columns = 0; // current number of columns - private int lines = 0; // current number of lines - private int nobreak_count = 0; // "no-break" count - private boolean trigger_WBR = false; // word break trigger - private StringBuffer output_buffer = null; // output buffer for characters - private StringBuffer temp_buffer = null; // temporary buffer used within one state - private ArrayList tag_stack = null; // stack of tags that have been opened - private HashMap counters = new HashMap(); // the CountingRewriter instances - private ArrayList string_rewriters = new ArrayList(); // string rewriter instances - private ArrayList word_rewriters = new ArrayList(); // word rewriter instances - private ArrayList tag_rewriters = new ArrayList(); // tag rewriter instances - private ArrayList paren_rewriters = new ArrayList(); // paren rewriter instances - private HashMap context_data = new HashMap(); // context variables + private HTMLCheckerConfigImpl m_config; // the configuration we're working from + private boolean m_started = false; // have we started parsing? + private boolean m_finished = false; // have we finished parsing? + private short m_state = ST_WHITESPACE; // current parser state + private char m_quote_char; // quote character to match + private int m_paren_level = 0; // parenthesization level + private short m_columns = 0; // current number of columns + private int m_lines = 0; // current number of lines + private int m_nobreak_count = 0; // "no-break" count + private boolean m_trigger_wbr = false; // word break trigger + private StringBuffer m_output_buffer = null; // output buffer for characters + private StringBuffer m_temp_buffer = null; // temporary buffer used within one state + private ArrayList m_tag_stack = null; // stack of tags that have been opened + private HashMap m_counters = new HashMap(); // the CountingRewriter instances + private ArrayList m_string_rewriters = new ArrayList(); // string rewriter instances + private ArrayList m_word_rewriters = new ArrayList(); // word rewriter instances + private ArrayList m_tag_rewriters = new ArrayList(); // tag rewriter instances + private ArrayList m_paren_rewriters = new ArrayList(); // paren rewriter instances + private HashMap m_context_data = new HashMap(); // context variables /*-------------------------------------------------------------------------------- * Constructor @@ -127,11 +147,11 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic HTMLCheckerImpl(HTMLCheckerConfigImpl config) { - this.config = config; - copyRewriters(string_rewriters,config.getStringRewriters()); - copyRewriters(word_rewriters,config.getWordRewriters()); - copyRewriters(tag_rewriters,config.getTagRewriters()); - copyRewriters(paren_rewriters,config.getParenRewriters()); + this.m_config = config; + copyRewriters(m_string_rewriters,config.getStringRewriters()); + copyRewriters(m_word_rewriters,config.getWordRewriters()); + copyRewriters(m_tag_rewriters,config.getTagRewriters()); + copyRewriters(m_paren_rewriters,config.getParenRewriters()); } // end constructor @@ -198,22 +218,21 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic */ private final void copyRewriters(ArrayList dest, List source) { - Iterator it = source.iterator(); - while (it.hasNext()) + for (Iterator it=source.iterator(); it.hasNext(); ) { // get each rewriter, and wrap it if it has a name Rewriter r = (Rewriter)(it.next()); String name = r.getName(); if (name!=null) { // wrap it in a CountingRewriter and hash it... CountingRewriter cr = new CountingRewriter(r); - counters.put(name,cr); + m_counters.put(name,cr); r = cr; } // end if dest.add(r); - } // end while + } // end for dest.trimToSize(); @@ -221,24 +240,23 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic /** * Use the specified list of rewriters to attempt to rewrite the specified string data. - * The first rewriter in the list that returns a valid MarkupData object takes + * The first rewriter in the list that returns a valid MarkupData object takes * precedence. * * @param rewriters List of rewriters to try against the rewriter data. * @param data String data to attempt to rewrite. - * @return A MarkupData object that contains the marked-up data to output, or - * null if no rewriter handled the data. + * @return A MarkupData object that contains the marked-up data to output, or + * null if no rewriter handled the data. */ private final MarkupData attemptRewrite(List rewriters, String data) { - Iterator it = rewriters.iterator(); MarkupData rc = null; - while ((rc==null) && it.hasNext()) + for (Iterator it=rewriters.iterator(); (rc==null) && it.hasNext(); ) { // look at each rewriter in turn and try seeing if it will mark this text up Rewriter r = (Rewriter)(it.next()); rc = r.rewrite(data,this); - } // end while + } // end for return rc; @@ -249,9 +267,9 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic */ private final void initState() { - output_buffer = new StringBuffer(1024); - temp_buffer = new StringBuffer(64); - tag_stack = new ArrayList(); + m_output_buffer = new StringBuffer(1024); + m_temp_buffer = new StringBuffer(64); + m_tag_stack = new ArrayList(); } // end initState @@ -260,10 +278,10 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic */ private final void killState() { - temp_buffer = null; - if (tag_stack!=null) - tag_stack.clear(); - tag_stack = null; + m_temp_buffer = null; + if (m_tag_stack!=null) + m_tag_stack.clear(); + m_tag_stack = null; } // end killState @@ -280,20 +298,19 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic boolean handled = false; if (filters.size()>0) { // look through all the output filters to see what we can do - Iterator it = filters.iterator(); - while (!handled && it.hasNext()) + for (Iterator it=filters.iterator(); !handled && it.hasNext(); ) { // look for an output filter that matches this character OutputFilter of = (OutputFilter)(it.next()); - handled = of.tryOutputCharacter(output_buffer,ch); + handled = of.tryOutputCharacter(m_output_buffer,ch); - } // end while + } // end for } // end if if (!handled) // output the character - output_buffer.append(ch); - if (count_cols && (config.getWordWrapLength()>0)) - columns++; // adjust column indicator + m_output_buffer.append(ch); + if (count_cols && (m_config.getWordWrapLength()>0)) + m_columns++; // adjust column indicator } // end emitChar @@ -302,18 +319,20 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic * * @param str String to output. * @param filters List of filters to use to attempt to process the string. - * @param count_cols true if the characters output add to the column counter, - * false if not. + * @param count_cols true if the characters output add to the column counter, + * false if not. */ private final void emitString(String str, List filters, boolean count_cols) { - boolean real_count_cols = count_cols && (config.getWordWrapLength()>0); + if (str==null) + return; + boolean real_count_cols = count_cols && (m_config.getWordWrapLength()>0); if (filters.size()==0) { // if there are no filters, just append the entire string directly - output_buffer.append(str); + m_output_buffer.append(str); if (real_count_cols) - columns += (short)(str.length()); + m_columns += (short)(str.length()); return; } // end if @@ -327,9 +346,8 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic // Now look at each of the output filters to see if we should try outputting // a lesser amount (i.e., does the string contain a "stopper" that one of the // output filters would like to mogrify?) - Iterator it = filters.iterator(); OutputFilter stopper = null; - while (it.hasNext() && (output_len>0)) + for (Iterator it = filters.iterator(); it.hasNext() && (output_len>0); ) { // look to find the length of characters that doesn't match this filter OutputFilter of = (OutputFilter)(it.next()); int lnm = of.lengthNoMatch(temp); @@ -340,23 +358,23 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic } // end if - } // end while (looking through filters) + } // end for (all filters) if (output_len>0) { // At least this many unaltered characters can be output, so copy them. - output_buffer.append(temp.substring(0,output_len)); + m_output_buffer.append(temp.substring(0,output_len)); if (real_count_cols) - columns += (short)output_len; + m_columns += (short)output_len; } // end if if (stopper!=null) { // one of the output filters stopped us, so invoke it char tmpch = temp.charAt(output_len++); - if (!(stopper.tryOutputCharacter(output_buffer,tmpch))) - output_buffer.append(tmpch); + if (!(stopper.tryOutputCharacter(m_output_buffer,tmpch))) + m_output_buffer.append(tmpch); if (real_count_cols) - columns++; + m_columns++; } // end if @@ -376,10 +394,10 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic */ private final void emitLineBreak() { - emitString("\r\n",config.getRawOutputFilters(),false); - if (config.getWordWrapLength()>0) - columns = 0; - lines++; + emitString("\r\n",m_config.getRawOutputFilters(),false); + if (m_config.getWordWrapLength()>0) + m_columns = 0; + m_lines++; } // end emitLineBreak @@ -389,7 +407,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic */ private final void emitPossibleLineBreak() { - if ((config.getWordWrapLength()>0) && (nobreak_count<=0) && (columns>=config.getWordWrapLength())) + if ((m_config.getWordWrapLength()>0) && (m_nobreak_count<=0) && (m_columns>=m_config.getWordWrapLength())) emitLineBreak(); } // end emitPossibleLineBreak @@ -402,9 +420,9 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic */ private final void ensureSpaceOnLine(int nchars) { - if ((config.getWordWrapLength()>0) && (nobreak_count<=0)) + if ((m_config.getWordWrapLength()>0) && (m_nobreak_count<=0)) { // line break might be required here - int remain_space = (int)(config.getWordWrapLength() - columns); + int remain_space = (int)(m_config.getWordWrapLength() - m_columns); if (remain_space0) && (nobreak_count<=0)) + if ((m_config.getWordWrapLength()>0) && (m_nobreak_count<=0)) { // adjust output if necessary for word wrapping - int remain_space = (int)(config.getWordWrapLength() - columns); + int remain_space = (int)(m_config.getWordWrapLength() - m_columns); if (remain_space0) - emitString(temp_buffer.substring(0,output_len),config.getOutputFilters(),true); + emitString(m_temp_buffer.substring(0,output_len),m_config.getOutputFilters(),true); // clear out the buffer - temp_buffer.setLength(0); + m_temp_buffer.setLength(0); } // end doFlushWhitespace @@ -470,9 +494,9 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic { //logger.debug("FlushNewLines"); int line_breaks = 0, crs = 0; - for (int i=0; i0) emitLineBreak(); // emit the line breaks - temp_buffer.setLength(0); // clear out the buffer - state = ST_WHITESPACE; + m_temp_buffer.setLength(0); // clear out the buffer + m_state = ST_WHITESPACE; } // end doFlushNewlines @@ -521,25 +545,25 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic if (nchars<=0) return; // can't emit less than 1 character! - if ((config.getWordWrapLength()>0) && (nobreak_count<=0)) + if ((m_config.getWordWrapLength()>0) && (m_nobreak_count<=0)) { // we can output the line break anywhere in the subsequence... while (nchars>0) { // figure out how many characters we can output WITHOUT causing a line break int curlen = nchars; - int remaining_space = (int)(config.getWordWrapLength() - columns); + int remaining_space = (int)(m_config.getWordWrapLength() - m_columns); if (curlen>remaining_space) curlen = remaining_space; // EJB 10/2/2001 - only output if we have something to output (and there is space for it) if (curlen>0) { // output those characters - emitString(temp_buffer.substring(0,curlen),config.getOutputFilters(),true); - temp_buffer.delete(0,curlen); + emitString(m_temp_buffer.substring(0,curlen),m_config.getOutputFilters(),true); + m_temp_buffer.delete(0,curlen); nchars -= curlen; } // end if - if (columns>=config.getWordWrapLength()) // EJB 10/2/2001 - might be greater + if (m_columns>=m_config.getWordWrapLength()) // EJB 10/2/2001 - might be greater emitLineBreak(); // and line break us to get to the next line } // end while @@ -547,34 +571,41 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic } // end if else { // just output the run of characters straight - emitString(temp_buffer.substring(0,nchars),config.getOutputFilters(),true); - temp_buffer.delete(0,nchars); + emitString(m_temp_buffer.substring(0,nchars),m_config.getOutputFilters(),true); + m_temp_buffer.delete(0,nchars); } // end else } // end emitFromStartOfTempBuffer - private final void doFlushString() + private final boolean doFlushString() { - MarkupData md = attemptRewrite(string_rewriters,temp_buffer.toString()); + MarkupData md = attemptRewrite(m_string_rewriters,m_temp_buffer.toString()); if (md!=null) { // we've got something marked up! output it... emitMarkupData(md); - temp_buffer.setLength(0); - return; + m_temp_buffer.setLength(0); + if (md.getRescan()) + { // reparse and flag + parse(md.getAll()); + return true; + + } // end if + + return false; } // end if boolean first = true; - while (temp_buffer.length()>0) + while (m_temp_buffer.length()>0) { // find the length of the initial string of word or non-word characters - int sublen = getRunLength(temp_buffer); + int sublen = getRunLength(m_temp_buffer); - if (isWordChar(temp_buffer.charAt(0))) + if (isWordChar(m_temp_buffer.charAt(0))) { // we need to check the word...but first, we must eliminate leading hyphens and apostrophes int hyph_count = 0; final String hyph_apos = "-\'"; - while ((hyph_count=0)) + while ((hyph_count=0)) hyph_count++; emitFromStartOfTempBuffer(hyph_count); sublen -= hyph_count; @@ -582,7 +613,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic // now determine how many hyphens/apostrophes there are at the end of the word... int word_len = sublen; hyph_count = 0; - while ((word_len>0) && (hyph_apos.indexOf(temp_buffer.charAt(word_len-1))>=0)) + while ((word_len>0) && (hyph_apos.indexOf(m_temp_buffer.charAt(word_len-1))>=0)) { // decrement word length, increment hyphen/apostrophe count hyph_count++; word_len--; @@ -591,17 +622,22 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic if (word_len>0) { // extract the word from the start of the buffer - String word = temp_buffer.substring(0,word_len); - temp_buffer.delete(0,word_len); + String word = m_temp_buffer.substring(0,word_len); + m_temp_buffer.delete(0,word_len); // try to rewrite this word... - md = attemptRewrite(word_rewriters,word); + md = attemptRewrite(m_word_rewriters,word); if (md!=null) + { // emit and/or re-parse emitMarkupData(md); + if (md.getRescan()) + parse(md.getAll()); + + } // end if else { // just output the word normally ensureSpaceOnLine(word.length()); - emitString(word,config.getOutputFilters(),true); + emitString(word,m_config.getOutputFilters(),true); } // end else @@ -613,12 +649,12 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic } // end if else { // just emit this many characters, line-breaking where required - if ((sublen==temp_buffer.length()) && !first && (sublen<=MARGIN_SLOP)) + if ((sublen==m_temp_buffer.length()) && !first && (sublen<=MARGIN_SLOP)) { // This is intended to handle a small run of non-word characters at the end of a string (i.e. // followed by whitespace) that should stay on the same line with its preceding word, to // eliminate "funnies" in punctuation formatting. - emitString(temp_buffer.toString(),config.getOutputFilters(),true); - temp_buffer.setLength(0); + emitString(m_temp_buffer.toString(),m_config.getOutputFilters(),true); + m_temp_buffer.setLength(0); break; } // end if @@ -627,9 +663,9 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic // characters at the START of a word (preceded by whitespace and followed by at least // one word character), then ensure that we can keep that word and its prefixing non-word // characters on the same line (again, avoiding "funnies" in formatting). - if ((sublenTagRepository.getMaxTagLength())) @@ -676,7 +714,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic } // end if // Look up the tag name to get a tag index from the repository. - String poss_tag_name = temp_buffer.substring(start_cmd,end_cmd); + String poss_tag_name = m_temp_buffer.substring(start_cmd,end_cmd); int tag_index = TagRepository.tagNameToIndex(poss_tag_name); if (tag_index<0) { // not a known HTML tag @@ -698,9 +736,9 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic // Get the HTML tag set index for this tag, and see if we allow that set. int tag_set_id = TagRepository.tagIndexToSet(tag_index); - if (!(config.isTagSetAllowed(tag_set_id))) + if (!(m_config.isTagSetAllowed(tag_set_id))) { // the tag is not allowed - either discard it or leave it in verbatim - if (config.getDiscardHTMLTags() || config.getDiscardRejectedHTML()) + if (m_config.getDiscardHTMLTags() || m_config.getDiscardRejectedHTML()) { // throw this tag the hell away! if (logger.isDebugEnabled()) logger.debug("<" + poss_tag_name + "> tag rejected and discarded"); @@ -717,21 +755,21 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic } // end if (tag rejected by HTML rules) - if (!(config.getDiscardHTMLTags()) && tagobj.balanceTags()) + if (!(m_config.getDiscardHTMLTags()) && tagobj.balanceTags()) { // this tag needs to be balanced - here is where we manipulate the stack boolean valid = false; if (closing_tag) { // hunt through the list to find the most recently-opened tag of this type - int i = tag_stack.size(); + int i = m_tag_stack.size(); while ((--i)>=0) { // look through the stack... - Integer foo = (Integer)(tag_stack.get(i)); + Integer foo = (Integer)(m_tag_stack.get(i)); if (foo.intValue()==tag_index) { // found it - remove it from the tag stack if (logger.isDebugEnabled()) logger.debug("balanced closure of <" + poss_tag_name + ">"); - tag_stack.remove(i); + m_tag_stack.remove(i); valid = true; break; @@ -744,7 +782,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic { // push a new opening tag! if (logger.isDebugEnabled()) logger.debug("open form of <" + poss_tag_name + ">"); - tag_stack.add(new Integer(tag_index)); + m_tag_stack.add(new Integer(tag_index)); valid = true; } // end else @@ -761,8 +799,8 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic // else tag doesn't need to be auto-balanced, or is being discarded // Give the tag object one last chance to dictate what we do with the tag. - String real_tag_data = tagobj.rewriteTagContents(temp_buffer.toString(),closing_tag,this); - if ((real_tag_data==null) || config.getDiscardHTMLTags()) + String real_tag_data = tagobj.rewriteTagContents(m_temp_buffer.toString(),closing_tag,this); + if ((real_tag_data==null) || m_config.getDiscardHTMLTags()) { // tag is being erased by rewriter, or is being discarded anyway if (logger.isDebugEnabled()) logger.debug("rewriter erasure or discard of <" + poss_tag_name + ">"); @@ -774,14 +812,14 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic logger.debug("real tag data = [" + real_tag_data + "]"); // Emit the tag to the output. - List filters = config.getRawOutputFilters(); + List filters = m_config.getRawOutputFilters(); emitChar('<',filters,false); emitString(real_tag_data,filters,false); emitChar('>',filters,false); // Determine whether this tag causes a "logical line break." boolean logical_line_break = false; - if (trigger_WBR && !closing_tag && (nobreak_count>0)) + if (m_trigger_wbr && !closing_tag && (m_nobreak_count>0)) { // a word break is a logical line break (but only if within ...) if (logger.isDebugEnabled()) logger.debug("<" + poss_tag_name + "> WORD BREAKS"); @@ -794,7 +832,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic { // logical line break is triggered if (logger.isDebugEnabled()) logger.debug("<" + poss_tag_name + "> triggers logical line break"); - columns = 0; + m_columns = 0; } // end if @@ -810,7 +848,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic */ private final boolean containsHTMLComment() { - return ((temp_buffer.length()>=3) && (temp_buffer.substring(0,3).equals("!--"))); + return ((m_temp_buffer.length()>=3) && (m_temp_buffer.substring(0,3).equals("!--"))); } // end containsHTMLComment @@ -822,11 +860,11 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic */ private final boolean containsCompleteHTMLComment() { - int l = temp_buffer.length(); + int l = m_temp_buffer.length(); // note that a minimum HTML comment is , i.e. "" with no characters // in between... - return ((l>=5) && (temp_buffer.substring(0,3).equals("!--")) - && (temp_buffer.substring(l-2,l).equals("--"))); + return ((l>=5) && (m_temp_buffer.substring(0,3).equals("!--")) + && (m_temp_buffer.substring(l-2,l).equals("--"))); } // end containsCompleteHTMLComment @@ -840,11 +878,11 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic private final boolean containsXMLConstruct() { int ptr = 0; - if ((temp_buffer.length()>1) && (temp_buffer.charAt(0)=='/')) + if ((m_temp_buffer.length()>1) && (m_temp_buffer.charAt(0)=='/')) ptr++; - while (ptr',filters,false); } // end if // clear our state and return to parsing - temp_buffer.setLength(0); - state = ST_WHITESPACE; + m_temp_buffer.setLength(0); + m_state = ST_WHITESPACE; return; } // end if if (handleAsHTML()) { // the tag has been handled as an HTML tag - bail out immediately - temp_buffer.setLength(0); - state = ST_WHITESPACE; + m_temp_buffer.setLength(0); + m_state = ST_WHITESPACE; return; } // end if // now try to handle it using a tag rewriter - MarkupData md = attemptRewrite(tag_rewriters,temp_buffer.toString()); + MarkupData md = attemptRewrite(m_tag_rewriters,m_temp_buffer.toString()); if (md!=null) { // we've got something marked up! output it... emitMarkupData(md,'<','>'); - temp_buffer.setLength(0); - state = ST_WHITESPACE; + m_temp_buffer.setLength(0); + m_state = ST_WHITESPACE; + if (md.getRescan()) + { // shift to character state to parse the rescan stuff + m_temp_buffer.setLength(0); + m_temp_buffer.append('<'); + m_state = ST_CHARS; + parse(md.getAll() + ">"); + + } // end if return; } // end if - if (config.getDiscardXMLConstructs() && containsXMLConstruct()) + if (m_config.getDiscardXMLConstructs() && containsXMLConstruct()) { // the tag is an XML construct, and is to be discarded - temp_buffer.setLength(0); - state = ST_WHITESPACE; + m_temp_buffer.setLength(0); + m_state = ST_WHITESPACE; return; } // end if // This tag has been rejected! We need to process it normally, as character data. - String rejection = temp_buffer.toString(); - temp_buffer.setLength(0); - temp_buffer.append('<'); - state = ST_CHARS; + String rejection = m_temp_buffer.toString(); + m_temp_buffer.setLength(0); + m_temp_buffer.append('<'); + m_state = ST_CHARS; if (rejection.length()>0) parse(rejection); // just run it through the parser, now that we've fixed up the state parse(">"); @@ -920,23 +966,32 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic private final void finishParen() { // Try to handle the paren element using a paren rewriter. - MarkupData md = attemptRewrite(paren_rewriters,temp_buffer.toString()); + MarkupData md = attemptRewrite(m_paren_rewriters,m_temp_buffer.toString()); if (md!=null) { // we've got something marked up! output it... emitMarkupData(md,'(',')'); - temp_buffer.setLength(0); - state = ST_WHITESPACE; - paren_level = 0; + m_temp_buffer.setLength(0); + m_state = ST_WHITESPACE; + m_paren_level = 0; + if (md.getRescan()) + { // rescan the interior... + m_temp_buffer.setLength(0); + m_temp_buffer.append('('); + m_state = ST_CHARS; + parse(md.getAll() + ")"); + + } // end if + return; } // end if // This tag has been rejected! We need to process it normally, as character data. - String rejection = temp_buffer.toString(); - temp_buffer.setLength(0); - temp_buffer.append('('); - state = ST_CHARS; - paren_level = 0; + String rejection = m_temp_buffer.toString(); + m_temp_buffer.setLength(0); + m_temp_buffer.append('('); + m_state = ST_CHARS; + m_paren_level = 0; if (rejection.length()>0) parse(rejection); // just run it through the parser, now that we've fixed up the state parse(")"); @@ -951,7 +1006,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic char ch = str.charAt(i); // now process differently based on the current parser state - switch (state) + switch (m_state) { case ST_WHITESPACE: { // Whitespace handling - look at the character @@ -959,26 +1014,26 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic { case ' ': // append spaces and tabs verbatim to the temp buffer case '\t': - temp_buffer.append(ch); + m_temp_buffer.append(ch); i++; break; case '\r': // flush the whitespace and go to NEWLINE state case '\n': doFlushWhitespace(); - state = ST_NEWLINE; - temp_buffer.append(ch); + m_state = ST_NEWLINE; + m_temp_buffer.append(ch); i++; break; case '<': doFlushWhitespace(); // flush the whitespace we've already got - if (config.getProcessAngles()) - state = ST_LEFTANGLE; + if (m_config.getProcessAngles()) + m_state = ST_LEFTANGLE; else { // just process as an ordinary character - state = ST_CHARS; - temp_buffer.append(ch); + m_state = ST_CHARS; + m_temp_buffer.append(ch); } // end else i++; @@ -986,12 +1041,12 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic case '(': doFlushWhitespace(); // flush the whitespace we've already got - if (config.getProcessParens()) - state = ST_PAREN; + if (m_config.getProcessParens()) + m_state = ST_PAREN; else { // just process as an ordinary character - state = ST_CHARS; - temp_buffer.append(ch); + m_state = ST_CHARS; + m_temp_buffer.append(ch); } // end else i++; @@ -999,13 +1054,13 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic case '\\': // backslash processing is complex - shift to ST_CHARS state to handle it doFlushWhitespace(); - state = ST_CHARS; + m_state = ST_CHARS; break; default: doFlushWhitespace(); // flush the whitespace we've already got - state = ST_CHARS; - temp_buffer.append(ch); + m_state = ST_CHARS; + m_temp_buffer.append(ch); i++; break; @@ -1021,68 +1076,70 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic case ' ': // whitespace - drop back to whitespace mode case '\t': doFlushString(); - state = ST_WHITESPACE; - temp_buffer.append(ch); + m_state = ST_WHITESPACE; + m_temp_buffer.append(ch); i++; break; case '\r': // newline characters - flush out the buffer and go to NEWLINE state case '\n': doFlushString(); - state = ST_NEWLINE; - temp_buffer.append(ch); + m_state = ST_NEWLINE; + m_temp_buffer.append(ch); i++; break; case '<': // left angle bracket - may be a start-of-tag - if (config.getProcessAngles()) + if (m_config.getProcessAngles()) { // this is a tag start - go to LEFTANGLE state doFlushString(); - state = ST_LEFTANGLE; + m_state = ST_LEFTANGLE; } // end if else // just handle it normally - temp_buffer.append(ch); + m_temp_buffer.append(ch); i++; break; + /* EJB 7/27/2004 - don't go into PAREN state from CHARS because this may be part of a smiley case '(': // left parenthesis - may be a start-of-paren - if (config.getProcessParens()) + if (m_config.getProcessParens()) { // we're going into Parens mode... doFlushString(); - paren_level = 0; - state = ST_PAREN; + m_paren_level = 0; + m_state = ST_PAREN; } // end if else // just handle it normally - temp_buffer.append(ch); + m_temp_buffer.append(ch); i++; break; + */ case '\\': if (i<(str.length()-1)) { // look at the character following the backslash ch = str.charAt(++i); - if (((ch=='(') && config.getProcessParens()) || ((ch=='<') && config.getProcessAngles())) + if (((ch=='(') && m_config.getProcessParens()) || ((ch=='<') && m_config.getProcessAngles())) { // append the escaped character, omitting the backslash - temp_buffer.append(ch); + m_temp_buffer.append(ch); i++; } // end if else // append the backslash and hit the new character - temp_buffer.append('\\'); + m_temp_buffer.append('\\'); } // end if else { // just append the backslash normally - temp_buffer.append('\\'); + m_temp_buffer.append('\\'); i++; } // end else break; default: // just append the next non-white character - temp_buffer.append(ch); + m_temp_buffer.append(ch); i++; break; @@ -1099,18 +1156,18 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic case '\t': case '\r': case '\n': // output the < and click back to whitespace mode - emitChar('<',config.getOutputFilters(),true); - state = ST_WHITESPACE; + emitChar('<',m_config.getOutputFilters(),true); + m_state = ST_WHITESPACE; break; case '<': // output the < and stay in this mode - emitChar('<',config.getOutputFilters(),true); + emitChar('<',m_config.getOutputFilters(),true); i++; break; default: // click over to TAG mode - state = ST_TAG; - temp_buffer.append(ch); + m_state = ST_TAG; + m_temp_buffer.append(ch); i++; break; @@ -1130,14 +1187,14 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic case '\'': // go into "quote string" mode inside tag case '\"': - temp_buffer.append(ch); - state = ST_TAGQUOTE; - quote_char = ch; + m_temp_buffer.append(ch); + m_state = ST_TAGQUOTE; + m_quote_char = ch; i++; break; default: // just append more data to the temp buffer - temp_buffer.append(ch); + m_temp_buffer.append(ch); i++; break; @@ -1151,25 +1208,25 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic switch (ch) { case '(': // append the open parenthesis and kick it up a notch! - temp_buffer.append(ch); - paren_level++; + m_temp_buffer.append(ch); + m_paren_level++; i++; break; case ')': - if (paren_level==0) + if (m_paren_level==0) finishParen(); // will change the parser state else { // append the close parenthesis and kick it DOWN a notch - temp_buffer.append(ch); - paren_level--; + m_temp_buffer.append(ch); + m_paren_level--; } // end else i++; break; default: - temp_buffer.append(ch); + m_temp_buffer.append(ch); i++; break; @@ -1179,16 +1236,16 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic break; case ST_TAGQUOTE: - temp_buffer.append(ch); - if (ch==quote_char) // close quote seen - go back to ST_TAG state - state = ST_TAG; + m_temp_buffer.append(ch); + if (ch==m_quote_char) // close quote seen - go back to ST_TAG state + m_state = ST_TAG; i++; break; case ST_NEWLINE: if ((ch=='\r') || (ch=='\n')) { // handle newlines - temp_buffer.append(ch); + m_temp_buffer.append(ch); i++; } // end if @@ -1212,12 +1269,12 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic public void append(String str) throws AlreadyFinishedException { - if (finished) + if (m_finished) throw new AlreadyFinishedException(); - if (!started) + if (!m_started) { // initialize the parser state initState(); - started = true; + m_started = true; } // end if @@ -1228,12 +1285,12 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic public void finish() throws AlreadyFinishedException { - if (finished) + if (m_finished) throw new AlreadyFinishedException(); - if (!started) + if (!m_started) { // set up the initial parser state (so we don't kill ourselves later) initState(); - started = true; + m_started = true; } // end if @@ -1244,28 +1301,28 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic { // what we do depends on the parser state... running = false; // make sure we stop unless running is set to true here - switch (state) + switch (m_state) { case ST_WHITESPACE: case ST_NEWLINE: break; // discard any whitespace or newlines at the end of output case ST_CHARS: - doFlushString(); // flush out the temporary buffer + running = doFlushString(); // flush out the temporary buffer break; case ST_LEFTANGLE: // just emit a '<' character emitPossibleLineBreak(); - emitChar('<',config.getOutputFilters(),true); + emitChar('<',m_config.getOutputFilters(),true); break; case ST_TAG: case ST_TAGQUOTE: { // we won't finish this tag, so it's automagically rejected - String rejection = temp_buffer.toString(); - temp_buffer.setLength(0); - temp_buffer.append('<'); - state = ST_CHARS; + String rejection = m_temp_buffer.toString(); + m_temp_buffer.setLength(0); + m_temp_buffer.append('<'); + m_state = ST_CHARS; // now parse the tag contents again if (rejection.length()>0) @@ -1278,11 +1335,11 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic case ST_PAREN: { // we won't finish this paren tag, so it's automagically rejected - String rejection = temp_buffer.toString(); - temp_buffer.setLength(0); - temp_buffer.append('('); - state = ST_CHARS; - paren_level = 0; + String rejection = m_temp_buffer.toString(); + m_temp_buffer.setLength(0); + m_temp_buffer.append('('); + m_state = ST_CHARS; + m_paren_level = 0; // now parse the parenthesis contents again if (rejection.length()>0) @@ -1298,74 +1355,73 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic } while (running); // end do // Now close all the HTML tags that were left open. - for (int i=(tag_stack.size()-1); i>=0; i--) + for (int i=(m_tag_stack.size()-1); i>=0; i--) { // get each element in the tag stack and append the appropriate closing tag - Integer foo = (Integer)(tag_stack.get(i)); + Integer foo = (Integer)(m_tag_stack.get(i)); SimpleTag tagobj = TagRepository.tagIndexToObject(foo.intValue()); - output_buffer.append(tagobj.makeClosingTag()); + m_output_buffer.append(tagobj.makeClosingTag()); } // end for // deallocate some excess crap and mark the object as finished killState(); - lines++; // there's one extra line at the end - finished = true; + m_lines++; // there's one extra line at the end + m_finished = true; } // end finish public void reset() { - started = false; - finished = false; - trigger_WBR = false; - state = ST_WHITESPACE; - quote_char = '\0'; - columns = 0; - lines = 0; - paren_level = 0; - output_buffer = null; + m_started = false; + m_finished = false; + m_trigger_wbr = false; + m_state = ST_WHITESPACE; + m_quote_char = '\0'; + m_columns = 0; + m_lines = 0; + m_paren_level = 0; + m_output_buffer = null; killState(); // Also reset all the counters. - Iterator it = counters.values().iterator(); - while (it.hasNext()) + for (Iterator it=m_counters.values().iterator(); it.hasNext(); ) { // reset each counter in turn CountingRewriter cr = (CountingRewriter)(it.next()); cr.reset(); - } // end while + } // end for } // end reset public String getValue() throws NotYetFinishedException { - if (!finished) + if (!m_finished) throw new NotYetFinishedException(); - return output_buffer.toString(); + return m_output_buffer.toString(); } // end getValue public int getLength() throws NotYetFinishedException { - if (!finished) + if (!m_finished) throw new NotYetFinishedException(); - return output_buffer.length(); + return m_output_buffer.length(); } // end getLength public int getLines() throws NotYetFinishedException { - if (!finished) + if (!m_finished) throw new NotYetFinishedException(); - return lines; + return m_lines; } // end getLines public int getCounter(String name) throws NotYetFinishedException { - if (!finished) + if (!m_finished) throw new NotYetFinishedException(); - CountingRewriter cr = (CountingRewriter)(counters.get(name)); + CountingRewriter cr = (CountingRewriter)(m_counters.get(name)); if (cr==null) return 0; else @@ -1375,13 +1431,13 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic public Object getContextValue(String name) { - return context_data.get(name); + return m_context_data.get(name); } // end getContextValue public void setContextValue(String name, Object val) { - context_data.put(name,val); + m_context_data.put(name,val); } // end setContextValue @@ -1393,7 +1449,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic public String getCheckerAttrValue(String name) { if (name=="ANCHORTAIL") - return config.getAnchorTail(); + return m_config.getAnchorTail(); throw new IllegalArgumentException("attribute \"" + name + "\" is not defined"); @@ -1403,21 +1459,21 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic { if (msg=="NOBR") { // increment the no-break count - nobreak_count++; + m_nobreak_count++; return; } // end if if (msg=="/NOBR") { // decrement the no-break count - nobreak_count--; + m_nobreak_count--; return; } // end if if (msg=="WBR") { // trigger a word break - trigger_WBR = true; + m_trigger_wbr = true; return; } // end if @@ -1428,7 +1484,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic public Object getCheckerContextValue(String name) { - return context_data.get(name); + return m_context_data.get(name); } // end getCheckerContextValue @@ -1445,7 +1501,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic public Object getRewriterContextValue(String name) { - return context_data.get(name); + return m_context_data.get(name); } // end getRewriterContextValue diff --git a/src/com/silverwrist/venice/ui/conf/jsp/PostRewriteTag.java b/src/com/silverwrist/venice/ui/conf/jsp/PostRewriteTag.java index 74c3d2b..67e5536 100644 --- a/src/com/silverwrist/venice/ui/conf/jsp/PostRewriteTag.java +++ b/src/com/silverwrist/venice/ui/conf/jsp/PostRewriteTag.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -23,6 +23,7 @@ import javax.servlet.jsp.tagext.*; import com.silverwrist.venice.db.PostLinkRewriter; import com.silverwrist.venice.db.UserNameRewriter; import com.silverwrist.venice.ui.*; +import com.silverwrist.venice.ui.config.EmoticonManager; import com.silverwrist.venice.ui.helpers.HTMLRendering; import com.silverwrist.venice.util.IDUtils; @@ -59,6 +60,10 @@ public class PostRewriteTag extends VeniceConfBodyTagSupport BodyContent body = getBodyContent(); String data = body.getString(); + // Remap emoticons. + EmoticonManager em = (EmoticonManager)(getRequestInput().queryService(EmoticonManager.class)); + data = em.rewriteText(getRequestOutput(),data); + if ((data.indexOf(PostLinkRewriter.URI_PREFIX)<0) && (data.indexOf(UserNameRewriter.URI_PREFIX)<0)) { // no post links or user links in here - output what we've got and call it output(body,data); diff --git a/src/com/silverwrist/venice/ui/config/EmoticonManager.java b/src/com/silverwrist/venice/ui/config/EmoticonManager.java index d8bbe96..9a830ee 100644 --- a/src/com/silverwrist/venice/ui/config/EmoticonManager.java +++ b/src/com/silverwrist/venice/ui/config/EmoticonManager.java @@ -18,9 +18,13 @@ package com.silverwrist.venice.ui.config; import java.util.*; +import org.apache.log4j.*; +import org.apache.regexp.*; import org.w3c.dom.*; import com.silverwrist.util.*; import com.silverwrist.venice.except.*; +import com.silverwrist.venice.ui.*; +import com.silverwrist.venice.ui.helpers.*; import com.silverwrist.venice.util.XMLLoader; public class EmoticonManager @@ -63,11 +67,43 @@ public class EmoticonManager // Get the text data. m_text = h.getSubElementText("text"); + if (m_text==null) + m_text = ""; } // end constructor + /*==================================================================== + * External operations + *==================================================================== + */ + + String format(RequestOutput out) + { + StringBuffer buf = new StringBuffer("\"").append(m_text).append("\""); + return buf.toString(); + + } // end format + } // end class IconDefinition + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(EmoticonManager.class); + /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- @@ -106,4 +142,44 @@ public class EmoticonManager } // end constructor + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public String rewriteText(RequestOutput out, String txt) + { + RE r = new RE(""); + if (!(r.match(txt))) + { // null it out + logger.debug("EmoticonManager.rewriteText matched nothing at all"); + return txt; + + } // end if + + StringBuffer buf = new StringBuffer(); + String work = txt; + do + { // figure out how many characters to skip + int skip = r.getParenStart(0); + if (skip>0) + buf.append(work.substring(0,skip)); + skip += r.getParenLength(0); + + // get the icon name + String icon_name = r.getParen(1); + IconDefinition defn = (IconDefinition)(m_iconmap.get(icon_name)); + if (defn==null) + buf.append(StringUtil.encodeHTML(r.getParen(0))); + else + buf.append(defn.format(out)); + + work = work.substring(skip); // skip over stuff + + } while (r.match(work)); // end do + + return buf.append(work).toString(); // all done! + + } // end rewriteText + } // end class EmoticonManager diff --git a/src/com/silverwrist/venice/ui/servlet/BaseServlet.java b/src/com/silverwrist/venice/ui/servlet/BaseServlet.java index 0e4a608..0e66463 100644 --- a/src/com/silverwrist/venice/ui/servlet/BaseServlet.java +++ b/src/com/silverwrist/venice/ui/servlet/BaseServlet.java @@ -425,6 +425,12 @@ public abstract class BaseServlet extends HttpServlet init(config,ctxt,engine,rootconf,root_file_path); } // end try + catch (RuntimeException e) + { // report an error + logger.fatal("RuntimeException in configuration: " + e.getMessage(),e); + throw new ServletException("Venice configuration failed: " + e.getMessage(),e); + + } // end catch finally { // make sure and pop the diagnostic context before we go NDC.pop(); diff --git a/src/com/silverwrist/venice/ui/servlet/RequestImpl.java b/src/com/silverwrist/venice/ui/servlet/RequestImpl.java index dd8c54a..a5ada66 100644 --- a/src/com/silverwrist/venice/ui/servlet/RequestImpl.java +++ b/src/com/silverwrist/venice/ui/servlet/RequestImpl.java @@ -81,6 +81,8 @@ public class RequestImpl implements RequestInput return RequestImpl.this.queryService(klass); if (klass==BrowserInformation.class) return RequestImpl.this.queryService(klass); + if (klass==EmoticonManager.class) + return RequestImpl.this.queryService(klass); throw new NoSuchServiceException("RequestOutput",klass); } // end queryService @@ -899,8 +901,8 @@ public class RequestImpl implements RequestInput * * @param klass The class of the object that should be returned as a service. * @return A service object. The service object is guaranteed to be of the class - * specified by klass; that is, if queryService(klass) - * yields some object x, then the expression klass.isInstance(x) + * specified by klass; that is, if queryService(klass) + * yields some object x, then the expression klass.isInstance(x) * is true. * @exception com.silverwrist.venice.except.NoSuchServiceException If no service is available in * the specified class. @@ -958,6 +960,9 @@ public class RequestImpl implements RequestInput } // end if + if (klass==EmoticonManager.class) + return config.getEmoticonManager(); + throw new NoSuchServiceException("RequestInput",klass); } // end queryService