You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ga...@apache.org on 2012/12/18 20:15:59 UTC
svn commit: r1423584 - in /geronimo/site/trunk/wiki-export: ./ conf/ src/
src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/cxf/ src/main/java/org/apache/cxf/cwiki/
Author: gawor
Date: Tue Dec 18 19:15:57 2012
New Revision: 1423584
URL: http://svn.apache.org/viewvc?rev=1423584&view=rev
Log:
wiki exporter based on Dan Kulp's work
Added:
geronimo/site/trunk/wiki-export/
geronimo/site/trunk/wiki-export/README
geronimo/site/trunk/wiki-export/conf/
geronimo/site/trunk/wiki-export/conf/GMOxDEV.cfg
geronimo/site/trunk/wiki-export/conf/GMOxDOC10.cfg
geronimo/site/trunk/wiki-export/conf/GMOxDOC11.cfg
geronimo/site/trunk/wiki-export/conf/GMOxDOC22.cfg
geronimo/site/trunk/wiki-export/conf/GMOxDOC30.cfg
geronimo/site/trunk/wiki-export/conf/GMOxKB.cfg
geronimo/site/trunk/wiki-export/conf/GMOxSITE.cfg
geronimo/site/trunk/wiki-export/pom.xml (with props)
geronimo/site/trunk/wiki-export/src/
geronimo/site/trunk/wiki-export/src/main/
geronimo/site/trunk/wiki-export/src/main/java/
geronimo/site/trunk/wiki-export/src/main/java/org/
geronimo/site/trunk/wiki-export/src/main/java/org/apache/
geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/
geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/
geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java (with props)
geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Page.java (with props)
geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/PageManager.java (with props)
geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Renderer.java (with props)
geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/SiteExporter.java (with props)
geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Space.java (with props)
Added: geronimo/site/trunk/wiki-export/README
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/README?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/README (added)
+++ geronimo/site/trunk/wiki-export/README Tue Dec 18 19:15:57 2012
@@ -0,0 +1,31 @@
+
+1) Build wiki exporter code:
+
+mvn clean install
+
+2) Configure exporter code:
+
+You will need to pass credentials for a valid confluence user. This can be
+done in one of two ways:
+
+a) Command line:
+ -Dconfluence.user=username -Dconfluence.password=password
+
+b) Profile in .m2/settings.xml
+ <profile>
+ <id>confluence</id>
+ <properties>
+ <confluence.user>user</confluence.user>
+ <confluence.password>passwd</confluence.password>
+ </properties>
+ </profile>
+
+3) Export the space:
+
+mvn -Pconfluence exec:java
+
+The exported content should appear ./content directory. To specify another
+location where the content should be placed specify
+-Dgeronimo.site.output=/path/to/content property.
+
+
Added: geronimo/site/trunk/wiki-export/conf/GMOxDEV.cfg
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/conf/GMOxDEV.cfg?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/conf/GMOxDEV.cfg (added)
+++ geronimo/site/trunk/wiki-export/conf/GMOxDEV.cfg Tue Dec 18 19:15:57 2012
@@ -0,0 +1,6 @@
+spaceKey:GMOxDEV
+pageCacheFile:cache/GMOxDEV.pageCache
+templateName:../template/GMOxDEV_autoexport_template.xml
+outputDir:/GMOxDEV
+globalPages:Navigation,Banner,QuickLinks
+mainDivClass:wiki-content maincontent
Added: geronimo/site/trunk/wiki-export/conf/GMOxDOC10.cfg
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/conf/GMOxDOC10.cfg?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/conf/GMOxDOC10.cfg (added)
+++ geronimo/site/trunk/wiki-export/conf/GMOxDOC10.cfg Tue Dec 18 19:15:57 2012
@@ -0,0 +1,6 @@
+spaceKey:GMOxDOC10
+pageCacheFile:cache/GMOxDOC10.pageCache
+templateName:../template/GMOxDOC10_autoexport_template.xml
+outputDir:/
+globalPages:Navigation,Banner,QuickLinks
+mainDivClass:wiki-content maincontent
Added: geronimo/site/trunk/wiki-export/conf/GMOxDOC11.cfg
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/conf/GMOxDOC11.cfg?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/conf/GMOxDOC11.cfg (added)
+++ geronimo/site/trunk/wiki-export/conf/GMOxDOC11.cfg Tue Dec 18 19:15:57 2012
@@ -0,0 +1,6 @@
+spaceKey:GMOxDOC11
+pageCacheFile:cache/GMOxDOC11.pageCache
+templateName:../templates/GMOxDOC11_autoexport_template.xml
+outputDir:/GMOxDOC11
+globalPages:Navigation,Banner,QuickLinks
+mainDivClass:wiki-content maincontent
Added: geronimo/site/trunk/wiki-export/conf/GMOxDOC22.cfg
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/conf/GMOxDOC22.cfg?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/conf/GMOxDOC22.cfg (added)
+++ geronimo/site/trunk/wiki-export/conf/GMOxDOC22.cfg Tue Dec 18 19:15:57 2012
@@ -0,0 +1,6 @@
+spaceKey:GMOxDOC22
+pageCacheFile:cache/GMOxDOC22.pageCache
+templateName:../template/GMOxDOC22_autoexport_template.xml
+outputDir:/
+globalPages:Navigation,Banner,QuickLinks
+mainDivClass:wiki-content maincontent
Added: geronimo/site/trunk/wiki-export/conf/GMOxDOC30.cfg
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/conf/GMOxDOC30.cfg?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/conf/GMOxDOC30.cfg (added)
+++ geronimo/site/trunk/wiki-export/conf/GMOxDOC30.cfg Tue Dec 18 19:15:57 2012
@@ -0,0 +1,6 @@
+spaceKey:GMOxDOC30
+pageCacheFile:cache/GMOxDOC30.pageCache
+templateName:../template/GMOxDOC30_autoexport_template.xml
+outputDir:/GMOxDOC30
+globalPages:Navigation,Banner,QuickLinks
+mainDivClass:wiki-content maincontent
Added: geronimo/site/trunk/wiki-export/conf/GMOxKB.cfg
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/conf/GMOxKB.cfg?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/conf/GMOxKB.cfg (added)
+++ geronimo/site/trunk/wiki-export/conf/GMOxKB.cfg Tue Dec 18 19:15:57 2012
@@ -0,0 +1,6 @@
+spaceKey:GMOxKB
+pageCacheFile:cache/GMOxKB.pageCache
+templateName:../template/GMOxKB_autoexport_template.xml
+outputDir:/GMOxKB
+globalPages:Navigation,Banner,QuickLinks
+mainDivClass:wiki-content maincontent
Added: geronimo/site/trunk/wiki-export/conf/GMOxSITE.cfg
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/conf/GMOxSITE.cfg?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/conf/GMOxSITE.cfg (added)
+++ geronimo/site/trunk/wiki-export/conf/GMOxSITE.cfg Tue Dec 18 19:15:57 2012
@@ -0,0 +1,6 @@
+spaceKey:GMOxSITE
+pageCacheFile:cache/GMOxSITE.pageCache
+templateName:../template/GMOxSITE_autoexport_template.xml
+outputDir:/
+globalPages:Navigation,Banner,QuickLinks
+mainDivClass:wiki-content maincontent
Added: geronimo/site/trunk/wiki-export/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/pom.xml?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/pom.xml (added)
+++ geronimo/site/trunk/wiki-export/pom.xml Tue Dec 18 19:15:57 2012
@@ -0,0 +1,115 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.geronimo</groupId>
+ <artifactId>geronimo-site-export</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0-SNAPSHOT</version>
+ <name>Apache Geronimo Confluence Site Exporter</name>
+ <url>http://geronimo.apache.org</url>
+<!--
+ <parent>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-parent</artifactId>
+ <version>2.5.2</version>
+ </parent>
+-->
+ <properties>
+ <cxf.version>2.5.2</cxf.version>
+ <extra.arg></extra.arg>
+ <svn.arg1></svn.arg1>
+ <svn.arg2></svn.arg2>
+ <site.output>${basedir}/content</site.output>
+ <geronimo.site.output>${site.output}</geronimo.site.output>
+ <maven.test.skip>true</maven.test.skip>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-frontend-jaxws</artifactId>
+ <version>${cxf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-transports-http</artifactId>
+ <version>${cxf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ <version>1.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ccil.cowan.tagsoup</groupId>
+ <artifactId>tagsoup</artifactId>
+ <version>1.2.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2</version>
+ <configuration>
+ <mainClass>org.apache.cxf.cwiki.SiteExporter</mainClass>
+ <arguments>
+ <argument>-d</argument>
+ <argument>${geronimo.site.output}</argument>
+ <argument>-password</argument>
+ <argument>${confluence.password}</argument>
+ <argument>-user</argument>
+ <argument>${confluence.user}</argument>
+ <argument>${extra.arg}</argument>
+ <argument>${svn.arg1}</argument>
+ <argument>${svn.arg2}</argument>
+ <!--argument>-force</argument-->
+ <argument>${basedir}/conf/GMOxDEV.cfg</argument>
+<!-- <argument>${basedir}/conf/GMOxDOC30.cfg</argument>-->
+ </arguments>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+
+ <profiles>
+ <profile>
+ <id>svn</id>
+ <properties>
+ <svn.arg1>-svn</svn.arg1>
+ <svn.arg2>-commit</svn.arg2>
+ </properties>
+ </profile>
+ </profiles>
+</project>
Propchange: geronimo/site/trunk/wiki-export/pom.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/site/trunk/wiki-export/pom.xml
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/site/trunk/wiki-export/pom.xml
------------------------------------------------------------------------------
svn:mime-type = text/xml
Added: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java (added)
+++ geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java Tue Dec 18 19:15:57 2012
@@ -0,0 +1,313 @@
+/**
+ * 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.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import org.ccil.cowan.tagsoup.XMLWriter;
+
+/**
+ *
+ */
+public class ConfluenceCleanupWriter extends XMLWriter {
+
+ private final Page page;
+ private final SiteExporter exporter;
+ private final String divId;
+ private final String divCls;
+ private final Stack<Integer> trStack = new Stack<Integer>();
+ private int curTrCount;
+
+ public ConfluenceCleanupWriter(SiteExporter exp, Writer writer, Page page,
+ String id, String divCls) {
+ super(writer);
+ this.page = page;
+ this.exporter = exp;
+ this.divId = id;
+ this.divCls = divCls;
+ }
+
+ //CHECKSTYLE:OFF
+ public void startElement(String uri, String localName, String qName, final Attributes atts)
+ throws SAXException {
+ AttributesWrapper newAtts = new AttributesWrapper(atts);
+ if ("a".equals(localName.toLowerCase())
+ || "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");
+ if (href != null && href.startsWith("/confluence/display/")) {
+ String params = "";
+ if (href.indexOf('#') != -1) {
+ params = href.substring(href.indexOf('#'));
+ href = href.substring(0, href.indexOf('#'));
+ }
+ if (href.indexOf('?') != -1) {
+ if (params.length() > 0) {
+ params = href.substring(href.indexOf('?')) + "#" + params;
+ } else {
+ params = href.substring(href.indexOf('?'));
+ }
+ href = href.substring(0, href.indexOf('?'));
+ }
+ try {
+ final Page p = exporter.findPageByURL(href);
+ if (p != null) {
+ newAtts.addMapping("href", p.createFileName() + params);
+ } else {
+ if (href.indexOf('~') == -1) {
+ //link to a user page is OK, don't warn about it
+ System.out.println("Could not find page for " + href
+ + " linked from " + page.getTitle());
+ }
+ newAtts.addMapping("href", SiteExporter.ROOT + href.substring(11));
+ }
+ } catch (Exception e) {
+ throw new SAXException(e);
+ }
+ } else if (href != null && href.startsWith("/confluence/plugins/")) {
+ newAtts.addMapping("href", SiteExporter.ROOT + href.substring(11));
+ } else if (href != null && href.contains("/confluence/pages/viewpage.action")) {
+ int idx = href.indexOf("pageId=");
+ String id = href.substring(idx + 7);
+ Page p = exporter.findPageByID(id);
+ if (p != null) {
+ newAtts.addMapping("href", p.createFileName());
+ } else {
+ System.out.println("Could not find page for id: " + id
+ + " linked from " + page.getTitle());
+ }
+ } else if (href != null && href.contains("/confluence/download/attachments")) {
+ href = href.substring(href.lastIndexOf("/"));
+ String dirName = page.createFileName();
+ dirName = dirName.substring(0, dirName.lastIndexOf(".")) + ".data";
+
+ newAtts.addMapping("href", dirName + href);
+ } else if (href != null && href.contains("/confluence/pages/createpage.action")) {
+ System.out.println("Adding createpage link for " + href + " from " + page.getTitle());
+ newAtts.addMapping("href", SiteExporter.HOST + href);
+ } else if (href != null
+ && (href.startsWith("http://")
+ || href.startsWith("https://"))) {
+ URL url;
+ try {
+ url = new URL(href);
+ if (url.getHost().contains("apache.org")) {
+ newAtts.remove("rel");
+ }
+ if (url.getHost().equals("cxf.apache.org")
+ && "external-link".equals(newAtts.getValue("class"))) {
+ newAtts.remove("class");
+ }
+ } catch (MalformedURLException e) {
+ //ignore
+ }
+ }
+ } else if ("img".equals(localName.toLowerCase())
+ || "img".equals(qName.toLowerCase())) {
+ String href = atts.getValue("src");
+ if ("absmiddle".equalsIgnoreCase(atts.getValue("align"))) {
+ newAtts.addMapping("align", "middle");
+ }
+ String cls = atts.getValue("class");
+ if (href != null && href.startsWith("/confluence/images/")) {
+ newAtts.addMapping("src", SiteExporter.HOST + href);
+ } else if (href != null && href.startsWith("/confluence/download/attachments")) {
+ if (cls == null) {
+ href = href.substring(0, href.lastIndexOf('?'));
+ href = href.substring(href.lastIndexOf('/'));
+ String dirName = page.createFileName();
+ dirName = dirName.substring(0, dirName.lastIndexOf(".")) + ".data";
+
+ newAtts.addMapping("src", dirName + href);
+ } else if (cls.contains("userLogo")) {
+ String name = href;
+ try {
+ name = exporter.loadUserImage(page, href);
+ } catch (Exception ex) {
+ System.out.println("Could not download userLogo " + href
+ + " linked from " + page.getTitle());
+ }
+ String dirName = page.createFileName();
+ dirName = dirName.substring(0, dirName.lastIndexOf(".")) + ".userimage/";
+
+ newAtts.addMapping("src", dirName + name);
+ } else {
+ newAtts.addMapping("src", SiteExporter.HOST + href);
+ }
+ } else if (href != null && href.startsWith("/confluence/download/thumbnails")) {
+ String name = href;
+ try {
+ name = exporter.loadThumbnail(page, href);
+ } catch (Exception ex) {
+ System.out.println("Could not download thumbnail " + href
+ + " linked from " + page.getTitle());
+ }
+ String dirName = page.createFileName();
+ dirName = dirName.substring(0, dirName.lastIndexOf(".")) + ".thumbs/";
+
+ newAtts.addMapping("src", dirName + name);
+ } else if (href != null && href.startsWith("/confluence")) {
+ newAtts.addMapping("src", SiteExporter.HOST + href);
+ }
+ } else if ("th".equals(localName.toLowerCase())
+ || "th".equals(qName.toLowerCase())) {
+ curTrCount++;
+ } else if ("td".equals(localName.toLowerCase())
+ || "td".equals(qName.toLowerCase())) {
+ curTrCount++;
+ if (newAtts.getIndex("nowrap") != -1) {
+ //make sure nowrap attribute is set to nowrap per HTML spec
+ newAtts.addMapping("nowrap", "nowrap");
+ }
+ } else if ("tr".equals(localName.toLowerCase())
+ || "tr".equals(qName.toLowerCase())) {
+ trStack.push(curTrCount);
+ curTrCount = 0;
+ } else if ("div".equals(localName.toLowerCase())
+ || "div".equals(qName.toLowerCase())) {
+ String id = atts.getValue("id");
+ if ("ConfluenceContent".equals(id)) {
+ if (divCls != null) {
+ newAtts.addMapping("class", divCls);
+ newAtts.remove("id");
+ }
+ if (divId != null) {
+ newAtts.addMapping("id", divId);
+ }
+ }
+ } else if ("input".equals(localName.toLowerCase())
+ || "input".equals(qName.toLowerCase())) {
+ String value = atts.getValue("value");
+ if (value != null && value.startsWith("/confluence/")) {
+ newAtts.addMapping("value", SiteExporter.ROOT + value.substring(11));
+ }
+ }
+ super.startElement(uri, localName, qName, newAtts);
+ }
+
+
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if ("tr".equals(localName.toLowerCase())
+ || "tr".equals(qName.toLowerCase())) {
+ if (curTrCount == 0) {
+ super.startElement("td");
+ super.endElement("td");
+ }
+ curTrCount = trStack.pop();
+ }
+ super.endElement(uri, localName, qName);
+ }
+
+ final class AttributesWrapper implements Attributes {
+ private final Map<String, String> atts = new LinkedHashMap<String, String>();
+
+ private AttributesWrapper(Attributes atts) {
+ for (int x = 0; x < atts.getLength(); x++) {
+ this.atts.put(atts.getQName(x), atts.getValue(x));
+ }
+ }
+ private Map.Entry<String, String> getByIndex(int i) {
+ for (Map.Entry<String, String> a : atts.entrySet()) {
+ if (i == 0) {
+ return a;
+ }
+ --i;
+ }
+ return null;
+ }
+ private int findIndex(String k) {
+ int i = 0;
+ for (Map.Entry<String, String> a : atts.entrySet()) {
+ if (a.getKey().equals(k)) {
+ return i;
+ }
+ ++i;
+ }
+ return -1;
+ }
+
+ public void remove(String k) {
+ atts.remove(k);
+ }
+
+ public void addMapping(String k, String v) {
+ atts.put(k, v);
+ }
+
+ public int getLength() {
+ return atts.size();
+ }
+
+ public String getURI(int index) {
+ return "";
+ }
+
+ public String getLocalName(int index) {
+ return getByIndex(index).getKey();
+ }
+
+ public String getQName(int index) {
+ return getByIndex(index).getKey();
+ }
+
+ public String getType(int index) {
+ return "CDATA";
+ }
+
+ public int getIndex(String uri, String localName) {
+ return findIndex(localName);
+ }
+
+ public int getIndex(String qName) {
+ return findIndex(qName);
+ }
+
+ public String getType(String uri, String localName) {
+ return "CDATA";
+ }
+
+ public String getType(String qName) {
+ return "CDATA";
+ }
+
+ public String getValue(int index) {
+ return getByIndex(index).getValue();
+ }
+
+ public String getValue(String uri, String localName) {
+ return atts.get(localName);
+ }
+
+ public String getValue(String qName) {
+ return atts.get(qName);
+ }
+ }
+
+}
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/ConfluenceCleanupWriter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Page.java
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Page.java?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Page.java (added)
+++ geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Page.java Tue Dec 18 19:15:57 2012
@@ -0,0 +1,237 @@
+/**
+ * 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.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.w3c.dom.Document;
+
+import org.apache.cxf.helpers.DOMUtils;
+
+/**
+ *
+ */
+public class Page implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ XMLGregorianCalendar modified;
+ final String id;
+ final String parent;
+ final String title;
+ final String url;
+ final String spaceKey;
+ Map<String, String> attachments;
+ Set<String> includes;
+ Map<String, Integer> childrenOf;
+
+ transient String renderedContent;
+ transient String renderedDivContent;
+ transient String divIdForContent;
+ transient SiteExporter exporter;
+
+ public Page(Document doc) throws Exception {
+ //org.apache.cxf.helpers.XMLUtils.printDOM(doc.getDocumentElement());
+
+ id = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "id");
+ parent = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "parentId");
+ title = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "title");
+ url = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "url");
+ spaceKey = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "space");
+
+ String mod = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "modified");
+ modified = DatatypeFactory.newInstance().newXMLGregorianCalendar(mod);
+
+ String c = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "content");
+ if (c != null) {
+ 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);
+ }
+ }
+ }
+
+ 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 getId() {
+ return id;
+ }
+ public String getParentId() {
+ return parent;
+ }
+ public String getTitle() {
+ return title;
+ }
+ public XMLGregorianCalendar getModifiedTime() {
+ return modified;
+ }
+
+ public void setContent(String c) {
+ renderedContent = c;
+ }
+ public String getContent() {
+ return renderedContent;
+ }
+ public String getURL() {
+ return url;
+ }
+
+ public String getSpaceKey() {
+ return spaceKey;
+ }
+
+ public String createFileName() {
+ StringBuffer buffer = new StringBuffer();
+ char array[] = getTitle().toLowerCase().toCharArray();
+ boolean separated = true;
+ for (int x = 0; x < array.length; x++) {
+ if ("abcdefghijklmnopqrstuvwxyz0123456789".indexOf(array[x]) >= 0) {
+ buffer.append(Character.toLowerCase(array[x]));
+ separated = false;
+ } else if ("\r\n\t -".indexOf(array[x]) >= 0) {
+ if (separated) {
+ continue;
+ }
+ buffer.append('-');
+ separated = true;
+ }
+ }
+ if (buffer.length() == 0) {
+ return getId() + ".html";
+ }
+ return buffer.append(".html").toString();
+ }
+
+ 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 exporter.getSpace(spaceKey);
+ }
+
+ public boolean hasChildren() {
+ return exporter.hasChildren(this);
+ }
+
+ public List<Page> getChildren() {
+ return exporter.getChildren(this);
+ }
+
+ void setExporter(SiteExporter exporter) {
+ this.exporter = exporter;
+ }
+}
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Page.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Page.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Page.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/PageManager.java
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/PageManager.java?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/PageManager.java (added)
+++ geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/PageManager.java Tue Dec 18 19:15:57 2012
@@ -0,0 +1,44 @@
+/**
+ * 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;
+
+/**
+ *
+ */
+public class PageManager {
+
+ private SiteExporter exporter;
+
+ public PageManager(SiteExporter exporter) {
+ this.exporter = exporter;
+ }
+
+ public Page getPage(String spaceKey, String title) throws Exception {
+ Page page = exporter.findPage(title);
+ if (page != null) {
+ String s = page.getContent();
+ if (s == null) {
+ s = exporter.loadPageContent(page, null, null);
+ }
+ }
+ return page;
+ }
+
+}
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/PageManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/PageManager.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/PageManager.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Renderer.java
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Renderer.java?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Renderer.java (added)
+++ geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Renderer.java Tue Dec 18 19:15:57 2012
@@ -0,0 +1,50 @@
+/**
+ * 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;
+
+/**
+ *
+ */
+public class Renderer {
+
+ private SiteExporter exporter;
+
+ public Renderer(SiteExporter exporter) {
+ this.exporter = exporter;
+ }
+
+ public String convertWikiToXHtml(Object context, String content) {
+ int start = 0;
+ if (content.startsWith("<div")) {
+ int pos = content.indexOf(">", 1);
+ if (pos != -1) {
+ start = pos + 1;
+ }
+ }
+ int end = content.length();
+ if (content.endsWith("</div>")) {
+ end -= "</div>".length();
+ }
+ content = content.substring(start, end);
+
+ return content;
+ }
+
+}
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Renderer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Renderer.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Renderer.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/SiteExporter.java
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/SiteExporter.java?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/SiteExporter.java (added)
+++ geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/SiteExporter.java Tue Dec 18 19:15:57 2012
@@ -0,0 +1,912 @@
+/**
+ * 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.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+import javax.xml.ws.AsyncHandler;
+import javax.xml.ws.Dispatch;
+import javax.xml.ws.Response;
+import javax.xml.ws.Service;
+import javax.xml.ws.soap.SOAPBinding;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.helpers.FileUtils;
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.helpers.XMLUtils;
+import org.apache.cxf.interceptor.LoggingInInterceptor;
+import org.apache.cxf.interceptor.LoggingOutInterceptor;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.runtime.resource.loader.URLResourceLoader;
+import org.ccil.cowan.tagsoup.Parser;
+import org.ccil.cowan.tagsoup.XMLWriter;
+
+/**
+ *
+ */
+public class SiteExporter implements Runnable {
+
+ static final String HOST = "https://cwiki.apache.org";
+ static final String ROOT = HOST + "/confluence";
+ static final String RPC_ROOT = "/rpc/soap-axis/confluenceservice-v1";
+ static final String SOAPNS = "http://soap.rpc.confluence.atlassian.com";
+
+
+
+ static boolean debug;
+ static String userName = "cxf-export-user";
+ static String password;
+
+ static boolean svn;
+ static boolean commit;
+ static StringBuilder svnCommitMessage = new StringBuilder();
+
+ static File rootOutputDir = new File(".");
+ static String loginToken;
+ static Dispatch<Document> dispatch;
+ static AtomicInteger asyncCount = new AtomicInteger();
+
+ Map<String, Page> pages = new ConcurrentHashMap<String, Page>();
+ Collection<Page> modifiedPages = new ConcurrentLinkedQueue<Page>();
+ Set<String> globalPages = new CopyOnWriteArraySet<String>();
+ Map<String, Space> spaces = new ConcurrentHashMap<String, Space>();
+
+ String spaceKey = "CXF";
+ String pageCacheFile = "pagesConfig.obj";
+ String templateName = "template/template.vm";
+ String mainDivClass;
+ boolean forceAll;
+ String breadCrumbRoot;
+
+ File outputDir = rootOutputDir;
+
+ Template template;
+
+ public SiteExporter(String fileName, boolean force) throws Exception {
+ forceAll = force;
+
+ Properties props = new Properties();
+ props.load(new FileInputStream(fileName));
+
+ if (props.containsKey("spaceKey")) {
+ spaceKey = props.getProperty("spaceKey");
+ }
+ if (props.containsKey("pageCacheFile")) {
+ pageCacheFile = props.getProperty("pageCacheFile");
+ }
+ if (props.containsKey("templateName")) {
+ templateName = props.getProperty("templateName");
+ }
+ if (props.containsKey("outputDir")) {
+ outputDir = new File(rootOutputDir, props.getProperty("outputDir"));
+ }
+ if (props.containsKey("mainDivClass")) {
+ mainDivClass = props.getProperty("mainDivClass");
+ }
+ if (props.containsKey("breadCrumbRoot")) {
+ breadCrumbRoot = props.getProperty("breadCrumbRoot");
+ }
+ if (props.containsKey("globalPages")) {
+ String globals = props.getProperty("globalPages");
+ String[] pgs = globals.split(",");
+ globalPages.addAll(Arrays.asList(pgs));
+ }
+
+ props = new Properties();
+ String clzName = URLResourceLoader.class.getName();
+ props.put("resource.loader", "url");
+ props.put("url.resource.loader.class", clzName);
+ props.put("url.resource.loader.root", "");
+ synchronized (Velocity.class) {
+ Velocity.init(props);
+
+ URL url = ClassLoaderUtils.getResource(templateName, this.getClass());
+ if (url == null) {
+ File file = new File(templateName);
+ if (file.exists()) {
+ url = file.toURI().toURL();
+ }
+ }
+ template = Velocity.getTemplate(url.toURI().toString());
+ }
+ outputDir.mkdirs();
+ }
+
+ public static synchronized Dispatch<Document> getDispatch() {
+ if (dispatch == null) {
+ Service service = Service.create(new QName(SOAPNS, "Service"));
+ service.addPort(new QName(SOAPNS, "Port"),
+ SOAPBinding.SOAP11HTTP_BINDING,
+ ROOT + RPC_ROOT);
+
+ dispatch = service.createDispatch(new QName(SOAPNS, "Port"),
+ Document.class, Service.Mode.PAYLOAD);
+ if (debug) {
+ ((org.apache.cxf.jaxws.DispatchImpl<?>)dispatch).getClient()
+ .getEndpoint().getInInterceptors().add(new LoggingInInterceptor());
+ ((org.apache.cxf.jaxws.DispatchImpl<?>)dispatch).getClient()
+ .getEndpoint().getOutInterceptors().add(new LoggingOutInterceptor());
+ }
+ HTTPConduit c = (HTTPConduit)((org.apache.cxf.jaxws.DispatchImpl<?>)dispatch)
+ .getClient().getConduit();
+ HTTPClientPolicy clientPol = c.getClient();
+ if (clientPol == null) {
+ clientPol = new HTTPClientPolicy();
+ }
+ //CAMEL has a couple of HUGE HUGE pages that take a long time to render
+ clientPol.setReceiveTimeout(5 * 60 * 1000);
+ c.setClient(clientPol);
+
+ }
+ return dispatch;
+ }
+
+ public void run() {
+ try {
+ doExport();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void forcePage(String s) throws Exception {
+ Page p = findPage(s);
+ if (p != null) {
+ pages.remove(p.getId());
+ modifiedPages.add(p);
+ }
+ }
+
+ public void doExport() throws Exception {
+ if (!forceAll) {
+ loadPagesCache();
+ }
+
+ // debug stuff, force regen of a page
+ //forcePage("Navigation");
+ //forcePage("Index");
+ //forcePage("JavaDoc");
+ //forcePage("DOSGi Architecture");
+
+ if (modifiedPages.isEmpty() && checkRSS()) {
+ System.out.println("(" + spaceKey + ") No changes detected from RSS");
+ return;
+ }
+
+ doLogin();
+
+ Space space = getSpace(spaceKey);
+ breadCrumbRoot = space.getName();
+
+ loadPages();
+
+ for (Page p : modifiedPages) {
+ if (globalPages.contains(p.getTitle())) {
+ modifiedPages.clear();
+ modifiedPages.addAll(pages.values());
+ break;
+ }
+ }
+ if (forceAll) {
+ modifiedPages.clear();
+ modifiedPages.addAll(pages.values());
+ }
+
+
+ if (!modifiedPages.isEmpty()) {
+ renderPages();
+ savePages();
+ }
+
+
+ }
+
+
+ public boolean checkRSS() throws Exception {
+ if (forceAll || pages == null || pages.isEmpty()) {
+ return false;
+ }
+ URL url = new URL(ROOT + "/createrssfeed.action?types=page&types=blogpost&types=mail&"
+ //+ "types=comment&" //cannot handle comment updates yet
+ + "types=attachment&statuses=created&statuses=modified"
+ + "&spaces=" + spaceKey + "&rssType=atom&maxResults=20&timeSpan=2"
+ + "&publicFeed=true");
+ InputStream ins = url.openStream();
+ Document doc = StaxUtils.read(ins);
+ ins.close();
+ List<Element> els = DOMUtils.getChildrenWithName(doc.getDocumentElement(),
+ "http://www.w3.org/2005/Atom",
+ "entry");
+ //XMLUtils.printDOM(doc);
+ for (Element el : els) {
+ Element e2 = DOMUtils.getFirstChildWithName(el, "http://www.w3.org/2005/Atom", "updated");
+ String val = DOMUtils.getContent(e2);
+ XMLGregorianCalendar cal = DatatypeFactory.newInstance().newXMLGregorianCalendar(val);
+ e2 = DOMUtils.getFirstChildWithName(el, "http://www.w3.org/2005/Atom", "title");
+ String title = DOMUtils.getContent(e2);
+ Page p = findPage(title);
+
+ if (p != null) {
+ //found a modified page - need to rebuild
+ if (cal.compare(p.getModifiedTime()) > 0) {
+ System.out.println("(" + spaceKey + ") Changed page found: " + title);
+ return false;
+ }
+ } else {
+ System.out.println("(" + spaceKey + ") Did not find page for: " + title);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void savePages() throws Exception {
+ File file = new File(rootOutputDir, pageCacheFile);
+ file.getParentFile().mkdirs();
+ FileOutputStream fout = new FileOutputStream(file);
+ ObjectOutputStream oout = new ObjectOutputStream(fout);
+ oout.writeObject(pages);
+ oout.close();
+ }
+
+ private void renderPages() throws Exception {
+ int total = modifiedPages.size();
+ int count = 0;
+ for (Page p : modifiedPages) {
+ count++;
+ System.out.println("(" + spaceKey + ") Rendering " + p.getTitle()
+ + " (" + count + "/" + total + ")");
+ loadAttachments(p);
+
+ loadPageContent(p, null, null);
+ VelocityContext ctx = new VelocityContext();
+ ctx.put("autoexport", this);
+ ctx.put("page", p);
+ ctx.put("body", p.getContent());
+ ctx.put("confluenceUri", ROOT);
+ ctx.put("pageManager", new PageManager(this));
+ ctx.put("renderer", new Renderer(this));
+
+ File file = new File(outputDir, p.createFileName());
+ boolean isNew = !file.exists();
+
+ FileWriter writer = new FileWriter(file);
+ ctx.put("out", writer);
+ template.merge(ctx, writer);
+ writer.close();
+ if (isNew) {
+ //call "svn add"
+ callSvn("add", file.getAbsolutePath());
+ svnCommitMessage.append("Adding: " + file.getName() + "\n");
+ } else {
+ svnCommitMessage.append("Modified: " + file.getName() + "\n");
+ }
+ }
+ }
+ void callSvn(String ... commands) throws Exception {
+ callSvn(outputDir, commands);
+ }
+ static void callSvn(File dir, String ... commands) throws Exception {
+ if (svn) {
+ List<String> cmds = new ArrayList<String>();
+ cmds.add("svn");
+ cmds.add("--non-interactive");
+ cmds.addAll(Arrays.asList(commands));
+ Process p = Runtime.getRuntime().exec(cmds.toArray(new String[cmds.size()]),
+ new String[0], dir);
+ if (p.waitFor() != 0) {
+ IOUtils.copy(p.getErrorStream(), System.err);
+ }
+ }
+ }
+
+ private void loadAttachments(Page p) throws Exception {
+ Document doc = XMLUtils.newDocument();
+ Element el = doc.createElementNS(SOAPNS, "ns1:getAttachments");
+ Element el2 = doc.createElement("in0");
+ el.appendChild(el2);
+ el2.setTextContent(loginToken);
+ el2 = doc.createElement("in1");
+ el.appendChild(el2);
+ el2.setTextContent(p.getId());
+ el.appendChild(el2);
+ doc.appendChild(el);
+
+ doc = getDispatch().invoke(doc);
+ el = DOMUtils.getFirstElement(DOMUtils.getFirstElement(doc.getDocumentElement()));
+ while (el != null) {
+ try {
+ String filename = DOMUtils.getChildContent(el, "fileName");
+ String durl = DOMUtils.getChildContent(el, "url");
+ String aid = DOMUtils.getChildContent(el, "id");
+
+ p.addAttachment(aid, filename);
+
+ String dirName = p.createFileName();
+ dirName = dirName.substring(0, dirName.lastIndexOf(".")) + ".data";
+ File file = new File(outputDir, dirName);
+ if (!file.exists()) {
+ callSvn("mkdir", file.getAbsolutePath());
+ file.mkdirs();
+ }
+ filename = filename.replace(' ', '-');
+ file = new File(file, filename);
+ boolean exists = file.exists();
+ FileOutputStream out = new FileOutputStream(file);
+ URL url = new URL(durl);
+ InputStream ins = url.openStream();
+ IOUtils.copy(ins, out);
+ out.close();
+ ins.close();
+ if (!exists) {
+ callSvn("add", file.getAbsolutePath());
+ svnCommitMessage.append("Added: " + dirName + "/" + file.getName() + "\n");
+ } else {
+ svnCommitMessage.append("Modified: " + dirName + "/" + file.getName() + "\n");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ el = DOMUtils.getNextElement(el);
+ }
+ }
+ String loadUserImage(Page p, String href) throws Exception {
+ return loadPageBinaryData(p, href, "userimage", true);
+ }
+ String loadThumbnail(Page p, String href) throws Exception {
+ return loadPageBinaryData(p, href, "thumbs", false);
+ }
+ String loadPageBinaryData(Page p, String href, String type, boolean auth) throws Exception {
+ String filename = href.substring(href.lastIndexOf('/') + 1);
+ filename = filename.replace(' ', '_');
+ if (filename.indexOf('?') != -1) {
+ filename = filename.substring(0, filename.indexOf('?'));
+ }
+
+ String dirName = p.createFileName();
+ dirName = dirName.substring(0, dirName.lastIndexOf(".")) + "." + type;
+ File file = new File(outputDir, dirName);
+ if (!file.exists()) {
+ callSvn("mkdir", file.getAbsolutePath());
+ file.mkdirs();
+ }
+ file = new File(file, filename);
+ boolean exists = file.exists();
+ FileOutputStream out = new FileOutputStream(file);
+ if (auth) {
+ if (href.indexOf('?') != -1) {
+ href += "&os_authType=basic";
+ } else {
+ href += "?os_authType=basic";
+ }
+ }
+ URL url = new URL(HOST + href);
+ URLConnection con = url.openConnection();
+ if (auth) {
+ con.addRequestProperty("Authorization", getBasicAuthHeader());
+ }
+ InputStream ins = con.getInputStream();
+ IOUtils.copy(ins, out);
+ out.close();
+ ins.close();
+ if (!exists) {
+ callSvn("add", file.getAbsolutePath());
+ svnCommitMessage.append("Added: " + dirName + "/" + file.getName() + "\n");
+ } else {
+ svnCommitMessage.append("Modified: " + dirName + "/" + file.getName() + "\n");
+ }
+ return file.getName();
+ }
+ public String getBasicAuthHeader() {
+ String userAndPass = userName + ":" + password;
+ try {
+ return "Basic " + Base64Utility.encode(userAndPass.getBytes("ISO-8859-1"));
+ } catch (UnsupportedEncodingException e) {
+ return "Basic";
+ }
+ }
+ public Page findPage(String title) throws Exception {
+ for (Page p : pages.values()) {
+ if (title.equals(p.getTitle())) {
+ return p;
+ }
+ }
+ return null;
+ }
+ public Page findPageByURL(String url) throws Exception {
+ for (Page p : pages.values()) {
+ if (p.getURL().endsWith(url)) {
+ return p;
+ }
+ }
+ return null;
+ }
+ public Page findPageByID(String id) {
+ for (Page p : pages.values()) {
+ if (p.getId().equals(id)) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ public String breadcrumbs(Page page) {
+ String separator = ">";
+ String s = " " + separator + " ";
+
+ StringBuffer buffer = new StringBuffer();
+ List<Page> p = new LinkedList<Page>();
+ String parentId = page.getParentId();
+ Page parent = pages.get(parentId);
+ while (parent != null) {
+ p.add(0, parent);
+ parentId = parent.getParentId();
+ parent = pages.get(parentId);
+ }
+ if (breadCrumbRoot != null) {
+ buffer.append("<a href=\"");
+ buffer.append("index.html");
+ buffer.append("\">");
+ buffer.append(breadCrumbRoot);
+ buffer.append("</a>");
+ buffer.append(s);
+ }
+ for (Page p2 : p) {
+ buffer.append("<a href=\"");
+ buffer.append(p2.createFileName());
+ buffer.append("\">");
+ buffer.append(p2.getTitle());
+ buffer.append("</a>");
+ buffer.append(s);
+ }
+ buffer.append("<a href=\"");
+ buffer.append(page.createFileName());
+ buffer.append("\">");
+ buffer.append(page.getTitle());
+ buffer.append("</a>");
+
+ return buffer.toString();
+ }
+
+ public String getPageContent(String title, String divId) throws Exception {
+ Page p = findPage(title);
+ String s = p.getContentForDivId(divId);
+ if (s == null) {
+ s = loadPageContent(p, divId, null);
+ }
+ return s;
+ }
+ public String getPageContent(String title, String divId, String cls) throws Exception {
+ Page p = findPage(title);
+ String s = p.getContentForDivId(divId);
+ if (s == null) {
+ s = loadPageContent(p, divId, cls);
+ }
+ return s;
+ }
+ public String getPageContent(String title) throws Exception {
+ Page p = findPage(title);
+ String s = p.getContent();
+ if (s == null) {
+ loadPageContent(p, null, null);
+ }
+ return p.getContent();
+ }
+ protected String loadPageContent(Page p, String divId, String divCls) throws Exception {
+ Document doc = XMLUtils.newDocument();
+ Element el = doc.createElementNS(SOAPNS, "ns1:renderContent");
+ Element el2 = doc.createElement("in0");
+ el.appendChild(el2);
+ el2.setTextContent(loginToken);
+ el2 = doc.createElement("in1");
+ el.appendChild(el2);
+ el2.setTextContent(spaceKey);
+
+ el2 = doc.createElement("in2");
+ el.appendChild(el2);
+ el2.setTextContent(p.getId());
+
+ el2 = doc.createElement("in3");
+ el.appendChild(el2);
+
+ el2 = doc.createElement("in4"); //apachesoap map
+ el.appendChild(el2);
+
+ Element el4 = doc.createElement("item");
+ el2.appendChild(el4);
+
+ Element el3 = doc.createElement("key");
+ el3.setTextContent("style");
+ el4.appendChild(el3);
+ el3 = doc.createElement("value");
+ el3.setTextContent("clean");
+ el4.appendChild(el3);
+
+
+ doc.appendChild(el);
+ doc = getDispatch().invoke(doc);
+
+ String content = doc.getDocumentElement().getFirstChild().getTextContent().trim();
+ content = updateContentLinks(p, content, divId,
+ divCls == null && divId == null ? mainDivClass : divCls);
+ if (divId == null) {
+ p.setContent(content);
+ } else {
+ p.setContentForDivId(divId, content);
+ }
+ return content;
+ }
+
+ public String unwrap(String v) throws Exception {
+ return v.trim().replaceFirst("^<div[^>]*>", "").replaceFirst("</div>$", "");
+ }
+
+ private static synchronized void doLogin() throws Exception {
+ if (loginToken == null) {
+ Document doc = XMLUtils.newDocument();
+ Element el = doc.createElementNS(SOAPNS, "ns1:login");
+ Element el2 = doc.createElement("in0");
+
+ if (userName == null) {
+ System.out.println("Enter username: ");
+ el2.setTextContent(System.console().readLine());
+ } else {
+ el2.setTextContent(userName);
+ }
+ el.appendChild(el2);
+ el2 = doc.createElement("in1");
+ el.appendChild(el2);
+ if (password == null) {
+ System.out.println("Enter password: ");
+ el2.setTextContent(new String(System.console().readPassword()));
+ } else {
+ el2.setTextContent(password);
+ }
+ doc.appendChild(el);
+ doc = getDispatch().invoke(doc);
+ loginToken = doc.getDocumentElement().getFirstChild().getTextContent();
+ }
+ }
+
+ public void loadPagesCache() throws Exception {
+ File file = new File(rootOutputDir, pageCacheFile);
+ if (file.exists()) {
+ FileInputStream fin = new FileInputStream(file);
+ ObjectInputStream oin = new ObjectInputStream(fin);
+ pages = CastUtils.cast((Map<?, ?>)oin.readObject());
+ oin.close();
+ }
+ }
+ public void loadPages() throws Exception {
+ Document doc = XMLUtils.newDocument();
+ Element el = doc.createElementNS(SOAPNS, "ns1:getPages");
+ Element el2 = doc.createElement("in0");
+ el.appendChild(el2);
+ el2.setTextContent(loginToken);
+ el2 = doc.createElement("in1");
+ el.appendChild(el2);
+ el2.setTextContent(spaceKey);
+ doc.appendChild(el);
+ doc = getDispatch().invoke(doc);
+
+ Set<String> allPages = new CopyOnWriteArraySet<String>(pages.keySet());
+ Set<Page> newPages = new CopyOnWriteArraySet<Page>();
+ List<Future<?>> futures = new ArrayList<Future<?>>(allPages.size());
+
+ // XMLUtils.printDOM(doc.getDocumentElement());
+
+ Node nd = doc.getDocumentElement().getFirstChild().getFirstChild();
+ while (nd != null) {
+ if (nd instanceof Element) {
+ futures.add(loadPage((Element)nd, allPages, newPages));
+ }
+ nd = nd.getNextSibling();
+ }
+ for (Future<?> f : futures) {
+ //wait for all the pages to be done
+ f.get();
+ }
+ for (Page p : newPages) {
+ //pages have been added, need to check
+ checkForChildren(p);
+ }
+ for (String id : allPages) {
+ //these pages have been deleted
+ Page p = pages.remove(id);
+ checkForChildren(p);
+
+ File file = new File(outputDir, p.createFileName());
+ if (file.exists()) {
+ callSvn("rm", file.getAbsolutePath());
+ svnCommitMessage.append("Deleted: " + file.getName() + "\n");
+ }
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+ while (checkIncludes()) {
+ // nothing
+ }
+
+ }
+
+ public boolean checkIncludes() {
+ for (Page p : modifiedPages) {
+ if (checkIncludes(p)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean checkIncludes(Page p) {
+ for (Page p2 : pages.values()) {
+ if (p2.includesPage(p.getTitle())
+ && !modifiedPages.contains(p2)) {
+ modifiedPages.add(p2);
+ return true;
+ }
+ }
+ return false;
+ }
+ public void checkForChildren(Page p) {
+ Page parent = pages.get(p.getParentId());
+ int d = 1;
+ while (parent != null) {
+ for (Page p2 : pages.values()) {
+ if (p2.hasChildrenOf(parent.getTitle(), d)
+ && !modifiedPages.contains(p2)) {
+ modifiedPages.add(p2);
+ }
+ }
+ parent = pages.get(parent.getParentId());
+ d++;
+ }
+ }
+
+ public Space getSpace(String key) {
+ Space space = spaces.get(key);
+ if (space == null) {
+ try {
+ Document doc = XMLUtils.newDocument();
+ Element el = doc.createElementNS(SOAPNS, "ns1:getSpace");
+ Element el2 = doc.createElement("in0");
+ el.appendChild(el2);
+ el2.setTextContent(loginToken);
+ el2 = doc.createElement("in1");
+ el.appendChild(el2);
+ el2.setTextContent(key);
+ doc.appendChild(el);
+
+ Document out = getDispatch().invoke(doc);
+ space = new Space(out);
+ spaces.put(key, space);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return space;
+ }
+
+ public Future<?> loadPage(Element pageSumEl,
+ final Set<String> allPages,
+ final Set<Page> newPages) throws Exception {
+ Document doc = XMLUtils.newDocument();
+ Element el = doc.createElementNS(SOAPNS, "ns1:getPage");
+ Element el2 = doc.createElement("in0");
+ el.appendChild(el2);
+ el2.setTextContent(loginToken);
+ el2 = doc.createElement("in1");
+ el.appendChild(el2);
+ el2.setTextContent(DOMUtils.getChildContent(pageSumEl, "id"));
+ doc.appendChild(el);
+
+ //make sure we only fire off about 15-20 or confluence may get a bit overloaded
+ while (asyncCount.get() > 15) {
+ Thread.sleep(10);
+ }
+ asyncCount.incrementAndGet();
+ Future<?> f = getDispatch().invokeAsync(doc, new AsyncHandler<Document>() {
+ public void handleResponse(Response<Document> doc) {
+ try {
+ Page page = new Page(doc.get());
+ page.setExporter(SiteExporter.this);
+ Page oldPage = pages.put(page.getId(), page);
+ if (oldPage == null || page.getModifiedTime().compare(oldPage.getModifiedTime()) > 0) {
+ modifiedPages.add(page);
+ if (oldPage == null) {
+ //need to check parents to see if it has a {children} tag so we can re-render
+ newPages.add(page);
+ }
+ }
+ if (allPages.contains(page.getId())) {
+ allPages.remove(page.getId());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ asyncCount.decrementAndGet();
+ }
+ }
+ });
+ return f;
+ }
+
+ private String updateContentLinks(Page page, String content,
+ String id, String divCls) throws Exception {
+ XMLReader parser = createTagSoupParser();
+ StringWriter w = new StringWriter();
+ parser.setContentHandler(createContentHandler(page, w, id, divCls));
+ parser.parse(new InputSource(new StringReader(content)));
+ content = w.toString();
+ content = content.substring("<html><body>".length());
+ content = content.substring(0, content.lastIndexOf("</body></html>"));
+ return content;
+ }
+ protected XMLReader createTagSoupParser() throws Exception {
+ XMLReader reader = new Parser();
+ reader.setFeature(Parser.namespacesFeature, false);
+ reader.setFeature(Parser.namespacePrefixesFeature, false);
+ 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);
+ }
+ });
+
+ return reader;
+ }
+ protected ContentHandler createContentHandler(final Page page, Writer w,
+ String id, String divCls) {
+ XMLWriter xmlWriter = new ConfluenceCleanupWriter(this, w, page, id, divCls);
+ xmlWriter.setOutputProperty(XMLWriter.OMIT_XML_DECLARATION, "yes");
+ xmlWriter.setOutputProperty(XMLWriter.METHOD, "html");
+ return xmlWriter;
+ }
+
+ public static void main(String[] args) throws Exception {
+ Authenticator.setDefault(new Authenticator() {
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(userName, password.toCharArray());
+ }
+ });
+ ListIterator<String> it = Arrays.asList(args).listIterator();
+ List<String> files = new ArrayList<String>();
+ boolean forceAll = false;
+ while (it.hasNext()) {
+ String s = it.next();
+ if ("-debug".equals(s)) {
+ debug = true;
+ } else if ("-user".equals(s)) {
+ userName = it.next();
+ } else if ("-password".equals(s)) {
+ password = it.next();
+ } else if ("-d".equals(s)) {
+ rootOutputDir = new File(it.next());
+ } else if ("-force".equals(s)) {
+ forceAll = true;
+ } else if ("-svn".equals(s)) {
+ svn = true;
+ } else if ("-commit".equals(s)) {
+ commit = true;
+ } else if (s != null && s.length() > 0) {
+ files.add(s);
+ }
+ }
+
+ List<Thread> threads = new ArrayList<Thread>(files.size());
+ for (String file : files) {
+ Thread t = new Thread(new SiteExporter(file, forceAll));
+ threads.add(t);
+ t.start();
+ }
+ for (Thread t : threads) {
+ t.join();
+ }
+
+ if (commit) {
+ File file = FileUtils.createTempFile("svncommit", "txt");
+ FileWriter writer = new FileWriter(file);
+ writer.write(svnCommitMessage.toString());
+ writer.close();
+ callSvn(rootOutputDir, "commit", "-F", file.getAbsolutePath(), rootOutputDir.getAbsolutePath());
+ svnCommitMessage.setLength(0);
+ }
+ }
+
+ public boolean hasChildren(Page page) {
+ for (Page p : pages.values()) {
+ if (p == page) {
+ continue;
+ }
+ if (page.getId().equals(p.getParentId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public List<Page> getChildren(Page page) {
+ List<Page> children = new ArrayList<Page>();
+ for (Page p : pages.values()) {
+ if (p == page) {
+ continue;
+ }
+ if (page.getId().equals(p.getParentId())) {
+ children.add(p);
+ }
+ }
+ return children;
+ }
+
+ public String link(Page page) {
+ return page.getLink();
+ }
+
+}
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/SiteExporter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/SiteExporter.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/SiteExporter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Space.java
URL: http://svn.apache.org/viewvc/geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Space.java?rev=1423584&view=auto
==============================================================================
--- geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Space.java (added)
+++ geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Space.java Tue Dec 18 19:15:57 2012
@@ -0,0 +1,53 @@
+/**
+ * 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 org.w3c.dom.Document;
+
+import org.apache.cxf.helpers.DOMUtils;
+
+/**
+ *
+ */
+public class Space {
+
+ final String key;
+ final String name;
+ final String url;
+
+ public Space(Document doc) throws Exception {
+ // org.apache.cxf.helpers.XMLUtils.printDOM(doc.getDocumentElement());
+
+ key = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "key");
+ name = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "name");
+ url = DOMUtils.getChildContent(doc.getDocumentElement().getFirstChild(), "url");
+ }
+
+ public String getKey() {
+ return key;
+ }
+ public String getName() {
+ return name;
+ }
+ public String getTitle() {
+ return url;
+ }
+
+}
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Space.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Space.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/site/trunk/wiki-export/src/main/java/org/apache/cxf/cwiki/Space.java
------------------------------------------------------------------------------
svn:mime-type = text/plain