001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * thibaud 018 */ 019package org.nuxeo.diff.pictures; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.OutputStream; 024import java.io.Serializable; 025import java.util.HashMap; 026 027import javax.servlet.ServletException; 028import javax.servlet.http.HttpServlet; 029import javax.servlet.http.HttpServletRequest; 030import javax.servlet.http.HttpServletResponse; 031 032import org.apache.commons.lang.StringUtils; 033import org.apache.commons.logging.Log; 034import org.apache.commons.logging.LogFactory; 035import org.nuxeo.ecm.core.api.Blob; 036import org.nuxeo.ecm.core.api.CoreInstance; 037import org.nuxeo.ecm.core.api.CoreSession; 038import org.nuxeo.ecm.core.api.DocumentModel; 039import org.nuxeo.ecm.core.api.IdRef; 040import org.nuxeo.ecm.core.api.repository.RepositoryManager; 041import org.nuxeo.ecm.platform.commandline.executor.api.CommandNotAvailable; 042import org.nuxeo.ecm.platform.web.common.ServletHelper; 043import org.nuxeo.runtime.api.Framework; 044 045/** 046 * /nuxeo/diffPictures?&repo=therepo&leftDocId=123456&rightDocId= 456789012 047 * &xpath=file:content&commandLine=thecommandline&fuzz=1000&highlightColor=Red &lowlightColor=White&altExtension=jpg 048 * <p> 049 * <ul> 050 * <li><code>leftDocId</code> and <code>rightDocId</code> are required</li> 051 * <li>All other parameters are optional (commandLine, xpath, fuzz, ...). Default values are defined in 052 * <code>DiffPictures</code></li> 053 * <li><code>altExtension</code> is special. If the pictures to compare are _not_ jpeg, png, or gif, _and_ if this 054 * parameter is set, then the result picture will be of this kind. Useful when comparing 2 psd or tif files for example, 055 * and the browser can't display them</li> 056 * </ul> 057 * <p> 058 * commandline, xpath, fuzz, highlightColor, lowlightColor and repo are optional 059 * 060 * @since 7.4 061 */ 062public class DiffPicturesServlet extends HttpServlet { 063 064 private static final long serialVersionUID = 1L; 065 066 private static final Log log = LogFactory.getLog(DiffPicturesServlet.class); 067 068 protected static final int BUFFER_SIZE = 1024 * 512; 069 070 @Override 071 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 072 073 DocumentModel leftDoc, rightDoc; 074 075 String leftDocId = req.getParameter("leftDocId"); 076 String rightDocId = req.getParameter("rightDocId"); 077 078 if (StringUtils.isBlank(leftDocId)) { 079 sendTextResponse(resp, "you must specify a left document as origin"); 080 return; 081 } 082 if (StringUtils.isBlank(rightDocId)) { 083 sendTextResponse(resp, "you must specify 'right' used for comparison against the left document."); 084 return; 085 } 086 087 // WARNING: If you change the name of a parameter, also change it in nuxeo-diff-pictures.js 088 String repo = req.getParameter("repo"); 089 String xpath = req.getParameter("xpath"); 090 String commandLine = req.getParameter("commandLine"); 091 String fuzz = req.getParameter("fuzz"); 092 String highlightColor = req.getParameter("highlightColor"); 093 String lowlightColor = req.getParameter("lowlightColor"); 094 String altExtension = req.getParameter("altExtension"); 095 096 if (StringUtils.isBlank(repo)) { 097 repo = Framework.getLocalService(RepositoryManager.class).getDefaultRepository().getName(); 098 } 099 100 // This try-with-resources does an implicit close() at the end 101 try (CoreSession coreSession = CoreInstance.openCoreSession(repo)) { 102 103 leftDoc = coreSession.getDocument(new IdRef(leftDocId)); 104 rightDoc = coreSession.getDocument(new IdRef(rightDocId)); 105 106 DiffPictures dp = new DiffPictures(leftDoc, rightDoc, xpath); 107 108 HashMap<String, Serializable> params = new HashMap<String, Serializable>(); 109 if (StringUtils.isNotBlank(fuzz)) { 110 params.put("fuzz", fuzz); 111 } 112 if (StringUtils.isNotBlank(highlightColor)) { 113 params.put("highlightColor", highlightColor); 114 } 115 if (StringUtils.isNotBlank(lowlightColor)) { 116 params.put("lowlightColor", lowlightColor); 117 } 118 119 if (StringUtils.isNotBlank(altExtension)) { 120 // Using the leftDoc only 121 Blob leftB; 122 if (StringUtils.isBlank(xpath) || "null".equals(xpath)) { 123 leftB = (Blob) leftDoc.getPropertyValue(DiffPictures.DEFAULT_XPATH); 124 } else { 125 leftB = (Blob) leftDoc.getPropertyValue(xpath); 126 } 127 String fileName = leftB.getFilename(); 128 int dotPos = fileName.lastIndexOf("."); 129 String ext = fileName.substring(dotPos + 1); 130 ext = ext.toLowerCase(); 131 switch (ext) { 132 case "jpg": 133 case "jpeg": 134 case "png": 135 case "gif": 136 // No need to change anything 137 break; 138 139 default: 140 if (altExtension.indexOf(".") != 0) { 141 altExtension = "." + altExtension; 142 } 143 fileName = "comp-" + fileName + altExtension; 144 params.put("targetFileName", fileName); 145 break; 146 147 } 148 } 149 150 Blob bResult; 151 try { 152 bResult = dp.compare(commandLine, params); 153 } catch (CommandNotAvailable | IOException e) { 154 log.error("Unable to compare the pictures", e); 155 sendTextResponse(resp, "Unable to compare the pictures"); 156 return; 157 } 158 159 resp.setHeader("Cache-Control", "no-cache"); 160 resp.setHeader("Pragma", "no-cache"); 161 try { 162 sendBlobResult(req, resp, bResult); 163 } catch (IOException e) { 164 log.error("Unable to handleCompareResult", e); 165 sendTextResponse(resp, "Unable to return the result"); 166 return; 167 } 168 } 169 } 170 171 protected void sendTextResponse(HttpServletResponse resp, String response) throws IOException { 172 173 resp.setContentType("text/plain"); 174 resp.setContentLength(response.getBytes().length); 175 OutputStream out = resp.getOutputStream(); 176 out.write(response.getBytes()); 177 out.close(); 178 179 } 180 181 protected void sendBlobResult(HttpServletRequest req, HttpServletResponse resp, Blob blob) throws IOException { 182 183 InputStream in = blob.getStream(); 184 OutputStream out = resp.getOutputStream(); 185 String fileName = blob.getFilename(); 186 187 resp.setHeader("Content-Disposition", ServletHelper.getRFC2231ContentDisposition(req, fileName)); 188 resp.setContentType(blob.getMimeType()); 189 long fileSize = blob.getLength(); 190 resp.setContentLength((int) fileSize); 191 192 byte[] buffer = new byte[BUFFER_SIZE]; 193 int bytesRead; 194 while ((bytesRead = in.read(buffer)) != -1) { 195 out.write(buffer, 0, bytesRead); 196 } 197 198 } 199}