001/* 002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thierry Delprat 016 * Florent Guillaume 017 * 018 * $Id: ExportRestlet.java 30251 2008-02-18 19:17:33Z fguillaume $ 019 */ 020 021package org.nuxeo.ecm.platform.ui.web.restAPI; 022 023import java.io.IOException; 024import java.io.OutputStream; 025import java.io.Serializable; 026import java.util.Map; 027 028import org.nuxeo.ecm.core.api.CoreSession; 029import org.nuxeo.ecm.core.api.DocumentModel; 030import org.nuxeo.ecm.core.api.DocumentModelList; 031import org.nuxeo.ecm.core.api.DocumentSecurityException; 032import org.nuxeo.ecm.core.api.IdRef; 033import org.nuxeo.ecm.core.api.NuxeoException; 034import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; 035import org.nuxeo.ecm.core.api.security.SecurityConstants; 036import org.nuxeo.ecm.core.io.DocumentPipe; 037import org.nuxeo.ecm.core.io.DocumentReader; 038import org.nuxeo.ecm.core.io.DocumentWriter; 039import org.nuxeo.ecm.core.io.impl.DocumentPipeImpl; 040import org.nuxeo.ecm.core.io.impl.plugins.DocumentTreeReader; 041import org.nuxeo.ecm.core.io.impl.plugins.NuxeoArchiveWriter; 042import org.nuxeo.ecm.core.io.impl.plugins.SingleDocumentReader; 043import org.nuxeo.ecm.core.io.impl.plugins.XMLDocumentTreeWriter; 044import org.nuxeo.ecm.core.io.impl.plugins.XMLDocumentWriter; 045import org.restlet.data.CharacterSet; 046import org.restlet.data.Form; 047import org.restlet.data.MediaType; 048import org.restlet.data.Request; 049import org.restlet.data.Response; 050import org.restlet.resource.Representation; 051 052import com.noelios.restlet.http.HttpConstants; 053 054/** 055 * @deprecated since 7.2. Exports are now exposed directly as renditions on the document. Exports can be generated 056 * through the {@code ExportDocument} operation. See NXP-16585. 057 */ 058@Deprecated 059public class ExportRestlet extends BaseStatelessNuxeoRestlet implements Serializable { 060 061 private static final long serialVersionUID = 7831287875548588711L; 062 063 @Override 064 protected void doHandleStatelessRequest(Request req, Response res) { 065 boolean exportAsTree; 066 boolean exportAsZip; 067 String action = req.getResourceRef().getSegments().get(4); 068 if (action.equals("exportTree")) { 069 exportAsTree = true; 070 exportAsZip = true; 071 } else { 072 // "export", "exportSingle" 073 exportAsTree = false; 074 String format = req.getResourceRef().getQueryAsForm().getFirstValue("format"); 075 if (format != null) { 076 format = format.toLowerCase(); 077 } else { 078 format = "xml"; 079 } 080 exportAsZip = "zip".equals(format); 081 } 082 083 String repo = (String) req.getAttributes().get("repo"); 084 if (repo == null || repo.equals("*")) { 085 handleError(res, "you must specify a repository"); 086 return; 087 } 088 089 DocumentModel root; 090 String docid = (String) req.getAttributes().get("docid"); 091 boolean needUnrestricted = false; 092 093 try { 094 boolean init = initRepository(res, repo); 095 if (!init) { 096 handleError(res, "Unable to init repository"); 097 return; 098 } 099 if (docid == null || docid.equals("*")) { 100 root = session.getRootDocument(); 101 } else if (session.hasPermission(new IdRef(docid), SecurityConstants.READ)) { 102 root = session.getDocument(new IdRef(docid)); 103 } else { 104 UnrestrictedVersionExporter runner = new UnrestrictedVersionExporter(session, docid); 105 runner.runUnrestricted(); 106 root = runner.root; 107 needUnrestricted = true; 108 109 // if user can't read version, export is authorized 110 // if he can at least read a proxy pointing to this version 111 if (!root.isVersion()) { 112 throw new DocumentSecurityException("Not enough rights to export " + root.getPathAsString()); 113 } 114 DocumentModelList docs = session.getProxies(root.getRef(), null); 115 boolean hasReadableProxy = false; 116 for (DocumentModel doc : docs) { 117 if (session.hasPermission(doc.getRef(), SecurityConstants.READ)) { 118 hasReadableProxy = true; 119 break; 120 } 121 } 122 if (!hasReadableProxy) { 123 throw new DocumentSecurityException( 124 "Current user doesn't have access to any proxy pointing to version " 125 + root.getPathAsString()); 126 } 127 } 128 } catch (NuxeoException e) { 129 handleError(res, e); 130 return; 131 } 132 133 if (exportAsZip) { 134 // set the content disposition and file name 135 String FILENAME = "export.zip"; 136 137 // use the Facelets APIs to set a new header 138 Map<String, Object> attributes = res.getAttributes(); 139 Form headers = (Form) attributes.get(HttpConstants.ATTRIBUTE_HEADERS); 140 if (headers == null) { 141 headers = new Form(); 142 } 143 headers.add("Content-Disposition", String.format("attachment; filename=\"%s\";", FILENAME)); 144 attributes.put(HttpConstants.ATTRIBUTE_HEADERS, headers); 145 } 146 147 MediaType mediaType = exportAsZip ? MediaType.APPLICATION_ZIP : MediaType.TEXT_XML; 148 Representation entity = makeRepresentation(mediaType, root, exportAsTree, exportAsZip, needUnrestricted); 149 150 res.setEntity(entity); 151 if (mediaType == MediaType.TEXT_XML) { 152 res.getEntity().setCharacterSet(CharacterSet.UTF_8); 153 } 154 } 155 156 protected Representation makeRepresentation(MediaType mediaType, DocumentModel root, final boolean exportAsTree, 157 final boolean exportAsZip, final boolean isUnrestricted) { 158 159 return new ExportRepresentation(mediaType, root, isUnrestricted) { 160 161 @Override 162 protected DocumentPipe makePipe() { 163 if (exportAsTree) { 164 return new DocumentPipeImpl(10); 165 } else { 166 return new DocumentPipeImpl(); 167 } 168 } 169 170 @Override 171 protected DocumentReader makeDocumentReader(CoreSession documentManager, DocumentModel root) 172 { 173 DocumentReader documentReader; 174 if (exportAsTree) { 175 documentReader = new DocumentTreeReader(documentManager, root, false); 176 if (!exportAsZip) { 177 ((DocumentTreeReader) documentReader).setInlineBlobs(true); 178 } 179 } else { 180 documentReader = new SingleDocumentReader(documentManager, root); 181 } 182 return documentReader; 183 } 184 185 @Override 186 protected DocumentWriter makeDocumentWriter(OutputStream outputStream) throws IOException { 187 DocumentWriter documentWriter; 188 if (exportAsZip) { 189 documentWriter = new NuxeoArchiveWriter(outputStream); 190 } else { 191 if (exportAsTree) { 192 documentWriter = new XMLDocumentTreeWriter(outputStream); 193 } else { 194 documentWriter = new XMLDocumentWriter(outputStream); 195 } 196 } 197 return documentWriter; 198 } 199 }; 200 } 201 202 protected static class UnrestrictedVersionExporter extends UnrestrictedSessionRunner { 203 204 private final String docid; 205 206 public DocumentModel root; 207 208 protected UnrestrictedVersionExporter(CoreSession session, String docId) { 209 super(session); 210 docid = docId; 211 } 212 213 @Override 214 public void run() { 215 root = session.getDocument(new IdRef(docid)); 216 } 217 218 } 219 220}