diff --git a/src/main/java/org/olat/fileresource/ZippedDirectoryMediaResource.java b/src/main/java/org/olat/fileresource/ZippedDirectoryMediaResource.java new file mode 100644 index 0000000000000000000000000000000000000000..d0c2d9ed17beb2e91f89536303b128e034fc61bd --- /dev/null +++ b/src/main/java/org/olat/fileresource/ZippedDirectoryMediaResource.java @@ -0,0 +1,118 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.fileresource; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import javax.servlet.http.HttpServletResponse; + +import org.olat.core.gui.media.MediaResource; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.FileUtils; +import org.olat.core.util.StringHelper; + +/** + * + * Initial date: 20.01.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ZippedDirectoryMediaResource implements MediaResource { + + private static final OLog log = Tracing.createLoggerFor(ZippedDirectoryMediaResource.class); + + private final String filename; + private final File unzipDir; + + public ZippedDirectoryMediaResource(String filename, File unzipDir) { + this.filename = filename; + this.unzipDir = unzipDir; + } + + @Override + public String getContentType() { + return "application/zip"; + } + + @Override + public Long getSize() { + return null; + } + + @Override + public InputStream getInputStream() { + return null; + } + + @Override + public Long getLastModified() { + return null; + } + + @Override + public void prepare(HttpServletResponse hres) { + String label = StringHelper.transformDisplayNameToFileSystemName(filename) + ".zip"; + String urlEncodedLabel = StringHelper.urlEncodeUTF8(label); + hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + urlEncodedLabel); + hres.setHeader("Content-Description", urlEncodedLabel); + + try(ZipOutputStream zout = new ZipOutputStream(hres.getOutputStream())) { + zout.setLevel(9); + + final Path unzipPath = unzipDir.toPath(); + Files.walkFileTree(unzipPath, new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if(!attrs.isDirectory()) { + Path relativeFile = unzipPath.relativize(file); + String names = relativeFile.toString(); + zout.putNextEntry(new ZipEntry(names)); + + try(InputStream in=Files.newInputStream(file)) { + FileUtils.copy(in, zout); + } catch (Exception e) { + log.error("", e); + } + + zout.closeEntry(); + } + return FileVisitResult.CONTINUE; + } + }); + } catch (Exception e) { + log.error("", e); + } + } + + @Override + public void release() { + // + } +} diff --git a/src/main/java/org/olat/ims/cp/CPManagerImpl.java b/src/main/java/org/olat/ims/cp/CPManagerImpl.java index d57bd5047f854bbc40abc02982cdd2ac334d7c0e..0d1695f690af476d1b369d6276a3abdf1a40ba73 100644 --- a/src/main/java/org/olat/ims/cp/CPManagerImpl.java +++ b/src/main/java/org/olat/ims/cp/CPManagerImpl.java @@ -176,7 +176,6 @@ public class CPManagerImpl extends CPManager { File cpRoot = FileResourceManager.getInstance().unzipFileResource(ores); logDebug("createNewCP: cpRoot=" + cpRoot); logDebug("createNewCP: cpRoot.getAbsolutePath()=" + cpRoot.getAbsolutePath()); - System.out.println("createNewCP: cpRoot.getAbsolutePath()=" + cpRoot.getAbsolutePath()); LocalFolderImpl vfsWrapper = new LocalFolderImpl(cpRoot); ContentPackage cp = load(vfsWrapper, ores); diff --git a/src/main/java/org/olat/ims/qti/repository/handlers/QTISurveyHandler.java b/src/main/java/org/olat/ims/qti/repository/handlers/QTISurveyHandler.java index fbffb2db92415de2879429b91c8a45de726eb1a6..3db84d3a09c67b17bec5f0c78b3e6a6c54d6a87c 100644 --- a/src/main/java/org/olat/ims/qti/repository/handlers/QTISurveyHandler.java +++ b/src/main/java/org/olat/ims/qti/repository/handlers/QTISurveyHandler.java @@ -36,9 +36,11 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.layout.MainLayoutController; import org.olat.core.gui.control.generic.wizard.StepsMainRunController; +import org.olat.core.gui.media.MediaResource; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; +import org.olat.fileresource.FileResourceManager; import org.olat.fileresource.types.ResourceEvaluation; import org.olat.ims.qti.QTIRuntimeController; import org.olat.ims.qti.editor.QTIEditorMainController; @@ -102,6 +104,11 @@ public class QTISurveyHandler extends QTIHandler { return super.importResource(initialAuthor, displayname, description, new SurveyFileResource(), file, filename); } + @Override + public MediaResource getAsMediaResource(OLATResourceable res, boolean backwardsCompatible) { + return FileResourceManager.getInstance().getAsDownloadeableMediaResource(res); + } + @Override public String getSupportedType() { return SurveyFileResource.TYPE_NAME; diff --git a/src/main/java/org/olat/ims/qti/repository/handlers/QTITestHandler.java b/src/main/java/org/olat/ims/qti/repository/handlers/QTITestHandler.java index 358f795232f0d4e1c6c03d37b64ce2d9abd9c1b1..247818a4117a508514a37994740f2cc48587e675 100644 --- a/src/main/java/org/olat/ims/qti/repository/handlers/QTITestHandler.java +++ b/src/main/java/org/olat/ims/qti/repository/handlers/QTITestHandler.java @@ -36,9 +36,11 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.layout.MainLayoutController; import org.olat.core.gui.control.generic.wizard.StepsMainRunController; +import org.olat.core.gui.media.MediaResource; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; +import org.olat.fileresource.FileResourceManager; import org.olat.fileresource.types.ResourceEvaluation; import org.olat.ims.qti.QTIRuntimeController; import org.olat.ims.qti.editor.QTIEditorMainController; @@ -102,6 +104,11 @@ public class QTITestHandler extends QTIHandler { return super.importResource(initialAuthor, displayname, description, new TestFileResource(), file, filename); } + @Override + public MediaResource getAsMediaResource(OLATResourceable res, boolean backwardsCompatible) { + return FileResourceManager.getInstance().getAsDownloadeableMediaResource(res); + } + @Override public String getSupportedType() { return TestFileResource.TYPE_NAME; diff --git a/src/main/java/org/olat/repository/handlers/FileHandler.java b/src/main/java/org/olat/repository/handlers/FileHandler.java index e36108471a7e8b231de27e06843616032097f203..0b22fe8f133c9a69e7fb062b18775a7f1a91afe0 100644 --- a/src/main/java/org/olat/repository/handlers/FileHandler.java +++ b/src/main/java/org/olat/repository/handlers/FileHandler.java @@ -55,11 +55,6 @@ public abstract class FileHandler implements RepositoryHandler { // } - @Override - public MediaResource getAsMediaResource(OLATResourceable res, boolean backwardsCompatible) { - return FileResourceManager.getInstance().getAsDownloadeableMediaResource(res); - } - @Override public VFSContainer getMediaContainer(RepositoryEntry repoEntry) { return FileResourceManager.getInstance() diff --git a/src/main/java/org/olat/repository/handlers/ImsCPHandler.java b/src/main/java/org/olat/repository/handlers/ImsCPHandler.java index 16fce20e36ce74d145f271fad9aa94d380c4ab10..da69365f02ac1cf0d2523107bdb934e6ba95a2d4 100644 --- a/src/main/java/org/olat/repository/handlers/ImsCPHandler.java +++ b/src/main/java/org/olat/repository/handlers/ImsCPHandler.java @@ -41,6 +41,7 @@ import org.olat.core.gui.control.generic.iframe.DeliveryOptions; import org.olat.core.gui.control.generic.layout.MainLayout3ColumnsController; import org.olat.core.gui.control.generic.layout.MainLayoutController; import org.olat.core.gui.control.generic.wizard.StepsMainRunController; +import org.olat.core.gui.media.MediaResource; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; @@ -54,6 +55,7 @@ import org.olat.core.util.vfs.QuotaManager; import org.olat.core.util.vfs.callbacks.FullAccessWithQuotaCallback; import org.olat.core.util.vfs.callbacks.VFSSecurityCallback; import org.olat.fileresource.FileResourceManager; +import org.olat.fileresource.ZippedDirectoryMediaResource; import org.olat.fileresource.types.FileResource; import org.olat.fileresource.types.ImsCPFileResource; import org.olat.fileresource.types.ResourceEvaluation; @@ -65,6 +67,7 @@ import org.olat.ims.cp.ui.CPRuntimeController; import org.olat.modules.cp.CPDisplayController; import org.olat.modules.cp.CPOfflineReadableManager; import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; import org.olat.repository.RepositoryService; import org.olat.repository.model.RepositoryEntrySecurity; import org.olat.repository.ui.RepositoryEntryRuntimeController.RuntimeControllerCreator; @@ -155,6 +158,14 @@ public class ImsCPHandler extends FileHandler { return target; } + @Override + public MediaResource getAsMediaResource(OLATResourceable res, boolean backwardsCompatible) { + File unzippedDir = FileResourceManager.getInstance().unzipFileResource(res); + String displayName = CoreSpringFactory.getImpl(RepositoryManager.class) + .lookupDisplayNameByOLATResourceableId(res.getResourceableId()); + return new ZippedDirectoryMediaResource(displayName, unzippedDir); + } + @Override public String getSupportedType() { return ImsCPFileResource.TYPE_NAME; diff --git a/src/main/java/org/olat/repository/handlers/SCORMCPHandler.java b/src/main/java/org/olat/repository/handlers/SCORMCPHandler.java index 7cc65dd5c37701b77e29fdbad621ad8c77d9b8f1..ac6ac06256ab33649afb75936e1da65e3ef78212 100644 --- a/src/main/java/org/olat/repository/handlers/SCORMCPHandler.java +++ b/src/main/java/org/olat/repository/handlers/SCORMCPHandler.java @@ -36,6 +36,7 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.layout.MainLayoutController; import org.olat.core.gui.control.generic.wizard.StepsMainRunController; +import org.olat.core.gui.media.MediaResource; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; @@ -43,6 +44,7 @@ import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; import org.olat.core.util.FileUtils; import org.olat.core.util.coordinate.LockResult; import org.olat.fileresource.FileResourceManager; +import org.olat.fileresource.ZippedDirectoryMediaResource; import org.olat.fileresource.types.FileResource; import org.olat.fileresource.types.ResourceEvaluation; import org.olat.fileresource.types.ScormCPFileResource; @@ -50,6 +52,7 @@ import org.olat.modules.scorm.ScormMainManager; import org.olat.modules.scorm.ScormPackageConfig; import org.olat.modules.scorm.ScormRuntimeController; import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; import org.olat.repository.RepositoryService; import org.olat.repository.model.RepositoryEntrySecurity; import org.olat.repository.ui.RepositoryEntryRuntimeController.RuntimeControllerCreator; @@ -127,6 +130,14 @@ public class SCORMCPHandler extends FileHandler { } return target; } + + @Override + public MediaResource getAsMediaResource(OLATResourceable res, boolean backwardsCompatible) { + File unzippedDir = FileResourceManager.getInstance().unzipFileResource(res); + String displayName = CoreSpringFactory.getImpl(RepositoryManager.class) + .lookupDisplayNameByOLATResourceableId(res.getResourceableId()); + return new ZippedDirectoryMediaResource(displayName, unzippedDir); + } @Override public String getSupportedType() { diff --git a/src/main/java/org/olat/repository/handlers/WebDocumentHandler.java b/src/main/java/org/olat/repository/handlers/WebDocumentHandler.java index 6b14372bc221f022dec8b845a7ca6febdd41907b..0ad4cdc410c91877a50c81c38fb32f58f8af81ec 100644 --- a/src/main/java/org/olat/repository/handlers/WebDocumentHandler.java +++ b/src/main/java/org/olat/repository/handlers/WebDocumentHandler.java @@ -39,6 +39,7 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.layout.MainLayoutController; import org.olat.core.gui.control.generic.wizard.StepsMainRunController; +import org.olat.core.gui.media.MediaResource; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; @@ -186,6 +187,11 @@ public class WebDocumentHandler extends FileHandler { return target; } + @Override + public MediaResource getAsMediaResource(OLATResourceable res, boolean backwardsCompatible) { + return FileResourceManager.getInstance().getAsDownloadeableMediaResource(res); + } + @Override public String getSupportedType() { return supportedType;