001/* 002 * (C) Copyright 2006-2007 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 * Nuxeo - initial API and implementation 018 * 019 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $ 020 */ 021 022package org.nuxeo.ecm.platform.picture.web; 023 024import static org.jboss.seam.ScopeType.CONVERSATION; 025 026import java.io.IOException; 027import java.io.Serializable; 028import java.util.ArrayList; 029import java.util.Arrays; 030import java.util.HashMap; 031import java.util.Map; 032 033import org.apache.commons.logging.Log; 034import org.apache.commons.logging.LogFactory; 035import org.jboss.seam.annotations.Create; 036import org.jboss.seam.annotations.Destroy; 037import org.jboss.seam.annotations.In; 038import org.jboss.seam.annotations.Name; 039import org.jboss.seam.annotations.Observer; 040import org.jboss.seam.annotations.Scope; 041import org.jboss.seam.annotations.intercept.BypassInterceptors; 042import org.jboss.seam.annotations.remoting.WebRemote; 043import org.jboss.seam.annotations.web.RequestParameter; 044import org.nuxeo.ecm.core.api.Blob; 045import org.nuxeo.ecm.core.api.CoreSession; 046import org.nuxeo.ecm.core.api.DocumentLocation; 047import org.nuxeo.ecm.core.api.DocumentModel; 048import org.nuxeo.ecm.core.api.IdRef; 049import org.nuxeo.ecm.core.api.model.Property; 050import org.nuxeo.ecm.platform.commandline.executor.api.CommandAvailability; 051import org.nuxeo.ecm.platform.commandline.executor.api.CommandLineExecutorService; 052import org.nuxeo.ecm.platform.picture.api.adapters.PictureResourceAdapter; 053import org.nuxeo.ecm.platform.ui.web.api.NavigationContext; 054import org.nuxeo.ecm.platform.ui.web.rest.RestHelper; 055import org.nuxeo.ecm.platform.ui.web.tag.fn.DocumentModelFunctions; 056import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils; 057import org.nuxeo.ecm.platform.url.api.DocumentView; 058import org.nuxeo.ecm.platform.url.codec.DocumentFileCodec; 059import org.nuxeo.ecm.platform.util.RepositoryLocation; 060import org.nuxeo.ecm.webapp.helpers.EventNames; 061import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor; 062import org.nuxeo.runtime.api.Framework; 063 064/** 065 * @author <a href="mailto:[email protected]">Laurent Doguin</a> 066 */ 067@Name("pictureManager") 068@Scope(CONVERSATION) 069public class PictureManagerBean implements PictureManager, Serializable { 070 071 private static final long serialVersionUID = 1L; 072 073 private static final Log log = LogFactory.getLog(PictureManagerBean.class); 074 075 protected static Boolean imageMagickAvailable; 076 077 @In(create = true, required = false) 078 protected transient CoreSession documentManager; 079 080 @RequestParameter 081 protected String fileFieldFullName; 082 083 @In(required = true, create = true) 084 protected transient NavigationContext navigationContext; 085 086 @In(create = true, required = false) 087 protected ResourcesAccessor resourcesAccessor; 088 089 protected String fileurlPicture; 090 091 protected String filename; 092 093 protected Blob fileContent; 094 095 protected Integer index; 096 097 protected String cropCoords; 098 099 protected ArrayList<Map<String, Object>> selectItems; 100 101 @Override 102 @Create 103 public void initialize() { 104 log.debug("Initializing..."); 105 index = 0; 106 } 107 108 protected DocumentModel getCurrentDocument() { 109 return navigationContext.getCurrentDocument(); 110 } 111 112 @Override 113 @SuppressWarnings("unchecked") 114 public String getFileurlPicture() { 115 ArrayList<Map<String, Object>> views = (ArrayList) getCurrentDocument().getProperty("picture", "views"); 116 return views.get(index).get("title") + ":content"; 117 } 118 119 @Override 120 public void setFileurlPicture(String fileurlPicture) { 121 this.fileurlPicture = fileurlPicture; 122 } 123 124 @SuppressWarnings({ "unchecked", "rawtypes" }) 125 protected void initSelectItems() { 126 selectItems = new ArrayList<Map<String, Object>>(); 127 DocumentModel doc = getCurrentDocument(); 128 ArrayList<Map<String, Object>> views = (ArrayList) doc.getProperty("picture", "views"); 129 for (int i = 0; i < views.size(); i++) { 130 Map<String, Object> map = new HashMap<String, Object>(); 131 map.put("title", views.get(i).get("title")); 132 map.put("idx", i); 133 selectItems.add(map); 134 } 135 } 136 137 @Override 138 public ArrayList getSelectItems() { 139 if (selectItems == null) { 140 initSelectItems(); 141 return selectItems; 142 } else { 143 return selectItems; 144 } 145 } 146 147 @Override 148 public void setSelectItems(ArrayList selectItems) { 149 this.selectItems = selectItems; 150 } 151 152 @Override 153 public String rotate90left() throws IOException { 154 DocumentModel doc = getCurrentDocument(); 155 PictureResourceAdapter picture = doc.getAdapter(PictureResourceAdapter.class); 156 picture.doRotate(-90); 157 documentManager.saveDocument(doc); 158 documentManager.save(); 159 navigationContext.setCurrentDocument(doc); 160 return null; 161 } 162 163 @Override 164 public String rotate90right() throws IOException { 165 DocumentModel doc = getCurrentDocument(); 166 PictureResourceAdapter picture = doc.getAdapter(PictureResourceAdapter.class); 167 picture.doRotate(90); 168 documentManager.saveDocument(doc); 169 documentManager.save(); 170 navigationContext.setCurrentDocument(doc); 171 return null; 172 } 173 174 @Override 175 public String crop() throws IOException { 176 if (cropCoords != null && !cropCoords.equals("")) { 177 DocumentModel doc = getCurrentDocument(); 178 PictureResourceAdapter picture = doc.getAdapter(PictureResourceAdapter.class); 179 picture.doCrop(cropCoords); 180 documentManager.saveDocument(doc); 181 documentManager.save(); 182 navigationContext.setCurrentDocument(doc); 183 } 184 return null; 185 } 186 187 @Override 188 @Observer(value = { EventNames.DOCUMENT_SELECTION_CHANGED, EventNames.DOCUMENT_CHANGED }) 189 @BypassInterceptors 190 public void resetFields() { 191 filename = ""; 192 fileContent = null; 193 selectItems = null; 194 index = 0; 195 cropCoords = null; 196 } 197 198 @WebRemote 199 public String remoteDownload(String patternName, String docID, String blobPropertyName, String filename) 200 { 201 IdRef docref = new IdRef(docID); 202 DocumentModel doc = documentManager.getDocument(docref); 203 return DocumentModelFunctions.fileUrl(patternName, doc, blobPropertyName, filename); 204 } 205 206 @WebRemote 207 public static String urlPopup(String url) { 208 return RestHelper.addCurrentConversationParameters(url); 209 } 210 211 @Override 212 public void download(DocumentView docView) { 213 if (docView != null) { 214 DocumentLocation docLoc = docView.getDocumentLocation(); 215 // fix for NXP-1799 216 if (documentManager == null) { 217 RepositoryLocation loc = new RepositoryLocation(docLoc.getServerName()); 218 navigationContext.setCurrentServerLocation(loc); 219 documentManager = navigationContext.getOrCreateDocumentManager(); 220 } 221 DocumentModel doc = documentManager.getDocument(docLoc.getDocRef()); 222 if (doc == null) { 223 return; 224 } 225 String path = docView.getParameter(DocumentFileCodec.FILE_PROPERTY_PATH_KEY); 226 String[] propertyPath = path.split(":"); 227 String title = null; 228 String field = null; 229 Property datamodel; 230 if (propertyPath.length == 2) { 231 title = propertyPath[0]; 232 field = propertyPath[1]; 233 datamodel = doc.getProperty("picture:views"); 234 } else if (propertyPath.length == 3) { 235 String schema = propertyPath[0]; 236 title = propertyPath[1]; 237 field = propertyPath[2]; 238 datamodel = doc.getProperty(schema + ":" + "views"); 239 } else { 240 log.debug("Invalid property path: " + Arrays.toString(propertyPath)); 241 return; 242 } 243 Property view = null; 244 for (Property property : datamodel) { 245 if (property.get("title").getValue().equals(title)) { 246 view = property; 247 } 248 } 249 250 if (view == null) { 251 for (Property property : datamodel) { 252 if (property.get("title").getValue().equals("Thumbnail")) { 253 view = property; 254 } 255 } 256 } 257 if (view == null) { 258 return; 259 } 260 Blob blob = (Blob) view.getValue(field); 261 String filename = (String) view.getValue("filename"); 262 // download 263 ComponentUtils.download(doc, path, blob, filename, "picture"); 264 } 265 } 266 267 @Override 268 @Destroy 269 public void destroy() { 270 log.debug("Removing Seam action listener..."); 271 fileurlPicture = null; 272 filename = null; 273 fileContent = null; 274 index = null; 275 selectItems = null; 276 } 277 278 @Override 279 public String getFilename() { 280 return filename; 281 } 282 283 @Override 284 public void setFilename(String filename) { 285 this.filename = filename; 286 } 287 288 @Override 289 public Blob getFileContent() { 290 return fileContent; 291 } 292 293 @Override 294 public void setFileContent(Blob fileContent) { 295 this.fileContent = fileContent; 296 } 297 298 @Override 299 public Integer getIndex() { 300 return index; 301 } 302 303 @Override 304 public void setIndex(Integer index) { 305 this.index = index; 306 } 307 308 @Override 309 public String getCropCoords() { 310 return cropCoords; 311 } 312 313 @Override 314 public void setCropCoords(String cropCoords) { 315 this.cropCoords = cropCoords; 316 } 317 318 public Boolean isImageMagickAvailable() { 319 if (imageMagickAvailable == null) { 320 CommandLineExecutorService cles = Framework.getService(CommandLineExecutorService.class); 321 CommandAvailability ca = cles.getCommandAvailability("cropAndResize"); 322 imageMagickAvailable = ca.isAvailable(); 323 } 324 return imageMagickAvailable; 325 } 326}