Author: tmortagne
Date: 2007-12-04 12:09:32 +0100 (Tue, 04 Dec 2007)
New Revision: 6275
Added:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/export/
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/export/html/
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/export/html/HtmlPackager.java
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportURLFactory.java
Modified:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportAction.java
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/PDFAction.java
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java
xwiki-platform/core/trunk/xwiki-core/src/main/resources/ApplicationResources.properties
Log:
XWIKI-564: Export pages in HTML, in a zip file
- support a range a multiwiki pages in view mode without request parameters
- add skin dependencies in the package
- add attachments in the package
- modify links targeting skin, attachment and exported pages in exported pages
(using a custom URL factory)
- package all this in a zip file
- add albatross ui button on same menu than pdf/rtf export
Modified:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
===================================================================
---
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
2007-12-04 10:19:40 UTC (rev 6274)
+++
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
2007-12-04 11:09:32 UTC (rev 6275)
@@ -177,7 +177,17 @@
public static final int HAS_CLASS = 4;
private int elements = HAS_OBJECTS | HAS_ATTACHMENTS;
-
+
+ /**
+ * Separator string between database name and space name.
+ */
+ public static final String DB_SPACE_SEP = ":";
+
+ /**
+ * Separator string between space name and page name.
+ */
+ public static final String SPACE_NAME_SEP = ".";
+
// Meta Data
private BaseClass xWikiClass;
Added:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/export/html/HtmlPackager.java
===================================================================
---
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/export/html/HtmlPackager.java
(rev 0)
+++
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/export/html/HtmlPackager.java
2007-12-04 11:09:32 UTC (rev 6275)
@@ -0,0 +1,240 @@
+package com.xpn.xwiki.export.html;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.commons.lang.RandomStringUtils;
+
+import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.web.ExportURLFactory;
+
+/**
+ * Create a zip package containing a range of HTML pages with skin and
attachment dependencies.
+ *
+ * @version $Id: $
+ */
+public class HtmlPackager
+{
+ /**
+ * The name of the package for which packager append ".zip".
+ */
+ private String name = "html.export";
+
+ /**
+ * A description of the package.
+ */
+ private String description = "";
+
+ /**
+ * The pages to export. A [EMAIL PROTECTED] Set} of page name.
+ */
+ private Set pages = new HashSet();
+
+ /**
+ * Modify the name of the package for which packager append ".zip".
+ *
+ * @param name the name of the page.
+ */
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * @return the name of the package for which packager append ".zip".
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Modify the description of the package.
+ *
+ * @param description the description of the package.
+ */
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ /**
+ * @return the description of the package.
+ */
+ public String getDescription()
+ {
+ return description;
+ }
+
+ /**
+ * Add a page to export.
+ *
+ * @param page the name of the page to export.
+ */
+ public void addPage(String page)
+ {
+ this.pages.add(page);
+ }
+
+ /**
+ * Add a range of pages to export.
+ *
+ * @param pages a range od pages to export.
+ */
+ public void addPages(Collection pages)
+ {
+ for (Iterator it = pages.iterator(); it.hasNext();) {
+ this.pages.add(it.next());
+ }
+ }
+
+ /**
+ * Apply export and create the ZIP package.
+ *
+ * @param context the XWiki context used to render pages.
+ * @throws IOException error when creating the package.
+ * @throws XWikiException error when render the pages.
+ */
+ public void export(XWikiContext context) throws IOException, XWikiException
+ {
+ // ////////////////////////////////////////////
+ // Create custom URL factory
+ // ////////////////////////////////////////////
+
+ ExportURLFactory urlf = new ExportURLFactory();
+ File dir =
+ (File)
context.getEngineContext().getAttribute("javax.servlet.context.tempdir");
+ File tempdir = new File(dir, RandomStringUtils.randomAlphanumeric(8));
+ tempdir.mkdirs();
+ File attachmentDir = new File(tempdir, "attachment");
+ attachmentDir.mkdirs();
+ urlf.init(this.pages, tempdir, context);
+ context.setURLFactory(urlf);
+
+ // ////////////////////////////////////////////
+ // Configure response
+ // ////////////////////////////////////////////
+
+ context.getResponse().setContentType("application/zip");
+ context.getResponse().addHeader("Content-disposition",
+ "attachment; filename=" + context.getWiki().getURLEncoded(name) +
".zip");
+ context.setFinished(true);
+
+ // ////////////////////////////////////////////
+ // Render pages to export
+ // ////////////////////////////////////////////
+
+ ZipOutputStream zos = new
ZipOutputStream(context.getResponse().getOutputStream());
+
+ XWikiContext renderContext = (XWikiContext) context.clone();
+
+ for (Iterator it = this.pages.iterator(); it.hasNext();) {
+ String pageName = (String) it.next();
+
+ XWikiDocument doc = context.getWiki().getDocument(pageName,
context);
+
+ String zipname =
+ doc.getDatabase() + "." + doc.getSpace() + "." + doc.getName()
+ ".html";
+ String language = doc.getLanguage();
+ if ((language != null) && (!language.equals(""))) {
+ zipname += "." + language;
+ }
+ ZipEntry zipentry = new ZipEntry(zipname);
+ zos.putNextEntry(zipentry);
+
+ renderContext.setDoc(doc);
+ String content = context.getWiki().parseTemplate("view.vm",
renderContext);
+
+ zos.write(content.getBytes(context.getWiki().getEncoding()));
+ zos.closeEntry();
+ }
+
+ // ////////////////////////////////////////////
+ // Add needed skins to zip file
+ // ////////////////////////////////////////////
+ for (Iterator it = urlf.getNeededSkins().iterator(); it.hasNext();) {
+ String skinName = (String) it.next();
+ addSkinToZip(skinName, zos, context);
+ }
+
+ // ////////////////////////////////////////////
+ // Add resources files to zip file
+ // ////////////////////////////////////////////
+ addDirToZip(tempdir, zos, "");
+
+ zos.setComment(description);
+
+ // Finish zip file
+ zos.finish();
+ zos.flush();
+ }
+
+ /**
+ * Add skin to the package in sub-directory "skins".
+ *
+ * @param skinName the name of the skin.
+ * @param out the ZIP output stream where to put the skin.
+ * @param context the XWiki context.
+ * @throws IOException error when adding the skin to package.
+ */
+ private static void addSkinToZip(String skinName, ZipOutputStream out,
XWikiContext context)
+ throws IOException
+ {
+ File file =
+ new
File(context.getWiki().getEngineContext().getRealPath("/skins/" + skinName));
+ addDirToZip(file, out, "skins/" + skinName + "/");
+ }
+
+ /**
+ * Add a directory and all its sub-directories to the package.
+ *
+ * @param directory the directory to add.
+ * @param out the ZIP output stream where to put the skin.
+ * @param basePath the path where to put the directory in the package.
+ * @throws IOException error when adding the directory to package.
+ */
+ private static void addDirToZip(File directory, ZipOutputStream out,
String basePath)
+ throws IOException
+ {
+ if (!directory.isDirectory()) {
+ return;
+ }
+
+ File[] files = directory.listFiles();
+
+ if (files == null) {
+ return;
+ }
+
+ byte[] tmpBuf = new byte[1024];
+
+ for (int i = 0; i < files.length; ++i) {
+ File file = files[i];
+ if (file.isDirectory()) {
+ addDirToZip(file, out, basePath + file.getName() + "/");
+ continue;
+ }
+
+ FileInputStream in = new FileInputStream(file);
+
+ out.putNextEntry(new ZipEntry(basePath + file.getName()));
+
+ int len;
+ while ((len = in.read(tmpBuf)) > 0) {
+ out.write(tmpBuf, 0, len);
+ }
+
+ out.closeEntry();
+ in.close();
+ }
+ }
+}
Property changes on:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/export/html/HtmlPackager.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportAction.java
===================================================================
---
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportAction.java
2007-12-04 10:19:40 UTC (rev 6274)
+++
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportAction.java
2007-12-04 11:09:32 UTC (rev 6275)
@@ -22,18 +22,25 @@
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.export.html.HtmlPackager;
import com.xpn.xwiki.pdf.impl.PdfExportImpl;
import com.xpn.xwiki.plugin.packaging.PackageAPI;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
- * Exports in XAR, PDF or RTF formats
+ * Exports in XAR, PDF, RTF or HTML formats.
+ *
+ * @version $Id: $
*/
public class ExportAction extends XWikiAction
{
/**
* [EMAIL PROTECTED]
+ *
* @see XWikiAction#render(XWikiContext)
*/
public String render(XWikiContext context) throws XWikiException
@@ -46,23 +53,64 @@
if ((format == null) || (format.equals("xar"))) {
defaultPage = exportXAR(context);
+ } else if (format.equals("html")) {
+ defaultPage = exportHTML(context);
} else {
defaultPage = exportPDFOrRTF(format, context);
}
} catch (Exception e) {
throw new XWikiException(XWikiException.MODULE_XWIKI_APP,
XWikiException.ERROR_XWIKI_APP_EXPORT,
- "Exception while exporting", e);
+ "Exception while exporting",
+ e);
}
return defaultPage;
}
- private String exportPDFOrRTF(String format, XWikiContext context)
- throws XWikiException, IOException
+ private String exportHTML(XWikiContext context) throws XWikiException,
IOException
{
- XWikiURLFactory urlf = context.getWiki().getURLFactoryService()
- .createURLFactory(XWikiContext.MODE_PDF, context);
+ XWikiRequest request = context.getRequest();
+
+ String description = request.get("description");
+ String name = request.get("name");
+ String[] pages = request.getParameterValues("pages");
+
+ List pageList;
+ if (pages == null || pages.length == 0) {
+ pageList = new ArrayList();
+ pageList.add(context.getDoc().getFullName());
+
+ if (name == null || name.trim().length() == 0) {
+ name = context.getDoc().getFullName();
+ }
+ } else {
+ pageList = Arrays.asList(pages);
+ }
+
+ HtmlPackager packager = new HtmlPackager();
+
+ if (name != null && name.trim().length() > 0) {
+ packager.setName(name);
+ }
+
+ if (description != null) {
+ packager.setDescription(description);
+ }
+
+ packager.addPages(pageList);
+
+ packager.export(context);
+
+ return null;
+ }
+
+ private String exportPDFOrRTF(String format, XWikiContext context) throws
XWikiException,
+ IOException
+ {
+ XWikiURLFactory urlf =
+
context.getWiki().getURLFactoryService().createURLFactory(XWikiContext.MODE_PDF,
+ context);
context.setURLFactory(urlf);
PdfExportImpl pdfexport = new PdfExportImpl();
XWikiDocument doc = context.getDoc();
@@ -76,9 +124,10 @@
}
context.getResponse().setContentType("application/" + format);
- context.getResponse().addHeader("Content-disposition", "inline;
filename=" +
- Utils.encode(doc.getSpace(), context) + "_" +
- Utils.encode(doc.getName(), context) + "." + format);
+ context.getResponse().addHeader(
+ "Content-disposition",
+ "inline; filename=" + Utils.encode(doc.getSpace(), context) + "_"
+ + Utils.encode(doc.getName(), context) + "." + format);
pdfexport.export(doc, context.getResponse().getOutputStream(), type,
context);
return null;
@@ -107,8 +156,7 @@
return "export";
}
- PackageAPI export =
- ((PackageAPI) context.getWiki().getPluginApi("package", context));
+ PackageAPI export = ((PackageAPI)
context.getWiki().getPluginApi("package", context));
if ("true".equals(history)) {
export.setWithVersions(true);
} else {
Added:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportURLFactory.java
===================================================================
---
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportURLFactory.java
(rev 0)
+++
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportURLFactory.java
2007-12-04 11:09:32 UTC (rev 6275)
@@ -0,0 +1,233 @@
+package com.xpn.xwiki.web;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.doc.XWikiAttachment;
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.util.Util;
+
+public class ExportURLFactory extends XWikiServletURLFactory
+{
+ /**
+ * Pages for which to convert URL to local.
+ */
+ protected Set exportedPages = new HashSet();
+
+ /**
+ * Directory where to export attachment.
+ */
+ protected File exportDir;
+
+ /**
+ * Names of skins needed by rendered page(s).
+ */
+ private Set neededSkins = new HashSet();
+
+ public ExportURLFactory()
+ {
+ }
+
+ public void init(Collection exportedPages, File exportDir, XWikiContext
context)
+ {
+ super.init(context);
+
+ if (exportDir != null) {
+ this.exportDir = exportDir;
+ }
+
+ if (exportedPages != null) {
+ XWikiDocument doc = new XWikiDocument();
+
+ for (Iterator it = exportedPages.iterator(); it.hasNext();) {
+ String pageName = (String) it.next();
+
+ doc.setDatabase(null);
+ doc.setSpace(null);
+ doc.setName(null);
+
+ doc.setFullName(pageName);
+
+ String absolutePageName = "";
+
+ if (doc.getDatabase() != null) {
+ absolutePageName += doc.getDatabase().toLowerCase();
+ } else {
+ absolutePageName += context.getDatabase().toLowerCase();
+ }
+
+ absolutePageName += XWikiDocument.DB_SPACE_SEP;
+
+ absolutePageName += doc.getFullName();
+
+ this.exportedPages.add(absolutePageName);
+ }
+ }
+ }
+
+ public URL createSkinURL(String filename, String skin, XWikiContext
context)
+ {
+ try {
+ getNeededSkins().add(skin);
+
+ StringBuffer newpath = new StringBuffer();
+
+ newpath.append("file://");
+
+ newpath.append("skins/");
+ newpath.append(skin);
+
+ addFileName(newpath, filename, false, context);
+
+ return new URL(newpath.toString());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return super.createSkinURL(filename, skin, context);
+ }
+
+ public URL createSkinURL(String filename, String web, String name, String
xwikidb,
+ XWikiContext context)
+ {
+ if (!"skins".equals(web)) {
+ return createSkinURL(filename, web, name, xwikidb, context);
+ }
+
+ try {
+ getNeededSkins().add(name);
+
+ StringBuffer newpath = new StringBuffer();
+
+ newpath.append("file://");
+
+ newpath.append("skins/");
+ newpath.append(name);
+
+ addFileName(newpath, filename, false, context);
+
+ return new URL(newpath.toString());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return super.createSkinURL(filename, web, name, xwikidb, context);
+ }
+
+ public URL createURL(String web, String name, String action, String
querystring,
+ String anchor, String xwikidb, XWikiContext context)
+ {
+ try {
+ if (this.exportedPages.contains((xwikidb == null ?
context.getDatabase()
+ .toLowerCase() : xwikidb.toLowerCase())
+ + XWikiDocument.DB_SPACE_SEP + web +
XWikiDocument.SPACE_NAME_SEP)
+ && !"view".equals(action) && context.getLinksAction() == null)
{
+ StringBuffer newpath = new StringBuffer(servletPath);
+
+ newpath.append("file://");
+
+ newpath.append(xwikidb.toLowerCase());
+ newpath.append(".");
+ newpath.append(web);
+ newpath.append(".");
+ newpath.append(name);
+
+ if ((anchor != null) && (!anchor.equals(""))) {
+ newpath.append("#");
+ newpath.append(anchor);
+ }
+
+ newpath.append(".html");
+
+ return new URL(newpath.toString());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return super.createURL(web, name, action, querystring, anchor,
xwikidb, context);
+ }
+
+ public URL createAttachmentURL(String filename, String web, String name,
String action,
+ String querystring, String xwikidb, XWikiContext context)
+ {
+ try {
+ String path =
+ "attachment/" + context.getDatabase() + "." + web + "." + name
+ "." + filename;
+
+ File tempdir = exportDir;
+ File file = new File(tempdir, path);
+ if (!file.exists()) {
+ XWikiDocument doc =
+ context.getWiki().getDocument(web +
XWikiDocument.SPACE_NAME_SEP + name,
+ context);
+ XWikiAttachment attachment = doc.getAttachment(filename);
+ byte[] data = attachment.getContent(context);
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(data);
+ fos.close();
+ }
+
+ return new URI("file://" + path).toURL();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return super.createAttachmentURL(filename, web, name, action,
null, xwikidb, context);
+ }
+ }
+
+ public URL createAttachmentRevisionURL(String filename, String web, String
name,
+ String revision, String xwikidb, XWikiContext context)
+ {
+ try {
+ String path =
+ "attachment/" + context.getDatabase() + "." + web + "." + name
+ "." + filename;
+
+ File tempdir = exportDir;
+ File file = new File(tempdir, path);
+ if (!file.exists()) {
+ XWikiDocument doc =
+ context.getWiki().getDocument(web +
XWikiDocument.SPACE_NAME_SEP + name,
+ context);
+ XWikiAttachment attachment =
+
doc.getAttachment(filename).getAttachmentRevision(revision, context);
+ byte[] data = attachment.getContent(context);
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(data);
+ fos.close();
+ }
+
+ return new URI("file://" + path).toURL();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return super.createAttachmentRevisionURL(filename, web, name,
revision, xwikidb,
+ context);
+ }
+ }
+
+ public String getURL(URL url, XWikiContext context)
+ {
+ if (url == null) {
+ return "";
+ }
+
+ String path = Util.escapeURL(url.toString());
+
+ if (url.getProtocol().equals("file")) {
+ path = path.substring("file://".length());
+ }
+
+ return path;
+ }
+
+ public Collection getNeededSkins()
+ {
+ return neededSkins;
+ }
+}
Property changes on:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/ExportURLFactory.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/PDFAction.java
===================================================================
---
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/PDFAction.java
2007-12-04 10:19:40 UTC (rev 6274)
+++
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/PDFAction.java
2007-12-04 11:09:32 UTC (rev 6275)
@@ -27,6 +27,10 @@
import java.io.IOException;
+/**
+ *
+ * @deprecated Use [EMAIL PROTECTED] ExportAction}.
+ */
public class PDFAction extends XWikiAction {
public String render(XWikiContext context) throws XWikiException {
XWikiURLFactory urlf =
context.getWiki().getURLFactoryService().createURLFactory(XWikiContext.MODE_PDF,
context);
Modified:
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java
===================================================================
---
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java
2007-12-04 10:19:40 UTC (rev 6274)
+++
xwiki-platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java
2007-12-04 11:09:32 UTC (rev 6275)
@@ -217,12 +217,12 @@
}
}
- private void addFileName(StringBuffer newpath, String filename,
XWikiContext context)
+ protected void addFileName(StringBuffer newpath, String filename,
XWikiContext context)
{
addFileName(newpath, filename, true, context);
}
- private void addFileName(StringBuffer newpath, String filename, boolean
encode,
+ protected void addFileName(StringBuffer newpath, String filename, boolean
encode,
XWikiContext context)
{
newpath.append("/");
Modified:
xwiki-platform/core/trunk/xwiki-core/src/main/resources/ApplicationResources.properties
===================================================================
---
xwiki-platform/core/trunk/xwiki-core/src/main/resources/ApplicationResources.properties
2007-12-04 10:19:40 UTC (rev 6274)
+++
xwiki-platform/core/trunk/xwiki-core/src/main/resources/ApplicationResources.properties
2007-12-04 11:09:32 UTC (rev 6275)
@@ -742,6 +742,7 @@
core.menu.preview=Print preview
core.menu.export.pdf=Export as PDF
core.menu.export.rtf=Export as RTF
+core.menu.export.html=Export as HTML
core.menu.rights=Page access rights
core.menu.watch=Watch
core.menu.unwatch=Unwatch
_______________________________________________
notifications mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/notifications