/* * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Nuxeo - initial API and implementation * * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $ */ package org.nuxeo.ecm.platform.picture.web; import static org.jboss.seam.ScopeType.CONVERSATION; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipException; import java.util.zip.ZipOutputStream; import javax.faces.context.FacesContext; import javax.faces.model.SelectItem; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.seam.annotations.Create; import org.jboss.seam.annotations.Destroy; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Observer; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.intercept.BypassInterceptors; import org.jboss.seam.core.Events; import org.nuxeo.common.utils.ZipUtils; import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.PathRef; import org.nuxeo.ecm.core.api.blobholder.BlobHolder; import org.nuxeo.ecm.core.api.pathsegment.PathSegmentService; import org.nuxeo.ecm.platform.picture.api.adapters.AbstractPictureAdapter; import org.nuxeo.ecm.platform.picture.api.adapters.PictureBlobHolder; import org.nuxeo.ecm.platform.ui.web.api.NavigationContext; import org.nuxeo.ecm.platform.ui.web.api.UserAction; import org.nuxeo.ecm.webapp.base.InputController; import org.nuxeo.ecm.webapp.documentsLists.DocumentsListsManager; import org.nuxeo.ecm.webapp.helpers.EventNames; import org.nuxeo.runtime.api.Framework; /** * Provide Picture Book related Actions. * * @author <a href="mailto:ldoguin@nuxeo.com">Laurent Doguin</a> * @deprecated since 6.0. See NXP-15370. */ @Name("pictureBookManager") @Scope(CONVERSATION) @Deprecated public class PictureBookManagerBean extends InputController implements PictureBookManager, Serializable { private static final long serialVersionUID = 1L; private static final Log log = LogFactory.getLog(PictureBookManagerBean.class); @In(create = true) protected CoreSession documentManager; protected Integer maxsize; protected ArrayList<Map<String, Object>> views; protected String title; protected String viewtitle; protected String tag; protected String description; protected List<SelectItem> selectItems; protected String[] selectedViews = { "OriginalJpeg" }; @In(create = true) protected transient NavigationContext navigationContext; @In(create = true) protected transient DocumentsListsManager documentsListsManager; protected static final int BUFFER = 2048; protected DocumentModel getCurrentDocument() { return navigationContext.getCurrentDocument(); } @Override @Create public void initialize() { log.debug("Initializing..."); initViews(); } protected void initViews() { // Sets the default views original, thumbnail and medium. views = new ArrayList<Map<String, Object>>(); Map<String, Object> map = new HashMap<String, Object>(); map.put("title", "Medium"); map.put("maxsize", AbstractPictureAdapter.MEDIUM_SIZE); map.put("tag", "medium"); map.put("description", "MediumSize Picture"); views.add(map); map = new HashMap<String, Object>(); map.put("title", "Thumbnail"); map.put("maxsize", AbstractPictureAdapter.THUMB_SIZE); map.put("tag", "thumbnail"); map.put("description", "ThumbnailSize Picture"); views.add(map); map = new HashMap<String, Object>(); map.put("title", "OriginalJpeg"); map.put("maxsize", null); map.put("tag", "originalJpeg"); map.put("description", "Original Picture in JPEG format"); views.add(map); } @Destroy @BypassInterceptors public void destroy() { title = null; viewtitle = null; maxsize = null; tag = null; description = null; views = null; log.debug("Destroy"); } @Override public String createPictureBook() { PathSegmentService pss = Framework.getService(PathSegmentService.class); DocumentModel doc = navigationContext.getChangeableDocument(); String parentPath; if (getCurrentDocument() == null) { // creating item at the root parentPath = documentManager.getRootDocument().getPathAsString(); } else { parentPath = navigationContext.getCurrentDocument().getPathAsString(); } doc.setProperty("picturebook", "picturetemplates", views); Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED, documentManager.getDocument(new PathRef(parentPath))); doc.setPathInfo(parentPath, pss.generatePathSegment(doc)); doc = documentManager.createDocument(doc); documentManager.saveDocument(doc); documentManager.save(); return navigationContext.getActionResult(doc, UserAction.AFTER_CREATE); } @Override public void addView() { Map<String, Object> map = new HashMap<String, Object>(); map.put("title", viewtitle); map.put("maxsize", maxsize); map.put("tag", tag); map.put("description", description); views.add(map); } @Override @Observer({ EventNames.DOCUMENT_SELECTION_CHANGED }) @BypassInterceptors public void reset() { title = null; maxsize = null; viewtitle = null; tag = null; description = null; selectItems = null; selectedViews = new String[] { "Original" }; initViews(); } @Override public String downloadSelectedBook() throws IOException { List<DocumentModel> list = documentsListsManager.getWorkingList(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION); return createZip(list); } @Override public String downloadAll() throws IOException { DocumentModel currentDoc = navigationContext.getCurrentDocument(); if (currentDoc != null) { List<DocumentModel> list = documentManager.getChildren(currentDoc.getRef()); return createZip(list); } return null; } protected boolean isEmptyFolder(DocumentModel doc) { List<DocumentModel> docList = documentManager.getChildren(doc.getRef()); for (DocumentModel docChild : docList) { BlobHolder bh = docChild.getAdapter(BlobHolder.class); if (docChild.isFolder()) { return isEmptyFolder(docChild); } else if (bh != null) { return false; } } return true; } protected String formatFileName(String filename, String count) { StringBuilder sb = new StringBuilder(); CharSequence name = filename.subSequence(0, filename.lastIndexOf("")); CharSequence extension = filename.subSequence(filename.lastIndexOf(""), filename.length()); sb.append(name).append(count).append(extension); return sb.toString(); } protected void addBlobHolderToZip(String path, ZipOutputStream out, byte[] data, PictureBlobHolder bh) throws IOException { List<Blob> blobs; if (selectedViews != null) { blobs = bh.getBlobs(selectedViews); } else { blobs = bh.getBlobs(); } for (Blob content : blobs) { String fileName = content.getFilename(); if (content != null) { // Workaround to deal with duplicate file names. int tryCount = 0; while (true) { try { if (tryCount == 0) { ZipUtils._zip(path + fileName, content.getStream(), out); } else { ZipUtils._zip(path + formatFileName(fileName, "(" + tryCount + ")"), content.getStream(), out); } break; } catch (ZipException e) { tryCount++; } } } } } protected void addFolderToZip(String path, ZipOutputStream out, DocumentModel doc, byte[] data) throws IOException { String title = (String) doc.getProperty("dublincore", "title"); List<DocumentModel> docList = documentManager.getChildren(doc.getRef()); for (DocumentModel docChild : docList) { // NXP-2334 : skip deleted docs if (docChild.getCurrentLifeCycleState().equals("delete")) { continue; } BlobHolder bh = docChild.getAdapter(BlobHolder.class); if (docChild.isFolder() && !isEmptyFolder(docChild)) { addFolderToZip(path + title + "/", out, docChild, data); } else if (bh != null) { addBlobHolderToZip(path + title + "/", out, data, (PictureBlobHolder) bh); } } } protected String createZip(List<DocumentModel> documents) throws IOException { FacesContext context = FacesContext.getCurrentInstance(); HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); BufferedOutputStream buff = new BufferedOutputStream(response.getOutputStream()); ZipOutputStream out = new ZipOutputStream(buff); out.setMethod(ZipOutputStream.DEFLATED); out.setLevel(9); byte[] data = new byte[BUFFER]; for (DocumentModel doc : documents) { // first check if DM is attached to the core if (doc.getSessionId() == null) { // refetch the doc from the core doc = documentManager.getDocument(doc.getRef()); } // NXP-2334 : skip deleted docs if (doc.getCurrentLifeCycleState().equals("delete")) { continue; } BlobHolder bh = doc.getAdapter(BlobHolder.class); if (doc.isFolder() && !isEmptyFolder(doc)) { addFolderToZip("", out, doc, data); } else if (bh != null) { addBlobHolderToZip("", out, data, (PictureBlobHolder) bh); } } try { out.close(); } catch (ZipException e) { // empty zip file, do nothing setFacesMessage("label.clipboard.emptyDocuments"); return null; } response.setHeader("Content-Disposition", "attachment; filename=\"" + "clipboard.zip" + "\";"); response.setContentType("application/gzip"); response.flushBuffer(); context.responseComplete(); return null; } protected void initSelectItems() { DocumentModel doc = getCurrentDocument(); List<Map<String, Object>> views = (List) doc.getProperty("picturebook", "picturetemplates"); selectItems = new ArrayList<SelectItem>(views.size()); String label; SelectItem selectItem; for (Map<String, Object> map : views) { label = (String) map.get("title"); selectItem = new SelectItem(label, label); selectItems.add(selectItem); } } @Override public List<SelectItem> getSelectItems() { if (selectItems == null) { initSelectItems(); return selectItems; } else { return selectItems; } } @Override public void setSelectItems(List<SelectItem> selectItems) { this.selectItems = selectItems; } @Override public String[] getSelectedViews() { return selectedViews; } @Override public void setSelectedViews(String[] selectedViews) { this.selectedViews = selectedViews; } @Override public Integer getMaxsize() { return maxsize; } @Override public void setMaxsize(Integer maxsize) { this.maxsize = maxsize; } @Override public String getTitle() { return title; } @Override public void setTitle(String title) { this.title = title; } @Override public String getTag() { return tag; } @Override public void setTag(String tag) { this.tag = tag; } @Override public String getDescription() { return description; } @Override public void setDescription(String description) { this.description = description; } @Override public String getViewtitle() { return viewtitle; } @Override public void setViewtitle(String viewtitle) { this.viewtitle = viewtitle; } @Override public ArrayList<Map<String, Object>> getViews() { return views; } @Override public void setViews(ArrayList<Map<String, Object>> views) { this.views = views; } }