Added Liferay export and import
diff --git a/conf/converter.liferayhierarchy.properties b/conf/converter.liferayhierarchy.properties
new file mode 100644
index 0000000..f1310ea
--- /dev/null
+++ b/conf/converter.liferayhierarchy.properties
@@ -0,0 +1,77 @@
+FilepathHierarchy.0001.switch.hierarchy-builder=UseBuilder
+FilepathHierarchy.0002.classname.hierarchy-builder=com.atlassian.uwc.hierarchies.FilepathHierarchy
+FilepathHierarchy.0003.doc-directory-attachments.property=C:\Temp\WikOut\attach
+FilepathHierarchy.0004.filepath-hierarchy-ext.property=
+#FilepathHierarchy.0005.filepath-hierarchy-matchpagename.property=true
+FilepathHierarchy.0006.filepath-hierarchy-ignorable-ancestors.property=C:\Temp\WikiOut\root
+#FilepathHierarchy.0007.doc-directory-template.property=/Users/laura/Code/Subversion/uwc-spac/sampleData/docdirectory/testtemplate.txt
+FilepathHierarchy.0008.doc-directory-exclude.property=\.svn
+FilepathHierarchy.0009.engine-saves-to-disk.property=true
+
+##### Tokenizer adds ######xxxyyy blocks that stop the regex's parsing the matched delimeters
+## This can be used to stop converters changing values in the source.
+
+## Disabled illegal names/links handling as this changes various links from [[ to [( for some reason?
+FilepathHierarchy..0010.illegal-handling=false
+
+FilepathHierarchy.0011-attachments.class=com.atlassian.uwc.converters.mediawiki.AttachmentConverter
+
+FilepathHierarchy.0012-html.java-regex-tokenizer=\{html\}((?s).*?)\{html\}{replace-with}{html}$1{html}
+
+
+## {{{ }}} is no format on LR
+FilepathHierarchy.0060-codeblock.java-regex-tokenizer=(?s)\{{3}(.*?)\}{3}{replace-with}{code}$1{code}
+
+## Code, Pre, and Leading Spaces
+FilepathHierarchy.0090-re_pre.java-regex-tokenizer=\<pre\>((?s).*?)\<\/pre\>{replace-with}{code}$1{code}
+FilepathHierarchy.0095-re_code.java-regex-tokenizer=\<code\>((?s).*?)\<\/code\>{replace-with}{code}$1{code}
+
+FilepathHierarchy.0356.span-color.java-regex-tokenizer=<span style=\"color:([^\"]+)\">(.*?)<\/span>{replace-with}{color:$1}$2{color}
+
+# TOC
+FilepathHierarchy.0063-format-TOC.java-regex-tokenizer=(<<TableOfContents>>){replace-with}{toc:style=decimal|maxLevel=2}
+
+## |= is heading in LR - in Confluence its ||
+FilepathHierarchy.0540-re_title.java-regex=(\|\=){replace-with}||
+
+## || is OK for table formattiog in LR, in Confluence we need spaces between
+FilepathHierarchy.0063-table-addspace.java-regex=(\|\|){replace-with} | |
+
+## [page|displayed link] in LR - in Confluence its [page].
+FilepathHierarchy.0420-re_links_alias.java-regex=\[\[([^|]*)\| *([^\]]*)\]\]{replace-with}[$1]
+
+## set the images-all property to false if you only want the images and
+## attachments that the page text refer to. Otherwise, all attached images will
+## be used.
+FilepathHierarchy.0500.images-all.property=true
+
+## == this is legal in LR for a heading so convert to h1. or h2.
+FilepathHierarchy.0338-rex_h4.java-regex=(?m)^={5}([\s\w\d()-:/,.]+)${replace-with}h4. $1
+FilepathHierarchy.0339-rex_h3.java-regex=(?m)^={4}([\s\w\d()-:/,.]+)${replace-with}h3. $1
+FilepathHierarchy.0340-rex_h2.java-regex=(?m)^={3}([\s\w\d()-:/,.]+)${replace-with}h2. $1
+FilepathHierarchy.0341-rex_h1.java-regex=(?m)^={2}([\s\w\d()-:/,.]+)${replace-with}h1. $1
+
+FilepathHierarchy.0500-re_h4.java-regex=={5}\s*(.*?)\s*={5}{replace-with}h4. $1
+FilepathHierarchy.0510-re_h3.java-regex=={4}\s*(.*?)\s*={4}{replace-with}h3. $1
+FilepathHierarchy.0520-re_h2.java-regex=={3}\s*(.*?)\s*={3}{replace-with}h2. $1
+FilepathHierarchy.0530-re_h1.java-regex=={2}\s*(.*?)\s*={2}{replace-with}h1. $1
+
+## bold text in LR is two *, in Confluence it's one.
+FilepathHierarchy.0550-re_text_bold.java-regex=\*\*(.+)\*\*{replace-with}*$1*
+
+## Italics in LR is //, in Confluence it's _one_.
+FilepathHierarchy.0560-re_text_italic.java-regex=//(.+)//{replace-with}_$1_
+
+
+## NOTE: Images must come after tables or the whitespace gets screwed up if a table has images
+## Images must come before Links or Alias handling will make Image conversion more complicated
+FilepathHierarchy.0370-re_images.class=com.atlassian.uwc.converters.mediawiki.ImageConverter
+FilepathHierarchy.0710-images_ws2underscore.class=com.atlassian.uwc.converters.mediawiki.ImageWhitespaceConverter
+
+## { } is insert macro in Confluence and nothing in LR so escape it
+FilepathHierarchy.0862-escaping-curlybrace.java-regex=(\{){replace-with} \\{
+
+
+##### For any tokenizer regex above, strip out tokens #####
+FilepathHierarchy.2000-detokenize.class=com.atlassian.uwc.converters.DetokenizerConverter
+
diff --git a/conf/exporter.liferayhierarchy.properties b/conf/exporter.liferayhierarchy.properties
new file mode 100644
index 0000000..662b3bc
--- /dev/null
+++ b/conf/exporter.liferayhierarchy.properties
@@ -0,0 +1,10 @@
+# Exporter class
+exporter.class=com.atlassian.uwc.exporters.LiferayExporter
+
+# The Liferay export.lar file is a zip archive.
+# Your directory where your unzipped liferay export is located
+src=C:\Temp\WikiIn\
+
+# Where your export dir should go
+out=C:\Temp\WikiOut\
+
diff --git a/lib/commons-cli-1.2.jar b/lib/commons-cli-1.2.jar
new file mode 100644
index 0000000..ce4b9ff
--- /dev/null
+++ b/lib/commons-cli-1.2.jar
Binary files differ
diff --git a/lib/commons-digester3-3.2-with-deps.jar b/lib/commons-digester3-3.2-with-deps.jar
new file mode 100644
index 0000000..ec79528
--- /dev/null
+++ b/lib/commons-digester3-3.2-with-deps.jar
Binary files differ
diff --git a/src/com/atlassian/uwc/exporters/LiferayExporter.java b/src/com/atlassian/uwc/exporters/LiferayExporter.java
new file mode 100644
index 0000000..db71214
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/LiferayExporter.java
@@ -0,0 +1,301 @@
+package com.atlassian.uwc.exporters;
+
+import java.io.File;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.RuntimeErrorException;
+
+import org.apache.commons.cli.BasicParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.apache.log4j.Logger;
+import org.xml.sax.SAXException;
+
+import com.atlassian.uwc.exporters.liferay.Params;
+import com.atlassian.uwc.exporters.liferay.Util;
+import com.atlassian.uwc.exporters.liferay.digester.Indigestion;
+import com.atlassian.uwc.exporters.liferay.digester.LrWikiTree;
+import com.atlassian.uwc.exporters.liferay.digester.Manifest;
+import com.atlassian.uwc.exporters.liferay.digester.Page;
+import com.atlassian.uwc.exporters.liferay.digester.Portlet;
+import com.atlassian.uwc.exporters.liferay.digester.PressCancelException;
+import com.atlassian.uwc.exporters.liferay.digester.WikiData;
+import com.atlassian.uwc.exporters.liferay.digester.WikiPage;
+import com.atlassian.uwc.ui.FileUtils;
+
+/**
+ * Liferay:
+ * Only Creole and HTML format pages are handled.
+ * Images attached to a Liferay page must be linked to in the page text i.e. [[filename.zip]].
+ * Takes the latest version only, no history.
+
+Simplified LAR structure. This ignores some unneeded directories and files.
+
+ manifest.xml - Export timestamp, path to portlet-data.xml (Same dir as portlet.xml)
+ groups
+ comments - Comments data
+ portlets
+ 113518
+ portlet-data.xml - Primary index for all nodes, pages and attachments.
+ bin - Attachment files
+ nodes
+ 1113469.xml - Wiki last change date?
+ pages - Page data (all versions, see portlet-data.xml to find current page versions)
+ comments.xml - Links comment and page data
+
+
+
+Confluence:
+The HTML Macro must be enabled if you have HTML pages to upload.
+
+ * @author SJC
+ *
+ */
+public class LiferayExporter implements Exporter {
+ private static Logger log = Logger.getLogger(LiferayExporter.class);
+ static final String VERSION = "1.1";
+ static final String OPT_HELP = "help";
+ static final String OPT_LARDIR = "lar";
+ static final String OPT_OUTDIR = "out";
+ static final String OPT_CON_START = "start";
+ static final String OPT_ORIGINAL = "original";
+ static final String OPT_NOHTML = "nohtml";
+ static final String OPT_CON_ORPHANS = "orphans";
+ private boolean running = false;
+ private Map<String, String> properties;
+
+ @Override
+ public void cancel() {
+ log.info("Export Cancelled.");
+ this.running = false;
+ }
+
+ @Override
+ public void export(Map properties) {
+ this.running = true;
+ setProperties(properties);
+
+ try {
+ Params params = new Params();
+
+ // TODO get other properties and set them in the params
+ // for instance opt.addOption(OPT_CON_ORPHANS, true, "Page name for orphan pages");
+
+ params.setLarDirectory(getProp("src"));
+ params.setOutputDir(new File(getProp("out")));
+
+ convert(params);
+
+ } catch (PressCancelException e) {
+ // do nothing here as user has decided to abort
+ log.debug("Received PressCancelException");
+ } catch (Exception e) {
+ log.error("Problem while exporting. Exiting.", e);
+ e.printStackTrace();
+
+ throw new RuntimeException(e);
+ }
+
+ if (this.running) {
+ log.info("Export Complete.");
+ }
+
+ this.running = false;
+ }
+
+ void checkCancel() {
+ if (!this.running) {
+ throw new PressCancelException();
+ }
+ }
+
+ public void setProperties(Map<String, String> props) {
+ this.properties = props;
+ }
+
+ public String getProp(String key) {
+ return getProperties().get(key);
+ }
+
+ public Map<String, String> getProperties() {
+ if (this.properties == null){
+ this.properties = new HashMap<String, String>();
+ }
+
+ return this.properties;
+ }
+
+ public static void main(String[] args) {
+ CommandLine cl = null;
+ HelpFormatter hf = new HelpFormatter();
+ Options opt = new Options();
+
+ try {
+ Util.initLog4j();
+
+ opt.addOption(OPT_HELP, false, "Print help for this application.");
+ opt.addOption(OPT_LARDIR, true, "Unzipped Lifieray .lar file directory");
+ opt.addOption(OPT_OUTDIR, true, "Output directory");
+ opt.addOption(OPT_CON_START, true, "Confluence Start page");
+ opt.addOption(OPT_ORIGINAL, false, "Save original files from .lar");
+ opt.addOption(OPT_NOHTML, false, "Uploads HTML formatted pages as {code}");
+ opt.addOption(OPT_CON_ORPHANS, true, "Page name for orphan pages");
+
+ BasicParser parser = new BasicParser();
+ cl = parser.parse(opt, args);
+
+ if (cl.hasOption(OPT_HELP)) {
+ printUsage(hf, opt);
+ } else {
+
+ if (cl.hasOption(OPT_LARDIR) && cl.hasOption(OPT_OUTDIR)) {
+ LiferayExporter wtx = new LiferayExporter();
+ Params params = new Params();
+
+ // the unzipped .lar file directory
+ params.setLarDirectory(cl.getOptionValue(OPT_LARDIR));
+
+ params.setOutputDir(new File(cl.getOptionValue(OPT_OUTDIR)));
+
+ // confluenceStartPage defaults to Home, this opt can overide this
+ String confluenceStartPage = cl.getOptionValue(OPT_CON_START);
+ if (confluenceStartPage != null) {
+ params.setConfluenceStartPage(confluenceStartPage);
+ }
+
+ // confluence page off root to hold orphans.
+ String confluenceOrphanPage = cl.getOptionValue(OPT_CON_ORPHANS);
+ if (confluenceOrphanPage != null) {
+ params.setOrphanPages(confluenceOrphanPage);
+ }
+
+ // copies the original pages into the destination. No conversion.
+ params.setOriginal(cl.hasOption(OPT_ORIGINAL));
+
+ // copies HTML pages as code
+ params.setNoHtml(cl.hasOption(OPT_NOHTML));
+
+ wtx.convert(params);
+ log.info("Completed Liferay to Confluence conversion");
+ } else {
+ printUsage(hf, opt);
+ }
+
+ System.exit(0);
+ }
+
+ } catch (Exception e) {
+ log.error("Main", e);
+ }
+ }
+
+ private static void printUsage(HelpFormatter hf, Options opt) {
+ hf.printHelp("WikiTransfer " + VERSION, "Use to pre process a Liferay Wiki export .lar file. "
+ + "Only looks at the latest version - no history is transfered.", opt,
+ "\nE.G. WikiTransfer -lar C:\\WikiIn -out C:\\WikiOut\n", true);
+
+ System.exit(1);
+ }
+
+ public void convert(Params params) throws IOException, SAXException {
+
+ // make the output directory if it doesn't exist, if it exists delete it.
+ createExportDir(params.getOutputDir());
+
+ LrWikiTree lrwt = new LrWikiTree();
+ log.info("Input directory (unzipped .lar): " + params.getLarDirectory());
+ readPagesInLarFile(params.getLarDirectory(), lrwt);
+
+ checkCancel();
+ lrwt.linkChildren(false);
+
+ WikiPage frontPage = lrwt.findPage(LrWikiTree.FRONTPAGE);
+ frontPage.setOutDir(params.getOutputDir());
+ log.info("Output directory: " + frontPage.getOutDir());
+
+ lrwt.recursePages(frontPage);
+
+ checkCancel();
+ lrwt.reformatAttachments();
+ lrwt.saveAttachments(params.getLarDirectory(),
+ params.getOutputDir() + File.separator + params.getAttachmentDir());
+
+ checkCancel();
+ lrwt.reformatHtmlPages(params.isNoHtml());
+
+ ArrayList<WikiPage> oList = lrwt.findOrphans();
+ checkCancel();
+
+ if (!oList.isEmpty()) {
+ // remove orphans from the linked list and save them in an Uncategorizd page.
+ log.info("Placing " + oList.size() + " orphan pages in " + params.getOrphanPage() + " directory");
+ lrwt.unlinkChildren(oList);
+
+ String unCategorized = frontPage.getOutDir() + File.separator + frontPage.getPath() + File.separator
+ + params.getConfluenceStartPage() + File.separator + params.getOrphanPage();
+
+ // create a page in the home directory that will hold all the orphans
+ lrwt.createUncategorizedChildPage(unCategorized, params.getOrphanPage());
+
+ lrwt.saveOrphanList(oList, unCategorized, params.isOriginal());
+ log.info("---End of orphan list---\r\n");
+ }
+
+ // Set Confluence home page by changing the page title. This title gets
+ // written as the filename directory on disk.
+ frontPage.set__title(params.getConfluenceStartPage());
+ checkCancel();
+
+ lrwt.saveRecursive(frontPage, params.isOriginal());
+ }
+
+ /**
+ * The lar structure is defined by file paths inside XML files. This function parses the successive XML files and
+ * finds the page content and attachments. The page history is discarded, we only want the current data.
+ *
+ * @param larDirectory
+ * @param lrwt
+ * this is filled with Java objects created from the files on disk.
+ * @throws IOException
+ * @throws SAXException
+ */
+ private void readPagesInLarFile(String larDirectory, LrWikiTree lrwt) throws IOException, SAXException {
+ Indigestion xmlDigest = new Indigestion();
+ Manifest mf = xmlDigest.readManifestXml(larDirectory);
+
+ String path = mf.getPortlet().getPath();
+ File file = new File(larDirectory, path);
+ Portlet portlet = xmlDigest.readPortletXml(file);
+
+ path = portlet.getPortlet().getPath();
+ file = new File(larDirectory, path);
+
+ WikiData wd = xmlDigest.readPortletDataXml(file);
+ ArrayList<Page> pageList = wd.getPages().getPageList();
+
+ for (Page page : pageList) {
+ path = page.getPath();
+ file = new File(larDirectory, path);
+ WikiPage wp = xmlDigest.readWikiPageXml(file, page.getAttachments());
+ lrwt.addPage(wp);
+ }
+ }
+
+ private void createExportDir(File export) {
+ if (export.exists()) {
+ log.debug("Deleting existing export dir: " + export.getAbsolutePath());
+ FileUtils.deleteDir(export);
+ }
+
+ if (!export.mkdirs()) {
+ log.error("Could not create export dir: " + export.getAbsolutePath());
+ }
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/Params.java b/src/com/atlassian/uwc/exporters/liferay/Params.java
new file mode 100644
index 0000000..1c023b2
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/Params.java
@@ -0,0 +1,79 @@
+package com.atlassian.uwc.exporters.liferay;
+
+import java.io.File;
+
+public class Params {
+ private String orphanPages = "Uncategorized";
+ private String confluenceStartPage = "Home";
+ private String attachmentDir = "attach";
+ private String larDirectory;
+ private File outputDir;
+ private boolean original = false;
+ private boolean noHtml = false;
+
+ /**
+ * This is the name of the page in Confluence that will hold the orphans
+ *
+ * @return
+ */
+ public String getOrphanPage() {
+ return orphanPages;
+ }
+
+ public void setOrphanPages(String orphanPages) {
+ this.orphanPages = orphanPages;
+ }
+
+ public String getConfluenceStartPage() {
+ return confluenceStartPage;
+ }
+
+ public void setConfluenceStartPage(String confluenceStartPage) {
+ this.confluenceStartPage = confluenceStartPage;
+ }
+
+ public String getAttachmentDir() {
+ return attachmentDir;
+ }
+
+ public void setAttachmentDir(String attachmentDir) {
+ this.attachmentDir = attachmentDir;
+ }
+
+ public String getLarDirectory() {
+ return larDirectory;
+ }
+
+ public void setLarDirectory(String larDirectory) {
+ this.larDirectory = larDirectory;
+ }
+
+ public File getOutputDir() {
+ return outputDir;
+ }
+
+ public void setOutputDir(File outputDir) {
+ this.outputDir = outputDir;
+ }
+
+ public boolean isOriginal() {
+ return original;
+ }
+
+ public void setOriginal(boolean original) {
+ this.original = original;
+ }
+
+ public void setOriginal(String original) {
+ this.original = Boolean.parseBoolean(original);
+ }
+
+ public boolean isNoHtml() {
+ return noHtml;
+ }
+
+ public void setNoHtml(boolean noHtml) {
+ this.noHtml = noHtml;
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/Util.java b/src/com/atlassian/uwc/exporters/liferay/Util.java
new file mode 100644
index 0000000..b0c42c6
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/Util.java
@@ -0,0 +1,140 @@
+package com.atlassian.uwc.exporters.liferay;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Properties;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+
+/** General utility methods */
+public class Util {
+
+ /** Load properties from resource. */
+ public static Properties load(Object context, String fileName) {
+ Properties properties = null;
+ InputStream inputStream = null;
+
+ String currentDir = new File(".").getAbsolutePath();
+
+ try {
+ properties = new Properties();
+ inputStream = new FileInputStream(fileName);
+ properties.load(inputStream);
+ inputStream.close();
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Properties file: " + currentDir + " " + fileName, e);
+ } finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (Exception e) {
+ /* Ignore */
+ }
+ }
+ }
+ return properties;
+ }
+
+ public static Reader loadResource(Object context, String fileName) {
+ Reader properties = null;
+
+ String currentDir = new File(".").getAbsolutePath();
+
+ try {
+ InputStream inputStream = context.getClass().getResourceAsStream(fileName);
+ properties = new InputStreamReader(inputStream);
+
+// inputStream.close();
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Properties file: " + currentDir + " " + fileName, e);
+ }
+
+ return properties;
+ }
+
+ static void printClasspath() {
+ System.out.println("Classpath:-");
+
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+
+ URL[] urls = ((URLClassLoader) cl).getURLs();
+
+ for (URL url : urls) {
+ System.out.println(url.getFile());
+ }
+
+ }
+
+ /** Load xml file */
+ public static Document loadXml(String fileName) {
+ Document doc = null;
+ InputStream inputStream = null;
+ String currentDir = new File(".").getAbsolutePath();
+
+ try {
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+
+ inputStream = new FileInputStream(fileName);
+
+ doc = dBuilder.parse(inputStream);
+ doc.getDocumentElement().normalize();
+
+ inputStream.close();
+ } catch (Exception e) {
+ throw new IllegalArgumentException("XML file path: " + currentDir, e);
+ } finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (Exception e) {
+ /* Ignore */
+ }
+ }
+ }
+
+ return doc;
+ }
+
+ public static String printDom(Document document) throws TransformerException {
+
+ String str = "";
+
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ Source source = new DOMSource(document);
+ Result output = new StreamResult(byteOut);
+ transformer.transform(source, output);
+ str = byteOut.toString();
+
+ return str;
+ }
+
+ /** Use default log4j config. */
+ public static void initLog4j() {
+ Logger root = Logger.getRootLogger();
+ if (!root.getAllAppenders().hasMoreElements()) {
+ BasicConfigurator.configure();
+ root.warn("log4j configuration file not found using defaults!!!");
+ }
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/Attachment.java b/src/com/atlassian/uwc/exporters/liferay/digester/Attachment.java
new file mode 100644
index 0000000..c283069
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/Attachment.java
@@ -0,0 +1,32 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+
+
+public class Attachment {
+
+ private String binPath = "b-pathX";
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getBinPath() {
+ return binPath;
+ }
+
+ public void setBinPath(String binPath) {
+ this.binPath = binPath;
+ }
+
+ @Override
+ public String toString() {
+ return "Attachment [name=" + name + "]";
+ }
+
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/Indigestion.java b/src/com/atlassian/uwc/exporters/liferay/digester/Indigestion.java
new file mode 100644
index 0000000..6a6b80c
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/Indigestion.java
@@ -0,0 +1,125 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.commons.digester3.Digester;
+import org.apache.log4j.Logger;
+import org.xml.sax.SAXException;
+
+public class Indigestion {
+ private static Logger _log = Logger.getLogger(Indigestion.class);
+
+ public Manifest readManifestXml(String directory) throws IOException, SAXException {
+ Manifest retval = null;
+ File file = new File(directory, "manifest.xml");
+
+ Digester digester = new Digester();
+ digester.setValidating(false);
+
+ digester.addObjectCreate("root", Manifest.class);
+ digester.addObjectCreate("root/portlet", ManifestPortlet.class);
+ digester.addSetProperties("root/portlet");
+ digester.addSetNext("root/portlet", "setPortlet");
+
+ retval = (Manifest) digester.parse(file);
+
+ _log.debug(retval.toString());
+
+ return retval;
+ }
+
+// @formatter:off
+/*
+ <portlet portlet-id="36" root-portlet-id="36" old-plid="113518" scope-layout-type="" scope-layout-uuid="">
+ <portlet-data path="/groups/113333/portlets/36/113518/portlet-data.xml"/>
+*/
+// @formatter:on
+ public Portlet readPortletXml(File file) throws IOException, SAXException {
+ Portlet retval = null;
+
+ Digester digester = new Digester();
+ digester.setValidating(false);
+
+ digester.addObjectCreate("portlet", Portlet.class);
+ digester.addObjectCreate("portlet/portlet-data", PortletData.class);
+ digester.addSetProperties("portlet/portlet-data");
+ digester.addSetNext("portlet/portlet-data", "setPortlet");
+
+ retval = (Portlet) digester.parse(file);
+
+ _log.debug(retval.toString());
+
+ return retval;
+ }
+
+// @formatter:off
+/*
+<wiki-data group-id="113333">
+ <pages>
+ <page image-path="/groups/113333/portlets/36/page/028b08d8-1a74-4542-a3ec-9e429374f36c/1.0/" path="/groups/113333/portlets/36/pages/320552.xml"/>
+ <page image-path="/groups/113333/portlets/36/page/0f07a009-8107-49bb-8612-48fb7b52c37a/1.0/" path="/groups/113333/portlets/36/pages/347437.xml">
+ <attachment name="java-proxy-settings.jpg" bin-path="/groups/113333/portlets/36/bin/347437/java-proxy-settings.jpg"/>
+ </page>
+*/
+// @formatter:on
+ public WikiData readPortletDataXml(File file) throws IOException, SAXException {
+ WikiData retval = null;
+
+ Digester digester = new Digester();
+ digester.setValidating(false);
+
+ digester.addObjectCreate("wiki-data", WikiData.class);
+ //element <pages>
+ digester.addObjectCreate("wiki-data/pages", Pages.class);
+ digester.addSetProperties("wiki-data/pages");
+ digester.addSetNext("wiki-data/pages", "setPages");
+
+ //element <page>
+ digester.addObjectCreate("wiki-data/pages/page", Page.class);
+ digester.addSetProperties("wiki-data/pages/page");
+ digester.addSetNext("wiki-data/pages/page", "setPage");
+
+ //element <attachment>
+ digester.addObjectCreate("wiki-data/pages/page/attachment", Attachment.class);
+ digester.addSetProperties("wiki-data/pages/page/attachment", "bin-path", "binPath");
+ digester.addSetNext("wiki-data/pages/page/attachment", "setAttachment");
+
+ retval = (WikiData) digester.parse(file);
+
+ _log.debug(retval.toString());
+
+ return retval;
+ }
+
+/* @formatter:off
+ <WikiPage>
+ <__new>false</__new>
+ ...
+*/
+// @formatter:on
+ public WikiPage readWikiPageXml(File file, ArrayList<Attachment> attachments) throws IOException, SAXException {
+ WikiPage retval = null;
+
+ Digester digester = new Digester();
+ digester.setValidating(false);
+
+ digester.addObjectCreate("WikiPage", WikiPage.class);
+ digester.addBeanPropertySetter("WikiPage/__title");
+ digester.addBeanPropertySetter("WikiPage/__parentTitle");
+ digester.addBeanPropertySetter("WikiPage/__redirectTitle");
+ digester.addBeanPropertySetter("WikiPage/__format");
+ digester.addBeanPropertySetter("WikiPage/__version");
+ digester.addBeanPropertySetter("WikiPage/__content");
+
+ retval = (WikiPage) digester.parse(file);
+ retval.setAttachments(attachments);
+ retval.setFile(file);
+
+ // _log.debug(retval.toString());
+
+ return retval;
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/LrWikiTree.java b/src/com/atlassian/uwc/exporters/liferay/digester/LrWikiTree.java
new file mode 100644
index 0000000..2672ac3
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/LrWikiTree.java
@@ -0,0 +1,511 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Liferay (LR) wiki page processor.
+ *
+ * @author Developer
+ *
+ */
+public class LrWikiTree {
+ public static final String FRONTPAGE = "FrontPage";
+
+ private ArrayList<WikiPage> pageList = new ArrayList<WikiPage>();
+ private static Logger _log = Logger.getLogger(LrWikiTree.class);
+
+ /**
+ * Adds pages to the internal page list. We only keep the current page and discard historical pages.
+ *
+ * @param page
+ */
+ public void addPage(WikiPage page) {
+ // if we have an existing page check the version and discard ancient pages
+ WikiPage wp = findPage(page.get__title());
+
+ if (wp != null) {
+ Double version = wp.getVersion();
+
+ // only keep latest version of the page
+ if (page.getVersion() > version) {
+ pageList.remove(wp);
+ pageList.add(page);
+ }
+ } else {
+ // no previous version so add the page
+ // _log.debug("Adding Page: " + page.get__title());
+ pageList.add(page);
+ }
+ }
+
+ /**
+ * Finds pages that don't have parents and are not named Frontpage.
+ *
+ * @return
+ */
+ public ArrayList<WikiPage> findOrphans() {
+ ArrayList<WikiPage> retval = new ArrayList<WikiPage>();
+
+ for (WikiPage page : pageList) {
+ String parentTitle = page.get__parentTitle();
+
+ if (parentTitle.isEmpty() && !page.get__title().equals(FRONTPAGE)) {
+ retval.add(page);
+ } else if (!page.get__redirectTitle().isEmpty()) {
+ retval.add(page);
+ }
+ }
+
+ return retval;
+ }
+
+ /**
+ * Creates a page in the home directory that will hold all the orphans. Also creates the directory structure on disk
+ * for the pages.
+ *
+ * @param outputDir
+ * @throws IOException
+ */
+ public void createUncategorizedChildPage(String outputDir, String orphanPage) throws IOException {
+ String uncategorizedPage = "== Overview ==\r\n\r\nPages that don't have parents are placed here after transfering the Wiki into Confluence.";
+
+ File dir = new File(outputDir);
+ dir.mkdirs();
+
+ File unCat = new File(outputDir + File.separator + orphanPage);
+
+ write(unCat, uncategorizedPage);
+ }
+
+ /**
+ * Copies the page content of the files in the list to the output directory.
+ *
+ * @param list
+ * @param outputDir
+ * @throws IOException
+ */
+ public void saveOrphanList(ArrayList<WikiPage> list, String outputDir, boolean original) throws IOException {
+
+ for (WikiPage page : list) {
+ page.setDepth(0); // page is an orphan so reset it's place to the root in the hierarchy
+ recursePages(page);
+
+ page.setPath("");
+ page.setOutDir(new File(outputDir));
+
+ saveOrphanRecursive(page, original);
+ }
+ }
+
+ /**
+ * Writes the content of the orphaned pages onto the Uncategorized directory. Child pages are written maintaining
+ * the hierarchy in the file system.
+ *
+ * @param frontPage
+ * @param copyOriginal
+ * true to copy the original xml file to the destination
+ * @throws IOException
+ */
+ public void saveOrphanRecursive(WikiPage frontPage, boolean copyOriginal) throws IOException {
+ String padding = "";
+ for (int i = 0; i < frontPage.getDepth(); i++) {
+ padding += " ";
+ }
+
+ _log.info(padding + frontPage.get__title());
+
+ File dir = new File(frontPage.getOutDir() + File.separator + frontPage.getPath());
+ dir.mkdirs();
+
+ // _log.info("++" + dir.getCanonicalPath());
+
+ // _log.debug("Create Dir: " + dir);
+ if (copyOriginal) {
+ copyFile(frontPage.getFile(), new File(dir, frontPage.get__title() + ".xml"));
+ } else {
+ File filePage = new File(dir, frontPage.get__title());
+ write(filePage, frontPage.get__content());
+ }
+
+ if (!frontPage.getAttachments().isEmpty()) {
+ _log.info(padding + " " + frontPage.getAttachments().size() + "-Attachments " + frontPage.getAttachments());
+ }
+
+ for (WikiPage page : frontPage.getChildren()) {
+ page.setPath(frontPage.getPath());
+ page.setOutDir(frontPage.getOutDir());
+
+ saveRecursive(page, copyOriginal);
+ }
+ }
+
+ /**
+ * Removes the parent child relationship for the given pages.
+ *
+ * @param pages
+ */
+ public void unlinkChildren(ArrayList<WikiPage> pages) {
+ for (WikiPage page : pages) {
+ _log.debug("Removing page '" + page.get__title() + "'");
+ if (!pageList.remove(page)) {
+ _log.error("Can't remove: " + page.get__title());
+ }
+
+ // We also need to remove the child from the parent child relationship
+ WikiPage parent = findPage(page.get__parentTitle());
+ if (parent != null) {
+ if (!parent.removeChild(page)) {
+ _log.error("Can't remove child from parent: " + page.get__parentTitle());
+ }
+ }
+ }
+ }
+
+ public WikiPage findPage(String title) {
+ WikiPage retval = null;
+
+ for (WikiPage page : pageList) {
+ if (page.get__title().equals(title)) {
+ retval = page;
+ break;
+ }
+ }
+
+ return retval;
+ }
+
+ /**
+ * Creates a parent child relationship with the internal pages.
+ *
+ * @param sort
+ */
+ public void linkChildren(boolean sort) {
+
+ if (sort) {
+ Collections.sort(pageList);
+ }
+
+ for (WikiPage page : pageList) {
+ String parentTitle = page.get__parentTitle();
+
+ if (!parentTitle.isEmpty()) {
+ WikiPage parent = findPage(parentTitle);
+
+ if (parent != null) {
+ parent.addChildPage(page);
+
+ } else {
+ _log.debug("!!!Error finding Parent!!! " + parentTitle);
+ }
+ }
+ }
+ }
+
+ /**
+ * copies all the attachments for all the pages into the given directory.
+ *
+ * @param larDirectory
+ * @param destDirName
+ * @throws IOException
+ */
+ public void saveAttachments(String larDirectory, String destDirName) throws IOException {
+ File destDir = new File(destDirName);
+ destDir.mkdirs();
+ _log.info("Copying attachments to: " + destDirName);
+
+ for (WikiPage page : pageList) {
+ ArrayList<Attachment> files = page.getAttachments();
+
+ for (Attachment attachment : files) {
+ String name = attachment.getBinPath();
+
+ copyFile(new File(larDirectory, name), new File(destDir, attachment.getName()));
+ }
+ }
+ }
+
+ /**
+ * Attachments in the LR export are indistinguishable from links. The function looks for [[xxx]], where xxx is an
+ * attachment and changes the download link to [^xxx]. This makes the UWC
+ * com.atlassian.uwc.hierarchies.FilepathHierarchy class upload the attachment.
+ *
+ * Image conversion {{image.jpg}} -> !image.jpg! is also handled here for the same reason as above.
+ *
+ */
+ public void reformatAttachments() {
+
+ for (WikiPage page : pageList) {
+ ArrayList<Attachment> files = page.getAttachments();
+
+ for (Attachment attachment : files) {
+ String name = attachment.getName();
+ String content = page.get__content();
+
+ if (content.indexOf(name) > 0) {
+ String replace = convertAttachLink(content, name);
+
+ replace = convertImageLink(replace, name);
+
+ page.set__content(replace);
+ }
+ }
+ }
+ }
+
+ /**
+ * [[link]] converts to [^link] and [[link|link name]] converts to [^link]
+ *
+ * Linking to an attachment in LR stopped working after the SP2 upgrade but we still use this mechanism to mark
+ * attachments for inclusion in Confluence.
+ *
+ * @param content
+ * @param name
+ * @return
+ */
+ public String convertAttachLink(String content, String name) {
+ String retval = content;
+
+ // [[attach] -> [^attach]
+ retval = content.replaceAll("\\[\\[" + name + "\\]\\]", "[^" + name + "]");
+
+ // [[attach|attach name]] -> [^attach]
+ // // "\\[\\[" + // opening left brackets
+ // // name is captured by replaceAll
+ // // "\\|" + // until a pipe
+ // // "[^\\]|]+" + // anything but a right bracket or | until
+ // // "\\]\\]"; // right brackets
+ retval = retval.replaceAll("\\[\\[" + name + "\\|[^\\]|]*]]", "[^" + name + "]");
+
+ return retval;
+ }
+
+ /**
+ * {{image.jpg}} is display image in LR - in Confluence its !image.jpg! We do this here as we can find out if it's
+ * an image by looking at the attachments.
+ *
+ * @param content
+ * @param name
+ * @return
+ */
+ public String convertImageLink(String content, String name) {
+ return content.replaceFirst("\\{\\{" + name + "\\}\\}", "!" + name + "!");
+ }
+
+ /**
+ * Html formatted pages need to be surrounded with {html}
+ *
+ * @param noHtml
+ * if true encloses the html fragment inside a code block this disables HTML rendering in Confluence
+ */
+ public void reformatHtmlPages(boolean noHtml) {
+
+ for (WikiPage page : pageList) {
+ String format = page.get__format();
+ if (format.equalsIgnoreCase("html")) {
+ if (noHtml) {
+ _log.debug("Disabling html formatting for page: " + page.get__title());
+ String content = page.get__content();
+ page.set__content("{code} " + content + "{code}");
+ } else {
+ _log.debug("Adding html formatting for page: " + page.get__title());
+ String content = page.get__content();
+ page.set__content("{html} " + content + "{html}");
+ }
+ } else if (format.equalsIgnoreCase("creole")) {
+ // This is the stuff we are expecting
+ } else {
+ _log.warn("Unsupported format detected: " + format);
+ }
+ }
+ }
+
+ /**
+ * Sets the depth value for the pages in the hierarchy.
+ *
+ * @param frontPage
+ */
+ public void recursePages(WikiPage frontPage) {
+
+ for (WikiPage page : frontPage.getChildren()) {
+
+ // if(page.get__title().contains("Admin")){
+ // _log.debug("!break " );
+ // }
+
+ page.setDepth(frontPage.getDepth() + 1);
+ recursePages(page);
+ }
+ }
+
+ /**
+ * Prints out the current tree structure.
+ *
+ * @param frontPage
+ */
+ public void showRecursive(WikiPage frontPage) {
+ String padding = "";
+ for (int i = 0; i < frontPage.getDepth(); i++) {
+ padding += " ";
+ }
+
+ _log.info(padding + frontPage.get__title());
+
+ if (!frontPage.getAttachments().isEmpty()) {
+ _log.info(padding + " " + frontPage.getAttachments().size() + "-Attachments " + frontPage.getAttachments());
+ }
+
+ for (WikiPage page : frontPage.getChildren()) {
+ showRecursive(page);
+ }
+ }
+
+ /**
+ * Copy the current pagelist original files into the given directory.
+ *
+ * @param dir
+ * @throws IOException
+ */
+ public void copyTo(String dir) throws IOException {
+ File destDir = new File(dir);
+ destDir.mkdir();
+ _log.info("Copying " + pageList.size() + " current pages to: " + dir);
+
+ for (WikiPage page : pageList) {
+ _log.info("XML Path: " + page.getFile().getAbsolutePath());
+ copyFile(page.getFile(), new File(destDir, page.get__title() + ".xml"));
+ }
+ }
+
+ /**
+ * Copy the source file to the destination overwriting the file if it exists.
+ *
+ * @param sourceFile
+ * @param destFile
+ * @throws IOException
+ */
+ public static void copyFile(File sourceFile, File destFile) throws IOException {
+ copyFile(sourceFile, destFile, true);
+ }
+
+ /**
+ * Copy the source file to the destination.
+ *
+ * @param sourceFile
+ * @param destFile
+ * @param overwrite
+ * overwrite the file if true.
+ * @throws IOException
+ */
+ public static void copyFile(File sourceFile, File destFile, boolean overwrite) throws IOException {
+ if (!destFile.exists()) {
+ destFile.createNewFile();
+ } else {
+ if (!overwrite) {
+ throw new IOException("Destination file exists! " + destFile);
+ }
+
+ _log.trace("Destination file exists: " + destFile);
+ }
+
+ FileChannel source = null;
+ FileChannel destination = null;
+
+ try {
+ source = new FileInputStream(sourceFile).getChannel();
+ destination = new FileOutputStream(destFile).getChannel();
+ destination.transferFrom(source, 0, source.size());
+ } finally {
+ if (source != null) {
+ source.close();
+ }
+ if (destination != null) {
+ destination.close();
+ }
+ }
+ }
+
+ /**
+ * Writes the content of the pages of the Wiki onto the directory, maintaining the hierarchy structure in the file
+ * system.
+ *
+ * @param frontPage
+ * @param copyOriginal
+ * true to copy the original xml file to the destination
+ * @throws IOException
+ */
+ public void saveRecursive(WikiPage frontPage, boolean copyOriginal) throws IOException {
+ String padding = "";
+ for (int i = 0; i < frontPage.getDepth(); i++) {
+ padding += " ";
+ }
+
+ _log.info(padding + frontPage.get__title());
+
+ File dir = new File(frontPage.getOutDir() + File.separator + frontPage.getPath(), frontPage.get__title());
+ dir.mkdirs();
+
+ // _log.debug("Create Dir: " + dir);
+ if (copyOriginal) {
+ copyFile(frontPage.getFile(), new File(dir, frontPage.get__title() + ".xml"));
+ } else {
+ File filePage = new File(dir, frontPage.get__title());
+ write(filePage, frontPage.get__content());
+ }
+
+ if (!frontPage.getAttachments().isEmpty()) {
+ _log.info(padding + " " + frontPage.getAttachments().size() + "-Attachments " + frontPage.getAttachments());
+ }
+
+ for (WikiPage page : frontPage.getChildren()) {
+ page.setPath(frontPage.getPath() + File.separator + frontPage.get__title());
+ page.setOutDir(frontPage.getOutDir());
+
+ saveRecursive(page, copyOriginal);
+ }
+ }
+
+ protected void write(File file, String content) {
+ try {
+ FileOutputStream fw = new FileOutputStream(file);
+ OutputStreamWriter outstream = new OutputStreamWriter(fw, "utf-8");
+ BufferedWriter out = new BufferedWriter(outstream);
+ out.write(content);
+ out.close();
+ } catch (IOException e) {
+ _log.error("Problem writing to file: " + file.getAbsolutePath());
+ e.printStackTrace();
+ }
+ }
+
+ public void showPages() {
+ _log.debug("---------Pages-----------");
+ for (WikiPage page : pageList) {
+ _log.info(page);
+
+ if (!page.showChildren().isEmpty()) {
+ _log.info(page.showChildren());
+ }
+ }
+ }
+
+ public void showPagesNoParentTitle() {
+ _log.info("---------showPagesNoParentTitle-----------");
+ for (WikiPage page : pageList) {
+
+ if (page.get__parentTitle().isEmpty()) {
+ _log.debug(page);
+ }
+ }
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/Manifest.java b/src/com/atlassian/uwc/exporters/liferay/digester/Manifest.java
new file mode 100644
index 0000000..dac5eb6
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/Manifest.java
@@ -0,0 +1,34 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+
+public class Manifest {
+
+ private String header = "head";
+ private ManifestPortlet portlet;
+
+ public Manifest() {
+ }
+
+
+ public ManifestPortlet getPortlet() {
+ return portlet;
+ }
+
+ public void setPortlet(ManifestPortlet portlet) {
+ this.portlet = portlet;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public void setHeader(String header) {
+ this.header = header;
+ }
+
+ @Override
+ public String toString() {
+ return "Manifest [header=" + header + ", portlet=" + portlet + "]";
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/ManifestPortlet.java b/src/com/atlassian/uwc/exporters/liferay/digester/ManifestPortlet.java
new file mode 100644
index 0000000..55c0441
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/ManifestPortlet.java
@@ -0,0 +1,22 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+
+
+public class ManifestPortlet {
+
+ private String path = "path1";
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public String toString() {
+ return "Portlet [path=" + path + "]";
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/Page.java b/src/com/atlassian/uwc/exporters/liferay/digester/Page.java
new file mode 100644
index 0000000..5f2c993
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/Page.java
@@ -0,0 +1,37 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+import java.util.ArrayList;
+
+
+
+public class Page {
+
+ private String path = "pathX";
+ private ArrayList<Attachment> attachments = new ArrayList<Attachment>();;
+
+ public Page() {
+ }
+
+ public ArrayList<Attachment> getAttachments() {
+ return attachments;
+ }
+
+ public void setAttachment(Attachment portlet) {
+ this.attachments.add(portlet);
+ }
+
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public String toString() {
+ return "Page [path=" + path + ", attachments=" + attachments + "]";
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/Pages.java b/src/com/atlassian/uwc/exporters/liferay/digester/Pages.java
new file mode 100644
index 0000000..3e7b450
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/Pages.java
@@ -0,0 +1,29 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+import java.util.ArrayList;
+
+
+
+public class Pages {
+
+ private ArrayList<Page> pageList = new ArrayList<Page>();;
+
+ public Pages() {
+ }
+
+ public ArrayList<Page> getPageList() {
+ return pageList;
+ }
+
+ public void setPage(Page portlet) {
+ this.pageList.add(portlet);
+ }
+
+
+ @Override
+ public String toString() {
+ return "Pages [pageList=" + pageList + "]";
+ }
+
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/Portlet.java b/src/com/atlassian/uwc/exporters/liferay/digester/Portlet.java
new file mode 100644
index 0000000..6167ca3
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/Portlet.java
@@ -0,0 +1,35 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+
+
+public class Portlet {
+
+ private String header = "head";
+ private PortletData portlet;
+
+ public Portlet() {
+ }
+
+
+ public PortletData getPortlet() {
+ return portlet;
+ }
+
+ public void setPortlet(PortletData portlet) {
+ this.portlet = portlet;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public void setHeader(String header) {
+ this.header = header;
+ }
+
+ @Override
+ public String toString() {
+ return "Portlet [header=" + header + ", portlet=" + portlet + "]";
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/PortletData.java b/src/com/atlassian/uwc/exporters/liferay/digester/PortletData.java
new file mode 100644
index 0000000..0d64d94
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/PortletData.java
@@ -0,0 +1,22 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+
+
+public class PortletData {
+
+ private String path = "path1";
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public String toString() {
+ return "Portlet [path=" + path + "]";
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/PressCancelException.java b/src/com/atlassian/uwc/exporters/liferay/digester/PressCancelException.java
new file mode 100644
index 0000000..2dedff5
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/PressCancelException.java
@@ -0,0 +1,26 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+public class PressCancelException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public PressCancelException() {
+ // TODO Auto-generated constructor stub
+ }
+
+ public PressCancelException(String arg0) {
+ super(arg0);
+ }
+
+ public PressCancelException(Throwable arg0) {
+ super(arg0);
+ }
+
+ public PressCancelException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/WikiData.java b/src/com/atlassian/uwc/exporters/liferay/digester/WikiData.java
new file mode 100644
index 0000000..09d7a9c
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/WikiData.java
@@ -0,0 +1,36 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+
+
+public class WikiData {
+
+ private String header = "head";
+ private Pages pages;
+
+ public WikiData() {
+ }
+
+
+ public Pages getPages() {
+ return pages;
+ }
+
+ public void setPages(Pages portlet) {
+ this.pages = portlet;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public void setHeader(String header) {
+ this.header = header;
+ }
+
+ @Override
+ public String toString() {
+ return "WikiData [header=" + header + ", pages=" + pages + "]";
+ }
+
+
+}
diff --git a/src/com/atlassian/uwc/exporters/liferay/digester/WikiPage.java b/src/com/atlassian/uwc/exporters/liferay/digester/WikiPage.java
new file mode 100644
index 0000000..5e6263e
--- /dev/null
+++ b/src/com/atlassian/uwc/exporters/liferay/digester/WikiPage.java
@@ -0,0 +1,186 @@
+package com.atlassian.uwc.exporters.liferay.digester;
+
+import java.io.File;
+import java.util.ArrayList;
+
+/* @formatter:off
+<WikiPage>
+<__new>false</__new>
+<__cachedModel>false</__cachedModel>
+<__escapedModel>false</__escapedModel>
+<__uuid>f1819813-8bba-4fcf-8eb8-df63e73f3882</__uuid>
+<__originalUuid>f1819813-8bba-4fcf-8eb8-df63e73f3882</__originalUuid>
+<__pageId>113470</__pageId>
+<__resourcePrimKey>113471</__resourcePrimKey>
+<__originalResourcePrimKey>113471</__originalResourcePrimKey>
+<__setOriginalResourcePrimKey>false</__setOriginalResourcePrimKey>
+<__groupId>113333</__groupId>
+<__originalGroupId>113333</__originalGroupId>
+<__setOriginalGroupId>false</__setOriginalGroupId>
+<__companyId>10233</__companyId>
+<__userId>10272</__userId>
+<__userUuid>5f04387c-e071-43d8-b2a1-ece933d80c31</__userUuid>
+<__userName>Test Test</__userName>
+<__createDate class="sql-timestamp">2011-03-25 10:35:13.0</__createDate>
+<__modifiedDate class="sql-timestamp">2011-03-25 10:35:13.0</__modifiedDate>
+<__nodeId>113469</__nodeId>
+<__originalNodeId>113469</__originalNodeId>
+<__setOriginalNodeId>false</__setOriginalNodeId>
+<__title>FrontPage</__title>
+<__originalTitle>FrontPage</__originalTitle>
+<__version>1.0</__version>
+<__originalVersion>1.0</__originalVersion>
+<__setOriginalVersion>false</__setOriginalVersion>
+<__minorEdit>true</__minorEdit>
+<__content></__content>
+<__summary>New</__summary>
+<__format>creole</__format>
+<__head>false</__head>
+<__parentTitle></__parentTitle>
+<__redirectTitle></__redirectTitle>
+<__status>0</__status>
+<__statusByUserId>10272</__statusByUserId>
+<__statusByUserName>Test Test</__statusByUserName>
+<__statusDate class="sql-timestamp">2011-10-03 16:45:33.0</__statusDate>
+</WikiPage>
+*/ //@formatter:on
+
+public class WikiPage implements Comparable<WikiPage>{
+ private String __title;
+ private String __version;
+ private String __parentTitle = "";
+ private String __redirectTitle = "";
+ private String __format = "";
+ private String __content;
+ private ArrayList<WikiPage> childList = new ArrayList<WikiPage>();
+ private ArrayList<Attachment> attachments = new ArrayList<Attachment>();
+ private int depth = 0;
+ private String path = "root";
+ private File file; // the location on disk of the data that produced this object
+ private File outDir;
+
+ public File getOutDir() {
+ return outDir;
+ }
+ public void setOutDir(File outDir) {
+ this.outDir = outDir;
+ }
+ public File getFile() {
+ return file;
+ }
+ public void setFile(File file) {
+ this.file = file;
+ }
+ public String getPath() {
+ return path;
+ }
+ public void setPath(String path) {
+ this.path = path;
+ }
+ public int getDepth() {
+ return depth;
+ }
+ public void setDepth(int depth) {
+ this.depth = depth;
+ }
+
+ public String get__format() {
+ return __format;
+ }
+
+ public void set__format(String __format) {
+ this.__format = __format;
+ }
+
+ public String get__parentTitle() {
+ return __parentTitle;
+ }
+
+ public void set__parentTitle(String __parentTitle) {
+ this.__parentTitle = __parentTitle;
+ }
+
+ public String get__redirectTitle() {
+ return __redirectTitle;
+ }
+
+ public void set__redirectTitle(String __redirectTitle) {
+ this.__redirectTitle = __redirectTitle;
+ }
+
+ public String get__title() {
+ return __title;
+ }
+
+ public void set__title(String __title) {
+ this.__title = __title;
+ }
+
+ public String get__version() {
+ return __version;
+ }
+
+ public Double getVersion() {
+ return Double.parseDouble(__version);
+ }
+
+ public void set__version(String __version) {
+ this.__version = __version;
+ }
+
+ public String get__content() {
+ return __content;
+ }
+
+ public void set__content(String __content) {
+ this.__content = __content;
+ }
+
+ public void addChildPage(WikiPage page) {
+ childList.add(page);
+ }
+ public ArrayList<WikiPage> getChildren() {
+ return childList;
+ }
+
+ public ArrayList<Attachment> getAttachments() {
+ return attachments;
+ }
+ public void setAttachments(ArrayList<Attachment> attachments) {
+ this.attachments = attachments;
+ }
+
+ boolean isFrontPage(){
+ boolean retval = false;
+ if( get__title().equals("FrontPage")){
+ retval = true;
+ }
+
+ return retval;
+ }
+
+ @Override
+ public String toString() {
+ return depth + "-WikiPage [__title=" + __title + ", __version=" + __version + ", __parentTitle=" + __parentTitle + "]";
+ }
+
+ @Override
+ public int compareTo(WikiPage o) {
+ return this.get__title().compareTo(o.get__title());
+ }
+
+ public String showChildren() {
+ String retval = "";
+
+ if (!childList.isEmpty()) {
+ retval = "[children(" + childList.size() + ") " + childList + "]";
+ }
+
+ return retval;
+ }
+
+ public boolean removeChild(WikiPage child) {
+ return childList.remove(child);
+ }
+
+}