Skip to content
Snippets Groups Projects
Commit 5799b87b authored by srosse's avatar srosse
Browse files

OO-990: import scorm and cp packaged in a root directory

parent ab21bdf6
No related branches found
No related tags found
No related merge requests found
Showing
with 185 additions and 36 deletions
...@@ -27,6 +27,7 @@ import java.io.IOException; ...@@ -27,6 +27,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult; import java.nio.file.FileVisitResult;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
...@@ -229,6 +230,8 @@ public class OnyxModule extends AbstractOLATModule implements ConfigOnOff { ...@@ -229,6 +230,8 @@ public class OnyxModule extends AbstractOLATModule implements ConfigOnOff {
} else { } else {
eval.setValid(false); eval.setValid(false);
} }
} catch(NoSuchFileException nsfe) {
eval.setValid(false);
} catch (IOException e) { } catch (IOException e) {
log.error("", e); log.error("", e);
eval.setValid(false); eval.setValid(false);
......
...@@ -112,13 +112,24 @@ public class FileResource implements OLATResourceable { ...@@ -112,13 +112,24 @@ public class FileResource implements OLATResourceable {
} else if(filename != null && filename.toLowerCase().endsWith(".zip")) { } else if(filename != null && filename.toLowerCase().endsWith(".zip")) {
//perhaps find root folder and return it //perhaps find root folder and return it
fPath = FileSystems.newFileSystem(file.toPath(), null).getPath("/"); fPath = FileSystems.newFileSystem(file.toPath(), null).getPath("/");
RootSearcher rootSearcher = searchRootDirectory(fPath);
if(rootSearcher.foundRoot()) {
Path rootPath = rootSearcher.getRoot();
fPath = fPath.resolve(rootPath);
}
} else { } else {
fPath = file.toPath(); fPath = file.toPath();
} }
return fPath; return fPath;
} }
protected static RootSearcher searchRootDirectory(Path fPath)
throws IOException {
RootSearcher rootSearcher = new RootSearcher();
Files.walkFileTree(fPath, rootSearcher);
return rootSearcher;
}
public static boolean copyResource(File file, String filename, File targetDirectory) { public static boolean copyResource(File file, String filename, File targetDirectory) {
return copyResource(file, filename, targetDirectory, new YesMatcher()); return copyResource(file, filename, targetDirectory, new YesMatcher());
} }
...@@ -131,13 +142,45 @@ public class FileResource implements OLATResourceable { ...@@ -131,13 +142,45 @@ public class FileResource implements OLATResourceable {
} }
Path destDir = targetDirectory.toPath(); Path destDir = targetDirectory.toPath();
Files.walkFileTree(path, new CopyVisitor(destDir, filter)); Files.walkFileTree(path, new CopyVisitor(path, destDir, filter));
return true; return true;
} catch (IOException e) { } catch (IOException e) {
log.error("", e); log.error("", e);
return false; return false;
} }
} }
public static class RootSearcher extends SimpleFileVisitor<Path> {
private Path root;
private boolean rootFound = false;
public Path getRoot() {
return root;
}
public boolean foundRoot() {
return root != null && rootFound;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
Path tokenZero = file.getName(0);
if("__MACOSX".equals(tokenZero.toString()) || Files.isHidden(file)) {
//ignore
} else if(root == null) {
if(Files.isRegularFile(file) && file.getNameCount() > 1) {
root = tokenZero;
rootFound = true;
}
} else if(!root.equals(tokenZero)) {
rootFound = false;
return FileVisitResult.TERMINATE;
}
return FileVisitResult.CONTINUE;
}
}
public static class YesMatcher implements PathMatcher { public static class YesMatcher implements PathMatcher {
@Override @Override
...@@ -147,11 +190,13 @@ public class FileResource implements OLATResourceable { ...@@ -147,11 +190,13 @@ public class FileResource implements OLATResourceable {
} }
public static class CopyVisitor extends SimpleFileVisitor<Path> { public static class CopyVisitor extends SimpleFileVisitor<Path> {
private final Path source;
private final Path destDir; private final Path destDir;
private final PathMatcher filter; private final PathMatcher filter;
public CopyVisitor(Path destDir, PathMatcher filter) { public CopyVisitor(Path source, Path destDir, PathMatcher filter) {
this.source = source;
this.destDir = destDir; this.destDir = destDir;
this.filter = filter; this.filter = filter;
} }
...@@ -159,7 +204,8 @@ public class FileResource implements OLATResourceable { ...@@ -159,7 +204,8 @@ public class FileResource implements OLATResourceable {
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException { throws IOException {
final Path destFile = Paths.get(destDir.toString(), file.toString()); Path relativeFile = source.relativize(file);
final Path destFile = Paths.get(destDir.toString(), relativeFile.toString());
if(filter.matches(file)) { if(filter.matches(file)) {
Files.copy(file, destFile, StandardCopyOption.REPLACE_EXISTING); Files.copy(file, destFile, StandardCopyOption.REPLACE_EXISTING);
} }
...@@ -169,7 +215,8 @@ public class FileResource implements OLATResourceable { ...@@ -169,7 +215,8 @@ public class FileResource implements OLATResourceable {
@Override @Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException { throws IOException {
final Path dirToCreate = Paths.get(destDir.toString(), dir.toString()); Path relativeDir = source.relativize(dir);
final Path dirToCreate = Paths.get(destDir.toString(), relativeDir.toString());
if(Files.notExists(dirToCreate)){ if(Files.notExists(dirToCreate)){
Files.createDirectory(dirToCreate); Files.createDirectory(dirToCreate);
} }
......
...@@ -62,30 +62,14 @@ public class ImsCPFileResource extends FileResource { ...@@ -62,30 +62,14 @@ public class ImsCPFileResource extends FileResource {
public ImsCPFileResource() { public ImsCPFileResource() {
super(TYPE_NAME); super(TYPE_NAME);
} }
/**
* Check for title and at least one resource.
* @param unzippedDir
* @return True if is of type.
*/
public static boolean validate(File unzippedDir) {
File fManifest = new File(unzippedDir, IMS_MANIFEST);
Document doc = IMSLoader.loadIMSDocument(fManifest);
//do not throw exception already here, as it might be only a generic zip file
if (doc == null) {
return false;
} else {
return validateImsManifest(doc);
}
}
public static ResourceEvaluation evaluate(File file, String filename) { public static ResourceEvaluation evaluate(File file, String filename) {
ResourceEvaluation eval = new ResourceEvaluation(); ResourceEvaluation eval = new ResourceEvaluation();
try { try {
ImsManifestFileFilter visitor = new ImsManifestFileFilter(); ImsManifestFileFilter visitor = new ImsManifestFileFilter();
Path fPath = PathUtils.visit(file, filename, visitor); Path fPath = PathUtils.visit(file, filename, visitor);
if(visitor.isValid()) { if(visitor.isValid()) {
Path manifestPath = fPath.resolve(IMS_MANIFEST); Path manifestPath = fPath.resolve(visitor.getManifestPath());
Document doc = IMSLoader.loadIMSDocument(manifestPath); Document doc = IMSLoader.loadIMSDocument(manifestPath);
if(validateImsManifest(doc)) { if(validateImsManifest(doc)) {
eval.setValid(true); eval.setValid(true);
...@@ -170,6 +154,7 @@ public class ImsCPFileResource extends FileResource { ...@@ -170,6 +154,7 @@ public class ImsCPFileResource extends FileResource {
private static class ImsManifestFileFilter extends SimpleFileVisitor<Path> { private static class ImsManifestFileFilter extends SimpleFileVisitor<Path> {
private boolean manifestFile; private boolean manifestFile;
private Path manifestPath;
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
...@@ -178,6 +163,7 @@ public class ImsCPFileResource extends FileResource { ...@@ -178,6 +163,7 @@ public class ImsCPFileResource extends FileResource {
String filename = file.getFileName().toString(); String filename = file.getFileName().toString();
if(IMS_MANIFEST.equals(filename)) { if(IMS_MANIFEST.equals(filename)) {
manifestFile = true; manifestFile = true;
manifestPath = file;
} }
return manifestFile ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE; return manifestFile ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE;
} }
...@@ -185,5 +171,9 @@ public class ImsCPFileResource extends FileResource { ...@@ -185,5 +171,9 @@ public class ImsCPFileResource extends FileResource {
public boolean isValid() { public boolean isValid() {
return manifestFile; return manifestFile;
} }
public Path getManifestPath() {
return manifestPath;
}
} }
} }
\ No newline at end of file
...@@ -28,6 +28,7 @@ package org.olat.fileresource.types; ...@@ -28,6 +28,7 @@ package org.olat.fileresource.types;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.FileVisitResult; import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
...@@ -67,24 +68,23 @@ public class ScormCPFileResource extends FileResource { ...@@ -67,24 +68,23 @@ public class ScormCPFileResource extends FileResource {
super(TYPE_NAME); super(TYPE_NAME);
} }
/**
* Check for title and at least one resource.
* @param unzippedDir
* @return True if is of type.
*/
public static boolean validate(File unzippedDir) {
File fManifest = new File(unzippedDir, "imsmanifest.xml");
Document doc = IMSLoader.loadIMSDocument(fManifest);
return validateImsManifest(doc);
}
public static ResourceEvaluation evaluate(File file, String filename) { public static ResourceEvaluation evaluate(File file, String filename) {
ResourceEvaluation eval = new ResourceEvaluation(); ResourceEvaluation eval = new ResourceEvaluation();
try { try {
ImsManifestFileFilter visitor = new ImsManifestFileFilter(); ImsManifestFileFilter visitor = new ImsManifestFileFilter();
Path fPath = PathUtils.visit(file, filename, visitor); Path fPath = PathUtils.visit(file, filename, visitor);
if(visitor.isValid()) { if(visitor.isValid()) {
Path manifestPath = fPath.resolve(IMS_MANIFEST); Path realManifestPath = visitor.getManifestPath();
Path manifestPath = fPath.resolve(realManifestPath);
RootSearcher rootSearcher = new RootSearcher();
Files.walkFileTree(fPath, rootSearcher);
if(rootSearcher.foundRoot()) {
manifestPath = rootSearcher.getRoot().resolve(IMS_MANIFEST);
} else {
manifestPath = fPath.resolve(IMS_MANIFEST);
}
Document doc = IMSLoader.loadIMSDocument(manifestPath); Document doc = IMSLoader.loadIMSDocument(manifestPath);
if(validateImsManifest(doc)) { if(validateImsManifest(doc)) {
eval.setValid(true); eval.setValid(true);
...@@ -214,6 +214,7 @@ public class ScormCPFileResource extends FileResource { ...@@ -214,6 +214,7 @@ public class ScormCPFileResource extends FileResource {
private static class ImsManifestFileFilter extends SimpleFileVisitor<Path> { private static class ImsManifestFileFilter extends SimpleFileVisitor<Path> {
private boolean manifestFile; private boolean manifestFile;
private Path manifestPath;
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
...@@ -222,6 +223,7 @@ public class ScormCPFileResource extends FileResource { ...@@ -222,6 +223,7 @@ public class ScormCPFileResource extends FileResource {
String filename = file.getFileName().toString(); String filename = file.getFileName().toString();
if(IMS_MANIFEST.equals(filename)) { if(IMS_MANIFEST.equals(filename)) {
manifestFile = true; manifestFile = true;
manifestPath = file;
} }
return manifestFile ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE; return manifestFile ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE;
} }
...@@ -229,5 +231,9 @@ public class ScormCPFileResource extends FileResource { ...@@ -229,5 +231,9 @@ public class ScormCPFileResource extends FileResource {
public boolean isValid() { public boolean isValid() {
return manifestFile; return manifestFile;
} }
public Path getManifestPath() {
return manifestPath;
}
} }
} }
/**
* <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.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import junit.framework.Assert;
import org.junit.Test;
import org.olat.fileresource.types.FileResource;
import org.olat.fileresource.types.ResourceEvaluation;
import org.olat.fileresource.types.ScormCPFileResource;
/**
*
* Initial date: 25.07.2014<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class FileResourceTest {
@Test
public void scormPackage() throws URISyntaxException {
URL fileUrl = FileResourceTest.class.getResource("very_simple_scorm.zip");
File file = new File(fileUrl.toURI());
ResourceEvaluation eval = ScormCPFileResource.evaluate(file, file.getName());
Assert.assertTrue(eval.isValid());
}
@Test
public void scormPackage_withinDirectory() throws URISyntaxException {
URL fileUrl = FileResourceTest.class.getResource("very_simple_scorm_in_directory.zip");
File file = new File(fileUrl.toURI());
ResourceEvaluation eval = ScormCPFileResource.evaluate(file, file.getName());
Assert.assertTrue(eval.isValid());
}
@Test
public void scormPackage_invalid() throws URISyntaxException {
URL fileUrl = FileResourceTest.class.getResource("invalid_scorm.zip");
File file = new File(fileUrl.toURI());
ResourceEvaluation eval = ScormCPFileResource.evaluate(file, file.getName());
Assert.assertFalse(eval.isValid());
}
@Test
public void qtiPackage() throws URISyntaxException, IOException {
URL fileUrl = FileResourceTest.class.getResource("qti.zip");
File file = new File(fileUrl.toURI());
Path path = FileResource.getResource(file, file.getName());
//must be root
Assert.assertEquals(0, path.getNameCount());
}
}
File added
File added
File added
File added
/**
* <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.modules.coach; package org.olat.modules.coach;
import java.io.File; import java.io.File;
...@@ -21,6 +40,12 @@ import org.olat.test.JunitTestHelper; ...@@ -21,6 +40,12 @@ import org.olat.test.JunitTestHelper;
import org.olat.test.OlatTestCase; import org.olat.test.OlatTestCase;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 24.07.2014<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class CoachingDAOTest extends OlatTestCase { public class CoachingDAOTest extends OlatTestCase {
@Autowired @Autowired
......
...@@ -93,6 +93,7 @@ import org.junit.runners.Suite; ...@@ -93,6 +93,7 @@ import org.junit.runners.Suite;
org.olat.group.test.BusinessGroupRelationDAOTest.class,//ok org.olat.group.test.BusinessGroupRelationDAOTest.class,//ok
org.olat.group.test.BusinessGroupConcurrentTest.class,//ok org.olat.group.test.BusinessGroupConcurrentTest.class,//ok
org.olat.group.test.ContactDAOTest.class,//ok org.olat.group.test.ContactDAOTest.class,//ok
org.olat.fileresource.FileResourceTest.class,//ok
org.olat.resource.lock.pessimistic.PLockTest.class,//ok org.olat.resource.lock.pessimistic.PLockTest.class,//ok
org.olat.resource.references.ReferenceManagerTest.class,//ok org.olat.resource.references.ReferenceManagerTest.class,//ok
org.olat.resource.OLATResourceManagerTest.class,//ok org.olat.resource.OLATResourceManagerTest.class,//ok
...@@ -127,6 +128,7 @@ import org.junit.runners.Suite; ...@@ -127,6 +128,7 @@ import org.junit.runners.Suite;
org.olat.modules.wiki.WikiUnitTest.class,//ok org.olat.modules.wiki.WikiUnitTest.class,//ok
org.olat.modules.wiki.versioning.diff.CookbookDiffTest.class,//ok org.olat.modules.wiki.versioning.diff.CookbookDiffTest.class,//ok
org.olat.modules.wiki.gui.components.wikiToHtml.FilterUtilTest.class, org.olat.modules.wiki.gui.components.wikiToHtml.FilterUtilTest.class,
org.olat.modules.coach.CoachingDAOTest.class,//ok
org.olat.modules.coach.CoachingServiceTest.class,//ok org.olat.modules.coach.CoachingServiceTest.class,//ok
org.olat.properties.PropertyTest.class,//ok org.olat.properties.PropertyTest.class,//ok
org.olat.search.service.document.file.FileDocumentFactoryTest.class, org.olat.search.service.document.file.FileDocumentFactoryTest.class,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment