Index: content/content-api/api/src/java/org/sakaiproject/content/api/ResourceToolAction.java
===================================================================
--- content/content-api/api/src/java/org/sakaiproject/content/api/ResourceToolAction.java (revisión: 45398)
+++ content/content-api/api/src/java/org/sakaiproject/content/api/ResourceToolAction.java (copia de trabajo)
@@ -173,8 +173,17 @@
* must implement the CustomToolAction interface to provide Resources tool with a way to
* determine permissions, as well as either InteractionAction or ServiceLevelAction.
*/
- CUSTOM_TOOL_ACTION
-
+ CUSTOM_TOOL_ACTION,
+
+ /**
+ * Compress a selected folder to a zip archive with the same name.
+ */
+ COMPRESS_ZIP_FOLDER,
+
+ /**
+ * Expands a zip file into serveral folders and archives
+ */
+ EXPAND_ZIP_ARCHIVE
}
public static final String CREATE = "create";
@@ -193,6 +202,8 @@
public static final String REORDER = "revise_order";
public static final String EXPAND = "expand";
public static final String COLLAPSE = "collapse";
+ public static final String COMPRESS_ZIP_FOLDER = "compress_zip_folder";
+ public static final String EXPAND_ZIP_ARCHIVE = "expand_zip_archive";
public static final String ACTION_DELIMITER = ":";
Index: content/content-tool/tool/src/java/org/sakaiproject/content/tool/ResourcesAction.java
===================================================================
--- content/content-tool/tool/src/java/org/sakaiproject/content/tool/ResourcesAction.java (revisión: 45398)
+++ content/content-tool/tool/src/java/org/sakaiproject/content/tool/ResourcesAction.java (copia de trabajo)
@@ -846,6 +846,8 @@
CONTENT_MODIFY_ACTIONS.add(ActionType.REVISE_CONTENT);
CONTENT_MODIFY_ACTIONS.add(ActionType.REPLACE_CONTENT);
CONTENT_MODIFY_ACTIONS.add(ActionType.REVISE_ORDER);
+ CONTENT_MODIFY_ACTIONS.add(ActionType.COMPRESS_ZIP_FOLDER);
+ CONTENT_MODIFY_ACTIONS.add(ActionType.EXPAND_ZIP_ARCHIVE);
CONTENT_DELETE_ACTIONS.add(ActionType.MOVE);
CONTENT_DELETE_ACTIONS.add(ActionType.DELETE);
Index: content/content-bundles/types.properties
===================================================================
--- content/content-bundles/types.properties (revisión: 45398)
+++ content/content-bundles/types.properties (copia de trabajo)
@@ -40,7 +40,9 @@
action.reorder = Reorder
action.replace = Upload New Version
action.revise = Edit Content
-action.select = - Select Action -
+action.select = - Select Action -
+action.compresszipfolder = Compress to ZIP Archive
+action.expandziparchive = Expand ZIP Archive
alert.exists = The folder ''{0}'' already exists in this folder.
alert.noperm = You do not have permission to change this item.
alert.nofldr = Please provide the folder name.
Index: content/content-impl/.classpath
===================================================================
--- content/content-impl/.classpath (revisión: 45398)
+++ content/content-impl/.classpath (copia de trabajo)
@@ -31,5 +31,7 @@
+
+
Index: content/content-impl/impl/src/java/org/sakaiproject/content/impl/util/ZipContentUtil.java
===================================================================
--- content/content-impl/impl/src/java/org/sakaiproject/content/impl/util/ZipContentUtil.java (revisión: 0)
+++ content/content-impl/impl/src/java/org/sakaiproject/content/impl/util/ZipContentUtil.java (revisión: 0)
@@ -0,0 +1,220 @@
+package org.sakaiproject.content.impl.util;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import javax.activation.MimetypesFileTypeMap;
+
+import org.apache.commons.io.IOUtils;
+import org.sakaiproject.content.api.ContentCollection;
+import org.sakaiproject.content.api.ContentCollectionEdit;
+import org.sakaiproject.content.api.ContentResource;
+import org.sakaiproject.content.api.ContentResourceEdit;
+import org.sakaiproject.content.cover.ContentHostingService;
+import org.sakaiproject.entity.api.Entity;
+import org.sakaiproject.entity.api.Reference;
+import org.sakaiproject.entity.api.ResourcePropertiesEdit;
+
+public class ZipContentUtil {
+
+ private static final String ZIP_EXTENSION = ".zip";
+ private static final int BUFFER_SIZE = 8192;
+ private static final MimetypesFileTypeMap mime = new MimetypesFileTypeMap();
+
+ /**
+ * Compresses a ContentCollection to a new zip archive with the same folder name
+ *
+ * @param reference
+ * @throws Exception
+ */
+ public void compressFolder(Reference reference) throws Exception {
+ File temp = null;
+ try {
+ // Create the compressed archive in the filesystem
+ temp = File.createTempFile("sakai_content-", ".tmp");
+ temp.deleteOnExit();
+ ContentCollection collection = ContentHostingService.getCollection(reference.getId());
+ ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(temp),BUFFER_SIZE));
+ storeContentCollection(reference.getId(),collection,out);
+ out.close();
+
+ // Store the compressed archive in the repository
+ String resourceId = reference.getId().substring(0,reference.getId().lastIndexOf(Entity.SEPARATOR))+ZIP_EXTENSION;
+ String resourceName = extractName(resourceId);
+ ContentResourceEdit resourceEdit = ContentHostingService.addResource(resourceId);
+ resourceEdit.setContent(new FileInputStream(temp));
+ resourceEdit.setContentType(mime.getContentType(resourceId));
+ ResourcePropertiesEdit props = resourceEdit.getPropertiesEdit();
+ props.addProperty(ResourcePropertiesEdit.PROP_DISPLAY_NAME, resourceName);
+ ContentHostingService.commitResource(resourceEdit);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ finally {
+ temp.delete();
+ }
+ }
+
+ /**
+ * Extracts a compressed (zip) ContentResource to a new folder with the same name.
+ *
+ * @param reference
+ * @throws Exception
+ */
+ public void extractArchive(Reference reference) throws Exception {
+ ContentResource resource = ContentHostingService.getResource(reference.getId());
+ String rootCollectionId = extractZipCollectionPrefix(resource);
+
+ // Prepare Collection
+ ContentCollectionEdit rootCollection = ContentHostingService.addCollection(rootCollectionId);
+ ResourcePropertiesEdit prop = rootCollection.getPropertiesEdit();
+ prop.addProperty(ResourcePropertiesEdit.PROP_DISPLAY_NAME, extractZipCollectionName(resource));
+ ContentHostingService.commitCollection(rootCollection);
+
+ // Extract Zip File
+ File temp = null;
+ try {
+ temp = exportResourceToFile(resource);
+ ZipFile zipFile = new ZipFile(temp,ZipFile.OPEN_READ);
+ Enumeration extends ZipEntry> entries = zipFile.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry nextElement = entries.nextElement();
+ if (nextElement.isDirectory()) {
+ createContentCollection(rootCollectionId, nextElement);
+ }
+ else {
+ createContentResource(rootCollectionId, nextElement, zipFile);
+ }
+ }
+ zipFile.close();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ finally {
+ temp.delete();
+ }
+
+ }
+
+ /**
+ * Creates a new ContentResource extracted from ZipFile
+ *
+ * @param rootCollectionId
+ * @param nextElement
+ * @param zipFile
+ * @throws Exception
+ */
+ private void createContentResource(String rootCollectionId,
+ ZipEntry nextElement, ZipFile zipFile) throws Exception {
+ String resourceId = rootCollectionId + nextElement.getName();
+ String resourceName = extractName(nextElement.getName());
+ ContentResourceEdit resourceEdit = ContentHostingService.addResource(resourceId);
+ resourceEdit.setContent(zipFile.getInputStream(nextElement));
+ resourceEdit.setContentType(mime.getContentType(resourceName));
+ ResourcePropertiesEdit props = resourceEdit.getPropertiesEdit();
+ props.addProperty(ResourcePropertiesEdit.PROP_DISPLAY_NAME, resourceName);
+ ContentHostingService.commitResource(resourceEdit);
+ }
+
+ /**
+ * Creates a new ContentCollection in the rootCollectionId with the element.getName()
+ *
+ * @param rootCollectionId
+ * @param element
+ * @throws Exception
+ */
+ private void createContentCollection(String rootCollectionId,
+ ZipEntry element) throws Exception {
+ String resourceId = rootCollectionId + element.getName();
+ String resourceName = extractName(element.getName());
+ ContentCollectionEdit collection = ContentHostingService.addCollection(resourceId);
+ ResourcePropertiesEdit props = collection.getPropertiesEdit();
+ props.addProperty(ResourcePropertiesEdit.PROP_DISPLAY_NAME, resourceName);
+ ContentHostingService.commitCollection(collection);
+ }
+
+ /**
+ * Exports a the ContentResource zip file to the operating system
+ *
+ * @param resource
+ * @return
+ * @throws Exception
+ */
+ private File exportResourceToFile(ContentResource resource) throws Exception {
+ File temp = File.createTempFile("sakai_content-", ".tmp");
+ temp.deleteOnExit();
+
+ // Write content to file
+ FileOutputStream out = new FileOutputStream(temp);
+ IOUtils.copy(resource.streamContent(),out);
+ out.flush();
+ out.close();
+
+ return temp;
+ }
+
+ /**
+ * Iterates the collection.getMembers() and streams content resources recursively to the ZipOutputStream
+ *
+ * @param rootId
+ * @param collection
+ * @param out
+ * @throws Exception
+ */
+ private void storeContentCollection(String rootId, ContentCollection collection, ZipOutputStream out) throws Exception {
+ List members = collection.getMembers();
+ for (String memberId: members) {
+ if (memberId.endsWith(Entity.SEPARATOR)) {
+ ContentCollection memberCollection = ContentHostingService.getCollection(memberId);
+ storeContentCollection(rootId,memberCollection,out);
+ }
+ else {
+ ContentResource resource = ContentHostingService.getResource(memberId);
+ storeContentResource(rootId, resource, out);
+ }
+ }
+ }
+
+ /**
+ * Streams content resource to the ZipOutputStream
+ *
+ * @param rootId
+ * @param resource
+ * @param out
+ * @throws Exception
+ */
+ private void storeContentResource(String rootId, ContentResource resource, ZipOutputStream out) throws Exception {
+ String filename = resource.getId().substring(rootId.length(),resource.getId().length());
+ ZipEntry zipEntry = new ZipEntry(filename);
+ zipEntry.setSize(resource.getContentLength());
+ out.putNextEntry(zipEntry);
+ IOUtils.copy(resource.streamContent(),out);
+ }
+
+ private String extractZipCollectionPrefix(ContentResource resource) {
+ String idPrefix = resource.getContainingCollection().getId() +
+ extractZipCollectionName(resource) +
+ Entity.SEPARATOR;
+ return idPrefix;
+ }
+
+ private String extractName(String collectionName) {
+ String[] tmp = collectionName.split(Entity.SEPARATOR);
+ return tmp[tmp.length-1];
+ }
+
+ private String extractZipCollectionName(ContentResource resource) {
+ String tmp = extractName(resource.getId());
+ return tmp.substring(0, tmp.lastIndexOf("."));
+ }
+}
\ Sin fin-de-línea al final del archivo
Cambios de propiedades en content/content-impl/impl/src/java/org/sakaiproject/content/impl/util/ZipContentUtil.java
___________________________________________________________________
Nombre: svn:keywords
+ Date Revision Author HeadURL Id
Nombre: svn:eol-style
+ native
Index: content/content-impl/impl/src/java/org/sakaiproject/content/types/FileUploadType.java
===================================================================
--- content/content-impl/impl/src/java/org/sakaiproject/content/types/FileUploadType.java (revisión: 45398)
+++ content/content-impl/impl/src/java/org/sakaiproject/content/types/FileUploadType.java (copia de trabajo)
@@ -43,6 +43,7 @@
import org.sakaiproject.content.api.ServiceLevelAction;
import org.sakaiproject.content.api.ResourceToolAction.ActionType;
import org.sakaiproject.content.cover.ContentTypeImageService;
+import org.sakaiproject.content.impl.util.ZipContentUtil;
import org.sakaiproject.content.util.BaseResourceType;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.entity.api.ResourceProperties;
@@ -77,6 +78,7 @@
actions.put(ResourceToolAction.COPY, new FileUploadCopyAction());
actions.put(ResourceToolAction.MOVE, new FileUploadMoveAction());
actions.put(ResourceToolAction.DELETE, new FileUploadDeleteAction());
+ actions.put(ResourceToolAction.EXPAND_ZIP_ARCHIVE, new FileUploadExpandAction());
// initialize actionMap with an empty List for each ActionType
for(ResourceToolAction.ActionType type : ResourceToolAction.ActionType.values())
@@ -741,6 +743,55 @@
}
}
+ public class FileUploadExpandAction implements ServiceLevelAction {
+
+ private ZipContentUtil extractZipArchive = new ZipContentUtil();
+
+ public void cancelAction(Reference reference) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void finalizeAction(Reference reference) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void initializeAction(Reference reference) {
+ try {
+ extractZipArchive.extractArchive(reference);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ public boolean isMultipleItemAction() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean available(ContentEntity entity) {
+ return entity.getId().toLowerCase().endsWith(".zip");
+ }
+
+ public ActionType getActionType() {
+ return ResourceToolAction.ActionType.EXPAND_ZIP_ARCHIVE;
+ }
+
+ public String getId() {
+ return ResourceToolAction.EXPAND_ZIP_ARCHIVE;
+ }
+
+ public String getLabel() {
+ return rb.getString("action.expandziparchive");
+ }
+
+ public String getTypeId() {
+ return typeId;
+ }
+
+ }
+
public ResourceToolAction getAction(String actionId)
{
return (ResourceToolAction) actions.get(actionId);
Index: content/content-impl/impl/src/java/org/sakaiproject/content/types/FolderType.java
===================================================================
--- content/content-impl/impl/src/java/org/sakaiproject/content/types/FolderType.java (revisión: 45398)
+++ content/content-impl/impl/src/java/org/sakaiproject/content/types/FolderType.java (copia de trabajo)
@@ -44,6 +44,7 @@
import org.sakaiproject.content.api.ResourceType;
import org.sakaiproject.content.api.ServiceLevelAction;
import org.sakaiproject.content.api.ResourceToolAction.ActionType;
+import org.sakaiproject.content.impl.util.ZipContentUtil;
import org.sakaiproject.content.util.BaseResourceType;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.entity.api.ResourceProperties;
@@ -90,6 +91,7 @@
actions.put(ResourceToolAction.PERMISSIONS, new FolderPermissionsAction());
actions.put(ResourceToolAction.EXPAND, new FolderExpandAction());
actions.put(ResourceToolAction.COLLAPSE, new FolderCollapseAction());
+ actions.put(ResourceToolAction.COMPRESS_ZIP_FOLDER, new FolderCompressAction());
// initialize actionMap with an empty List for each ActionType
for(ResourceToolAction.ActionType type : ResourceToolAction.ActionType.values())
@@ -1392,6 +1394,52 @@
}
+ public class FolderCompressAction implements ServiceLevelAction {
+
+ private ZipContentUtil zipUtil = new ZipContentUtil();
+
+ public void cancelAction(Reference reference) {
+ // TODO Auto-generated method stub
+ }
+
+ public void finalizeAction(Reference reference) {
+ // TODO Auto-generated method stub
+ }
+
+ public void initializeAction(Reference reference) {
+ try {
+ zipUtil.compressFolder(reference);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ public boolean isMultipleItemAction() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean available(ContentEntity entity) {
+ return true;
+ }
+
+ public ActionType getActionType() {
+ return ResourceToolAction.ActionType.COMPRESS_ZIP_FOLDER;
+ }
+
+ public String getId() {
+ return ResourceToolAction.COMPRESS_ZIP_FOLDER;
+ }
+
+ public String getLabel() {
+ return rb.getString("action.compresszipfolder");
+ }
+
+ public String getTypeId() {
+ return typeId;
+ }
+ }
+
public ResourceToolAction getAction(String actionId)
{
return (ResourceToolAction) actions.get(actionId);
Index: content/content-impl/impl/pom.xml
===================================================================
--- content/content-impl/impl/pom.xml (revisión: 45398)
+++ content/content-impl/impl/pom.xml (copia de trabajo)
@@ -131,6 +131,16 @@
commons-logging
1.0.4
+
+ org.apache.commons
+ commons-io
+ 1.3.2
+
+
+ javax.activation
+ activation
+ 1.0.2
+
commons-dbcp