From fe69f30037e2038435d7da4768bd5a46f612a56d Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Sun, 6 Nov 2016 11:11:10 +0100
Subject: [PATCH] OO-2339: fix issue with caching during import, remove the
 forum key and other properties the same way by import and copy of wiki

---
 .../org/olat/modules/wiki/WikiManager.java    | 275 ++++++++++++------
 .../olat/repository/handlers/WikiHandler.java |  48 +--
 2 files changed, 187 insertions(+), 136 deletions(-)

diff --git a/src/main/java/org/olat/modules/wiki/WikiManager.java b/src/main/java/org/olat/modules/wiki/WikiManager.java
index ca4e71644da..5f40239ff40 100644
--- a/src/main/java/org/olat/modules/wiki/WikiManager.java
+++ b/src/main/java/org/olat/modules/wiki/WikiManager.java
@@ -27,6 +27,7 @@ package org.olat.modules.wiki;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.nio.file.FileVisitResult;
@@ -55,7 +56,6 @@ import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.FileUtils;
 import org.olat.core.util.cache.CacheWrapper;
 import org.olat.core.util.coordinate.CoordinatorManager;
-import org.olat.core.util.coordinate.SyncerExecutor;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
@@ -166,7 +166,7 @@ public class WikiManager {
 			}
 			
 			Path destDir = targetDirectory.toPath();
-			Files.walkFileTree(path, new CopyVisitor(destDir));
+			Files.walkFileTree(path, new ImportVisitor(destDir));
 			return true;
 		} catch (IOException e) {
 			log.error("", e);
@@ -174,20 +174,123 @@ public class WikiManager {
 		}
 	}
 	
+	/**
+	 * Copy the wiki pages, media but ignores the versions.
+	 * 
+	 */
+	public boolean copyWiki(File sourceDirectory, File targetDirectory) {
+		try {
+			Path path = sourceDirectory.toPath();
+			Path destDir = targetDirectory.toPath();
+			Files.walkFileTree(path, new CopyVisitor(path, destDir));
+			return true;
+		} catch (IOException e) {
+			log.error("", e);
+			return false;
+		}
+	}
 	
 	/**
-	 * Dispatch the content in the wiki and media folders
+	 * Reset the same properties as in the method resetCopiedPage
+	 * of WikiPage.
+	 * 
+	 * @param file
+	 * @param destFile
+	 */
+	private final static void resetAndCopyProperties(Path file, Path destFile) {
+		Properties props = new Properties();
+    	try(InputStream inStream = Files.newInputStream(file);
+    		OutputStream outStream = Files.newOutputStream(destFile)) {
+    		
+    		props.load(inStream);
+    		props.setProperty(VERSION, "0");
+    		props.setProperty(FORUM_KEY, "0");
+    		props.setProperty(MODIFY_AUTHOR, "0");
+    		props.setProperty(UPDATE_COMMENT, "0");
+    		props.setProperty(VIEW_COUNT, "0");
+    		props.setProperty(M_TIME, "0");
+    		props.store(outStream, "");
+    	} catch(Exception e) {
+    		log.error("", e);
+    	}
+	}
+
+	/**
+	 * Copy the content of a resource of type wiki where the files
+	 * are saved in different directories: wiki and media. The versions
+	 * are ignored.
+	 * 
 	 * Initial date: 02.05.2014<br>
 	 * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
 	 *
 	 */
 	public static class CopyVisitor extends SimpleFileVisitor<Path> {
 		
+		private final Path sourceDir;
+		private final Path destDir;
+		
+		public CopyVisitor(Path sourceDir, Path destDir) throws IOException {
+			this.destDir = destDir;
+			this.sourceDir = sourceDir;
+			Path wikiDir = destDir.resolve(WIKI_RESOURCE_FOLDER_NAME);
+			Files.createDirectories(wikiDir);
+			Path mediaDir = destDir.resolve(WikiContainer.MEDIA_FOLDER_NAME);
+			Files.createDirectories(mediaDir);
+			Path versionDir = destDir.resolve(VERSION_FOLDER_NAME);
+			Files.createDirectories(versionDir);
+		}
+		
+		@Override
+		public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+	    throws IOException {
+
+			Path relFile = sourceDir.relativize(file);
+			
+	        String filename = file.getFileName().toString();
+	        if(filename.endsWith(WikiManager.WIKI_PROPERTIES_SUFFIX)) {
+	        	final Path destFile = Paths.get(destDir.toString(), relFile.toString());
+	        	resetAndCopyProperties(file, destFile);
+	        	
+	        } else if (filename.endsWith(WIKI_FILE_SUFFIX)) {
+	        	final Path destFile = Paths.get(destDir.toString(), relFile.toString());
+				Files.copy(file, destFile, StandardCopyOption.REPLACE_EXISTING);
+			} else if (!filename.contains(WIKI_FILE_SUFFIX + "-")
+					&& !filename.contains(WIKI_PROPERTIES_SUFFIX + "-")) {
+				final Path destFile = Paths.get(destDir.toString(), relFile.toString());
+				Files.copy(file, destFile, StandardCopyOption.REPLACE_EXISTING);
+			}
+	        return FileVisitResult.CONTINUE;
+		}
+	 
+		@Override
+		public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+		throws IOException {
+			dir = sourceDir.relativize(dir);
+			
+	        final Path dirToCreate = Paths.get(destDir.toString(), dir.toString());
+	        if(Files.notExists(dirToCreate)){
+	        	Files.createDirectory(dirToCreate);
+	        }
+	        return FileVisitResult.CONTINUE;
+		}
+	}
+	
+	
+	/**
+	 * Dispatch the content in the wiki and media folders from an import
+	 * where all the files are flatted at the root of the archive.
+	 * 
+	 * Initial date: 02.05.2014<br>
+	 * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+	 *
+	 */
+	public static class ImportVisitor extends SimpleFileVisitor<Path> {
+		
 		private final Path destDir;
 		private final Path wikiDir;
 		private final Path mediaDir;
 		
-		public CopyVisitor(Path destDir) throws IOException {
+		public ImportVisitor(Path destDir) throws IOException {
 			this.destDir = destDir;
 			wikiDir = destDir.resolve(WIKI_RESOURCE_FOLDER_NAME);
 			Files.createDirectories(wikiDir);
@@ -201,11 +304,14 @@ public class WikiManager {
 		public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
 	    throws IOException {
 	        String filename = file.getFileName().toString();
-	        if (filename.endsWith(WikiManager.WIKI_FILE_SUFFIX) || filename.endsWith(WikiManager.WIKI_PROPERTIES_SUFFIX)) {
+	        if(filename.endsWith(WikiManager.WIKI_PROPERTIES_SUFFIX)) {
+	        	final Path destFile = Paths.get(wikiDir.toString(), file.toString());
+	        	resetAndCopyProperties(file, destFile);
+	        } else if (filename.endsWith(WIKI_FILE_SUFFIX)) {
 	        	final Path destFile = Paths.get(wikiDir.toString(), file.toString());
 				Files.copy(file, destFile, StandardCopyOption.REPLACE_EXISTING);
-			} else if (!filename.contains(WikiManager.WIKI_FILE_SUFFIX + "-")
-					&& !filename.contains(WikiManager.WIKI_PROPERTIES_SUFFIX + "-")) {
+			} else if (!filename.contains(WIKI_FILE_SUFFIX + "-")
+					&& !filename.contains(WIKI_PROPERTIES_SUFFIX + "-")) {
 				final Path destFile = Paths.get(mediaDir.toString(), file.toString());
 				Files.copy(file, destFile, StandardCopyOption.REPLACE_EXISTING);
 			}
@@ -302,98 +408,85 @@ public class WikiManager {
 		if (wikiCache == null) {
 			wikiCache =  coordinator.getCoordinator().getCacher().getCache(WikiManager.class.getSimpleName(), "wiki");
 		}
-		Wiki wiki = wikiCache.get(wikiKey);
-		if (wiki != null) {
-			log.debug("loading wiki from cache. Ores: " + ores.getResourceableId());
-			return wiki;
-		}
-		// No wiki in cache => load it form file-system
-			coordinator.getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor() {
-			public void execute() {
-
-				long start = 0;
-				// wiki not in cache load form filesystem
-				if (log.isDebug()) {
-					log.debug("wiki not in cache. Loading wiki from filesystem. Ores: " + ores.getResourceableId());
-					start = System.currentTimeMillis();
-				}
+		return wikiCache.computeIfAbsent(wikiKey, (key) -> {
+			long start = 0;
+			// wiki not in cache load form filesystem
+			if (log.isDebug()) {
+				log.debug("wiki not in cache. Loading wiki from filesystem. Ores: " + ores.getResourceableId());
+				start = System.currentTimeMillis();
+			}
 
-				Wiki wiki = null;
-				VFSContainer folder = getWikiContainer(ores, WIKI_RESOURCE_FOLDER_NAME);
-				// wiki folder structure does not yet exists, but resource does. Create
-				// wiki in group context
-				if (folder == null) {
-					// createWikiforExistingResource(ores);
-					createFolders(ores);
-					folder = getWikiContainer(ores, WIKI_RESOURCE_FOLDER_NAME);
-				}
-				// folders should be present, create the wiki
-				wiki = new Wiki(getWikiRootContainer(ores));
-				// filter for xyz.properties files
-				List<VFSItem> wikiLeaves = folder.getItems(new VFSItemSuffixFilter(new String[] { WikiManager.WIKI_PROPERTIES_SUFFIX }));
-				for (Iterator<VFSItem> iter = wikiLeaves.iterator(); iter.hasNext();) {
-					VFSLeaf propertiesFile = (VFSLeaf) iter.next();
-					WikiPage page = Wiki.assignPropertiesToPage(propertiesFile);
-					if (page == null) {
-						// broken pages get automatically cleaned from filesystem
-						String contentFileToBeDeleted = (propertiesFile.getName().substring(0,
-								propertiesFile.getName().length() - WikiManager.WIKI_PROPERTIES_SUFFIX.length()) + WikiManager.WIKI_FILE_SUFFIX);
-						folder.resolve(contentFileToBeDeleted).delete();
-						propertiesFile.delete();
-						continue;
-					}
-					// index and menu page are loaded by default
-					if (page.getPageName().equals(WikiPage.WIKI_INDEX_PAGE) || page.getPageName().equals(WikiPage.WIKI_MENU_PAGE)) {
-						VFSLeaf leaf = (VFSLeaf) folder.resolve(page.getPageId() + "." + WikiManager.WIKI_FILE_SUFFIX);
-						page.setContent(FileUtils.load(leaf.getInputStream(), "utf-8"));
-					}
-
-					// due to a bug we have to rename some pages that start with an non
-					// ASCII lowercase letter
-					String idOutOfFileName = propertiesFile.getName().substring(0, propertiesFile.getName().indexOf("."));
-					if (!page.getPageId().equals(idOutOfFileName)) {
-						// rename corrupt prop file
-						propertiesFile.rename(page.getPageId() + "." + WikiManager.WIKI_PROPERTIES_SUFFIX);
-						// load content and delete corrupt content file
-						VFSLeaf contentFile = (VFSLeaf) folder.resolve(idOutOfFileName + "." + WikiManager.WIKI_FILE_SUFFIX);
-						contentFile.rename(page.getPageId() + "." + WikiManager.WIKI_FILE_SUFFIX);
-					}
-
-					wiki.addPage(page);
+			VFSContainer folder = getWikiContainer(ores, WIKI_RESOURCE_FOLDER_NAME);
+			// wiki folder structure does not yet exists, but resource does. Create
+			// wiki in group context
+			if (folder == null) {
+				// createWikiforExistingResource(ores);
+				createFolders(ores);
+				folder = getWikiContainer(ores, WIKI_RESOURCE_FOLDER_NAME);
+			}
+			
+			// folders should be present, create the wiki
+			Wiki wiki = new Wiki(getWikiRootContainer(ores));
+			// filter for xyz.properties files
+			List<VFSItem> wikiLeaves = folder.getItems(new VFSItemSuffixFilter(new String[] { WikiManager.WIKI_PROPERTIES_SUFFIX }));
+			for (Iterator<VFSItem> iter = wikiLeaves.iterator(); iter.hasNext();) {
+				VFSLeaf propertiesFile = (VFSLeaf) iter.next();
+				WikiPage page = Wiki.assignPropertiesToPage(propertiesFile);
+				if (page == null) {
+					// broken pages get automatically cleaned from filesystem
+					String contentFileToBeDeleted = (propertiesFile.getName().substring(0,
+							propertiesFile.getName().length() - WikiManager.WIKI_PROPERTIES_SUFFIX.length()) + WikiManager.WIKI_FILE_SUFFIX);
+					folder.resolve(contentFileToBeDeleted).delete();
+					propertiesFile.delete();
+					continue;
 				}
-				// if index and menu page not present create the first page and save it
-				if (wiki.getNumberOfPages() == 0) {
-					WikiPage indexPage = new WikiPage(WikiPage.WIKI_INDEX_PAGE);
-					WikiPage menuPage = new WikiPage(WikiPage.WIKI_MENU_PAGE);
-					indexPage.setCreationTime(System.currentTimeMillis());
-					wiki.addPage(indexPage);
-					menuPage.setCreationTime(System.currentTimeMillis());
-					menuPage.setContent("* [[Index]]\n* [[Index|Your link]]");
-					wiki.addPage(menuPage);
-					saveWikiPage(ores, indexPage, false, wiki);
-					saveWikiPage(ores, menuPage, false, wiki);
+				// index and menu page are loaded by default
+				if (page.getPageName().equals(WikiPage.WIKI_INDEX_PAGE) || page.getPageName().equals(WikiPage.WIKI_MENU_PAGE)) {
+					VFSLeaf leaf = (VFSLeaf) folder.resolve(page.getPageId() + "." + WikiManager.WIKI_FILE_SUFFIX);
+					page.setContent(FileUtils.load(leaf.getInputStream(), "utf-8"));
 				}
-				// add pages internally used for displaying dynamic data, they are not
-				// persisted
-				WikiPage recentChangesPage = new WikiPage(WikiPage.WIKI_RECENT_CHANGES_PAGE);
-				WikiPage a2zPage = new WikiPage(WikiPage.WIKI_A2Z_PAGE);
-				wiki.addPage(recentChangesPage);
-				wiki.addPage(a2zPage);
-
-				// wikiCache.put(OresHelper.createStringRepresenting(ores), wiki);
-				if (log.isDebug()) {
-					long stop = System.currentTimeMillis();
-					log.debug("loading of wiki from filessystem took (ms) " + (stop - start));
+
+				// due to a bug we have to rename some pages that start with an non
+				// ASCII lowercase letter
+				String idOutOfFileName = propertiesFile.getName().substring(0, propertiesFile.getName().indexOf("."));
+				if (!page.getPageId().equals(idOutOfFileName)) {
+					// rename corrupt prop file
+					propertiesFile.rename(page.getPageId() + "." + WikiManager.WIKI_PROPERTIES_SUFFIX);
+					// load content and delete corrupt content file
+					VFSLeaf contentFile = (VFSLeaf) folder.resolve(idOutOfFileName + "." + WikiManager.WIKI_FILE_SUFFIX);
+					contentFile.rename(page.getPageId() + "." + WikiManager.WIKI_FILE_SUFFIX);
 				}
-				wikiCache.put(wikiKey, wiki);
+
+				wiki.addPage(page);
 			}
+			
+			// if index and menu page not present create the first page and save it
+			if (wiki.getNumberOfPages() == 0) {
+				WikiPage indexPage = new WikiPage(WikiPage.WIKI_INDEX_PAGE);
+				WikiPage menuPage = new WikiPage(WikiPage.WIKI_MENU_PAGE);
+				indexPage.setCreationTime(System.currentTimeMillis());
+				wiki.addPage(indexPage);
+				menuPage.setCreationTime(System.currentTimeMillis());
+				menuPage.setContent("* [[Index]]\n* [[Index|Your link]]");
+				wiki.addPage(menuPage);
+				saveWikiPage(ores, indexPage, false, wiki);
+				saveWikiPage(ores, menuPage, false, wiki);
+			}
+			
+			// add pages internally used for displaying dynamic data, they are not persisted
+			WikiPage recentChangesPage = new WikiPage(WikiPage.WIKI_RECENT_CHANGES_PAGE);
+			WikiPage a2zPage = new WikiPage(WikiPage.WIKI_A2Z_PAGE);
+			wiki.addPage(recentChangesPage);
+			wiki.addPage(a2zPage);
+
+			if (log.isDebug()) {
+				long stop = System.currentTimeMillis();
+				log.debug("loading of wiki from filessystem took (ms) " + (stop - start));
+			}
+			return wiki;
 		});
-		//at this point there will be something in the cache
-		return wikiCache.get(wikiKey);
-
 	}
 		
-
 	public DifferenceService getDiffService() {
 		return new CookbookDifferenceService();
 	}
diff --git a/src/main/java/org/olat/repository/handlers/WikiHandler.java b/src/main/java/org/olat/repository/handlers/WikiHandler.java
index 8cee4fe6edb..6576cd39b33 100644
--- a/src/main/java/org/olat/repository/handlers/WikiHandler.java
+++ b/src/main/java/org/olat/repository/handlers/WikiHandler.java
@@ -26,7 +26,6 @@
 package org.olat.repository.handlers;
 
 import java.io.File;
-import java.util.List;
 import java.util.Locale;
 
 import org.olat.basesecurity.BaseSecurityModule;
@@ -54,21 +53,15 @@ import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.core.util.coordinate.LockResult;
 import org.olat.core.util.resource.OLATResourceableJustBeforeDeletedEvent;
 import org.olat.core.util.vfs.VFSContainer;
-import org.olat.core.util.vfs.VFSItem;
 import org.olat.core.util.vfs.VFSLeaf;
-import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.VFSMediaResource;
-import org.olat.core.util.vfs.filters.VFSItemSuffixFilter;
 import org.olat.course.assessment.AssessmentMode;
 import org.olat.course.assessment.manager.UserCourseInformationsManager;
 import org.olat.fileresource.FileResourceManager;
 import org.olat.fileresource.types.ResourceEvaluation;
 import org.olat.fileresource.types.WikiResource;
-import org.olat.modules.wiki.Wiki;
-import org.olat.modules.wiki.WikiContainer;
 import org.olat.modules.wiki.WikiMainController;
 import org.olat.modules.wiki.WikiManager;
-import org.olat.modules.wiki.WikiPage;
 import org.olat.modules.wiki.WikiSecurityCallback;
 import org.olat.modules.wiki.WikiSecurityCallbackImpl;
 import org.olat.modules.wiki.WikiToZipUtils;
@@ -144,44 +137,9 @@ public class WikiHandler implements RepositoryHandler {
 		final OLATResource sourceResource = source.getOlatResource();
 		final OLATResource targetResource = target.getOlatResource();
 		final FileResourceManager frm = FileResourceManager.getInstance();
-		
-		VFSContainer sourceWikiContainer = WikiManager.getInstance().getWikiContainer(sourceResource, WikiManager.WIKI_RESOURCE_FOLDER_NAME);
-		if(sourceWikiContainer == null) {
-			//if the wiki container is null, let the WikiManager to create one
-			WikiManager.getInstance().getOrLoadWiki(sourceResource);
-			sourceWikiContainer = WikiManager.getInstance().getWikiContainer(sourceResource, WikiManager.WIKI_RESOURCE_FOLDER_NAME);
-		}
-		
-		VFSContainer targetRootContainer = frm.getFileResourceRootImpl(targetResource);
-		VFSContainer targetWikiContainer = VFSManager.getOrCreateContainer(targetRootContainer, WikiManager.WIKI_RESOURCE_FOLDER_NAME);
-		VFSManager.copyContent(sourceWikiContainer, targetWikiContainer);
-		
-		VFSContainer sourceRootContainer = sourceWikiContainer.getParentContainer();
-		
-		//create versions folder
-		targetRootContainer.createChildContainer(WikiManager.VERSION_FOLDER_NAME);
-		
-		//create media folders and copy it
-		VFSContainer targetMediaContainer = VFSManager.getOrCreateContainer(targetRootContainer, WikiContainer.MEDIA_FOLDER_NAME); 
-		VFSItem sourceMediaItem = sourceRootContainer.resolve(WikiContainer.MEDIA_FOLDER_NAME);
-		if(sourceMediaItem instanceof VFSContainer) {
-			VFSContainer sourceMediaContainer = (VFSContainer)sourceMediaItem;
-			VFSManager.copyContent(sourceMediaContainer, targetMediaContainer);
-		}
-
-		//reset properties files to default values
-		String[] filteredSuffix = new String[]{ WikiManager.WIKI_PROPERTIES_SUFFIX };
-		List<VFSItem> items = targetWikiContainer.getItems(new VFSItemSuffixFilter(filteredSuffix));
-		for (VFSItem item: items) {
-			if(item instanceof VFSLeaf) {
-				VFSLeaf leaf = (VFSLeaf)item;
-				WikiPage page = Wiki.assignPropertiesToPage(leaf);
-				//reset the copied pages to a the default values
-				page.resetCopiedPage();
-				WikiManager.getInstance().updateWikiPageProperties(targetResource, page);
-			}
-		}
-		
+		File sourceDir = frm.getFileResourceRoot(sourceResource);
+		File targetDir = frm.getFileResourceRoot(targetResource);
+		WikiManager.getInstance().copyWiki(sourceDir, targetDir);
 		return target;
 	}
 
-- 
GitLab