jspwiki-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ajaqu...@apache.org
Subject svn commit: r627255 [22/41] - in /incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src: ./ com/ com/ecyrd/ com/ecyrd/jspwiki/ com/ecyrd/jspwiki/action/ com/ecyrd/jspwiki/attachment/ com/ecyrd/jspwiki/auth/ com/ecyrd/jspwiki/auth/acl/ com/ecyrd/jspwiki...
Date Wed, 13 Feb 2008 05:54:24 GMT
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/HtmlStringToWikiTranslator.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/HtmlStringToWikiTranslator.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/HtmlStringToWikiTranslator.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/HtmlStringToWikiTranslator.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,88 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.htmltowiki;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.XMLOutputter;
+
+import com.ecyrd.jspwiki.WikiContext;
+
+/**
+ * Converting Html to Wiki Markup with NekoHtml for converting html to xhtml and
+ * Xhtml2WikiTranslator for converting xhtml to Wiki Markup.
+ * 
+ * @author Sebastian Baltes (sbaltes@gmx.com)
+ */
+public class HtmlStringToWikiTranslator
+{
+
+    private static final String CYBERNEKO_PARSER = "org.cyberneko.html.parsers.SAXParser";
+
+    public HtmlStringToWikiTranslator()
+    {}
+
+    public String translate( String html ) throws JDOMException, IOException
+    {
+        return translate( html, new XHtmlToWikiConfig() );
+    }
+
+    public String translate( String html, WikiContext wikiContext ) throws JDOMException, IOException
+    {
+        return translate( html, new XHtmlToWikiConfig( wikiContext ) );
+    }
+
+    public String translate( String html, XHtmlToWikiConfig config ) throws JDOMException, IOException
+    {
+        Element element = htmlStringToElement( html );
+        XHtmlElementToWikiTranslator xhtmlTranslator = new XHtmlElementToWikiTranslator( element, config );
+        String wikiMarkup = xhtmlTranslator.getWikiString();
+        return wikiMarkup;
+    }
+
+    /**
+     * use NekoHtml to parse HTML like well formed XHTML
+     * 
+     * @param html
+     * @return xhtml jdom root element (node "HTML")
+     * @throws JDOMException
+     * @throws IOException
+     */
+    private Element htmlStringToElement( String html ) throws JDOMException, IOException
+    {
+        SAXBuilder builder = new SAXBuilder( CYBERNEKO_PARSER, true );
+        Document doc = builder.build( new StringReader( html ) );
+        Element element = doc.getRootElement();
+        return element;
+    }
+
+    public static String element2String( Element element )
+    {
+        Document document = new Document( element );
+        XMLOutputter outputter = new XMLOutputter();
+        return outputter.outputString( document );
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/PersistentMapDecorator.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/PersistentMapDecorator.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/PersistentMapDecorator.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/PersistentMapDecorator.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,118 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.htmltowiki;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * Adds the load / save - functionality known from the Properties - class to any
+ * Map implementation.
+ * 
+ * @author Sebastian Baltes (sbaltes@gmx.com)
+ */
+public class PersistentMapDecorator extends Properties
+{
+    private static final long serialVersionUID = 0L;
+    
+    private Map m_delegate;
+
+    public PersistentMapDecorator( Map delegate )
+    {
+        this.m_delegate = delegate;
+    }
+
+    public void clear()
+    {
+        m_delegate.clear();
+    }
+
+    public boolean containsKey( Object key )
+    {
+        return m_delegate.containsKey( key );
+    }
+
+    public boolean containsValue( Object value )
+    {
+        return m_delegate.containsValue( value );
+    }
+
+    public Set entrySet()
+    {
+        return m_delegate.entrySet();
+    }
+
+    public boolean equals( Object obj )
+    {
+        return m_delegate.equals( obj );
+    }
+
+    public Object get( Object key )
+    {
+        return m_delegate.get( key );
+    }
+
+    public int hashCode()
+    {
+        return m_delegate.hashCode();
+    }
+
+    public boolean isEmpty()
+    {
+        return m_delegate.isEmpty();
+    }
+
+    public Set keySet()
+    {
+        return m_delegate.keySet();
+    }
+
+    public Object put( Object arg0, Object arg1 )
+    {
+        return m_delegate.put( arg0, arg1 );
+    }
+
+    public void putAll( Map arg0 )
+    {
+        m_delegate.putAll( arg0 );
+    }
+
+    public Object remove( Object key )
+    {
+        return m_delegate.remove( key );
+    }
+
+    public int size()
+    {
+        return m_delegate.size();
+    }
+
+    public String toString()
+    {
+        return m_delegate.toString();
+    }
+
+    public Collection values()
+    {
+        return m_delegate.values();
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/PropertiesUtils.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/PropertiesUtils.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/PropertiesUtils.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/PropertiesUtils.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,145 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.htmltowiki;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+
+/**
+ * some usefull methods for properties
+ *
+ * @author Sebastian Baltes (sbaltes@gmx.com)
+ * @version 1.0
+ */
+public final class PropertiesUtils
+{
+    private static final String OTHER_WHITESPACE = "\t\r\n\014";
+    private static final char[] HEXDIGIT = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+    /** Private constructor to prevent instantiation. */
+    private PropertiesUtils()
+    {}
+
+    /**
+     * <p>
+     * like Properties.store, but stores the properties in sorted order
+     * </p>
+     *
+     * @param properties the properties object
+     * @return String the properties, nicely formatted 
+     */
+    public static String toSortedString( Properties properties )
+    {
+        TreeMap treemap = new TreeMap( properties );
+        String string = "";
+        Iterator iterator = treemap.entrySet().iterator();
+        while( iterator.hasNext() )
+        {
+            Map.Entry entry = (Map.Entry)iterator.next();
+            String key = (String)entry.getKey();
+            String value = entry.getValue() == null ? "null" : entry.getValue().toString();
+            string += toLine( key, value ) + '\n';
+        }
+        return string;
+    }
+
+    /**
+     * Generates a property file line from a supplied key and value.
+     * @param key the property's key
+     * @param value the property's value
+     * @return the converted string
+     */
+    public static String toLine( String key, String value )
+    {
+        return saveConvert( key, true ) + '=' + saveConvert( value, false );
+    }
+
+    /**
+     * Encodes a property file string from a supplied key/value line.
+     * @param string the string to encode
+     * @param encodeWhiteSpace <code>true</code> if whitespace should be encoded also
+     * @return the converted string
+     */
+    public static String saveConvert( String string, boolean encodeWhiteSpace )
+    {
+        int i = string.length();
+        StringBuffer stringbuffer = new StringBuffer( i * 2 );
+        for( int i3 = 0; i3 < i; i3++ )
+        {
+            char c = string.charAt( i3 );
+            switch( c )
+            {
+                case ' ':
+                    if( i3 == 0 || encodeWhiteSpace )
+                    {
+                        stringbuffer.append( '\\' );
+                    }
+                    stringbuffer.append( ' ' );
+                    break;
+                case '\\':
+                    stringbuffer.append( '\\' );
+                    stringbuffer.append( '\\' );
+                    break;
+                case '\t':
+                    stringbuffer.append( '\\' );
+                    stringbuffer.append( 't' );
+                    break;
+                case '\n':
+                    stringbuffer.append( '\\' );
+                    stringbuffer.append( 'n' );
+                    break;
+                case '\r':
+                    stringbuffer.append( '\\' );
+                    stringbuffer.append( 'r' );
+                    break;
+                case '\014':
+                    stringbuffer.append( '\\' );
+                    stringbuffer.append( 'f' );
+                    break;
+                default:
+                    if( c < 32 || c > 126 )
+                    {
+                        stringbuffer.append( '\\' );
+                        stringbuffer.append( 'u' );
+                        stringbuffer.append( toHex( c >> 12 & 0xf ) );
+                        stringbuffer.append( toHex( c >> 8 & 0xf ) );
+                        stringbuffer.append( toHex( c >> 4 & 0xf ) );
+                        stringbuffer.append( toHex( c & 0xf ) );
+                    }
+                    else
+                    {
+                        if( OTHER_WHITESPACE.indexOf( c ) != -1 )
+                        {
+                            stringbuffer.append( '\\' );
+                        }
+                        stringbuffer.append( c );
+                    }
+            }
+        }
+        return stringbuffer.toString();
+    }
+
+    private static char toHex( int i )
+    {
+        return HEXDIGIT[i & 0xf];
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/WhitespaceTrimWriter.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/WhitespaceTrimWriter.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/WhitespaceTrimWriter.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/WhitespaceTrimWriter.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,120 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.htmltowiki;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Part of the XHtmlToWikiTranslator
+ * 
+ * @author Sebastian Baltes (sbaltes@gmx.com)
+ */
+public class WhitespaceTrimWriter extends Writer
+{
+
+    private StringBuffer m_result = new StringBuffer();
+
+    private StringBuffer m_buffer = new StringBuffer();
+
+    private boolean m_trimMode = true;
+
+    private static final Pattern ONLINE_PATTERN = Pattern.compile( ".*?\\n\\s*?", Pattern.MULTILINE );
+
+    private boolean m_currentlyOnLineBegin = true;
+
+    public void flush()
+    {
+        if( m_buffer.length() > 0 )
+        {
+            String s = m_buffer.toString();
+            s = s.replaceAll( "\r\n", "\n" );
+            if( m_trimMode )
+            {
+                s = s.replaceAll( "(\\w+) \\[\\?\\|Edit\\.jsp\\?page=\\1\\]", "[$1]" );
+                s = s.replaceAll( "\n{2,}", "\n\n" );
+                s = s.replaceAll( "\\p{Blank}+", " " );
+                s = s.replaceAll( "[ ]*\n[ ]*", "\n" );
+                s = replacePluginNewlineBackslashes( s );
+            }
+            m_result.append( s );
+            m_buffer = new StringBuffer();
+        }
+    }
+
+    private String replacePluginNewlineBackslashes( String s )
+    {
+        Pattern p = Pattern.compile( "\\{\\{\\{(.*?)\\}\\}\\}|\\{\\{(.*?)\\}\\}|\\[\\{(.*?)\\}\\]", Pattern.DOTALL
+                                                                                                    + Pattern.MULTILINE );
+        Matcher m = p.matcher( s );
+        StringBuffer sb = new StringBuffer();
+        while( m.find() )
+        {
+            String groupEscaped = m.group().replaceAll( "\\\\|\\$", "\\\\$0" );
+            if( m.group( 3 ) != null )
+            {
+                m.appendReplacement( sb, groupEscaped.replaceAll( "\\\\\\\\\\\\\\\\", "\n" ) );
+            }
+            else
+            {
+                m.appendReplacement( sb, groupEscaped );
+            }
+        }
+        m.appendTail( sb );
+        s = sb.toString();
+        return s;
+    }
+
+    public boolean isWhitespaceTrimMode()
+    {
+        return m_trimMode;
+    }
+
+    public void setWhitespaceTrimMode( boolean trimMode )
+    {
+        if( m_trimMode != trimMode )
+        {
+            flush();
+            m_trimMode = trimMode;
+        }
+    }
+
+    public void write( char[] arg0, int arg1, int arg2 ) throws IOException
+    {
+        m_buffer.append( arg0, arg1, arg2 );
+        m_currentlyOnLineBegin = ONLINE_PATTERN.matcher( m_buffer ).matches();
+    }
+
+    public void close() throws IOException
+    {}
+
+    public String toString()
+    {
+        flush();
+        return m_result.toString();
+    }
+
+    public boolean isCurrentlyOnLineBegin()
+    {
+        return m_currentlyOnLineBegin;
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/XHtmlElementToWikiTranslator.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/XHtmlElementToWikiTranslator.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/XHtmlElementToWikiTranslator.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/XHtmlElementToWikiTranslator.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,1049 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2007 JSPWiki Development Group
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.htmltowiki;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.jdom.Element;
+import org.jdom.Attribute;
+import org.jdom.JDOMException;
+import org.jdom.Text;
+import org.jdom.xpath.XPath;
+
+/**
+ * Converting XHtml to Wiki Markup
+ *
+ * @author Sebastian Baltes (sbaltes@gmx.com)
+ */
+public class XHtmlElementToWikiTranslator
+{
+    private static final String UTF8 = "UTF-8";
+
+    private XHtmlToWikiConfig m_config;
+
+    private WhitespaceTrimWriter m_outTimmer;
+
+    private PrintWriter m_out;
+
+    private LiStack m_liStack = new LiStack();
+
+    private PreStack m_preStack = new PreStack();
+
+    public XHtmlElementToWikiTranslator( Element base ) throws IOException, JDOMException
+    {
+        this( base, new XHtmlToWikiConfig() );
+    }
+
+    public XHtmlElementToWikiTranslator( Element base, XHtmlToWikiConfig config ) throws IOException, JDOMException
+    {
+        this.m_config = config;
+        m_outTimmer = new WhitespaceTrimWriter();
+        m_out = new PrintWriter( m_outTimmer );
+        print( base );
+    }
+
+    public String getWikiString()
+    {
+        return m_outTimmer.toString();
+    }
+
+    private void print( String s )
+    {
+        s = StringEscapeUtils.unescapeHtml( s );
+        m_out.print( s );
+    }
+
+    private void print( Object element ) throws IOException, JDOMException
+    {
+        if( element instanceof Text )
+        {
+            Text t = (Text)element;
+            String s = t.getText();
+            if( m_preStack.isPreMode() )
+            {
+                m_out.print( s );
+            }
+            else
+            {
+                // remove all "line terminator" characters
+                s = s.replaceAll( "[\\r\\n\\f\\u0085\\u2028\\u2029]", "" );
+                m_out.print( s );
+            }
+        }
+        else if( element instanceof Element )
+        {
+            Element base = (Element)element;
+            String n = base.getName().toLowerCase();
+            if( "imageplugin".equals( base.getAttributeValue( "class" ) ) )
+            {
+                printImage( base );
+            }
+            else if( "wikiform".equals( base.getAttributeValue( "class" ) ) )
+            {
+                // only print the children if the div's class="wikiform", but not the div itself.
+                printChildren( base );
+            }
+            else
+            {
+                boolean bold = false;
+                boolean italic = false;
+                boolean monospace = false;
+                String cssSpecial = null;
+                String cssClass = base.getAttributeValue( "class" );
+
+                // accomodate a FCKeditor bug with Firefox: when a link is removed, it becomes <span class="wikipage">text</span>.
+                boolean ignoredCssClass = cssClass != null && cssClass.matches( "wikipage|createpage|external|interwiki|attachment" );
+
+                Map styleProps = null;
+
+                // Only get the styles if it's not a link element. Styles for link elements are
+                // handled as an AugmentedWikiLink instead.
+                if( !n.equals( "a" ) )
+                {
+                    styleProps = getStylePropertiesLowerCase( base );
+                }
+
+                if( styleProps != null )
+                {
+                    String fontFamily = (String)styleProps.get( "font-family" );
+                    String whiteSpace = (String)styleProps.get( "white-space" );
+                    if( fontFamily != null && ( fontFamily.indexOf( "monospace" ) >= 0
+                            && whiteSpace != null && whiteSpace.indexOf( "pre" ) >= 0  ) )
+                    {
+                        styleProps.remove( "font-family" );
+                        styleProps.remove( "white-space" );
+                        monospace = true;
+                    }
+
+                    String weight = (String)styleProps.remove( "font-weight" );
+                    String style = (String)styleProps.remove( "font-style" );
+
+                    if( n.equals( "p" ) )
+                    {
+                        // change it so we can print out the css styles for <p>
+                        n = "div";
+                    }
+
+                    italic = "oblique".equals( style ) || "italic".equals( style );
+                    bold = "bold".equals( weight ) || "bolder".equals( weight );
+                    if( !styleProps.isEmpty() )
+                    {
+                        cssSpecial = propsToStyleString( styleProps );
+                    }
+                }
+                if( cssClass != null && !ignoredCssClass )
+                {
+                    if( n.equals( "div" ) )
+                    {
+                        m_out.print( "\n%%" + cssClass + " \n" );
+                    }
+                    else if( n.equals( "span" ) )
+                    {
+                        m_out.print( "%%" + cssClass + " " );
+                    }
+                }
+                if( bold )
+                {
+                    m_out.print( "__" );
+                }
+                if( italic )
+                {
+                    m_out.print( "''" );
+                }
+                if( monospace )
+                {
+                    m_out.print( "{{{" );
+                    m_preStack.push();
+                }
+                if( cssSpecial != null )
+                {
+                    if( n.equals( "div" ) )
+                    {
+                        m_out.print( "\n%%(" + cssSpecial + " )\n" );
+                    }
+                    else
+                    {
+                        m_out.print( "%%(" + cssSpecial + " )" );
+                    }
+                }
+                printChildren( base );
+                if( cssSpecial != null )
+                {
+                    if( n.equals( "div" ) )
+                    {
+                        m_out.print( "\n%%\n" );
+                    }
+                    else
+                    {
+                        m_out.print( "%%" );
+                    }
+                }
+                if( monospace )
+                {
+                    m_preStack.pop();
+                    m_out.print( "}}}" );
+                }
+                if( italic )
+                {
+                    m_out.print( "''" );
+                }
+                if( bold )
+                {
+                    m_out.print( "__" );
+                }
+                if( cssClass != null && !ignoredCssClass )
+                {
+                    if( n.equals( "div" ) )
+                    {
+                        m_out.print( "\n%%\n" );
+                    }
+                    else if( n.equals( "span" ) )
+                    {
+                        m_out.print( "%%" );
+                    }
+                }
+            }
+        }
+    }
+
+    private void printChildren( Element base ) throws IOException, JDOMException
+    {
+        for( Iterator i = base.getContent().iterator(); i.hasNext(); )
+        {
+            Object c = i.next();
+            if( c instanceof Element )
+            {
+                Element e = (Element)c;
+                String n = e.getName().toLowerCase();
+                if( n.equals( "h1" ) )
+                {
+                    m_out.print( "\n!!! " );
+                    print( e );
+                    m_out.println();
+                }
+                else if( n.equals( "h2" ) )
+                {
+                    m_out.print( "\n!!! " );
+                    print( e );
+                    m_out.println();
+                }
+                else if( n.equals( "h3" ) )
+                {
+                    m_out.print( "\n!! " );
+                    print( e );
+                    m_out.println();
+                }
+                else if( n.equals( "h4" ) )
+                {
+                    m_out.print( "\n! " );
+                    print( e );
+                    m_out.println();
+                }
+                else if( n.equals( "p" ) )
+                {
+                    if( e.getContentSize() != 0 ) // we don't want to print empty elements: <p></p>
+                    {
+                        m_out.println();
+                        print( e );
+                        m_out.println();
+                    }
+                }
+                else if( n.equals( "br" ) )
+                {
+                    if( m_preStack.isPreMode() )
+                    {
+                        m_out.println();
+                    }
+                    else
+                    {
+                        String parentElementName = base.getName().toLowerCase();
+
+                        //
+                        // To beautify the generated wiki markup, we print a newline character after a linebreak.
+                        // It's only safe to do this when the parent element is a <p> or <div>; when the parent
+                        // element is a table cell or list item, a newline character would break the markup.
+                        // We also check that this isn't being done inside a plugin body.
+                        //
+                        if( parentElementName.matches( "p|div" ) 
+                            && !base.getText().matches( "(?s).*\\[\\{.*\\}\\].*" ) )
+                        {
+                            m_out.print( " \\\\\n" );
+                        }
+                        else
+                        {
+                            m_out.print( " \\\\" );
+                        }
+                    }
+                    print( e );
+                }
+                else if( n.equals( "hr" ) )
+                {
+                    m_out.println();
+                    print( "----" );
+                    print( e );
+                    m_out.println();
+                }
+                else if( n.equals( "table" ) )
+                {
+                    if( !m_outTimmer.isCurrentlyOnLineBegin() )
+                    {
+                        m_out.println();
+                    }
+                    print( e );
+                }
+                else if( n.equals( "tr" ) )
+                {
+                    print( e );
+                    m_out.println();
+                }
+                else if( n.equals( "td" ) )
+                {
+                    m_out.print( "| " );
+                    print( e );
+                    if( !m_preStack.isPreMode() )
+                    {
+                        print( " " );
+                    }
+                }
+                else if( n.equals( "th" ) )
+                {
+                    m_out.print( "|| " );
+                    print( e );
+                    if( !m_preStack.isPreMode() )
+                    {
+                        print( " " );
+                    }
+                }
+                else if( n.equals( "a" ) )
+                {
+                    if( !isIgnorableWikiMarkupLink( e ) )
+                    {
+                        if( e.getChild( "IMG" ) != null )
+                        {
+                            printImage( e );
+                        }
+                        else
+                        {
+                            String ref = e.getAttributeValue( "href" );
+                            if( ref == null )
+                            {
+                                if( isUndefinedPageLink( e ) )
+                                {
+                                    m_out.print( "[" );
+                                    print( e );
+                                    m_out.print( "]" );
+                                }
+                                else
+                                {
+                                    print( e );
+                                }
+                            }
+                            else
+                            {
+                                ref = trimLink( ref );
+                                if( ref != null )
+                                {
+                                    if( ref.startsWith( "#" ) )
+                                    {
+                                        print( e );
+                                    }
+                                    else
+                                    {
+                                        Map augmentedWikiLinkAttributes = getAugmentedWikiLinkAttributes( e );
+
+                                        m_out.print( "[" );
+                                        print( e );
+                                        if( !e.getTextTrim().equalsIgnoreCase( ref ) )
+                                        {
+                                            m_out.print( "|" );
+                                            print( ref );
+
+                                            if( !augmentedWikiLinkAttributes.isEmpty() )
+                                            {
+                                                m_out.print( "|" );
+
+                                                String augmentedWikiLink = augmentedWikiLinkMapToString( augmentedWikiLinkAttributes );
+                                                m_out.print( augmentedWikiLink );
+                                            }
+                                        }
+                                        else if( !augmentedWikiLinkAttributes.isEmpty() )
+                                        {
+                                            // If the ref has the same value as the text and also if there
+                                            // are attributes, then just print: [ref|ref|attributes] .
+                                            m_out.print( "|" + ref + "|" );
+                                            String augmentedWikiLink = augmentedWikiLinkMapToString( augmentedWikiLinkAttributes );
+                                            m_out.print( augmentedWikiLink );
+                                        }
+
+                                        m_out.print( "]" );
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                else if( n.equals( "b" ) || n.equals("strong") )
+                {
+                    m_out.print( "__" );
+                    print( e );
+                    m_out.print( "__" );
+                }
+                else if( n.equals( "i" ) || n.equals("em") || n.equals( "address" ) )
+                {
+                    m_out.print( "''" );
+                    print( e );
+                    m_out.print( "''" );
+                }
+                else if( n.equals( "u" ) )
+                {
+                    m_out.print( "%%( text-decoration:underline; )" );
+                    print( e );
+                    m_out.print( "%%" );
+                }
+                else if( n.equals( "strike" ) )
+                {
+                    m_out.print( "%%strike " );
+                    print( e );
+                    m_out.print( "%%" );
+                    // NOTE: don't print a space before or after the double percents because that can break words into two.
+                    // For example: %%(color:red)ABC%%%%(color:green)DEF%% is different from %%(color:red)ABC%% %%(color:green)DEF%%
+                }
+                else if( n.equals( "sup" ) )
+                {
+                    m_out.print( "%%sup " );
+                    print( e );
+                    m_out.print( "%%" );
+                }
+                else if( n.equals( "sub" ) )
+                {
+                    m_out.print( "%%sub " );
+                    print( e );
+                    m_out.print( "%%" );
+                }
+                else if( n.equals("dl") )
+                {
+                    m_out.print( "\n" );
+                    print( e );
+
+                    // print a newline after the definition list. If we don't,
+                    // it may cause problems for the subsequent element.
+                    m_out.print( "\n" );
+                }
+                else if( n.equals("dt") )
+                {
+                    m_out.print( ";" );
+                    print( e );
+                }
+                else if( n.equals("dd") )
+                {
+                    m_out.print( ":" );
+                    print( e );
+                }
+                else if( n.equals( "ul" ) )
+                {
+                    m_out.println();
+                    m_liStack.push( "*" );
+                    print( e );
+                    m_liStack.pop();
+                }
+                else if( n.equals( "ol" ) )
+                {
+                    m_out.println();
+                    m_liStack.push( "#" );
+                    print( e );
+                    m_liStack.pop();
+                }
+                else if( n.equals( "li" ) )
+                {
+                    m_out.print( m_liStack + " " );
+                    print( e );
+
+                    // The following line assumes that the XHTML has been "pretty-printed"
+                    // (newlines separate child elements from their parents).
+                    boolean lastListItem = base.indexOf( e ) == ( base.getContentSize() - 2 );
+                    boolean sublistItem = m_liStack.toString().length() > 1;
+
+                    // only print a newline if this <li> element is not the last item within a sublist.
+                    if( !sublistItem || !lastListItem )
+                    {
+                        m_out.println();
+                    }
+                }
+                else if( n.equals( "pre" ) )
+                {
+                    m_out.print( "\n{{{\n" ); // start JSPWiki "code blocks" on its own line
+                    m_preStack.push();
+                    print( e );
+                    m_preStack.pop();
+
+                    // print a newline before the closing braces for aesthetics and a newline after it
+                    // to avoid breaking any subsequent wiki markup that follows.
+                    m_out.print( "\n}}}\n" );
+                }
+                else if( n.equals( "code" ) || n.equals( "tt" ) )
+                {
+                    m_out.print( "{{" );
+                    m_preStack.push();
+                    print( e );
+                    m_preStack.pop();
+                    m_out.print( "}}" );
+                    // NOTE: don't print a newline after the closing brackets because if the Text is inside
+                    // a table or list, it would break it if there was a subsequent row or list item.
+                }
+                else if( n.equals( "img" ) )
+                {
+                    if( !isIgnorableWikiMarkupLink( e ) )
+                    {
+                        m_out.print( "[" );
+                        print( trimLink( e.getAttributeValue( "src" ) ) );
+                        m_out.print( "]" );
+                    }
+                }
+                else if( n.equals( "form" ) )
+                {
+                    // remove the hidden input where name="formname" since a new one will be generated again when the xhtml is rendered.
+                    Element formName = (Element)XPath.selectSingleNode( e, "INPUT[@name='formname']" );
+                    if( formName != null )
+                    {
+                        formName.detach();
+                    }
+
+                    String name = e.getAttributeValue( "name" );
+
+                    m_out.print( "\n[{FormOpen" );
+
+                    if( name != null )
+                    {
+                        m_out.print( " form='" + name + "'" );
+                    }
+
+                    m_out.print( "}]\n" );
+
+                    print( e );
+                    m_out.print( "\n[{FormClose}]\n" );
+                }
+                else if( n.equals( "input" ) )
+                {
+                    String type = e.getAttributeValue( "type" );
+                    String name = e.getAttributeValue( "name" );
+                    String value = e.getAttributeValue( "value" );
+                    String checked = e.getAttributeValue( "checked" );
+
+                    m_out.print( "[{FormInput" );
+
+                    if( type != null )
+                    {
+                        m_out.print( " type='" + type + "'" );
+                    }
+                    if( name != null )
+                    {
+                        // remove the "nbf_" that was prepended since new one will be generated again when the xhtml is rendered.
+                        if( name.startsWith( "nbf_" ) )
+                        {
+                            name = name.substring( 4, name.length( ));
+                        }
+                        m_out.print( " name='" + name + "'" );
+                    }
+                    if( value != null && !value.equals( "" ) )
+                    {
+                        m_out.print( " value='" + value + "'" );
+                    }
+                    if( checked != null )
+                    {
+                        m_out.print( " checked='" + checked + "'" );
+                    }
+
+                    m_out.print( "}]" );
+
+                    print( e );
+                }
+                else if( n.equals( "textarea" ) )
+                {
+                    String name = e.getAttributeValue( "name" );
+                    String rows = e.getAttributeValue( "rows" );
+                    String cols = e.getAttributeValue( "cols" );
+
+                    m_out.print( "[{FormTextarea" );
+
+                    if( name != null )
+                    {
+                        if( name.startsWith( "nbf_" ) )
+                        {
+                            name = name.substring( 4, name.length( ));
+                        }
+                        m_out.print( " name='" + name + "'" );
+                    }
+                    if( rows != null )
+                    {
+                        m_out.print( " rows='" + rows + "'" );
+                    }
+                    if( cols != null )
+                    {
+                        m_out.print( " cols='" + cols + "'" );
+                    }
+
+                    m_out.print( "}]" );
+                    print( e );
+                }
+                else if( n.equals( "select" ) )
+                {
+                    String name = e.getAttributeValue( "name" );
+
+                    m_out.print( "[{FormSelect" );
+
+                    if( name != null )
+                    {
+                        if( name.startsWith( "nbf_" ) )
+                        {
+                            name = name.substring( 4, name.length( ));
+                        }
+                        m_out.print( " name='" + name + "'" );
+                    }
+
+                    m_out.print( " value='" );
+                    print( e );
+                    m_out.print( "'}]" );
+                }
+                else if( n.equals( "option" ) )
+                {
+                    // If this <option> element isn't the second child element within the parent <select>
+                    // element, then we need to print a semicolon as a separator. (The first child element
+                    // is expected to be a newline character which is at index of 0).
+                    if( base.indexOf( e ) != 1 )
+                    {
+                        m_out.print( ";" );
+                    }
+
+                    Attribute selected = e.getAttribute( "selected" );
+                    if( selected !=  null )
+                    {
+                        m_out.print( "*" );
+                    }
+
+                    String value = e.getAttributeValue( "value" );
+                    if( value != null )
+                    {
+                        m_out.print( value );
+                    }
+                    else
+                    {
+                        print( e );
+                    }
+                }
+                else
+                {
+                    print( e );
+                }
+            }
+            else
+            {
+                print( c );
+            }
+        }
+    }
+
+    private void printImage( Element base ) throws JDOMException
+    {
+        Element child = (Element)XPath.selectSingleNode( base, "TBODY/TR/TD/*" );
+        if( child == null )
+        {
+            child = base;
+        }
+        Element img;
+        String href;
+        Map map = new ForgetNullValuesLinkedHashMap();
+        if( child.getName().equals( "A" ) )
+        {
+            img = child.getChild( "IMG" );
+            href = child.getAttributeValue( "href" );
+        }
+        else
+        {
+            img = child;
+            href = null;
+        }
+        if( img == null )
+        {
+            return;
+        }
+        String src = trimLink( img.getAttributeValue( "src" ) );
+        if( src == null )
+        {
+            return;
+        }
+        map.put( "align", base.getAttributeValue( "align" ) );
+        map.put( "height", img.getAttributeValue( "height" ) );
+        map.put( "width", img.getAttributeValue( "width" ) );
+        map.put( "alt", img.getAttributeValue( "alt" ) );
+        map.put( "caption", emptyToNull( XPath.newInstance( "CAPTION" ).valueOf( base ) ) );
+        map.put( "link", href );
+        map.put( "border", img.getAttributeValue( "border" ) );
+        map.put( "style", base.getAttributeValue( "style" ) );
+        if( map.size() > 0 )
+        {
+            m_out.print( "[{Image src='" + src + "'" );
+            for( Iterator i = map.entrySet().iterator(); i.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry)i.next();
+                if( !entry.getValue().equals( "" ) )
+                {
+                    m_out.print( " " + entry.getKey() + "='" + entry.getValue() + "'" );
+                }
+            }
+            m_out.print( "}]" );
+        }
+        else
+        {
+            m_out.print( "[" + src + "]" );
+        }
+    }
+
+    private String emptyToNull( String s )
+    {
+        return s == null ? null : (s.replaceAll( "\\s", "" ).length() == 0 ? null : s);
+    }
+
+    private String propsToStyleString( Map styleProps )
+    {
+        StringBuffer style = new StringBuffer();
+        for( Iterator i = styleProps.entrySet().iterator(); i.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry)i.next();
+            style.append( " " ).append( entry.getKey() ).append( ": " ).append( entry.getValue() ).append( ";" );
+        }
+        return style.toString();
+    }
+
+    private boolean isIgnorableWikiMarkupLink( Element a )
+    {
+        String ref = a.getAttributeValue( "href" );
+        String clazz = a.getAttributeValue( "class" );
+        return (ref != null && ref.startsWith( m_config.getPageInfoJsp() ))
+               || (clazz != null && clazz.trim().equalsIgnoreCase( m_config.getOutlink() ));
+    }
+
+    /**
+     * Checks if the link points to an undefined page.
+     */
+    private boolean isUndefinedPageLink( Element a)
+    {
+        String classVal = a.getAttributeValue( "class" );
+
+        return classVal != null && classVal.equals( "createpage" );
+    }
+
+    /**
+     *  Returns a Map containing the valid augmented wiki link attributes.
+     */
+    private Map getAugmentedWikiLinkAttributes( Element a )
+    {
+        Map attributesMap = new HashMap();
+
+        String id = a.getAttributeValue( "id" );
+        if( id != null && !id.equals( "" ) )
+        {
+            attributesMap.put( "id", id.replaceAll( "'", "\"" ) );
+        }
+
+        String cssClass = a.getAttributeValue( "class" );
+        if( cssClass != null && !cssClass.equals( "" )
+            && !cssClass.matches( "wikipage|createpage|external|interwiki|attachment" ) )
+        {
+            attributesMap.put( "class", cssClass.replaceAll( "'", "\"" ) );
+        }
+
+        String style = a.getAttributeValue( "style" );
+        if( style != null && !style.equals( "" ) )
+        {
+            attributesMap.put( "style", style.replaceAll( "'", "\"" ) );
+        }
+
+        String title = a.getAttributeValue( "title" );
+        if( title != null && !title.equals( "" ) )
+        {
+            attributesMap.put( "title", title.replaceAll( "'", "\"" ) );
+        }
+
+        String lang = a.getAttributeValue( "lang" );
+        if( lang != null && !lang.equals( "" ) )
+        {
+            attributesMap.put( "lang", lang.replaceAll( "'", "\"" ) );
+        }
+
+        String dir = a.getAttributeValue( "dir" );
+        if( dir != null && !dir.equals( "" ) )
+        {
+            attributesMap.put( "dir", dir.replaceAll( "'", "\"" ) );
+        }
+
+        String charset = a.getAttributeValue( "charset" );
+        if( charset != null && !charset.equals("") )
+        {
+            attributesMap.put( "charset", charset.replaceAll( "'", "\"" ) );
+        }
+
+        String type = a.getAttributeValue( "type" );
+        if( type != null && !type.equals( "" ) )
+        {
+            attributesMap.put( "type", type.replaceAll( "'", "\"" ) );
+        }
+
+        String hreflang = a.getAttributeValue( "hreflang" );
+        if( hreflang != null && !hreflang.equals( "" ) )
+        {
+            attributesMap.put( "hreflang", hreflang.replaceAll( "'", "\"" ) );
+        }
+
+        String rel = a.getAttributeValue( "rel" );
+        if( rel != null && !rel.equals( "" ) )
+        {
+            attributesMap.put( "rel", rel.replaceAll( "'", "\"" ) );
+        }
+
+        String rev = a.getAttributeValue( "rev" );
+        if( rev != null && !rev.equals( "" ) )
+        {
+            attributesMap.put( "rev", rev.replaceAll( "'", "\"" ) );
+        }
+
+        String accesskey = a.getAttributeValue( "accesskey" );
+        if( accesskey != null && !accesskey.equals( "" ) )
+        {
+            attributesMap.put( "accesskey", accesskey.replaceAll( "'", "\"" ) );
+        }
+
+        String tabindex = a.getAttributeValue( "tabindex" );
+        if( tabindex != null && !tabindex.equals( "" ) )
+        {
+            attributesMap.put( "tabindex", tabindex.replaceAll( "'", "\"" ) );
+        }
+
+        String target = a.getAttributeValue( "target" );
+        if( target != null && !target.equals( "" ) )
+        {
+            attributesMap.put( "target", target.replaceAll( "'", "\"" ) );
+        }
+
+        return attributesMap;
+    }
+
+    /**
+     * Converts the entries in the map to a string for use in a wiki link.
+     */
+    private String augmentedWikiLinkMapToString( Map attributesMap )
+    {
+        StringBuffer sb = new StringBuffer();
+
+        for ( Iterator itr = attributesMap.entrySet().iterator(); itr.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry)itr.next();
+            String attributeName = (String)entry.getKey();
+            String attributeValue = (String)entry.getValue();
+
+            sb.append( " " + attributeName + "='" + attributeValue + "'" );
+        }
+
+        return sb.toString().trim();
+    }
+
+    private Map getStylePropertiesLowerCase( Element base ) throws IOException
+    {
+        String n = base.getName().toLowerCase();
+
+        //"font-weight: bold; font-style: italic;"
+        String style = base.getAttributeValue( "style" );
+        if( style == null )
+        {
+            style = "";
+        }
+
+        if( n.equals( "p" ) || n.equals( "div" ) )
+        {
+            String align = base.getAttributeValue( "align" );
+            if( align != null )
+            {
+                // only add the value of the align attribute if the text-align style didn't already exist.
+                if( style.indexOf( "text-align" ) == -1 )
+                {
+                    style = style + ";text-align:" + align + ";";
+                }
+            }
+        }
+
+
+
+        if( n.equals( "font" ) )
+        {
+            String color = base.getAttributeValue( "color" );
+            String face = base.getAttributeValue( "face" );
+            String size = base.getAttributeValue( "size" );
+            if( color != null )
+            {
+                style = style + "color:" + color + ";";
+            }
+            if( face != null )
+            {
+                style = style + "font-family:" + face + ";";
+            }
+            if( size != null )
+            {
+                if( size.equals( "1" ) )
+                {
+                    style = style + "font-size:xx-small;";
+                }
+                else if( size.equals( "2" ) )
+                {
+                    style = style + "font-size:x-small;";
+                }
+                else if( size.equals( "3" ) )
+                {
+                    style = style + "font-size:small;";
+                }
+                else if( size.equals( "4" ) )
+                {
+                    style = style + "font-size:medium;";
+                }
+                else if( size.equals( "5" ) )
+                {
+                    style = style + "font-size:large;";
+                }
+                else if( size.equals( "6" ) )
+                {
+                    style = style + "font-size:x-large;";
+                }
+                else if( size.equals( "7" ) )
+                {
+                    style = style + "font-size:xx-large;";
+                }
+            }
+        }
+
+        if( style.equals( "" ) )
+        {
+            return null;
+        }
+
+        style = style.replace( ';', '\n' ).toLowerCase();
+        LinkedHashMap m = new LinkedHashMap();
+        new PersistentMapDecorator( m ).load( new ByteArrayInputStream( style.getBytes() ) );
+        return m;
+    }
+
+    private String trimLink( String ref )
+    {
+        if( ref == null )
+        {
+            return null;
+        }
+        try
+        {
+            ref = URLDecoder.decode( ref, UTF8 );
+            ref = ref.trim();
+            if( ref.startsWith( m_config.getAttachPage() ) )
+            {
+                ref = ref.substring( m_config.getAttachPage().length() );
+            }
+            if( ref.startsWith( m_config.getWikiJspPage() ) )
+            {
+                ref = ref.substring( m_config.getWikiJspPage().length() );
+
+                // Handle links with section anchors.
+                // For example, we need to translate the html string "TargetPage#section-TargetPage-Heading2"
+                // to this wiki string "TargetPage#Heading2".
+                ref = ref.replaceFirst( ".+#section-(.+)-(.+)", "$1#$2" );
+            }
+            if( ref.startsWith( m_config.getEditJspPage() ) )
+            {
+                ref = ref.substring( m_config.getEditJspPage().length() );
+            }
+            if( m_config.getPageName() != null )
+            {
+                if( ref.startsWith( m_config.getPageName() ) )
+                {
+                    ref = ref.substring( m_config.getPageName().length() );
+                }
+            }
+        }
+        catch ( UnsupportedEncodingException e )
+        {
+            // Shouldn't happen...
+        }
+        return ref;
+    }
+
+    // FIXME: These should probably be better used with java.util.Stack
+
+    static class LiStack
+    {
+
+        private StringBuffer m_li = new StringBuffer();
+
+        public void push( String c )
+        {
+            m_li.append( c );
+        }
+
+        public void pop()
+        {
+            m_li = m_li.deleteCharAt( m_li.length()-1 );
+            // m_li = m_li.substring( 0, m_li.length() - 1 );
+        }
+
+        public String toString()
+        {
+            return m_li.toString();
+        }
+
+    }
+
+    class PreStack
+    {
+
+        private int m_pre = 0;
+
+        public boolean isPreMode()
+        {
+            return m_pre > 0;
+        }
+
+        public void push()
+        {
+            m_pre++;
+            m_outTimmer.setWhitespaceTrimMode( !isPreMode() );
+        }
+
+        public void pop()
+        {
+            m_pre--;
+            m_outTimmer.setWhitespaceTrimMode( !isPreMode() );
+        }
+
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/XHtmlToWikiConfig.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/XHtmlToWikiConfig.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/XHtmlToWikiConfig.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/htmltowiki/XHtmlToWikiConfig.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,158 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.htmltowiki;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.action.AttachActionBean;
+import com.ecyrd.jspwiki.action.EditActionBean;
+import com.ecyrd.jspwiki.action.PageInfoActionBean;
+import com.ecyrd.jspwiki.action.ViewActionBean;
+
+/**
+ *  Defines a Wiki configuration to XHtmlToWikiTranslator, including things like
+ *  URLs.
+ *
+ * @author Sebastian Baltes (sbaltes@gmx.com)
+ */
+public class XHtmlToWikiConfig
+{
+    private String m_outlink = "outlink";
+
+    private String m_pageInfoJsp = "PageInfo.jsp";
+
+    private String m_wikiJspPage = "Wiki.jsp?page=";
+
+    private String m_editJspPage = "Edit.jsp?page=";
+
+    private String m_attachPage = "attach?page=";
+
+    private String m_pageName;
+
+    public XHtmlToWikiConfig()
+    {}
+
+    /**
+     *  The constructor initializes the different internal fields
+     *  according to the current URLConstructor.
+     *
+     * @param wikiContext
+     */
+    public XHtmlToWikiConfig( WikiContext wikiContext )
+    {
+        setWikiContext( wikiContext );
+
+        //
+        //  Figure out the actual URLs.
+        //
+        //  NB: The logic here will fail if you add something else after
+        //      the Wiki page name in VIEW or ATTACH
+        //
+        
+        m_wikiJspPage = wikiContext.getContext().getURL( ViewActionBean.class, "" );
+
+        m_editJspPage = wikiContext.getContext().getURL( EditActionBean.class, "" );
+
+        m_attachPage = wikiContext.getContext().getURL( AttachActionBean.class, "" );
+
+        m_pageInfoJsp = wikiContext.getContext().getURL( PageInfoActionBean.class, "" );
+    }
+
+    /*
+    // FIXME: Unused.
+    private String removeLast(String str, String remove )
+    {
+        int idx = str.lastIndexOf( remove );
+
+        if( idx != -1 )
+        {
+            str = StringUtils.left( str, idx ) + StringUtils.substring( str, idx+remove.length() );
+        }
+
+        return str;
+    }
+    */
+    private void setWikiContext( WikiContext wikiContext )
+    {
+        if( wikiContext.getPage() != null )
+        {
+            setPageName( wikiContext.getPage().getName() + '/' );
+        }
+    }
+
+    public String getAttachPage()
+    {
+        return m_attachPage;
+    }
+
+    public void setAttachPage( String attachPage )
+    {
+        m_attachPage = attachPage;
+    }
+
+    public String getOutlink()
+    {
+        return m_outlink;
+    }
+
+    public void setOutlink( String outlink )
+    {
+        m_outlink = outlink;
+    }
+
+    public String getPageInfoJsp()
+    {
+        return m_pageInfoJsp;
+    }
+
+    public void setPageInfoJsp( String pageInfoJsp )
+    {
+        m_pageInfoJsp = pageInfoJsp;
+    }
+
+    public String getPageName()
+    {
+        return m_pageName;
+    }
+
+    public void setPageName( String pageName )
+    {
+        m_pageName = pageName;
+    }
+
+    public String getWikiJspPage()
+    {
+        return m_wikiJspPage;
+    }
+
+    public void setWikiJspPage( String wikiJspPage )
+    {
+        m_wikiJspPage = wikiJspPage;
+    }
+
+    public String getEditJspPage()
+    {
+        return m_editJspPage;
+    }
+
+    public void setEditJspPage( String editJspPage )
+    {
+        m_editJspPage = editJspPage;
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/i18n/InternationalizationManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/i18n/InternationalizationManager.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/i18n/InternationalizationManager.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/i18n/InternationalizationManager.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,96 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.i18n;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import com.ecyrd.jspwiki.WikiEngine;
+
+/**
+ *  Manages all internationalization in JSPWiki.
+ *
+ *  @author Janne Jalkanen
+ *  @since 2.6
+ */
+public class InternationalizationManager
+{
+    /** The name of the ResourceBundle which contains any and all JSPWiki core
+     *  resource strings.  It's value is {@value}.
+     */
+    public static final String CORE_BUNDLE = "CoreResources";
+    // public static final String JSPWIKI_BUNDLE = "jspwiki";
+    // public static final String PLUGINS_BUNDLE = "plugins";
+
+    /**
+     *  Constructs a new InternationalizationManager.
+     *
+     *  @param engine To which engine this belongs to
+     */
+    public InternationalizationManager( WikiEngine engine )
+    {
+    }
+
+    /**
+     *  Returns a String from the CORE_BUNDLE using English as the default
+     *  locale.
+     *
+     *  @param key Key to find
+     *  @return The English string
+     *  @throws MissingResourceException If there is no such key
+     */
+    public String get( String key ) throws MissingResourceException
+    {
+        return get( CORE_BUNDLE, Locale.ENGLISH, key );
+    }
+
+    /**
+     *  Finds a resource bundle.
+     *
+     *  @param bundle The ResourceBundle to find.  Must exist.
+     *  @param locale The Locale to use.  Set to null to get the default locale.
+     *  @return A localized string
+     *  @throws MissingResourceException If the key cannot be located at all, even from the default locale.
+     */
+    public ResourceBundle getBundle( String bundle, Locale locale ) throws MissingResourceException
+    {
+        if( locale == null )
+            locale = Locale.getDefault();
+
+        ResourceBundle b = ResourceBundle.getBundle(bundle,locale);
+
+        return b;
+    }
+
+    /**
+     *  If you are too lazy to open your own bundle, use this method
+     *  to get a string simply from a bundle.
+     *  @param bundle Which bundle the string is in
+     *  @param locale Locale to use - null for default
+     *  @param key    Which key to use.
+     *  @return A localized string (or from the default language, if not found)
+     *  @throws MissingResourceException If the key cannot be located at all, even from the default locale.
+     */
+    public String get( String bundle, Locale locale, String key ) throws MissingResourceException
+    {
+        return getBundle(bundle,locale).getString(key);
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/InternalModule.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/InternalModule.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/InternalModule.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/InternalModule.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,38 @@
+/* 
+   JSPWiki - a JSP-based WikiWiki clone.
+
+   Copyright (C) 2001-2006 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+package com.ecyrd.jspwiki.modules;
+
+/**
+ *  This is a simple interface which is implemented by a number of JSPWiki
+ *  components to signal that they should not be included in things like
+ *  module listings and so on.  Because JSPWiki reuses its internal module
+ *  mechanisms for its own use as well (e.g. RenderingManager uses a PageFilter
+ *  to catch page saves), it's sort of dumb to have these all appear in the
+ *  "installed filters" list.
+ *  <p>
+ *  A plugin developer should never implement this interface.
+ *  
+ *  @author jalkanen
+ *  @since 2.4
+ */
+public interface InternalModule
+{
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/ModuleManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/ModuleManager.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/ModuleManager.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/ModuleManager.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,72 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.modules;
+
+import java.util.Collection;
+
+import com.ecyrd.jspwiki.Release;
+import com.ecyrd.jspwiki.WikiEngine;
+
+/**
+ *  Superclass for all JSPWiki managers for modules (plugins, etc).
+ *  @author jalkanen
+ */
+public abstract class ModuleManager
+{
+
+    /**
+     * Location of the property-files of plugins.
+     *  (Each plugin should include this property-file in its jar-file)
+     */
+    public static final String PLUGIN_RESOURCE_LOCATION = "ini/jspwiki_module.xml";
+    
+    public static final String LOAD_INCOMPATIBLE_MODULES = "jspwiki.loadIncompatibleModules";
+    
+    protected WikiEngine m_engine;
+    
+    private boolean m_loadIncompatibleModules = false;
+    
+    public ModuleManager( WikiEngine engine )
+    {
+        m_engine = engine;
+    }
+    
+    public boolean checkCompatibility( WikiModuleInfo info )
+    {
+        if( !m_loadIncompatibleModules )
+        {
+            String minVersion = info.getMinVersion();
+            String maxVersion = info.getMaxVersion();
+            
+            return Release.isNewerOrEqual( minVersion ) && Release.isOlderOrEqual( maxVersion );
+        }
+        
+        return true;
+    }
+    
+    /**
+     * Returns a collection of modules currently managed by this ModuleManager.  Each
+     * entry is an instance of the WikiModuleInfo class.  This method should return something
+     * which is safe to iterate over, even if the underlying collection changes.
+     * 
+     * @return A Collection of WikiModuleInfo instances.
+     */
+    public abstract Collection modules();
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/WikiModuleInfo.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/WikiModuleInfo.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/WikiModuleInfo.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/modules/WikiModuleInfo.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,181 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.modules;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URL;
+
+import org.jdom.Element;
+
+import com.ecyrd.jspwiki.FileUtil;
+
+/**
+ *  A WikiModule describes whatever JSPWiki plugin there is: it can be a plugin,
+ *  an editor, a filter, etc.
+ *  @author jalkanen
+ *  @since 2.4
+ */
+public class WikiModuleInfo
+    implements Comparable
+{
+    protected String m_name;
+    protected String m_scriptLocation;
+    protected String m_scriptText;
+    protected String m_stylesheetLocation;
+    protected String m_stylesheetText;
+    protected String m_author;
+    protected URL    m_resource;
+    protected String m_minVersion;
+    protected String m_maxVersion;
+    protected String m_adminBeanClass;
+    
+    public WikiModuleInfo( String name )
+    {
+        m_name = name;
+    }
+    
+    /**
+     *  The WikiModuleInfo is equal to another WikiModuleInfo, if the name is equal.  All
+     *  objects are unique across JSPWiki.
+     */
+    public boolean equals(Object obj)
+    {
+        if( obj instanceof WikiModuleInfo )
+        {
+            return ((WikiModuleInfo)obj).m_name.equals( m_name );
+        }
+        
+        return false;
+    }
+
+
+    public int hashCode()
+    {
+        return m_name.hashCode();
+    }
+
+
+    protected void initializeFromXML( Element el )
+    {
+        m_scriptLocation     = el.getChildText("script");
+        m_stylesheetLocation = el.getChildText("stylesheet");
+        m_author             = el.getChildText("author");
+        m_minVersion         = el.getChildText("minVersion");
+        m_maxVersion         = el.getChildText("maxVersion");
+        m_adminBeanClass     = el.getChildText("adminBean");
+    }
+
+    public String getAdminBeanClass()
+    {
+        return m_adminBeanClass;
+    }
+    
+    /**
+     *  Returns the common name for this particular module.  Note that
+     *  this is not the class name, nor is it an alias.  For different modules
+     *  the name may have different meanings.
+     *  <p>
+     *  Every module defines a name, so this method should never return null.
+     *  
+     *  @return A module name.
+     */
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public String getStylesheetLocation()
+    {
+        return m_stylesheetLocation;
+    }
+
+    public String getScriptLocation()
+    {
+        return m_scriptLocation;
+    }
+
+    /**
+     *  Returns the name of the author of this plugin (if defined).
+     * @return Author name, or null.
+     */
+    public String getAuthor()
+    {
+        return m_author;
+    }
+
+
+    public String getMinVersion()
+    {
+        return m_minVersion;
+    }
+    
+    public String getMaxVersion()
+    {
+        return m_maxVersion;
+    }
+
+    protected String getTextResource(String resourceLocation) 
+        throws IOException
+    {
+        if(m_resource == null)
+        {
+            return "";
+        }
+    
+        // The text of this resource should be loaded from the same
+        //   jar-file as the jspwiki_modules.xml -file! This is because 2 plugins
+        //   could have the same name of the resourceLocation!
+        //   (2 plugins could have their stylesheet-files in 'ini/jspwiki.css')
+    
+        // So try to construct a resource that loads this resource from the
+        //   same jar-file.
+        String spec = m_resource.toString();
+    
+        // Replace the 'PLUGIN_RESOURCE_LOCATION' with the requested
+        //   resourceLocation.
+        int length = ModuleManager.PLUGIN_RESOURCE_LOCATION.length();
+        spec = spec.substring(0, spec.length() - length) + resourceLocation;
+    
+        URL url = new URL(spec);
+        BufferedInputStream   in  = new BufferedInputStream(url.openStream());
+        ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
+        
+        FileUtil.copyContents( in, out );
+    
+        in.close();
+        String text = out.toString();
+        out.close();
+        
+        return text;
+    }
+
+    public int compareTo(Object arg0)
+    {
+        if( arg0 instanceof WikiModuleInfo )
+        {
+            return m_name.compareTo( ((WikiModuleInfo)arg0).getName() );
+        }
+        
+        throw new ClassCastException(arg0.getClass().getName());
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/package.html
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/package.html?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/package.html (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/package.html Tue Feb 12 21:53:55 2008
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Insert title here</title>
+</head>
+<body>
+The chief package of JSPWiki.
+
+This package contains most of the core classes that JSPWiki uses, and a bunch of other ones.
+
+<h3>Package Specification</h3>
+
+<h3>Related Documentation</h3>
+
+</body>
+</html>
\ No newline at end of file



Mime
View raw message