diff --git a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVMergeSource.java b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVMergeSource.java new file mode 100644 index 0000000000000000000000000000000000000000..f3ea6267b15689518e5bb97008c4b3c1717ef7d8 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVMergeSource.java @@ -0,0 +1,137 @@ +/** + * <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.core.commons.services.webdav.manager; + +import java.util.List; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.services.taskexecutor.TaskExecutorManager; +import org.olat.core.id.Identity; +import org.olat.core.util.vfs.MergeSource; +import org.olat.core.util.vfs.VFSConstants; +import org.olat.core.util.vfs.VFSContainer; +import org.olat.core.util.vfs.VFSItem; +import org.olat.core.util.vfs.VFSStatus; +import org.olat.core.util.vfs.filters.VFSItemFilter; + +/** + * + * Initial date: 06.05.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public abstract class WebDAVMergeSource extends MergeSource { + + private boolean init = false; + private final Identity identity; + private long loadTime; + + public WebDAVMergeSource(Identity identity) { + super(null, null); + this.identity = identity; + } + + public Identity getIdentity() { + return identity; + } + + @Override + public VFSStatus canWrite() { + return VFSConstants.NO; + } + + @Override + public VFSStatus canDelete() { + return VFSConstants.NO; + } + + @Override + public VFSStatus canRename() { + return VFSConstants.NO; + } + + @Override + public VFSStatus canCopy() { + return VFSConstants.NO; + } + + @Override + public VFSStatus delete() { + return VFSConstants.NO; + } + + @Override + public void setDefaultItemFilter(VFSItemFilter defaultFilter) { + // + } + + @Override + public List<VFSItem> getItems() { + checkInitialization(); + return super.getItems(); + } + + @Override + public List<VFSItem> getItems(VFSItemFilter filter) { + checkInitialization(); + return super.getItems(filter); + } + + @Override + public VFSItem resolve(String path) { + checkInitialization(); + return super.resolve(path); + } + + private void checkInitialization() { + if(!init) { + synchronized(this) { + if(!init) { + loadTime = System.currentTimeMillis(); + init(); + } + } + } else if((System.currentTimeMillis() - loadTime) > 60000) { + synchronized(this) { + if((System.currentTimeMillis() - loadTime) > 60000) { + loadTime = System.currentTimeMillis(); + CoreSpringFactory.getImpl(TaskExecutorManager.class).execute(new AsyncInit()); + } + } + } + } + + @Override + protected void init() { + List<VFSContainer> containers = loadMergedContainers(); + setMergedContainers(containers); + loadTime = System.currentTimeMillis(); + init = true; + } + + protected abstract List<VFSContainer> loadMergedContainers(); + + public class AsyncInit implements Runnable { + @Override + public void run() { + init(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/webdav/servlets/RequestUtil.java b/src/main/java/org/olat/core/commons/services/webdav/servlets/RequestUtil.java index cabd61b0c43b6805d33764af1e0a58f01caca7a5..cf65d96346f6b0472137fe6bc2320bdc68d2ac92 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/servlets/RequestUtil.java +++ b/src/main/java/org/olat/core/commons/services/webdav/servlets/RequestUtil.java @@ -485,7 +485,7 @@ public final class RequestUtil { .replace("/", "_").replace("\\", "_") .replace("?", "_").replace("<", "_").replace(">", "_") .replace("%", "_").replace("\"", "_").replace("'", "_") - .replace(":", "_").replace("*", "_") + .replace(":", "_").replace("*", "_").replace("&", "_") .replace(".", "_"); String nameNormalized = Normalizer.normalize(nameSanitized, Normalizer.Form.NFC); return nameNormalized; diff --git a/src/main/java/org/olat/core/util/vfs/VFSManager.java b/src/main/java/org/olat/core/util/vfs/VFSManager.java index 7fea9be18c3dd790c4ef00c6d3b0455934baf256..9d7821078611f5f791afe5522e6f6d7cb4a7e229 100644 --- a/src/main/java/org/olat/core/util/vfs/VFSManager.java +++ b/src/main/java/org/olat/core/util/vfs/VFSManager.java @@ -153,7 +153,7 @@ public class VFSManager extends BasicManager { if (t.isDirectory()) { VFSContainer subContainer; if (fsPath.startsWith(bcroot)) { - fsPath = fsPath.replace(bcroot,""); + fsPath = fsPath.substring(bcroot.length(), fsPath.length()); subContainer = new OlatRootFolderImpl(fsPath, rootContainer); } else { subContainer = new LocalFolderImpl (t, rootContainer); diff --git a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java index 1976b0cfedd02b0a51282bfd1af9b1bad5567c92..6f42055cfe9f28e60923c15ef03608e72f194d7f 100644 --- a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java +++ b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java @@ -22,15 +22,11 @@ package org.olat.course; import java.util.ArrayList; import java.util.List; +import org.olat.core.commons.services.webdav.manager.WebDAVMergeSource; import org.olat.core.commons.services.webdav.servlets.RequestUtil; import org.olat.core.id.Identity; -import org.olat.core.util.vfs.MergeSource; import org.olat.core.util.vfs.NamedContainerImpl; -import org.olat.core.util.vfs.VFSConstants; import org.olat.core.util.vfs.VFSContainer; -import org.olat.core.util.vfs.VFSItem; -import org.olat.core.util.vfs.VFSStatus; -import org.olat.core.util.vfs.filters.VFSItemFilter; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; @@ -40,79 +36,16 @@ import org.olat.repository.RepositoryManager; * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ -class CoursefolderWebDAVMergeSource extends MergeSource { - - private boolean init = false; - private final Identity identity; - private long loadTime; +class CoursefolderWebDAVMergeSource extends WebDAVMergeSource { public CoursefolderWebDAVMergeSource(Identity identity) { - super(null, null); - this.identity = identity; - } - - @Override - public VFSStatus canWrite() { - return VFSConstants.NO; - } - - @Override - public VFSStatus canDelete() { - return VFSConstants.NO; - } - - @Override - public VFSStatus canRename() { - return VFSConstants.NO; - } - - @Override - public VFSStatus canCopy() { - return VFSConstants.NO; - } - - @Override - public VFSStatus delete() { - return VFSConstants.NO; - } - - @Override - public void setDefaultItemFilter(VFSItemFilter defaultFilter) { - // - } - - @Override - public List<VFSItem> getItems() { - checkInitialization(); - return super.getItems(); - } - - @Override - public List<VFSItem> getItems(VFSItemFilter filter) { - checkInitialization(); - return super.getItems(filter); - } - - @Override - public VFSItem resolve(String path) { - checkInitialization(); - return super.resolve(path); - } - - private void checkInitialization() { - if(!init || (System.currentTimeMillis() - loadTime) > 60000) { - synchronized(this) { - if(!init || (System.currentTimeMillis() - loadTime) > 60000) { - init(); - } - } - } + super(identity); } @Override - protected void init() { + protected List<VFSContainer> loadMergedContainers() { RepositoryManager rm = RepositoryManager.getInstance(); - List<RepositoryEntry> courseEntries = rm.queryByEditor(identity, CourseModule.getCourseTypeName()); + List<RepositoryEntry> courseEntries = rm.queryByEditor(getIdentity(), CourseModule.getCourseTypeName()); List<VFSContainer> containers = new ArrayList<>(); // Add all found repo entries to merge source for (RepositoryEntry re:courseEntries) { @@ -120,8 +53,6 @@ class CoursefolderWebDAVMergeSource extends MergeSource { NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(courseTitle, re.getOlatResource()); addContainerToList(cfContainer, containers); } - setMergedContainers(containers); - loadTime = System.currentTimeMillis(); - init = true; + return containers; } } \ No newline at end of file diff --git a/src/main/java/org/olat/group/GroupfoldersWebDAVMergeSource.java b/src/main/java/org/olat/group/GroupfoldersWebDAVMergeSource.java index 7cc3ea59da0d71df77ea49fcdab2c84412a69c55..0c65a25fc13c5cd51ac6f4e405997ec9a42ad650 100644 --- a/src/main/java/org/olat/group/GroupfoldersWebDAVMergeSource.java +++ b/src/main/java/org/olat/group/GroupfoldersWebDAVMergeSource.java @@ -30,117 +30,53 @@ import org.olat.collaboration.CollaborationTools; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.commons.services.notifications.SubscriptionContext; +import org.olat.core.commons.services.webdav.manager.WebDAVMergeSource; import org.olat.core.commons.services.webdav.servlets.RequestUtil; import org.olat.core.id.Identity; -import org.olat.core.util.vfs.MergeSource; import org.olat.core.util.vfs.NamedContainerImpl; import org.olat.core.util.vfs.Quota; import org.olat.core.util.vfs.QuotaManager; -import org.olat.core.util.vfs.VFSConstants; import org.olat.core.util.vfs.VFSContainer; -import org.olat.core.util.vfs.VFSItem; -import org.olat.core.util.vfs.VFSStatus; import org.olat.core.util.vfs.callbacks.FullAccessWithQuotaCallback; import org.olat.core.util.vfs.callbacks.ReadOnlyCallback; import org.olat.core.util.vfs.callbacks.VFSSecurityCallback; -import org.olat.core.util.vfs.filters.VFSItemFilter; import org.olat.group.model.SearchBusinessGroupParams; /** * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ -class GroupfoldersWebDAVMergeSource extends MergeSource { +class GroupfoldersWebDAVMergeSource extends WebDAVMergeSource { - private boolean init = false; - private final Identity identity; private final CollaborationManager collaborationManager; - private long loadTime; - + public GroupfoldersWebDAVMergeSource(Identity identity, CollaborationManager collaborationManager) { - super(null, null); - this.identity = identity; + super(identity); this.collaborationManager = collaborationManager; } @Override - public VFSStatus canWrite() { - return VFSConstants.NO; - } - - @Override - public VFSStatus canDelete() { - return VFSConstants.NO; - } - - @Override - public VFSStatus canRename() { - return VFSConstants.NO; - } - - @Override - public VFSStatus canCopy() { - return VFSConstants.NO; - } - - @Override - public VFSStatus delete() { - return VFSConstants.NO; - } - - @Override - public List<VFSItem> getItems() { - checkInitialization(); - return super.getItems(); - } - - @Override - public List<VFSItem> getItems(VFSItemFilter filter) { - checkInitialization(); - return super.getItems(filter); - } - - @Override - public VFSItem resolve(String path) { - checkInitialization(); - return super.resolve(path); - } - - private void checkInitialization() { - if(!init || (System.currentTimeMillis() - loadTime) > 60000) { - synchronized(this) { - if(!init || (System.currentTimeMillis() - loadTime) > 60000) { - init(); - } - } - } - } - - @Override - protected void init() { - // collect buddy groups + protected List<VFSContainer> loadMergedContainers() { BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class); Set<Long> addedGroupKeys = new HashSet<Long>(); Set<String> addedGroupNames = new HashSet<String>(); List<VFSContainer> containers = new ArrayList<>(); - SearchBusinessGroupParams params = new SearchBusinessGroupParams(identity, true, false); + SearchBusinessGroupParams params = new SearchBusinessGroupParams(getIdentity(), true, false); params.addTools(CollaborationTools.TOOL_FOLDER); List<BusinessGroup> tutorGroups = bgs.findBusinessGroups(params, null, 0, -1); for (BusinessGroup group : tutorGroups) { addContainer(group, addedGroupKeys, addedGroupNames, containers, true); } - SearchBusinessGroupParams paramsParticipants = new SearchBusinessGroupParams(identity, false, true); + SearchBusinessGroupParams paramsParticipants = new SearchBusinessGroupParams(getIdentity(), false, true); paramsParticipants.addTools(CollaborationTools.TOOL_FOLDER); List<BusinessGroup> participantsGroups = bgs.findBusinessGroups(paramsParticipants, null, 0, -1); for (BusinessGroup group : participantsGroups) { addContainer(group, addedGroupKeys, addedGroupNames, containers, false); } - setMergedContainers(containers); - loadTime = System.currentTimeMillis(); - init = true; + return containers; } private void addContainer(BusinessGroup group, Set<Long> addedGroupKeys, Set<String> addedGroupNames, diff --git a/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVMergeSource.java b/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVMergeSource.java index f56262c9f1329786da542d3e4ef043cdfd186148..667310311b837c6084bfb4ff2ce04750678103e5 100644 --- a/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVMergeSource.java +++ b/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVMergeSource.java @@ -27,14 +27,12 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import org.olat.core.commons.services.webdav.manager.WebDAVMergeSource; import org.olat.core.id.Identity; import org.olat.core.id.Roles; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; -import org.olat.core.util.vfs.MergeSource; import org.olat.core.util.vfs.VFSContainer; -import org.olat.core.util.vfs.VFSItem; -import org.olat.core.util.vfs.filters.VFSItemFilter; import org.olat.fileresource.types.SharedFolderFileResource; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; @@ -45,56 +43,24 @@ import org.olat.repository.RepositoryManager; * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ -public class SharedFolderWebDAVMergeSource extends MergeSource { +public class SharedFolderWebDAVMergeSource extends WebDAVMergeSource { - private OLog log = Tracing.createLoggerFor(SharedFolderWebDAVMergeSource.class); + private static final OLog log = Tracing.createLoggerFor(SharedFolderWebDAVMergeSource.class); - private boolean init = false; - private long loadTime; - private final Identity identity; private final List<String> publiclyReadableFolders; public SharedFolderWebDAVMergeSource(Identity identity, List<String> publiclyReadableFolders) { - super(null, "root"); - this.identity = identity; + super(identity); this.publiclyReadableFolders = publiclyReadableFolders; } @Override - public List<VFSItem> getItems() { - checkInitialization(); - return super.getItems(); - } - - @Override - public List<VFSItem> getItems(VFSItemFilter filter) { - checkInitialization(); - return super.getItems(filter); - } - - @Override - public VFSItem resolve(String path) { - checkInitialization(); - return super.resolve(path); - } - - private void checkInitialization() { - if(!init || (System.currentTimeMillis() - loadTime) > 60000) { - synchronized(this) { - if(!init || (System.currentTimeMillis() - loadTime) > 60000) { - init(); - } - } - } - } - - @Override - protected void init() { + protected List<VFSContainer> loadMergedContainers() { SharedFolderManager sfm = SharedFolderManager.getInstance(); RepositoryManager repoManager = RepositoryManager.getInstance(); List<VFSContainer> containers = new ArrayList<>(); Set<Long> addedEntries = new HashSet<>(); - List<RepositoryEntry> ownerEntries = (List<RepositoryEntry>) repoManager.queryByOwner(identity, SharedFolderFileResource.TYPE_NAME); + List<RepositoryEntry> ownerEntries = (List<RepositoryEntry>) repoManager.queryByOwner(getIdentity(), SharedFolderFileResource.TYPE_NAME); for (RepositoryEntry entry : ownerEntries) { VFSContainer container = sfm.getNamedSharedFolder(entry, true); addContainerToList(container, containers); @@ -111,7 +77,7 @@ public class SharedFolderWebDAVMergeSource extends MergeSource { // fake role that represents normally logged in user Roles registeredUserRole = new Roles(false, false, false, false, false, false, false); List<String> types = Collections.singletonList(SharedFolderFileResource.TYPE_NAME); - List<RepositoryEntry> allEntries = repoManager.queryByTypeLimitAccess(identity, types, registeredUserRole); + List<RepositoryEntry> allEntries = repoManager.queryByTypeLimitAccess(getIdentity(), types, registeredUserRole); for (RepositoryEntry entry : allEntries) { addReadonlyFolder(entry, sfm, addedEntries, containers); } @@ -130,9 +96,7 @@ public class SharedFolderWebDAVMergeSource extends MergeSource { } } - setMergedContainers(containers); - loadTime = System.currentTimeMillis(); - init = true; + return containers; } private void addReadonlyFolder(RepositoryEntry entry, SharedFolderManager sfm, diff --git a/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java b/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java index 414e44d6979f57d39dd60929cc674d116019f38c..39d00bef97addbe8c04e028bdba4d6a70be9c694 100644 --- a/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java +++ b/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java @@ -42,6 +42,8 @@ import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpOptions; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.BasicCredentialsProvider; @@ -62,9 +64,9 @@ import org.apache.http.util.EntityUtils; */ public class WebDAVConnection implements Closeable { - private int port = WebDAVTestCase.PORT; - private String host = WebDAVTestCase.HOST; - private String protocol = WebDAVTestCase.PROTOCOL; + private final int port; + private final String host; + private final String protocol; private final BasicCookieStore cookieStore = new BasicCookieStore(); private final CredentialsProvider provider = new BasicCredentialsProvider(); @@ -72,9 +74,21 @@ public class WebDAVConnection implements Closeable { private final CloseableHttpClient httpclient; public WebDAVConnection() { + this(WebDAVTestCase.PROTOCOL, WebDAVTestCase.HOST, WebDAVTestCase.PORT); + } + + public WebDAVConnection(String protocol, String host, int port) { + this.protocol = protocol; + this.host = host; + this.port = port; + + SSLConnectionSocketFactory sslFactory + = new SSLConnectionSocketFactory(SSLContexts.createDefault(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + httpclient = HttpClientBuilder.create() .setDefaultCookieStore(cookieStore) .setDefaultCredentialsProvider(provider) + .setSSLSocketFactory(sslFactory) .build(); } diff --git a/src/test/java/org/olat/core/commons/services/webdav/WebDAVExternalTest.java b/src/test/java/org/olat/core/commons/services/webdav/WebDAVExternalTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3d58e120ed882dc7cdbd7e7660ecfc3a4a99754a --- /dev/null +++ b/src/test/java/org/olat/core/commons/services/webdav/WebDAVExternalTest.java @@ -0,0 +1,93 @@ +package org.olat.core.commons.services.webdav; + +import java.io.IOException; +import java.io.StringReader; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.util.EntityUtils; +import org.apache.poi.util.IOUtils; +import org.junit.Test; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * This is not a real Unit Test. I use it + * to debug some issues with a Java client + * on external servers. + * + * + * Initial date: 06.05.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class WebDAVExternalTest { + + @Test + public void test() + throws IOException, URISyntaxException { + + WebDAVConnection conn = new WebDAVConnection("http", "kivik.frentix.com", 443); + conn.setCredentials("kanu", "kanu01"); + + URI publicUri = conn.getBaseURI().path("webdav").path("coursefolders").path("Info").path("TP_learningmap").build(); + String response = conn.propfind(publicUri, 1); + + URI mapUri = conn.getBaseURI().path("webdav").path("coursefolders").path("Info").path("TP_learningmap").path("mapstyles.css").build(); + HttpGet getMap = conn.createGet(mapUri); + + HttpResponse mapResonse = conn.execute(getMap); + String map = EntityUtils.toString(mapResonse.getEntity()); + System.out.println(map); + + IOUtils.closeQuietly(conn); + parse(response); + } + + private void parse(String response) { + try { + SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); + InputSource in = new InputSource(new StringReader(response)); + saxParser.parse(in, new WebDAVHandler()); + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + } + + public static class WebDAVHandler extends DefaultHandler { + private StringBuilder sb; + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + if("D:href".equals(qName)) { + sb = new StringBuilder(); + } + } + + @Override + public void characters(char[] ch, int start, int length) + throws SAXException { + if(sb != null) { + sb.append(ch, start, length); + } + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException { + if(sb != null) { + System.out.println(sb.toString()); + sb = null; + } + } + } +} \ No newline at end of file