/** * OLAT - Online Learning and Training<br> * http://www.olat.org * <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 * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <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> * Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> * University of Zurich, Switzerland. * <hr> * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * This file has been modified by the OpenOLAT community. Changes are licensed * under the Apache 2.0 license as the original file. */ package org.olat.fileresource; import java.io.File; import org.olat.core.commons.modules.bc.FolderConfig; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.gui.media.MediaResource; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.OLATRuntimeException; import org.olat.core.manager.BasicManager; import org.olat.core.util.FileUtils; import org.olat.core.util.ZipUtil; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.SyncerCallback; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSItem; import org.olat.fileresource.types.FileResource; /** * Initial Date: Apr 8, 2004 * * @author Mike Stock */ public class FileResourceManager extends BasicManager { public static final String ZIPDIR = "_unzipped_"; private static FileResourceManager INSTANCE; /** * spring */ private FileResourceManager() { INSTANCE = this; } /** * @return Singleton. */ public static final FileResourceManager getInstance() { return INSTANCE; } /** * @param res */ public void deleteFileResource(OLATResourceable res) { // delete resources File fResourceFileroot = getFileResourceRoot(res); FileUtils.deleteDirsAndFiles(fResourceFileroot, true, true); } /** * @param res * @return Canonical root of file resource */ public File getFileResourceRoot(OLATResourceable res) { return getFileResourceRootImpl(res).getBasefile(); } /** * @param res * @return olat root folder implementation of file resource */ public OlatRootFolderImpl getFileResourceRootImpl(OLATResourceable res) { return new OlatRootFolderImpl(FolderConfig.getRepositoryHome() + "/" + res.getResourceableId(), null); } public VFSContainer getFileResourceMedia(OLATResourceable res) { VFSContainer folder = getFileResourceRootImpl(res); VFSItem item = folder.resolve("media"); VFSContainer mediaContainer; if(item == null) { mediaContainer = folder.createChildContainer("media"); } else if(item instanceof VFSContainer) { mediaContainer = (VFSContainer)item; } else { mediaContainer = null; } return mediaContainer; } /** * @param res * @return Get resourceable as file. */ public File getFileResource(OLATResourceable res) { return getFileResource(res, null); } /** * @param res * @return Get resourceable as file. */ private File getFileResource(OLATResourceable res, String resourceFolderName) { FileResource fr = getAsGenericFileResource(res); File f = getFile(fr, resourceFolderName); if (f == null) {// folder not existing or no file in it throw new OLATRuntimeException(FileResourceManager.class, "could not getFileResource for OLATResourceable " + res.getResourceableId() + ":" + res.getResourceableTypeName(), null); } return f; } /** * Get the specified file or the first zip archive. * * @param fr * @return The specified file, the first zip archive or null */ private File getFile(FileResource fr) { return getFile(fr, null); } /** * Get the specified file or the first zip archive. * * @param fr * @param resourceFolderName * @return The specified file, the first zip archive or null */ private File getFile(FileResource fr, String resourceFolderName) { File fResourceFileroot = getFileResourceRoot(fr); if (!fResourceFileroot.exists()) return null; File[] contents = fResourceFileroot.listFiles(); File firstFile = null; for (int i = 0; i < contents.length; i++) { File file = contents[i]; if (file.getName().equals(ZIPDIR)) continue; // skip ZIPDIR if (resourceFolderName != null) { // search for specific file name if (file.getName().equals(resourceFolderName)) { return file; } } else if (file.getName().toLowerCase().endsWith(".zip")) { // we use first zip file we find return file; } else if (firstFile == null) { // store the first file to be able to return it later. this is needed // for wikis. firstFile = file; } } // Neither the specified resource nor any zip file could be found. Return // the first file that is not ZIPDIR or null. return firstFile; } /** * @param res * @return File resource as downloadeable media resource. */ public MediaResource getAsDownloadeableMediaResource(OLATResourceable res) { FileResource fr = getAsGenericFileResource(res); File f = getFile(fr); if (f == null) // folder not existing or no file in it throw new OLATRuntimeException(FileResourceManager.class, "could not get File for OLATResourceable " + res.getResourceableId() + ":" + res.getResourceableTypeName(), null); return new DownloadeableMediaResource(f); } /** * @param res * @return Directory wherer unzipped files of file resourcea are located. */ public String getUnzippedDirRel(OLATResourceable res) { return res.getResourceableId() + "/" + ZIPDIR; } /** * Unzips a resource and returns the unzipped folder's root. * * @param res * @return Unzip contents of ZIP file resource. */ public File unzipFileResource(final OLATResourceable res) { final File dir = getFileResourceRoot(res); return unzipFileResource(res, dir); } public OlatRootFolderImpl unzipContainerResource(final OLATResourceable res) { OlatRootFolderImpl container = getFileResourceRootImpl(res); File dir = container.getBasefile(); File unzipDir = unzipFileResource(res, dir); if(unzipDir == null) { return null; } return (OlatRootFolderImpl)container.resolve(unzipDir.getName()); } private final File unzipFileResource(final OLATResourceable res, final File dir) { if (!dir.exists()) { return null; } File zipTargetDir = new File(dir, ZIPDIR); if (!zipTargetDir.exists()) { // if not unzipped yet, synchronize all unzipping processes // o_clusterOK by:ld zipTargetDir = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(res, new SyncerCallback<File>() { public File execute() { File targetDir = null; // now we are the only one unzipping. We // only need to unzip when the previous // threads that aquired this lock have not unzipped "our" version's // resources yet targetDir = new File(dir, ZIPDIR); if (!targetDir.exists()) { // means I am the first to unzip this // version's resource targetDir.mkdir(); File zipFile = getFileResource(res); if (!ZipUtil.unzip(zipFile, targetDir)) { return null; } } return targetDir; } }); } return zipTargetDir; } /** * Deletes the contents of the last unzip operation. * * @param res * @return True upon success. */ public boolean deleteUnzipContent(OLATResourceable res) { File dir = getFileResourceRoot(res); if (!dir.exists()) return false; File zipTargetDir = new File(dir, ZIPDIR); return FileUtils.deleteDirsAndFiles(zipTargetDir, true, true); } private FileResource getAsGenericFileResource(OLATResourceable res) { FileResource fr = new FileResource(); fr.overrideResourceableId(res.getResourceableId()); return fr; } }