You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by bo...@apache.org on 2015/07/19 22:50:19 UTC

svn commit: r1691854 [1/3] - in /tapestry/tapestry-site/trunk: ./ src/main/java/org/apache/cxf/cwiki/ src/main/resources/ src/test/ src/test/resources/ src/test/resources/wadl/

Author: bobharner
Date: Sun Jul 19 20:50:18 2015
New Revision: 1691854

URL: http://svn.apache.org/r1691854
Log:
Applied Dan Kulp's latest cxf-web changes to our copy of the SiteExporter code, and updated the README.txt to match

Added:
    tapestry/tapestry-site/trunk/src/main/resources/
    tapestry/tapestry-site/trunk/src/main/resources/confluence-rest.wadl
    tapestry/tapestry-site/trunk/src/test/
    tapestry/tapestry-site/trunk/src/test/resources/
    tapestry/tapestry-site/trunk/src/test/resources/wadl/
Modified:
    tapestry/tapestry-site/trunk/README
    tapestry/tapestry-site/trunk/pom.xml
    tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java
    tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/Page.java
    tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/SiteExporter.java

Modified: tapestry/tapestry-site/trunk/README
URL: http://svn.apache.org/viewvc/tapestry/tapestry-site/trunk/README?rev=1691854&r1=1691853&r2=1691854&view=diff
==============================================================================
--- tapestry/tapestry-site/trunk/README (original)
+++ tapestry/tapestry-site/trunk/README Sun Jul 19 20:50:18 2015
@@ -8,7 +8,12 @@ static website checked out to a local di
 
 To build the SiteExporter Java (command-line) program itself:
 
+  mvn cxf-wadl2java:wadl2java
   mvn install
+  
+The first step above builds some generated WADL code that is referenced in
+SiteExporter.java, so you'll need to do that step (and maybe a maven update
+project) before compiler errors will go away in your IDE. 
 
 To run the SiteExporter program, you will need to pass credentials for a valid
 Confluence user, and specify the directory where the static content resides.

Modified: tapestry/tapestry-site/trunk/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry-site/trunk/pom.xml?rev=1691854&r1=1691853&r2=1691854&view=diff
==============================================================================
--- tapestry/tapestry-site/trunk/pom.xml (original)
+++ tapestry/tapestry-site/trunk/pom.xml Sun Jul 19 20:50:18 2015
@@ -28,18 +28,17 @@
     <parent>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-parent</artifactId>
-        <version>2.6.8</version>
+        <version>3.1.1</version>
     </parent>
 
     <properties>
-        <cxf.version>2.6.8</cxf.version>
+        <cxf.version>3.1.1</cxf.version>
         <extra.arg></extra.arg>
         <svn.arg1></svn.arg1>
         <svn.arg2></svn.arg2>
         <site.output>${basedir}/content</site.output>
         <cxf.site.output>${site.output}</cxf.site.output>
-        <maven.test.skip>true</maven.test.skip>
-        <checkstyle.skip>true</checkstyle.skip>
+        <!--maven.test.skip>true</maven.test.skip-->
     </properties>
 
     <dependencies>
@@ -50,6 +49,16 @@
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-client</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
             <artifactId>cxf-rt-transports-http</artifactId>
             <version>${cxf.version}</version>
         </dependency>
@@ -62,6 +71,24 @@
             <artifactId>tagsoup</artifactId>
             <version>1.2.1</version>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.5.4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>6.8</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>junit</groupId>
+                    <artifactId>junit</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
     </dependencies>
 
     <build>
@@ -98,6 +125,30 @@
                 </plugin>
             </plugins>
         </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.cxf</groupId>
+                <artifactId>cxf-wadl2java-plugin</artifactId>
+                <version>${cxf.version}</version>
+                <executions>
+                    <execution>
+                        <id>generate-sources</id>
+                        <phase>generate-sources</phase>
+                        <configuration>
+                            <sourceRoot>${basedir}/target/generated/src/main/java</sourceRoot>
+                            <wadlOptions>
+                                <wadlOption>
+                                    <wadl>${basedir}/src/main/resources/confluence-rest.wadl</wadl>
+                                </wadlOption>
+                            </wadlOptions>
+                        </configuration>
+                        <goals>
+                            <goal>wadl2java</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
     </build>
 
     <profiles>

Modified: tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java?rev=1691854&r1=1691853&r2=1691854&view=diff
==============================================================================
--- tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java (original)
+++ tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java Sun Jul 19 20:50:18 2015
@@ -140,7 +140,10 @@ public class ConfluenceCleanupWriter ext
             || "a".equals(qName.toLowerCase())) {
             String href = atts.getValue("href");
             //Confluence sticks this on links from blog entries, but it's invalid
-            newAtts.remove("data-username"); 
+            newAtts.remove("data-username");
+            if (href != null) {
+                href = href.trim();
+            }
             if (href != null && href.startsWith("/confluence/display/")) {
                 String params = "";
                 if (href.indexOf('#') != -1) {
@@ -225,7 +228,7 @@ public class ConfluenceCleanupWriter ext
             }
             String cls = atts.getValue("class");
             if (href != null && href.startsWith("/confluence/images/")) {
-                newAtts.addMapping("src", SiteExporter.HOST + href);
+                newAtts.addMapping("src", href.replaceFirst("^/confluence/images/", "/images/confluence/"));
             } else if (href != null && href.startsWith("/confluence/download/attachments")) {
                 if (cls == null || cls.contains("confluence-embedded-image")) {
                     href = href.substring(0, href.lastIndexOf('?'));

Modified: tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/Page.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/Page.java?rev=1691854&r1=1691853&r2=1691854&view=diff
==============================================================================
--- tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/Page.java (original)
+++ tapestry/tapestry-site/trunk/src/main/java/org/apache/cxf/cwiki/Page.java Sun Jul 19 20:50:18 2015
@@ -1,632 +1,655 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.cxf.cwiki;
-
-
-import java.io.Serializable;
-import java.io.StringReader;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.datatype.XMLGregorianCalendar;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-
-import org.apache.cxf.common.util.StringUtils;
-import org.apache.cxf.helpers.DOMUtils;
-import org.ccil.cowan.tagsoup.Parser;
-
-/**
- * 
- */
-public class Page extends AbstractPage implements Serializable {
-    
-
-    private static final long serialVersionUID = 1L;
-    private static final Map<String, String> CODE_TYPE_MAP = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
-    static {
-        CODE_TYPE_MAP.put("applescript", "shBrushAppleScript.js");
-        CODE_TYPE_MAP.put("actionscript3", "shBrushAS3.js");
-        CODE_TYPE_MAP.put("as3", "shBrushAS3.js");
-        CODE_TYPE_MAP.put("bash", "shBrushBash.js");
-        CODE_TYPE_MAP.put("shell", "shBrushBash.js");
-        CODE_TYPE_MAP.put("coldfusion", "shBrushColdFusion.js");
-        CODE_TYPE_MAP.put("cpp", "shBrushCpp.js");
-        CODE_TYPE_MAP.put("c", "shBrushCpp.js");
-        CODE_TYPE_MAP.put("c#", "shBrushCSharp.js");
-        CODE_TYPE_MAP.put("c-sharp", "shBrushCSharp.js");
-        CODE_TYPE_MAP.put("csharp", "shBrushCSharp.js");
-        CODE_TYPE_MAP.put("css", "shBrushCss.js");
-        CODE_TYPE_MAP.put("delphi", "shBrushDelphi.js");
-        CODE_TYPE_MAP.put("pascal", "shBrushDelphi.js");
-        CODE_TYPE_MAP.put("diff", "shBrushDiff.js");
-        CODE_TYPE_MAP.put("patch", "shBrushDiff.js");
-        CODE_TYPE_MAP.put("pas", "shBrushDiff.js");
-        CODE_TYPE_MAP.put("erl", "shBrushErlang.js");
-        CODE_TYPE_MAP.put("erlang", "shBrushErlang.js");
-        CODE_TYPE_MAP.put("groovy", "shBrushGroovy.js");
-        CODE_TYPE_MAP.put("java", "shBrushJava.js");
-        CODE_TYPE_MAP.put("jfx", "shBrushJavaFX.js");
-        CODE_TYPE_MAP.put("javafx", "shBrushJavaFX.js");
-        CODE_TYPE_MAP.put("js", "shBrushJScript.js");
-        CODE_TYPE_MAP.put("jscript", "shBrushJScript.js");
-        CODE_TYPE_MAP.put("javascript", "shBrushJScript.js");
-        CODE_TYPE_MAP.put("perl", "shBrushPerl.js");
-        CODE_TYPE_MAP.put("pl", "shBrushPerl.js");
-        CODE_TYPE_MAP.put("php", "shBrushPhp.js");
-        CODE_TYPE_MAP.put("text", "shBrushPlain.js");
-        CODE_TYPE_MAP.put("plain", "shBrushPlain.js");
-        CODE_TYPE_MAP.put("none", "shBrushPlain.js");
-        CODE_TYPE_MAP.put("py", "shBrushPython.js");
-        CODE_TYPE_MAP.put("python", "shBrushPython.js");
-        CODE_TYPE_MAP.put("powershell", "shBrushPowerShell.js");
-        CODE_TYPE_MAP.put("ps", "shBrushPowerShell.js");
-        CODE_TYPE_MAP.put("posh", "shBrushPowerShell.js");
-        CODE_TYPE_MAP.put("ruby", "shBrushRuby.js");
-        CODE_TYPE_MAP.put("rails", "shBrushRuby.js");
-        CODE_TYPE_MAP.put("ror", "shBrushRuby.js");
-        CODE_TYPE_MAP.put("rb", "shBrushRuby.js");
-        CODE_TYPE_MAP.put("sass", "shBrushSass.js");
-        CODE_TYPE_MAP.put("scss", "shBrushSass.js");
-        CODE_TYPE_MAP.put("scala", "shBrushScala.js");
-        CODE_TYPE_MAP.put("sql", "shBrushSql.js");
-        CODE_TYPE_MAP.put("vb", "shBrushVb.js");
-        CODE_TYPE_MAP.put("vbnet", "shBrushVb.js");
-        CODE_TYPE_MAP.put("xml", "shBrushXml.js");
-        CODE_TYPE_MAP.put("xhtml", "shBrushXml.js");
-        CODE_TYPE_MAP.put("xslt", "shBrushXml.js");
-        CODE_TYPE_MAP.put("html", "shBrushXml.js");
-        CODE_TYPE_MAP.put("html/xml", "shBrushXml.js");
-    }
-    
-    final XMLGregorianCalendar modified;
-    final String parent;
-    final String spaceKey;
-    Map<String, String> attachments;
-    Set<String> includes;
-    Map<String, Integer> childrenOf;
-    boolean hasBlog;
-    Set<String> codeTypes;
-    
-    transient String renderedContent;
-    transient String renderedDivContent;
-    transient String divIdForContent;
-    
-    transient SiteExporter exporter;
-
-    public Page(Document doc, SiteExporter exp) throws Exception {
-        this(DOMUtils.getFirstElement(doc.getDocumentElement()), exp);
-    }
-    
-    public Page(Element root, SiteExporter exp) throws Exception {
-        super(root);
-        exporter = exp;
-        //org.apache.cxf.helpers.XMLUtils.printDOM(doc.getDocumentElement());
-
-        parent = DOMUtils.getChildContent(root, "parentId");
-        spaceKey = DOMUtils.getChildContent(root, "space");
-
-        String mod = DOMUtils.getChildContent(root, "modified");
-        modified = DatatypeFactory.newInstance().newXMLGregorianCalendar(mod);
-        modified.setMillisecond(0);
-        
-        String c = DOMUtils.getChildContent(root, "content");
-        if (c != null) {
-            if (exp.getAPIVersion() == 2) {
-                checkContentV2(c);
-            } else {
-                checkContentV1(c);                
-            }
-        }
-    }
-    /*
-     * Makes a shallow copy without any content
-     */
-    public Page(Page source) {
-        super(source);
-        this.modified = source.modified;
-        this.parent = source.parent;
-        this.spaceKey = source.spaceKey;
-        this.attachments = source.attachments;
-        this.includes = source.includes;
-        this.childrenOf = source.childrenOf;
-        this.exporter = source.exporter;
-        this.hasBlog = source.hasBlog;
-        this.codeTypes = source.codeTypes;
-    }
-    
-    private void checkContentV2(final String c) {
-        try {
-            //if ("Content Based Router".equals(title)) {
-            //    System.out.println(c);
-            //}
-            
-            XMLReader reader = new Parser();
-            reader.setFeature(Parser.namespacesFeature, true);
-            reader.setFeature(Parser.namespacePrefixesFeature, true);
-            reader.setProperty(Parser.schemaProperty, new org.ccil.cowan.tagsoup.HTMLSchema() {
-                {
-                    //problem with nested lists that the confluence {toc} macro creates
-                    elementType("ul", M_LI, M_BLOCK | M_LI, 0);
-                }
-            });
-            reader.setContentHandler(new V2ContentHandler(this));
-            reader.parse(new InputSource(new StringReader(c)));
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    private void checkContentV1(String c) {
-        int idx = c.indexOf("{children");
-        while (idx != -1) {
-            if (childrenOf == null) {
-                childrenOf = new HashMap<String, Integer>();
-            }
-            idx += 9;
-            if (c.charAt(idx) != '}') {
-                // {children:page=Foo|...}
-                idx++;
-                int idx2 = c.indexOf('}', idx);
-                String paramString = c.substring(idx, idx2);
-                String params[] = paramString.split("\\||=");
-                String page = null;
-                int depth = 1;
-                for (int x = 0; x < params.length; x++) {
-                    if ("page".equals(params[x])) {
-                        page = params[x + 1];
-                        x++;
-                    } else if ("depth".equals(params[x])) {
-                        depth = Integer.parseInt(params[x + 1]);
-                        x++;
-                    }
-                }
-                childrenOf.put(page, depth);
-            } else {
-                childrenOf.put(title, 1);
-            }
-            idx = c.indexOf("{children", idx);
-        }
-        
-        idx = c.indexOf("{include:");
-        while (idx != -1) {
-            int idx2 = c.indexOf("}", idx);
-            String inc = c.substring(idx + 9, idx2);
-            if (includes == null) {
-                includes = new CopyOnWriteArraySet<String>();
-            }
-            includes.add(inc);
-            idx = c.indexOf("{include:", idx2);
-        }
-        idx = c.indexOf("{blog-posts");
-        if (idx != -1) {
-            hasBlog = true;
-        }
-        handleCode(c);
-    }
-
-    private void handleCode(String c) {
-        int idx = c.indexOf("{code");
-        while (idx != -1) {
-            String type = "java";
-            idx += 5;
-            if (c.charAt(idx) != '}') {
-                idx++;
-                int idx2 = c.indexOf('}', idx);
-                if (idx2 != -1) {
-                    String paramString = c.substring(idx, idx2);
-                    String params[] = paramString.split("\\||=");
-                    for (int x = 0; x < params.length; x++) {
-                        if ("type".equalsIgnoreCase(params[x])) {
-                            type = params[x + 1];
-                            x++;
-                        } else if (CODE_TYPE_MAP.containsKey(params[x].toLowerCase())) {
-                            type = params[x];
-                        }
-                    }
-                }
-            }
-
-            if (codeTypes == null) {
-                codeTypes = new CopyOnWriteArraySet<String>();
-            }
-            codeTypes.add(type);
-            idx = c.indexOf("{code", idx + 1);
-        } 
-        idx = c.indexOf("{snippet");
-        while (idx != -1) {
-            String type = "java";
-            idx += 8;
-            if (c.charAt(idx) != '}') {
-                idx++;
-                int idx2 = c.indexOf('}', idx);
-                if (idx2 != -1) {
-                    String paramString = c.substring(idx, idx2);
-                    String params[] = paramString.split("\\||=");
-                    for (int x = 0; x < params.length; x++) {
-                        if ("lang".equalsIgnoreCase(params[x])) {
-                            type = params[x + 1];
-                            x++;
-                        } else if (CODE_TYPE_MAP.containsKey(params[x].toLowerCase())) {
-                            type = params[x];
-                        }
-                    }
-                }
-            }
-
-            if (codeTypes == null) {
-                codeTypes = new CopyOnWriteArraySet<String>();
-            }
-            codeTypes.add(type);
-            idx = c.indexOf("{snippet", idx + 1);
-        } 
-    }
-    
-    public boolean hasChildrenOf(String t, int d) {
-        if (childrenOf == null) {
-            return false;
-        }
-        Integer i = childrenOf.get(t);
-        if (i == null) {
-            return false;
-        }
-        return d <= i;
-    }
-    
-    public boolean includesPage(String s) {
-        if (includes == null) {
-            return false;
-        }
-        return includes.contains(s);
-    }
-    
-
-    public String getParentId() {
-        return parent;
-    }
-
-    public XMLGregorianCalendar getModifiedTime() {
-        return modified;
-    }
-
-    public void setContent(String c) {
-        renderedContent = c;
-    }
-    
-    public String getContent() {
-        return renderedContent;
-    }
-
-    public String getSpaceKey() {
-        return spaceKey;
-    }
-
-    public void addAttachment(String aid, String filename) {
-        if (attachments == null) {
-            attachments = new HashMap<String, String>();
-        }
-        attachments.put(aid, filename);
-    }
-    public String getAttachmentFilename(String aid) {
-        if (attachments == null) {
-            return null;
-        }
-        return attachments.get(aid);
-    }
-
-    public void setContentForDivId(String divId, String content) {
-        renderedDivContent = content;
-        divIdForContent = divId;
-    }
-
-    public String getContentForDivId(String divId) {
-        if (divId == null) {
-            return renderedContent;
-        }
-        if (divId.equals(divIdForContent)) {
-            return renderedDivContent;
-        }
-        return null;
-    }
-
-    public String getLink() {
-        StringBuffer buffer = new StringBuffer();
-        buffer.append("<a href=\"");
-        buffer.append(url);
-        buffer.append("\" title=\"");
-        buffer.append(title);
-        buffer.append("\">");
-        buffer.append(title);
-        buffer.append("</a>");
-        return buffer.toString();
-    }
-
-    public Space getSpace() {
-        return SiteExporter.getSpace(spaceKey);
-    }
-
-    public boolean hasChildren() {
-        return exporter.hasChildren(this);
-    }
-
-    public List<Page> getChildren() {
-        return exporter.getChildren(this);
-    }
-
-    protected void setExporter(SiteExporter exporter) {
-        this.exporter = exporter;
-    }
-    
-    protected SiteExporter getExporter() {
-        return exporter;
-    }
-
-    public boolean hasBlog() {
-        return hasBlog;
-    }
-    
-    public boolean getHasCode() {
-        return hasCode();
-    }
-
-    public boolean hasCode() {
-        if (codeTypes != null && !codeTypes.isEmpty()) {
-            return true;
-        }
-        if (includes != null) {
-            for (String i : includes) {
-                try {
-                    Page p = exporter.findPage(i);
-                    if (p != null && p.hasCode()) {
-                        return true;
-                    }
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-        return false;
-    }
-    
-    public Set<String> getCodeScripts() throws Exception {
-        Set<String> scripts = new HashSet<String>();
-        if (codeTypes != null) {
-            for (String s : codeTypes) {
-                String sc = CODE_TYPE_MAP.get(s);
-                if (sc == null) {
-                    System.out.println("WARNING: no code highlighter for " + s);
-                } else {
-                    scripts.add(sc);
-                }
-            }
-        }
-        if (scripts.isEmpty()) {
-            scripts.add(CODE_TYPE_MAP.get("java"));
-            scripts.add(CODE_TYPE_MAP.get("plain"));
-        }
-        if (includes != null) {
-            for (String i : includes) {
-                try {
-                    Page p = exporter.findPage(i);
-                    if (p != null && p.hasCode()) {
-                        scripts.addAll(p.getCodeScripts());
-                    } else if (p == null) {
-                        System.out.println("    Did not find page " + i);
-                    }
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-        return scripts;
-    }
-
-    
-    static class V2ContentHandler implements ContentHandler {
-        private final Page page;
-        
-        enum State {
-            NONE,
-            CHILDREN,
-            INCLUDE,
-            BLOG_POSTS,
-            CODE,
-        };
-        private State state = State.NONE;
-        private Map<String, String> params = new HashMap<String, String>();
-        private String paramName;
-        private boolean unmigrated;
-
-        V2ContentHandler(Page pg) {
-            page = pg;
-        }
-
-        public void setDocumentLocator(Locator locator) {
-        }
-
-        public void startDocument() throws SAXException {
-        }
-
-        public void endDocument() throws SAXException {
-        }
-
-        public void startPrefixMapping(String prefix, String uri) throws SAXException {
-        }
-
-        public void endPrefixMapping(String prefix) throws SAXException {
-        }
-
-        public void startElement(String uri, String localName, String qName, Attributes atts)
-            throws SAXException {
-            if ("macro".equals(localName)) {
-                String s = atts.getValue(uri, "name");
-                if ("children".equals(s)) {
-                    state = State.CHILDREN;
-                } else if ("include".equals(s)) {
-                    state = State.INCLUDE;
-                } else if ("blog-posts".equals(s)) {
-                    state = State.BLOG_POSTS;
-                } else if ("code".equals(s)) {
-                    state = State.CODE;
-                } else if ("snippet".equals(s)) {
-                    state = State.CODE;
-                } else if ("unmigrated-wiki-markup".equals(s)
-                    || "unmigrated-inline-wiki-markup".equals(s)) {
-                    if (!unmigrated) {
-                        System.out.println("WARNING: Page \"" + page.title + "\" (" 
-                            + page.spaceKey + ") has unmigrated wiki content.");
-                        unmigrated = true;
-                        //no idea what is in there, lets just turn on the code highlighting
-                        if (page.codeTypes == null) {
-                            page.codeTypes = new CopyOnWriteArraySet<String>();
-                        }
-                        page.codeTypes.add("java");
-                        page.codeTypes.add("xml");
-                        page.codeTypes.add("plain");
-                    }
-                } else {
-                    //System.out.println("Unknown macro: " + s);
-                }
-                params.clear();
-                paramName = null;
-            } else if ("parameter".equals(localName)) {
-                paramName = atts.getValue(uri, "name");
-            } else if ("default-parameter".equals(localName)) {
-                paramName = "default-parameter";
-            }
-        }
-
-        public void endElement(String uri, String localName, String qName) throws SAXException {
-            if ("macro".equals(localName)) {
-                switch (state) {
-                case CHILDREN: {
-                    String pageName = params.get("page");
-                    String depth = params.get("depth");
-                    if (depth == null || "".equals(depth.trim())) {
-                        depth = "1";
-                    }
-                    if (page.childrenOf == null) {
-                        page.childrenOf = new HashMap<String, Integer>();
-                    }
-                    if (pageName == null) {
-                        page.childrenOf.put(page.title, Integer.parseInt(depth));                    
-                    } else {
-                        page.childrenOf.put(pageName, Integer.parseInt(depth));
-                    }
-                    params.clear();
-                    state = State.NONE;
-                    break;
-                }
-                case INCLUDE: {
-                    if (page.includes == null) {
-                        page.includes = new CopyOnWriteArraySet<String>();
-                    }
-                    String inc = params.get("default-parameter");
-                    if (inc == null) {
-                        inc = params.get("title");
-                    }
-                    if (inc == null) {
-                        System.out.println(page.title + ": Did not find an include name " + params);
-                    } else {
-                        page.includes.add(inc);
-                    }
-                    break;
-                }
-                case BLOG_POSTS:
-                    page.hasBlog = true;
-                    break;
-                case CODE: {
-                    if (page.codeTypes == null) {
-                        page.codeTypes = new CopyOnWriteArraySet<String>();
-                    }
-                    String lang = null;
-                    for (Map.Entry<String, String> ent : params.entrySet()) {
-                        if ("language".equals(ent.getKey())) {
-                            lang = ent.getValue();
-                        } else if (ent.getKey().contains(":")) {
-                            String parts[] = ent.getKey().split(":");
-                            for (String s : parts) {
-                                if (("title".equals(s) && !params.containsKey("title"))
-                                    || (!params.containsKey("language") 
-                                        && ("xml".equals(s) || "java".equals(s)))) {
-                                    System.out.println("WARNING Page " + page.title + " has a broken code block");
-                                }
-                            }
-                        } else if ("default-parameter".equals(ent.getKey())) {
-                            String s = ent.getValue();
-                            if ("xml".equals(s) || "java".equals(s)) {
-                                lang = s;
-                            }
-                        }
-                    }
-                    /*
-                    if (page.getTitle().equals("Security")) {
-                        System.out.println(params);
-                        System.out.println("lang: " + lang);
-                    }
-                    */
-                    if (StringUtils.isEmpty(lang)) {
-                        lang = "java";
-                    }
-                    page.codeTypes.add(lang);
-                    break;
-                }                    
-                default:
-                    state = State.NONE;
-                    break;
-                }
-            } else if ("parameter".equals(localName)) {
-                paramName = null;
-            } else if ("default-parameter".equals(localName)) {
-                paramName = null;
-            }            
-        }
-
-        public void characters(char[] ch, int start, int length) throws SAXException {
-            if (paramName != null) {
-                params.put(paramName, new String(ch, start, length));
-            }
-        }
-
-        public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
-        }
-
-        public void processingInstruction(String target, String data) throws SAXException {
-        }
-
-        public void skippedEntity(String name) throws SAXException {
-        }
-    }
-    
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.cwiki;
+
+
+import java.io.Serializable;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.ccil.cowan.tagsoup.Parser;
+
+/**
+ * 
+ */
+public class Page extends AbstractPage implements Serializable {
+    
+
+    private static final long serialVersionUID = 1L;
+    private static final Map<String, String> CODE_TYPE_MAP = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
+    static {
+        CODE_TYPE_MAP.put("applescript", "shBrushAppleScript.js");
+        CODE_TYPE_MAP.put("actionscript3", "shBrushAS3.js");
+        CODE_TYPE_MAP.put("as3", "shBrushAS3.js");
+        CODE_TYPE_MAP.put("bash", "shBrushBash.js");
+        CODE_TYPE_MAP.put("shell", "shBrushBash.js");
+        CODE_TYPE_MAP.put("coldfusion", "shBrushColdFusion.js");
+        CODE_TYPE_MAP.put("cpp", "shBrushCpp.js");
+        CODE_TYPE_MAP.put("c", "shBrushCpp.js");
+        CODE_TYPE_MAP.put("c#", "shBrushCSharp.js");
+        CODE_TYPE_MAP.put("c-sharp", "shBrushCSharp.js");
+        CODE_TYPE_MAP.put("csharp", "shBrushCSharp.js");
+        CODE_TYPE_MAP.put("css", "shBrushCss.js");
+        CODE_TYPE_MAP.put("delphi", "shBrushDelphi.js");
+        CODE_TYPE_MAP.put("pascal", "shBrushDelphi.js");
+        CODE_TYPE_MAP.put("diff", "shBrushDiff.js");
+        CODE_TYPE_MAP.put("patch", "shBrushDiff.js");
+        CODE_TYPE_MAP.put("pas", "shBrushDiff.js");
+        CODE_TYPE_MAP.put("erl", "shBrushErlang.js");
+        CODE_TYPE_MAP.put("erlang", "shBrushErlang.js");
+        CODE_TYPE_MAP.put("groovy", "shBrushGroovy.js");
+        CODE_TYPE_MAP.put("java", "shBrushJava.js");
+        CODE_TYPE_MAP.put("jfx", "shBrushJavaFX.js");
+        CODE_TYPE_MAP.put("javafx", "shBrushJavaFX.js");
+        CODE_TYPE_MAP.put("js", "shBrushJScript.js");
+        CODE_TYPE_MAP.put("jscript", "shBrushJScript.js");
+        CODE_TYPE_MAP.put("javascript", "shBrushJScript.js");
+        CODE_TYPE_MAP.put("perl", "shBrushPerl.js");
+        CODE_TYPE_MAP.put("pl", "shBrushPerl.js");
+        CODE_TYPE_MAP.put("php", "shBrushPhp.js");
+        CODE_TYPE_MAP.put("text", "shBrushPlain.js");
+        CODE_TYPE_MAP.put("plain", "shBrushPlain.js");
+        CODE_TYPE_MAP.put("none", "shBrushPlain.js");
+        CODE_TYPE_MAP.put("py", "shBrushPython.js");
+        CODE_TYPE_MAP.put("python", "shBrushPython.js");
+        CODE_TYPE_MAP.put("powershell", "shBrushPowerShell.js");
+        CODE_TYPE_MAP.put("ps", "shBrushPowerShell.js");
+        CODE_TYPE_MAP.put("posh", "shBrushPowerShell.js");
+        CODE_TYPE_MAP.put("ruby", "shBrushRuby.js");
+        CODE_TYPE_MAP.put("rails", "shBrushRuby.js");
+        CODE_TYPE_MAP.put("ror", "shBrushRuby.js");
+        CODE_TYPE_MAP.put("rb", "shBrushRuby.js");
+        CODE_TYPE_MAP.put("sass", "shBrushSass.js");
+        CODE_TYPE_MAP.put("scss", "shBrushSass.js");
+        CODE_TYPE_MAP.put("scala", "shBrushScala.js");
+        CODE_TYPE_MAP.put("sql", "shBrushSql.js");
+        CODE_TYPE_MAP.put("vb", "shBrushVb.js");
+        CODE_TYPE_MAP.put("vbnet", "shBrushVb.js");
+        CODE_TYPE_MAP.put("xml", "shBrushXml.js");
+        CODE_TYPE_MAP.put("xhtml", "shBrushXml.js");
+        CODE_TYPE_MAP.put("xslt", "shBrushXml.js");
+        CODE_TYPE_MAP.put("html", "shBrushXml.js");
+        CODE_TYPE_MAP.put("html/xml", "shBrushXml.js");
+    }
+    
+    final XMLGregorianCalendar modified;
+    final String parent;
+    final String spaceKey;
+    Map<String, String> attachments;
+    Set<String> includes;
+    Map<String, Integer> childrenOf;
+    boolean hasBlog;
+    Set<String> codeTypes;
+    
+    transient String renderedContent;
+    transient String renderedDivContent;
+    transient String divIdForContent;
+    
+    transient SiteExporter exporter;
+
+    public Page(Document doc, SiteExporter exp) throws Exception {
+        this(DOMUtils.getFirstElement(doc.getDocumentElement()), exp);
+    }
+    
+    public Page(Element root, SiteExporter exp) throws Exception {
+        super(root);
+        exporter = exp;
+        //org.apache.cxf.helpers.XMLUtils.printDOM(doc.getDocumentElement());
+
+        parent = DOMUtils.getChildContent(root, "parentId");
+        spaceKey = DOMUtils.getChildContent(root, "space");
+
+        String mod = DOMUtils.getChildContent(root, "modified");
+        modified = DatatypeFactory.newInstance().newXMLGregorianCalendar(mod);
+        modified.setMillisecond(0);
+        
+        String c = DOMUtils.getChildContent(root, "content");
+        if (c != null) {
+            if (exp.getAPIVersion() == 2) {
+                checkContentV2(c);
+            } else {
+                checkContentV1(c);                
+            }
+        }
+    }
+    /*
+     * Makes a shallow copy without any content
+     */
+    public Page(Page source) {
+        super(source);
+        this.modified = source.modified;
+        this.parent = source.parent;
+        this.spaceKey = source.spaceKey;
+        this.attachments = source.attachments;
+        this.includes = source.includes;
+        this.childrenOf = source.childrenOf;
+        this.exporter = source.exporter;
+        this.hasBlog = source.hasBlog;
+        this.codeTypes = source.codeTypes;
+    }
+    
+    private void checkContentV2(final String c) {
+        try {
+            //if ("Content Based Router".equals(title)) {
+            //    System.out.println(c);
+            //}
+            
+            XMLReader reader = new Parser();
+            reader.setFeature(Parser.namespacesFeature, true);
+            reader.setFeature(Parser.namespacePrefixesFeature, true);
+            reader.setProperty(Parser.schemaProperty, new org.ccil.cowan.tagsoup.HTMLSchema() {
+                {
+                    //problem with nested lists that the confluence {toc} macro creates
+                    elementType("ul", M_LI, M_BLOCK | M_LI, 0);
+                }
+            });
+            reader.setContentHandler(new V2ContentHandler(this));
+            reader.parse(new InputSource(new StringReader(c)));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void checkContentV1(String c) {
+        int idx = c.indexOf("{children");
+        while (idx != -1) {
+            if (childrenOf == null) {
+                childrenOf = new HashMap<String, Integer>();
+            }
+            idx += 9;
+            if (c.charAt(idx) != '}') {
+                // {children:page=Foo|...}
+                idx++;
+                int idx2 = c.indexOf('}', idx);
+                String paramString = c.substring(idx, idx2);
+                String params[] = paramString.split("\\||=");
+                String page = null;
+                int depth = 1;
+                for (int x = 0; x < params.length; x++) {
+                    if ("page".equals(params[x])) {
+                        page = params[x + 1];
+                        x++;
+                    } else if ("depth".equals(params[x])) {
+                        depth = Integer.parseInt(params[x + 1]);
+                        x++;
+                    }
+                }
+                childrenOf.put(page, depth);
+            } else {
+                childrenOf.put(title, 1);
+            }
+            idx = c.indexOf("{children", idx);
+        }
+        
+        idx = c.indexOf("{include:");
+        while (idx != -1) {
+            int idx2 = c.indexOf("}", idx);
+            String inc = c.substring(idx + 9, idx2);
+            if (includes == null) {
+                includes = new CopyOnWriteArraySet<String>();
+            }
+            includes.add(inc);
+            idx = c.indexOf("{include:", idx2);
+        }
+        idx = c.indexOf("{blog-posts");
+        if (idx != -1) {
+            hasBlog = true;
+        }
+        handleCode(c);
+    }
+
+    private void handleCode(String c) {
+        int idx = c.indexOf("{code");
+        while (idx != -1) {
+            String type = "java";
+            idx += 5;
+            if (c.charAt(idx) != '}') {
+                idx++;
+                int idx2 = c.indexOf('}', idx);
+                if (idx2 != -1) {
+                    String paramString = c.substring(idx, idx2);
+                    String params[] = paramString.split("\\||=");
+                    for (int x = 0; x < params.length; x++) {
+                        if ("type".equalsIgnoreCase(params[x])) {
+                            type = params[x + 1];
+                            x++;
+                        } else if (CODE_TYPE_MAP.containsKey(params[x].toLowerCase())) {
+                            type = params[x];
+                        }
+                    }
+                }
+            }
+
+            if (codeTypes == null) {
+                codeTypes = new CopyOnWriteArraySet<String>();
+            }
+            codeTypes.add(type);
+            idx = c.indexOf("{code", idx + 1);
+        } 
+        idx = c.indexOf("{snippet");
+        while (idx != -1) {
+            String type = "java";
+            idx += 8;
+            if (c.charAt(idx) != '}') {
+                idx++;
+                int idx2 = c.indexOf('}', idx);
+                if (idx2 != -1) {
+                    String paramString = c.substring(idx, idx2);
+                    String params[] = paramString.split("\\||=");
+                    for (int x = 0; x < params.length; x++) {
+                        if ("lang".equalsIgnoreCase(params[x])) {
+                            type = params[x + 1];
+                            x++;
+                        } else if (CODE_TYPE_MAP.containsKey(params[x].toLowerCase())) {
+                            type = params[x];
+                        }
+                    }
+                }
+            }
+
+            if (codeTypes == null) {
+                codeTypes = new CopyOnWriteArraySet<String>();
+            }
+            codeTypes.add(type);
+            idx = c.indexOf("{snippet", idx + 1);
+        } 
+    }
+    
+    public boolean hasChildrenOf(String t, int d) {
+        if (childrenOf == null) {
+            return false;
+        }
+        Integer i = childrenOf.get(t);
+        if (i == null) {
+            return false;
+        }
+        return d <= i;
+    }
+    
+    public boolean includesPage(String s) {
+        if (includes == null) {
+            return false;
+        }
+        return includes.contains(s);
+    }
+    
+
+    public String getParentId() {
+        return parent;
+    }
+
+    public XMLGregorianCalendar getModifiedTime() {
+        return modified;
+    }
+
+    public void setContent(String c) {
+        renderedContent = c;
+    }
+    
+    public String getContent() {
+        return renderedContent;
+    }
+
+    public String getSpaceKey() {
+        return spaceKey;
+    }
+
+    public void addAttachment(String aid, String filename) {
+        if (attachments == null) {
+            attachments = new HashMap<String, String>();
+        }
+        attachments.put(aid, filename);
+    }
+    public String getAttachmentFilename(String aid) {
+        if (attachments == null) {
+            return null;
+        }
+        return attachments.get(aid);
+    }
+
+    public void setContentForDivId(String divId, String content) {
+        renderedDivContent = content;
+        divIdForContent = divId;
+    }
+
+    public String getContentForDivId(String divId) {
+        if (divId == null) {
+            return renderedContent;
+        }
+        if (divId.equals(divIdForContent)) {
+            return renderedDivContent;
+        }
+        return null;
+    }
+
+    public String getLink() {
+        StringBuffer buffer = new StringBuffer();
+        buffer.append("<a href=\"");
+        buffer.append(url);
+        buffer.append("\" title=\"");
+        buffer.append(title);
+        buffer.append("\">");
+        buffer.append(title);
+        buffer.append("</a>");
+        return buffer.toString();
+    }
+
+    public Space getSpace() {
+        return SiteExporter.getSpace(spaceKey);
+    }
+
+    public boolean hasChildren() {
+        return exporter.hasChildren(this);
+    }
+
+    public List<Page> getChildren() {
+        return exporter.getChildren(this);
+    }
+
+    protected void setExporter(SiteExporter exporter) {
+        this.exporter = exporter;
+    }
+    
+    protected SiteExporter getExporter() {
+        return exporter;
+    }
+
+    public boolean hasBlog() {
+        return hasBlog;
+    }
+    
+    public boolean getHasCode() {
+        return hasCode(new HashMap<String, Boolean>());
+    }
+
+    public boolean hasCode(Map<String, Boolean> done) {
+        if (done.containsKey(getTitle())) {
+            return done.get(getTitle());
+        }
+        if (codeTypes != null && !codeTypes.isEmpty()) {
+            done.put(this.getTitle(), true);
+            return true;
+        }
+        if (includes != null) {
+            done.put(getTitle(), false);
+            for (String i : includes) {
+                try {
+                    Page p = exporter.findPage(i);
+                    if (p != null && p.hasCode(done)) {
+                        done.put(this.getTitle(), true);
+                        return true;
+                    }
+                } catch (Throwable e) {
+                    e.printStackTrace();
+                    System.out.println(done);
+                }
+            }
+        }
+        return false;
+    }
+    
+    public Set<String> getCodeScripts() throws Exception {
+        Set<String> scripts = new HashSet<String>();
+        if (codeTypes != null) {
+            for (String s : codeTypes) {
+                String sc = CODE_TYPE_MAP.get(s);
+                if (sc == null) {
+                    System.out.println("WARNING: no code highlighter for " + s);
+                } else {
+                    scripts.add(sc);
+                }
+            }
+        }
+        if (scripts.isEmpty()) {
+            scripts.add(CODE_TYPE_MAP.get("java"));
+            scripts.add(CODE_TYPE_MAP.get("plain"));
+        }
+        if (includes != null) {
+            for (String i : includes) {
+                try {
+                    Page p = exporter.findPage(i);
+                    if (p != null && p.getHasCode()) {
+                        scripts.addAll(p.getCodeScripts());
+                    } else if (p == null) {
+                        System.out.println("    Did not find page " + i);
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return scripts;
+    }
+
+    
+    static class V2ContentHandler implements ContentHandler {
+        private final Page page;
+        
+        enum State {
+            NONE,
+            CHILDREN,
+            INCLUDE,
+            BLOG_POSTS,
+            CODE,
+        };
+        private State state = State.NONE;
+        private Map<String, String> params = new HashMap<String, String>();
+        private String paramName;
+        private boolean unmigrated;
+
+        V2ContentHandler(Page pg) {
+            page = pg;
+        }
+
+        public void setDocumentLocator(Locator locator) {
+        }
+
+        public void startDocument() throws SAXException {
+        }
+
+        public void endDocument() throws SAXException {
+        }
+
+        public void startPrefixMapping(String prefix, String uri) throws SAXException {
+        }
+
+        public void endPrefixMapping(String prefix) throws SAXException {
+        }
+
+        public void startElement(String uri, String localName, String qName, Attributes atts)
+            throws SAXException {
+            if ("macro".equals(localName) || "structured-macro".equals(localName)) {
+                String s = atts.getValue(uri, "name");
+                if ("children".equals(s)) {
+                    state = State.CHILDREN;
+                } else if ("include".equals(s)) {
+                    state = State.INCLUDE;
+                } else if ("blog-posts".equals(s)) {
+                    state = State.BLOG_POSTS;
+                } else if ("code".equals(s)) {
+                    state = State.CODE;
+                } else if ("snippet".equals(s)) {
+                    state = State.CODE;
+                } else if ("unmigrated-wiki-markup".equals(s)
+                    || "unmigrated-inline-wiki-markup".equals(s)) {
+                    if (!unmigrated) {
+                        System.out.println("WARNING: Page \"" + page.title + "\" (" 
+                            + page.spaceKey + ") has unmigrated wiki content.");
+                        unmigrated = true;
+                        //no idea what is in there, lets just turn on the code highlighting
+                        if (page.codeTypes == null) {
+                            page.codeTypes = new CopyOnWriteArraySet<String>();
+                        }
+                        page.codeTypes.add("java");
+                        page.codeTypes.add("xml");
+                        page.codeTypes.add("plain");
+                    }
+                } else {
+                    //System.out.println("Unknown macro: " + s);
+                }
+                params.clear();
+                paramName = null;
+            } else if ("parameter".equals(localName)) {
+                paramName = atts.getValue(uri, "name");
+            } else if ("default-parameter".equals(localName)) {
+                paramName = "default-parameter";
+            } else if ("page".equals(localName) && state == State.INCLUDE) {
+                for (int x = 0; x < atts.getLength(); x++) {
+                    if (atts.getLocalName(x).equals("content-title")
+                        && paramName != null) {
+                        params.put(paramName, atts.getValue(x));
+                    }
+                }
+            }
+        }
+
+        public void endElement(String uri, String localName, String qName) throws SAXException {
+            if ("macro".equals(localName) || "structured-macro".equals(localName)) {
+                switch (state) {
+                case CHILDREN: {
+                    String pageName = params.get("page");
+                    String depth = params.get("depth");
+                    if (depth == null || "".equals(depth.trim())) {
+                        depth = "1";
+                    }
+                    if (page.childrenOf == null) {
+                        page.childrenOf = new HashMap<String, Integer>();
+                    }
+                    if (pageName == null) {
+                        page.childrenOf.put(page.title, Integer.parseInt(depth));                    
+                    } else {
+                        page.childrenOf.put(pageName, Integer.parseInt(depth));
+                    }
+                    params.clear();
+                    state = State.NONE;
+                    break;
+                }
+                case INCLUDE: {
+                    if (page.includes == null) {
+                        page.includes = new CopyOnWriteArraySet<String>();
+                    }
+                    String inc = params.get("default-parameter");
+                    if (inc == null) {
+                        inc = params.get("title");
+                    }
+                    if (inc == null) {
+                        inc = params.get("");
+                    }
+                    if (inc == null) {
+                        System.out.println(page.title + ": Did not find an include name " + params);
+                    } else {
+                        page.includes.add(inc);
+                    }
+                    state = State.NONE;
+                    break;
+                }
+                case BLOG_POSTS:
+                    page.hasBlog = true;
+                    state = State.NONE;
+                    break;
+                case CODE: {
+                    if (page.codeTypes == null) {
+                        page.codeTypes = new CopyOnWriteArraySet<String>();
+                    }
+                    String lang = null;
+                    for (Map.Entry<String, String> ent : params.entrySet()) {
+                        if ("language".equals(ent.getKey())) {
+                            lang = ent.getValue();
+                        } else if (ent.getKey().contains(":")) {
+                            String parts[] = ent.getKey().split(":");
+                            for (String s : parts) {
+                                if (("title".equals(s) && !params.containsKey("title"))
+                                    || (!params.containsKey("language") 
+                                        && ("xml".equals(s) || "java".equals(s)))) {
+                                    System.out.println("WARNING Page " + page.title + " has a broken code block");
+                                }
+                            }
+                        } else if ("default-parameter".equals(ent.getKey())) {
+                            String s = ent.getValue();
+                            if ("xml".equals(s) || "java".equals(s)) {
+                                lang = s;
+                            }
+                        }
+                    }
+                    if (lang == null) {
+                        lang = params.get("");
+                    }
+                    /*
+                    if (page.getTitle().equals("Security")) {
+                        System.out.println(params);
+                        System.out.println("lang: " + lang);
+                    }
+                    */
+                    if (StringUtils.isEmpty(lang)) {
+                        lang = "java";
+                    }
+                    page.codeTypes.add(lang);
+                    state = State.NONE;
+                    break;
+                }                    
+                default:
+                    state = State.NONE;
+                    break;
+                }
+            } else if ("parameter".equals(localName)) {
+                paramName = null;
+            } else if ("default-parameter".equals(localName)) {
+                paramName = null;
+            }            
+        }
+
+        public void characters(char[] ch, int start, int length) throws SAXException {
+            if (paramName != null) {
+                params.put(paramName, new String(ch, start, length));
+            }
+        }
+
+        public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+        }
+
+        public void processingInstruction(String target, String data) throws SAXException {
+        }
+
+        public void skippedEntity(String name) throws SAXException {
+        }
+    }
+    
+}