diff --git a/Java/androidfsstorage/README.md b/Java/android/androidfsstorage/README.md similarity index 100% rename from Java/androidfsstorage/README.md rename to Java/android/androidfsstorage/README.md diff --git a/Java/androidfsstorage/app/build.gradle b/Java/android/androidfsstorage/app/build.gradle similarity index 94% rename from Java/androidfsstorage/app/build.gradle rename to Java/android/androidfsstorage/app/build.gradle index 909a7f0..4b6dfaa 100644 --- a/Java/androidfsstorage/app/build.gradle +++ b/Java/android/androidfsstorage/app/build.gradle @@ -34,7 +34,7 @@ android { jarJar { rules = [ 'stax-api-1.0.1.jar' : 'javax.xml.** com.ithit.webdav.xml.@1', - 'webdav-server-6.2.9090-Beta.jar': 'javax.xml.stream.** com.ithit.webdav.xml.stream.@1' + 'webdav-server-6.3.9510-Beta.jar': 'javax.xml.stream.** com.ithit.webdav.xml.stream.@1' ] } @@ -75,11 +75,11 @@ dependencies { implementation 'commons-io:commons-io:2.7' implementation 'com.google.code.gson:gson:2.8.9' implementation 'com.android.support:appcompat-v7:27.1.1' - implementation('com.ithit.webdav.integration:android-integration:6.2.9090-Beta', { + implementation('com.ithit.webdav.integration:android-integration:6.3.9510-Beta', { exclude group: 'org.nanohttpd', module: 'nanohttpd' }) implementation 'com.android.support.constraint:constraint-layout:1.0.2' jarJar 'stax:stax-api:1.0.1' - jarJar 'com.ithit.webdav:webdav-server:6.2.9090-Beta' + jarJar 'com.ithit.webdav:webdav-server:6.3.9510-Beta' testImplementation 'junit:junit:4.12' } diff --git a/Java/androidfsstorage/app/libs/nanohttpd-2.3.1.jar b/Java/android/androidfsstorage/app/libs/nanohttpd-2.3.1.jar similarity index 100% rename from Java/androidfsstorage/app/libs/nanohttpd-2.3.1.jar rename to Java/android/androidfsstorage/app/libs/nanohttpd-2.3.1.jar diff --git a/Java/androidfsstorage/app/libs/stax-android-1.2.0.jar b/Java/android/androidfsstorage/app/libs/stax-android-1.2.0.jar similarity index 100% rename from Java/androidfsstorage/app/libs/stax-android-1.2.0.jar rename to Java/android/androidfsstorage/app/libs/stax-android-1.2.0.jar diff --git a/Java/androidfsstorage/app/lint.xml b/Java/android/androidfsstorage/app/lint.xml similarity index 100% rename from Java/androidfsstorage/app/lint.xml rename to Java/android/androidfsstorage/app/lint.xml diff --git a/Java/androidfsstorage/app/proguard-rules.pro b/Java/android/androidfsstorage/app/proguard-rules.pro similarity index 100% rename from Java/androidfsstorage/app/proguard-rules.pro rename to Java/android/androidfsstorage/app/proguard-rules.pro diff --git a/Java/androidfsstorage/app/src/main/AndroidManifest.xml b/Java/android/androidfsstorage/app/src/main/AndroidManifest.xml similarity index 100% rename from Java/androidfsstorage/app/src/main/AndroidManifest.xml rename to Java/android/androidfsstorage/app/src/main/AndroidManifest.xml diff --git a/Java/androidfsstorage/app/src/main/assets/MyCustomHandlerPage.html b/Java/android/androidfsstorage/app/src/main/assets/MyCustomHandlerPage.html similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/MyCustomHandlerPage.html rename to Java/android/androidfsstorage/app/src/main/assets/MyCustomHandlerPage.html diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Document.pages b/Java/android/androidfsstorage/app/src/main/assets/Storage/Document.pages similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Document.pages rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Document.pages diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/General.docx b/Java/android/androidfsstorage/app/src/main/assets/Storage/General.docx similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/General.docx rename to Java/android/androidfsstorage/app/src/main/assets/Storage/General.docx diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Introduction.pptx b/Java/android/androidfsstorage/app/src/main/assets/Storage/Introduction.pptx similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Introduction.pptx rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Introduction.pptx diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Library/Content.txt b/Java/android/androidfsstorage/app/src/main/assets/Storage/Library/Content.txt similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Library/Content.txt rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Library/Content.txt diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Library/General.doc b/Java/android/androidfsstorage/app/src/main/assets/Storage/Library/General.doc similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Library/General.doc rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Library/General.doc diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Library/Introduction.ppt b/Java/android/androidfsstorage/app/src/main/assets/Storage/Library/Introduction.ppt similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Library/Introduction.ppt rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Library/Introduction.ppt diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Library/Stat.xls b/Java/android/androidfsstorage/app/src/main/assets/Storage/Library/Stat.xls similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Library/Stat.xls rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Library/Stat.xls diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Library/Vision.mpp b/Java/android/androidfsstorage/app/src/main/assets/Storage/Library/Vision.mpp similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Library/Vision.mpp rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Library/Vision.mpp diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/My Directory/Notes.txt b/Java/android/androidfsstorage/app/src/main/assets/Storage/My Directory/Notes.txt similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/My Directory/Notes.txt rename to Java/android/androidfsstorage/app/src/main/assets/Storage/My Directory/Notes.txt diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Notes.txt b/Java/android/androidfsstorage/app/src/main/assets/Storage/Notes.txt similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Notes.txt rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Notes.txt diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Presentation.key b/Java/android/androidfsstorage/app/src/main/assets/Storage/Presentation.key similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Presentation.key rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Presentation.key diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Products/General.doc b/Java/android/androidfsstorage/app/src/main/assets/Storage/Products/General.doc similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Products/General.doc rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Products/General.doc diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Products/General.vsd b/Java/android/androidfsstorage/app/src/main/assets/Storage/Products/General.vsd similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Products/General.vsd rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Products/General.vsd diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Products/Product.mpp b/Java/android/androidfsstorage/app/src/main/assets/Storage/Products/Product.mpp similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Products/Product.mpp rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Products/Product.mpp diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Project.pdf b/Java/android/androidfsstorage/app/src/main/assets/Storage/Project.pdf similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Project.pdf rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Project.pdf diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Sales/Australia/Plan.doc b/Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Australia/Plan.doc similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Sales/Australia/Plan.doc rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Australia/Plan.doc diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Sales/Australia/Prices.xls b/Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Australia/Prices.xls similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Sales/Australia/Prices.xls rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Australia/Prices.xls diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Introduction.ppt b/Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Introduction.ppt similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Introduction.ppt rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Introduction.ppt diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Prices.xls b/Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Prices.xls similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Prices.xls rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Prices.xls diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Product.mpp b/Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Product.mpp similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Product.mpp rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Product.mpp diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Stat.xls b/Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Stat.xls similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Stat.xls rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Canada/Stat.xls diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Sales/Europe/Stat.xls b/Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Europe/Stat.xls similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Sales/Europe/Stat.xls rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/Europe/Stat.xls diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Sales/USA/Vision.mpp b/Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/USA/Vision.mpp similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Sales/USA/Vision.mpp rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Sales/USA/Vision.mpp diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Spreadsheet.numbers b/Java/android/androidfsstorage/app/src/main/assets/Storage/Spreadsheet.numbers similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Spreadsheet.numbers rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Spreadsheet.numbers diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Stat.xlsx b/Java/android/androidfsstorage/app/src/main/assets/Storage/Stat.xlsx similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Stat.xlsx rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Stat.xlsx diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Templates/readme.txt b/Java/android/androidfsstorage/app/src/main/assets/Storage/Templates/readme.txt similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Templates/readme.txt rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Templates/readme.txt diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.dotx b/Java/android/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.dotx similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.dotx rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.dotx diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.potx b/Java/android/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.potx similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.potx rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.potx diff --git a/Java/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.xltx b/Java/android/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.xltx similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.xltx rename to Java/android/androidfsstorage/app/src/main/assets/Storage/Templates/template2013.xltx diff --git a/Java/androidfsstorage/app/src/main/assets/attributesErrorPage.html b/Java/android/androidfsstorage/app/src/main/assets/attributesErrorPage.html similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/attributesErrorPage.html rename to Java/android/androidfsstorage/app/src/main/assets/attributesErrorPage.html diff --git a/Java/androidfsstorage/app/src/main/assets/webdavsettings.json b/Java/android/androidfsstorage/app/src/main/assets/webdavsettings.json similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/webdavsettings.json rename to Java/android/androidfsstorage/app/src/main/assets/webdavsettings.json diff --git a/Java/androidfsstorage/app/src/main/assets/wwwroot/AjaxFileBrowser.html b/Java/android/androidfsstorage/app/src/main/assets/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/wwwroot/AjaxFileBrowser.html rename to Java/android/androidfsstorage/app/src/main/assets/wwwroot/AjaxFileBrowser.html diff --git a/Java/androidfsstorage/app/src/main/assets/wwwroot/AjaxIntegrationTests.html b/Java/android/androidfsstorage/app/src/main/assets/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/wwwroot/AjaxIntegrationTests.html rename to Java/android/androidfsstorage/app/src/main/assets/wwwroot/AjaxIntegrationTests.html diff --git a/Java/androidfsstorage/app/src/main/assets/wwwroot/css/webdav-layout.css b/Java/android/androidfsstorage/app/src/main/assets/wwwroot/css/webdav-layout.css similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/wwwroot/css/webdav-layout.css rename to Java/android/androidfsstorage/app/src/main/assets/wwwroot/css/webdav-layout.css diff --git a/Java/androidfsstorage/app/src/main/assets/wwwroot/js/package.json b/Java/android/androidfsstorage/app/src/main/assets/wwwroot/js/package.json similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/wwwroot/js/package.json rename to Java/android/androidfsstorage/app/src/main/assets/wwwroot/js/package.json diff --git a/Java/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-gridview.js b/Java/android/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-gridview.js similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-gridview.js rename to Java/android/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-gridview.js diff --git a/Java/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-uploader.js b/Java/android/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-uploader.js similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-uploader.js rename to Java/android/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-uploader.js diff --git a/Java/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-websocket.js b/Java/android/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-websocket.js similarity index 100% rename from Java/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-websocket.js rename to Java/android/androidfsstorage/app/src/main/assets/wwwroot/js/webdav-websocket.js diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/AndroidNanoLogger.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/AndroidNanoLogger.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/AndroidNanoLogger.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/AndroidNanoLogger.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/AndroidWebDavServer.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/AndroidWebDavServer.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/AndroidWebDavServer.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/AndroidWebDavServer.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/Config.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/Config.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/Config.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/Config.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/CustomFolderGetHandler.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/CustomFolderGetHandler.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/CustomFolderGetHandler.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/CustomFolderGetHandler.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/FileImpl.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/FileImpl.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/FileImpl.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/FileImpl.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/FolderImpl.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/FolderImpl.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/FolderImpl.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/FolderImpl.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/HierarchyItemImpl.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/HierarchyItemImpl.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/HierarchyItemImpl.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/HierarchyItemImpl.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/SerializationUtils.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/SerializationUtils.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/SerializationUtils.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/SerializationUtils.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/WebDavEngine.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/WebDavEngine.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/WebDavEngine.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/WebDavEngine.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/AndroidConfigurationHelper.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/AndroidConfigurationHelper.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/AndroidConfigurationHelper.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/AndroidConfigurationHelper.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/DatabaseHandlerImpl.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/DatabaseHandlerImpl.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/DatabaseHandlerImpl.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/DatabaseHandlerImpl.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/IDatabaseHandler.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/IDatabaseHandler.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/IDatabaseHandler.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/IDatabaseHandler.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/MainActivity.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/MainActivity.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/MainActivity.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/MainActivity.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/NanoBroadcastReceiver.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/NanoBroadcastReceiver.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/NanoBroadcastReceiver.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/NanoBroadcastReceiver.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/NanoIntentService.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/NanoIntentService.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/NanoIntentService.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/android/NanoIntentService.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/AndroidExtendedAttribute.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/AndroidExtendedAttribute.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/AndroidExtendedAttribute.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/AndroidExtendedAttribute.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttribute.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttribute.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttribute.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttribute.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttributeFactory.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttributeFactory.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttributeFactory.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttributeFactory.java diff --git a/Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttributesExtension.java b/Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttributesExtension.java similarity index 100% rename from Java/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttributesExtension.java rename to Java/android/androidfsstorage/app/src/main/java/com/ithit/webdav/samples/androidfsstorage/extendedattributes/ExtendedAttributesExtension.java diff --git a/Java/androidfsstorage/app/src/main/res/drawable/icon.png b/Java/android/androidfsstorage/app/src/main/res/drawable/icon.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/drawable/icon.png rename to Java/android/androidfsstorage/app/src/main/res/drawable/icon.png diff --git a/Java/androidfsstorage/app/src/main/res/layout/main.xml b/Java/android/androidfsstorage/app/src/main/res/layout/main.xml similarity index 100% rename from Java/androidfsstorage/app/src/main/res/layout/main.xml rename to Java/android/androidfsstorage/app/src/main/res/layout/main.xml diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-hdpi/ic_launcher.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-hdpi/ic_launcher_round.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-hdpi/ic_launcher_round.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-hdpi/icon.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-hdpi/icon.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-hdpi/icon.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-hdpi/icon.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-mdpi/ic_launcher.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-mdpi/ic_launcher_round.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-mdpi/ic_launcher_round.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-mdpi/icon.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-mdpi/icon.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-mdpi/icon.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-mdpi/icon.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xhdpi/icon.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xhdpi/icon.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xhdpi/icon.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xhdpi/icon.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xxhdpi/icon.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xxhdpi/icon.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xxhdpi/icon.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xxhdpi/icon.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/Java/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/icon.png b/Java/android/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/icon.png similarity index 100% rename from Java/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/icon.png rename to Java/android/androidfsstorage/app/src/main/res/mipmap-xxxhdpi/icon.png diff --git a/Java/androidfsstorage/app/src/main/res/values/colors.xml b/Java/android/androidfsstorage/app/src/main/res/values/colors.xml similarity index 100% rename from Java/androidfsstorage/app/src/main/res/values/colors.xml rename to Java/android/androidfsstorage/app/src/main/res/values/colors.xml diff --git a/Java/androidfsstorage/app/src/main/res/values/strings.xml b/Java/android/androidfsstorage/app/src/main/res/values/strings.xml similarity index 100% rename from Java/androidfsstorage/app/src/main/res/values/strings.xml rename to Java/android/androidfsstorage/app/src/main/res/values/strings.xml diff --git a/Java/androidfsstorage/app/src/main/res/values/styles.xml b/Java/android/androidfsstorage/app/src/main/res/values/styles.xml similarity index 100% rename from Java/androidfsstorage/app/src/main/res/values/styles.xml rename to Java/android/androidfsstorage/app/src/main/res/values/styles.xml diff --git a/Java/androidfsstorage/build.gradle b/Java/android/androidfsstorage/build.gradle similarity index 100% rename from Java/androidfsstorage/build.gradle rename to Java/android/androidfsstorage/build.gradle diff --git a/Java/androidfsstorage/buildAndroid b/Java/android/androidfsstorage/buildAndroid similarity index 100% rename from Java/androidfsstorage/buildAndroid rename to Java/android/androidfsstorage/buildAndroid diff --git a/Java/androidfsstorage/buildAndroid.bat b/Java/android/androidfsstorage/buildAndroid.bat similarity index 100% rename from Java/androidfsstorage/buildAndroid.bat rename to Java/android/androidfsstorage/buildAndroid.bat diff --git a/Java/androidfsstorage/gradle.properties b/Java/android/androidfsstorage/gradle.properties similarity index 100% rename from Java/androidfsstorage/gradle.properties rename to Java/android/androidfsstorage/gradle.properties diff --git a/Java/androidfsstorage/gradle/wrapper/gradle-wrapper.jar b/Java/android/androidfsstorage/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from Java/androidfsstorage/gradle/wrapper/gradle-wrapper.jar rename to Java/android/androidfsstorage/gradle/wrapper/gradle-wrapper.jar diff --git a/Java/androidfsstorage/gradle/wrapper/gradle-wrapper.properties b/Java/android/androidfsstorage/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from Java/androidfsstorage/gradle/wrapper/gradle-wrapper.properties rename to Java/android/androidfsstorage/gradle/wrapper/gradle-wrapper.properties diff --git a/Java/androidfsstorage/gradlew b/Java/android/androidfsstorage/gradlew similarity index 100% rename from Java/androidfsstorage/gradlew rename to Java/android/androidfsstorage/gradlew diff --git a/Java/androidfsstorage/gradlew.bat b/Java/android/androidfsstorage/gradlew.bat similarity index 100% rename from Java/androidfsstorage/gradlew.bat rename to Java/android/androidfsstorage/gradlew.bat diff --git a/Java/androidfsstorage/settings.gradle b/Java/android/androidfsstorage/settings.gradle similarity index 100% rename from Java/androidfsstorage/settings.gradle rename to Java/android/androidfsstorage/settings.gradle diff --git a/Java/filesystemstorage/README.md b/Java/jakarta/filesystemstorage/README.md similarity index 100% rename from Java/filesystemstorage/README.md rename to Java/jakarta/filesystemstorage/README.md diff --git a/Java/jakarta/filesystemstorage/pom.xml b/Java/jakarta/filesystemstorage/pom.xml new file mode 100644 index 0000000..7875e21 --- /dev/null +++ b/Java/jakarta/filesystemstorage/pom.xml @@ -0,0 +1,255 @@ + + + 4.0.0 + + com.ithit.webdav.samples + filesystemstorage + 6.3.9510-Beta + war + + + UTF-8 + 17 + 17 + + + + + com.google.code.gson + gson + 2.8.9 + compile + + + jakarta.platform + jakarta.jakartaee-api + 10.0.0 + + + com.ithit.webdav.integration + jakarta-integration + 6.3.9510-Beta + + + commons-io + commons-io + 2.7 + compile + + + commons-lang + commons-lang + 2.6 + + + org.apache.lucene + lucene-core + 7.5.0 + + + org.apache.lucene + lucene-queryparser + 7.5.0 + + + org.apache.lucene + lucene-highlighter + 7.5.0 + + + org.apache.tika + tika-core + 1.28.5 + + + org.apache.tika + tika-parsers + 1.28.5 + + + cxf-core + org.apache.cxf + + + cxf-rt-rs-client + org.apache.cxf + + + httpservices + edu.ucar + + + maven-scm-provider-svnexe + org.apache.maven.scm + + + maven-scm-api + org.apache.maven.scm + + + slf4j-log4j12 + org.slf4j + + + c3p0 + c3p0 + + + httpclient + org.apache.httpcomponents + + + grib + edu.ucar + + + cdm + edu.ucar + + + unit-api + javax.measure + + + activation + javax.activation + + + org.apache.sis.storage + sis-netcdf + + + + + com.ithit.webdav + webdav-server + 6.3.9510-Beta + + + net.java.dev.jna + jna-platform + 5.13.0 + + + + + + nuxeo + https://maven.nuxeo.org/nexus/content/groups/public + + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.2.0 + + + + src/main/storageresources + WEB-INF + + **/pom.xml + + + + + + + maven-antrun-plugin + org.apache.maven.plugins + 1.8 + + + windows + none + + run + + + + + + + + + + + linux + none + + run + + + + + + + + + + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + filesystem + 11021 + / + target/filesystemstorage-jakarta-6.3.9510-Beta + + + + com.github.eirslett + frontend-maven-plugin + 1.12.1 + + + install node and npm + + install-node-and-npm + + + ${java.io.tmpdir} + v16.14.2 + 8.7.0 + + + + npm update + + npm + + generate-resources + + update + src/main/webapp/WEB-INF/wwwroot/js + C:\Users\build\AppData\Local\Temp\ + + + + npm install + + npm + + generate-resources + + install + src/main/webapp/WEB-INF/wwwroot/js + ${java.io.tmpdir} + + + + + \ + + + + + diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/CustomFolderGetHandler.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/CustomFolderGetHandler.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/CustomFolderGetHandler.java rename to Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/CustomFolderGetHandler.java diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FileImpl.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FileImpl.java new file mode 100644 index 0000000..769a179 --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FileImpl.java @@ -0,0 +1,419 @@ +package com.ithit.webdav.samples.fsstorageservlet; + +import com.ithit.webdav.samples.fsstorageservlet.extendedattributes.ExtendedAttributesExtension; +import com.ithit.webdav.server.*; +import com.ithit.webdav.server.exceptions.ConflictException; +import com.ithit.webdav.server.exceptions.LockedException; +import com.ithit.webdav.server.exceptions.MultistatusException; +import com.ithit.webdav.server.exceptions.ServerException; +import com.ithit.webdav.server.resumableupload.ResumableUpload; +import com.ithit.webdav.server.resumableupload.UploadProgress; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * Represents file in the File System repository. + */ +final class FileImpl extends HierarchyItemImpl implements File, Lock, + ResumableUpload, UploadProgress { + + private static final int BUFFER_SIZE = 1048576; // 1 Mb + + private String snippet; + + private final OpenOption[] allowedOpenFileOptions; + + /** + * Initializes a new instance of the {@link FileImpl} class. + * + * @param name Name of hierarchy item. + * @param path Relative to WebDAV root folder path. + * @param created Creation time of the hierarchy item. + * @param modified Modification time of the hierarchy item. + * @param engine Instance of current {@link WebDavEngine}. + */ + private FileImpl(String name, String path, long created, long modified, WebDavEngine engine) { + super(name, path, created, modified, engine); + + /* Mac OS X and Ubuntu doesn't work with ExtendedOpenOption.NOSHARE_DELETE */ + String systemName = System.getProperty("os.name").toLowerCase(); + this.allowedOpenFileOptions = (systemName.contains("mac") || systemName.contains("linux")) ? + (new OpenOption[]{StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.READ}) : + (new OpenOption[]{StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.READ, + noShareDeleteOption()}); + } + + /** + * Load ExtendedOpenOption with reflection without direct reference - because most of Linux/MacOS jdks don't have it and not required. + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private OpenOption noShareDeleteOption() { + try { + Class enumClass = Class.forName("com.sun.nio.file.ExtendedOpenOption"); + return (OpenOption) Enum.valueOf(enumClass, "NOSHARE_DELETE"); + } catch (ClassNotFoundException e) { + return StandardOpenOption.READ; + } + } + + /** + * Returns file that corresponds to path. + * + * @param path Encoded path relative to WebDAV root. + * @param engine Instance of {@link WebDavEngine} + * @return File instance or null if physical file not found in file system. + * @throws ServerException in case of exception + */ + static FileImpl getFile(String path, WebDavEngine engine) throws ServerException { + BasicFileAttributes view = null; + Path fullPath; + String name = null; + try { + String pathFragment = decodeAndConvertToPath(path); + String rootFolder = getRootFolder(); + fullPath = Paths.get(rootFolder, pathFragment); + if (Files.exists(fullPath)) { + name = Paths.get(pathFragment).getFileName().toString(); + view = Files.getFileAttributeView(fullPath, BasicFileAttributeView.class).readAttributes(); + } + if (view == null) { + return null; + } + } catch (IOException e) { + throw new ServerException(); + } + long created = view.creationTime().toMillis(); + long modified = view.lastModifiedTime().toMillis(); + return new FileImpl(name, path, created, modified, engine); + } + + /** + * Array of items that are being uploaded to this item subtree. + * + * @return Return array with a single item if implemented on file items. Return all items that are being uploaded to this subtree if implemented on folder items. + * @throws ServerException - in case of an error. + */ + @Override + public List getUploadProgress() + throws ServerException { + return Collections.singletonList(this); + } + + /** + * In this method implementation you can delete partially uploaded file. + *

+ * Client do not plan to restore upload. Remove any temporary files / cleanup resources here. + * + * @throws LockedException - this item or its parent was locked and client did not provide lock token. + * @throws ServerException - in case of an error. + */ + @Override + public void cancelUpload() throws LockedException, ServerException { + ensureHasToken(); + } + + /** + * Amount of bytes successfully saved to your storage. + * + * @return Amount of bytes successfully saved. + * @throws ServerException in case of an error. + */ + @Override + public long getBytesUploaded() throws ServerException { + return getContentLength(); + } + + /** + * Indicates if item will be checked-in by the engine when last chunk of a file is uploaded + * if item was checked in when upload started. + * + * @return True if item will be checked in when upload finishes. + * @throws ServerException in case of an error. + */ + @Override + public boolean getCheckInOnFileComplete() throws ServerException { + return false; + } + + /** + * Shall store value which indicates whether file will be checked in when upload finishes. + * + * @param value True if item will be checked in when upload finishes. + * @throws ServerException in case of an error. + */ + @Override + public void setCheckInOnFileComplete(boolean value) throws ServerException { + throw new ServerException("Not implemented"); + } + + /** + * The date and time when the last chunk of file was saved in your storage. + * + * @return Time when last chunk of file was saved. + * @throws ServerException in case of an error. + */ + @Override + public long getLastChunkSaved() throws ServerException { + return getModified(); + } + + /** + * Total file size that is being uploaded. + * + * @return Total file size in bytes. + * @throws ServerException in case of an error. + */ + @Override + public long getTotalContentLength() throws ServerException { + return getContentLength(); + } + + /** + * Gets the size of the file content in bytes. + * + * @return Length of the file content in bytes. + * @throws ServerException In case of an error. + */ + @Override + public long getContentLength() throws ServerException { + Path fullPath = getFullPath(); + long size = 0; + if (Files.exists(fullPath)) { + try { + size = Files.size(fullPath); + } catch (IOException e) { + throw new ServerException(e); + } + } + return size; + } + + /** + * Gets the media type of the {@link FileImpl}. + * + * @return MIME type of the file. + * @throws ServerException In case of an error. + */ + @Override + public String getContentType() throws ServerException { + String name = this.getName(); + int periodIndex = name.lastIndexOf('.'); + String ext = name.substring(periodIndex + 1); + String contentType = MimeType.getInstance().getMimeType(ext); + if (contentType == null) + contentType = "application/octet-stream"; + return contentType; + } + + @Override + public String getEtag() throws ServerException { + return String.format("%s-%s", Long.hashCode(getModified()), getSerialNumber()); + } + + /** + * Writes the content of the file to the specified stream. + * + * @param out Output stream. + * @param startIndex Zero-based byte offset in file content at which to begin copying bytes to the output stream. + * @param count Number of bytes to be written to the output stream. + * @throws ServerException In case of an error. + */ + // <<<< readFileImpl + @Override + public void read(OutputStream out, long startIndex, long count) throws ServerException { + Path fullPath = this.getFullPath(); + byte[] buf = new byte[BUFFER_SIZE]; + int retVal; + try (InputStream in = Files.newInputStream(fullPath)) { + in.skip(startIndex); + while ((retVal = in.read(buf)) > 0) { + // Strict servlet API doesn't allow to write more bytes then content length. So we do this trick. + if (retVal > count) { + retVal = (int) count; + } + out.write(buf, 0, retVal); + startIndex += retVal; + count -= retVal; + } + } catch (IOException x) { + throw new ServerException(x); + } + } + // readFileImpl >>>> + + /** + * Saves the content of the file from the specified stream to the File System repository. + * + * @param content {@link InputStream} to read the content of the file from. + * @param contentType Indicates media type of the file. + * @param startIndex Index in file to which corresponds first byte in {@code content}. + * @param totalFileLength Total size of the file being uploaded. -1 if size is unknown. + * @return Number of bytes written. + * @throws LockedException File was locked and client did not provide lock token. + * @throws ServerException In case of an error. + * @throws IOException I/O error. + */ + // <<<< writeFileImpl + @Override + public long write(InputStream content, String contentType, long startIndex, long totalFileLength) + throws LockedException, ServerException, IOException { + ensureHasToken(); + SeekableByteChannel writer = Files.newByteChannel(getFullPath(), this.allowedOpenFileOptions); + if (startIndex == 0) { + // If we override the file we must set position to 0 because writer could be at not 0 position. + writer = writer.truncate(0); + } else { + // We must set to start position in case of resume upload. + writer.position(startIndex); + } + incrementSerialNumber(); + byte[] inputBuffer = new byte[BUFFER_SIZE]; + long totalWrittenBytes = startIndex; + int readBytes; + try { + while ((readBytes = content.read(inputBuffer)) > -1) { + ByteBuffer byteBuffer; + byteBuffer = ByteBuffer.wrap(inputBuffer, 0, readBytes); + writer.write(byteBuffer); + totalWrittenBytes += readBytes; + } + + try { + getEngine().getSearchFacade().getIndexer().indexFile(getName(), decode(getPath()), null, this); + } catch (Exception ex){ + getEngine().getLogger().logError("Errors during indexing.", ex); + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + writer.close(); + } + getEngine().getWebSocketServer().notifyUpdated(getPath(), getWebSocketID()); + return totalWrittenBytes; + } + // writeFileImpl >>>> + + private void incrementSerialNumber() { + try { + Property serialNumber = Property.create("", "SerialNumber", "1"); + String sn = getSerialNumber(); + if (!Objects.equals(sn, "0")) { + serialNumber.setValue(String.valueOf((Integer.parseInt(sn) + 1))); + } + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), "SerialNumber", SerializationUtils.serialize(Collections.singletonList(serialNumber))); + } catch (Exception ex) { + getEngine().getLogger().logError("Cannot update serial number.", ex); + } + } + + private String getSerialNumber() throws ServerException { + String serialJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), "SerialNumber"); + List properties = SerializationUtils.deserializeList(Property.class, serialJson); + if (properties.size() == 1) { + return properties.get(0).getXmlValueRaw(); + } + return "0"; + } + + + @Override + public void delete() throws LockedException, MultistatusException, ServerException { + ensureHasToken(); + try { + Files.delete(getFullPath()); + } catch (IOException e) { + getEngine().getLogger().logError("Tried to delete file in use.", e); + throw new ServerException(e); + } + getEngine().getWebSocketServer().notifyDeleted(getPath(), getWebSocketID()); + try { + getEngine().getSearchFacade().getIndexer().deleteIndex(this); + } catch (Exception ex) { + getEngine().getLogger().logError("Errors during indexing.", ex); + } + } + + @Override + public void copyTo(Folder folder, String destName, boolean deep) + throws LockedException, MultistatusException, ServerException, ConflictException { + ((FolderImpl) folder).ensureHasToken(); + String destinationFolder = Paths.get(getRootFolder(), HierarchyItemImpl.decodeAndConvertToPath(folder.getPath())).toString(); + if (!Files.exists(Paths.get(destinationFolder))) { + throw new ConflictException(); + } + Path newPath = Paths.get(destinationFolder, destName); + try { + Files.copy(getFullPath(), newPath); + } catch (IOException e) { + throw new ServerException(e); + } + // Locks should not be copied, delete them + if (ExtendedAttributesExtension.hasExtendedAttribute(newPath.toString(), activeLocksAttribute)) { + ExtendedAttributesExtension.deleteExtendedAttribute(newPath.toString(), activeLocksAttribute); + } + try { + String currentPath = folder.getPath() + encode(destName); + getEngine().getWebSocketServer().notifyCreated(currentPath, getWebSocketID()); + getEngine().getSearchFacade().getIndexer().indexFile(decode(destName), decode(currentPath), null, this); + } catch (Exception ex) { + getEngine().getLogger().logError("Errors during indexing.", ex); + } + } + + @Override + public void moveTo(Folder folder, String destName) throws LockedException, + ConflictException, MultistatusException, ServerException { + ensureHasToken(); + ((FolderImpl) folder).ensureHasToken(); + String destinationFolder = Paths.get(getRootFolder(), HierarchyItemImpl.decodeAndConvertToPath(folder.getPath())).toString(); + if (!Files.exists(Paths.get(destinationFolder))) { + throw new ConflictException(); + } + Path newPath = Paths.get(destinationFolder, destName); + try { + Files.move(getFullPath(), newPath, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new ServerException(e); + } + setName(destName); + // Locks should not be copied, delete them + if (ExtendedAttributesExtension.hasExtendedAttribute(newPath.toString(), activeLocksAttribute)) { + ExtendedAttributesExtension.deleteExtendedAttribute(newPath.toString(), activeLocksAttribute); + } + try { + String currentPath = folder.getPath() + encode(destName); + getEngine().getWebSocketServer().notifyMoved(getPath(), currentPath, getWebSocketID()); + getEngine().getSearchFacade().getIndexer().indexFile(decode(destName), decode(currentPath), getPath(), this); + } catch (Exception ex) { + getEngine().getLogger().logError("Errors during indexing.", ex); + } + } + + /** + * Returns snippet of file content that matches search conditions. + * + * @return Snippet of file content that matches search conditions. + */ + String getSnippet() { + return snippet; + } + + /** + * Sets snippet of file content that matches search conditions. + * + * @param snippet Snippet of file content that matches search conditions. + */ + void setSnippet(String snippet) { + this.snippet = snippet; + } +} diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FolderImpl.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FolderImpl.java new file mode 100644 index 0000000..8011c8e --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FolderImpl.java @@ -0,0 +1,409 @@ +package com.ithit.webdav.samples.fsstorageservlet; + +import com.ithit.webdav.server.File; +import com.ithit.webdav.server.Folder; +import com.ithit.webdav.server.HierarchyItem; +import com.ithit.webdav.server.Property; +import com.ithit.webdav.server.exceptions.*; +import com.ithit.webdav.server.paging.OrderProperty; +import com.ithit.webdav.server.paging.PageResults; +import com.ithit.webdav.server.quota.Quota; +import com.ithit.webdav.server.resumableupload.ResumableUploadBase; +import com.ithit.webdav.server.search.Search; +import com.ithit.webdav.server.search.SearchOptions; +import org.apache.commons.io.FileUtils; + +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +/** + * Represents a folder in the File system repository. + */ +final class FolderImpl extends HierarchyItemImpl implements Folder, Search, Quota, ResumableUploadBase { + + + /** + * Initializes a new instance of the {@link FolderImpl} class. + * + * @param name Name of hierarchy item. + * @param path Relative to WebDAV root folder path. + * @param created Creation time of the hierarchy item. + * @param modified Modification time of the hierarchy item. + * @param engine Instance of current {@link WebDavEngine} + */ + private FolderImpl(String name, String path, long created, long modified, + WebDavEngine engine) { + super(name, path, created, modified, engine); + } + + /** + * Returns folder that corresponds to path. + * + * @param path Encoded path relative to WebDAV root. + * @param engine Instance of {@link WebDavEngine} + * @return Folder instance or null if physical folder not found in file system. + * @throws ServerException in case of exception + */ + static FolderImpl getFolder(String path, WebDavEngine engine) throws ServerException { + BasicFileAttributes view = null; + Path fullPath; + String name = null; + try { + boolean root = path.equals("/"); + String pathFragment = decodeAndConvertToPath(path); + String rootFolder = getRootFolder(); + fullPath = root ? Paths.get(rootFolder) : Paths.get(rootFolder, pathFragment); + if (Files.exists(fullPath)) { + name = root ? "ROOT" : Paths.get(pathFragment).getFileName().toString(); + view = Files.getFileAttributeView(fullPath, BasicFileAttributeView.class).readAttributes(); + } + if (view == null || !view.isDirectory()) { + return null; + } + } catch (IOException e) { + throw new ServerException(); + } + + long created = view.creationTime().toMillis(); + long modified = view.lastModifiedTime().toMillis(); + return new FolderImpl(name, fixPath(path), created, modified, engine); + } + + private static String fixPath(String path) { + if (!Objects.equals(path.substring(path.length() - 1), "/")) { + path += "/"; + } + return path; + } + + /** + * Creates new {@link FileImpl} file with the specified name in this folder. + * + * @param name Name of the file to create. + * @return Reference to created {@link File}. + * @throws LockedException This folder was locked. Client did not provide the lock token. + * @throws ServerException In case of an error. + */ + // <<<< createFileImpl + @Override + public FileImpl createFile(String name) throws LockedException, ServerException { + ensureHasToken(); + + Path fullPath = Paths.get(this.getFullPath().toString(), name); + if (!Files.exists(fullPath)) { + try { + Files.createFile(fullPath); + } catch (IOException e) { + throw new ServerException(e); + } + final String itemPath = getPath() + encode(name); + getEngine().getWebSocketServer().notifyCreated(itemPath, getWebSocketID()); + return FileImpl.getFile(itemPath, getEngine()); + } + return null; + } + // createFileImpl >>>> + + /** + * Creates new {@link FolderImpl} folder with the specified name in this folder. + * + * @param name Name of the folder to create. + * @return Instance of newly created Folder. + * @throws LockedException This folder was locked. Client did not provide the lock token. + * @throws ServerException In case of an error. + */ + // <<<< createFolderImpl + @Override + public Folder createFolder(String name) throws LockedException, + ServerException { + createFolderInternal(name); + + getEngine().getWebSocketServer().notifyCreated(getPath() + encode(name), getWebSocketID()); + return FolderImpl.getFolder(getPath() + encode(name), getEngine()); + } + + private void createFolderInternal(String name) throws LockedException, + ServerException { + ensureHasToken(); + + Path fullPath = Paths.get(this.getFullPath().toString(), name); + if (!Files.exists(fullPath)) { + try { + Files.createDirectory(fullPath); + } catch (IOException e) { + throw new ServerException(e); + } + } + } + // createFolderImpl >>>> + + /** + * Gets the array of this folder's children. + * + * @param propNames List of properties to retrieve with the children. They will be queried by the engine later. + * @param offset The number of items to skip before returning the remaining items. + * @param nResults The number of items to return. + * @param orderProps List of order properties requested by the client. + * @return Instance of {@link PageResults} class that contains items on a requested page and total number of items in a folder. + * @throws ServerException In case of an error. + */ + // <<<< getChildren + @Override + public PageResults getChildren(List propNames, Long offset, Long nResults, List orderProps) throws ServerException { + String decodedPath = HierarchyItemImpl.decodeAndConvertToPath(getPath()); + Path fullFolderPath = Paths.get(getRootFolder() + decodedPath); + List children = new ArrayList<>(); + Long total = null; + try (DirectoryStream ds = Files.newDirectoryStream(fullFolderPath)) { + List paths = StreamSupport.stream(ds.spliterator(), false).collect(Collectors.toList()); + paths = sortChildren(paths, orderProps); + for (Path p : paths) { + String childPath = getPath() + encode(p.getFileName().toString()); + HierarchyItemImpl item = (HierarchyItemImpl) getEngine().getHierarchyItem(childPath); + children.add(item); + } + total = (long) paths.size(); + if (offset != null && nResults != null) + { + children = children.stream().skip(offset).limit(nResults).collect(Collectors.toList()); + } + } catch (IOException e) { + getEngine().getLogger().logError(e.getMessage(), e); + } + return new PageResults(children, total); + } + // getChildren >>>> + + // <<<< deleteFolderImpl + @Override + public void delete() throws LockedException, MultistatusException, + ServerException { + ensureHasToken(); + try { + removeIndex(getFullPath(), this); + FileUtils.deleteDirectory(getFullPath().toFile()); + } catch (IOException e) { + throw new ServerException(e); + } + getEngine().getWebSocketServer().notifyDeleted(getPath(), getWebSocketID()); + } + // deleteFolderImpl >>>> + + // <<<< copyToFolderImpl + @Override + public void copyTo(Folder folder, String destName, boolean deep) + throws LockedException, MultistatusException, ServerException { + ((FolderImpl) folder).ensureHasToken(); + + String relUrl = HierarchyItemImpl.decodeAndConvertToPath(folder.getPath()); + String destinationFolder = Paths.get(getRootFolder(), relUrl).toString(); + if (isRecursive(relUrl)) { + throw new ServerException("Cannot copy to subfolder", WebDavStatus.FORBIDDEN); + } + if (!Files.exists(Paths.get(destinationFolder))) + throw new ServerException(); + try { + Path sourcePath = this.getFullPath(); + Path destinationFullPath = Paths.get(destinationFolder, destName); + FileUtils.copyDirectory(sourcePath.toFile(), destinationFullPath.toFile()); + addIndex(destinationFullPath, folder.getPath() + destName, destName); + } catch (IOException e) { + throw new ServerException(e); + } + setName(destName); + getEngine().getWebSocketServer().notifyCreated(folder.getPath() + encode(destName), getWebSocketID()); + } + // copyToFolderImpl >>>> + + /** + * Check whether current folder is the parent to the destination. + * + * @param destFolder Path to the destination folder. + * @return True if current folder is parent for the destination, false otherwise. + * @throws ServerException in case of any server exception. + */ + private boolean isRecursive(String destFolder) throws ServerException { + return destFolder.startsWith(getPath().replace("/", java.io.File.separator)); + } + + /** + * Sorts array of FileSystemInfo according to the specified order. + * @param paths Array of files and folders to sort. + * @param orderProps Sorting order. + * @return Sorted list of files and folders. + */ + private List sortChildren(List paths, List orderProps) { + if (orderProps != null && !orderProps.isEmpty()) { + int index = 0; + Comparator comparator = null; + for (OrderProperty orderProperty : + orderProps) { + Comparator tempComp = null; + if ("is-directory".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> item.toFile().isDirectory(); + tempComp = Comparator.comparing(sortFunc); + } + if ("quota-used-bytes".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> item.toFile().length(); + tempComp = Comparator.comparing(sortFunc); + } + if ("getlastmodified".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> item.toFile().lastModified(); + tempComp = Comparator.comparing(sortFunc); + } + if ("displayname".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> item.getFileName().toString(); + tempComp = Comparator.comparing(sortFunc); + } + if ("getcontenttype".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> getExtension(item.getFileName().toString()); + tempComp = Comparator.comparing(sortFunc); + } + if (tempComp != null) { + if (index++ == 0) { + if (orderProperty.isAscending()) { + comparator = tempComp; + } else { + comparator = tempComp.reversed(); + } + } else { + if (orderProperty.isAscending()) { + comparator = comparator != null ? comparator.thenComparing(tempComp) : tempComp; + } else { + comparator = comparator != null ? comparator.thenComparing(tempComp.reversed()) : tempComp.reversed(); + } + } + } + } + if (comparator != null) { + paths = paths.stream().sorted(comparator).collect(Collectors.toList()); + } + } + return paths; + } + + private String getExtension(String name) { + int periodIndex = name.lastIndexOf('.'); + return periodIndex == -1 ? "" : name.substring(periodIndex + 1); + + } + + // <<<< moveToFolderImpl + @Override + public void moveTo(Folder folder, String destName) throws LockedException, + ConflictException, MultistatusException, ServerException { + ensureHasToken(); + ((FolderImpl) folder).ensureHasToken(); + String destinationFolder = Paths.get(getRootFolder(), HierarchyItemImpl.decodeAndConvertToPath(folder.getPath())).toString(); + if (!Files.exists(Paths.get(destinationFolder))) + throw new ConflictException(); + Path sourcePath = this.getFullPath(); + Path destinationFullPath = Paths.get(destinationFolder, destName); + try { + removeIndex(getFullPath(), this); + Files.move(sourcePath, destinationFullPath, StandardCopyOption.REPLACE_EXISTING); + addIndex(destinationFullPath, folder.getPath() + destName, destName); + } catch (IOException e) { + throw new ServerException(e); + } + setName(destName); + getEngine().getWebSocketServer().notifyMoved(getPath(), folder.getPath() + encode(destName), getWebSocketID()); + } + // moveToFolderImpl >>>> + + /** + * Returns list of items that correspond to search request. + * + * @param searchString A phrase to search. + * @param options Search parameters. + * @param propNames List of properties to retrieve with the children. They will be queried by the engine later. + * @param offset The number of items to skip before returning the remaining items. + * @param nResults The number of items to return. + * @return Instance of {@link PageResults} class that contains items on a requested page and total number of items in search results. + */ + // <<<< searchImpl + @Override + public PageResults search(String searchString, SearchOptions options, List propNames, Long offset, Long nResults) { + List results = new LinkedList<>(); + SearchFacade.Searcher searcher = getEngine().getSearchFacade().getSearcher(); + if (searcher == null) { + return new PageResults(results, (long) 0); + } + boolean snippet = propNames.stream().anyMatch(x -> SNIPPET.equalsIgnoreCase(x.getName())); + Map searchResult; + try { + String decodedPath = decode(getPath()); + searchResult = searcher.search(searchString, options, decodedPath, snippet); + for (Map.Entry entry : searchResult.entrySet()) { + try { + HierarchyItem item = getEngine().getHierarchyItem(entry.getKey()); + if (item != null) { + if (snippet && item instanceof FileImpl) { + ((FileImpl) item).setSnippet(entry.getValue()); + } + results.add(item); + } + } catch (Exception ex) { + getEngine().getLogger().logError("Error during search.", ex); + } + } + } catch (ServerException e) { + getEngine().getLogger().logError("Error during search.", e); + } + return new PageResults((offset != null && nResults != null) ? results.stream().skip(offset).limit(nResults).collect(Collectors.toList()) : results, (long) results.size()); + } + // searchImpl >>>> + + /** + * Returns free bytes available to current user. + * + * @return Returns free bytes available to current user. + */ + @Override + public long getAvailableBytes() { + return getFullPath().toFile().getFreeSpace(); + } + + /** + * Returns used bytes by current user. + * + * @return Returns used bytes by current user. + */ + @Override + public long getUsedBytes() { + long total = getFullPath().toFile().getTotalSpace(); + return total - getAvailableBytes(); + } + + private void removeIndex(Path sourcePath, FolderImpl itSelf) { + List filesToDelete = new ArrayList<>(); + getEngine().getSearchFacade().getFilesToIndex(sourcePath.toFile().listFiles(), filesToDelete, WebDavServlet.getRootLocalPath()); + filesToDelete.add(itSelf); + for (HierarchyItem hi : filesToDelete) { + try { + getEngine().getSearchFacade().getIndexer().deleteIndex(hi); + } catch (Exception e) { + getEngine().getLogger().logError("Cannot delete index.", e); + } + } + } + + private void addIndex(Path sourcePath, String path, String name) { + List filesToIndex = new ArrayList<>(); + getEngine().getSearchFacade().getFilesToIndex(sourcePath.toFile().listFiles(), filesToIndex, WebDavServlet.getRootLocalPath()); + getEngine().getSearchFacade().getIndexer().indexFile(name, decode(path), null, null); + for (HierarchyItem hi : filesToIndex) { + try { + getEngine().getSearchFacade().getIndexer().indexFile(hi.getName(), decode(hi.getPath()), null, hi); + } catch (Exception e) { + getEngine().getLogger().logError("Cannot index.", e); + } + } + } +} diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/HierarchyItemImpl.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/HierarchyItemImpl.java new file mode 100644 index 0000000..e65c4dd --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/HierarchyItemImpl.java @@ -0,0 +1,527 @@ +package com.ithit.webdav.samples.fsstorageservlet; + +import com.ithit.webdav.samples.fsstorageservlet.extendedattributes.ExtendedAttributesExtension; +import com.ithit.webdav.samples.fsstorageservlet.websocket.WebSocketServer; +import com.ithit.webdav.server.*; +import com.ithit.webdav.server.exceptions.*; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.FileTime; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Base class for WebDAV items (folders, files, etc). + */ +abstract class HierarchyItemImpl implements HierarchyItem, Lock { + + static final String SNIPPET = "snippet"; + private final String path; + private final long created; + private final long modified; + private final WebDavEngine engine; + private String name; + String activeLocksAttribute = "Locks"; + private static final String PROPERTIES_ATTRIBUTE = "Properties"; + private List properties; + private List activeLocks; + + /** + * Initializes a new instance of the {@link HierarchyItemImpl} class. + * + * @param name name of hierarchy item + * @param path Relative to WebDAV root folder path. + * @param created creation time of the hierarchy item + * @param modified modification time of the hierarchy item + * @param engine instance of current {@link WebDavEngine} + */ + HierarchyItemImpl(String name, String path, long created, long modified, WebDavEngine engine) { + this.name = name; + this.path = path; + this.created = created; + this.modified = modified; + this.engine = engine; + } + + /** + * Decodes URL and converts it to proper path string. + * + * @param url URL to decode. + * @return Path. + */ + static String decodeAndConvertToPath(String url) { + String path = decode(url); + return path.replace("/", File.separator); + } + + /** + * Decodes url. + * + * @param url url to decode. + * @return Path. + */ + static String decode(String url) { + try { + return URLDecoder.decode(url.replace("+", "%2B"), "UTF-8"); + } catch (UnsupportedEncodingException e) { + return URLDecoder.decode(url.replace("+", "%2B")); + } + } + + /** + * Encodes string to safe characters. + * + * @param val String to encode. + * @return Encoded string. + */ + String encode(String val) { + try { + return URLEncoder.encode(val, "UTF-8").replace("+", "%20"); + } catch (UnsupportedEncodingException e) { + return URLEncoder.encode(val).replace("+", "%20"); + } + } + + /** + * Returns path to the folder in File System which will be the root for the WebDav storage. + * + * @return Path to the folder in File System which will be the root for the WebDav storage. + */ + static String getRootFolder() { + return WebDavServlet.getRootLocalPath(); + } + + /** + * Creates a copy of this item with a new name in the destination folder. + * + * @param folder Destination folder. + * @param destName Name of the destination item. + * @param deep Indicates whether to copy entire subtree. + * @throws LockedException - the destination item was locked and client did not provide lock token. + * @throws ConflictException - destination folder does not exist. + * @throws MultistatusException - errors has occurred during processing of the subtree. + * Every item that has been either successfully copied or failed to copy must be present in exception with corresponding status. + * @throws ServerException - In case of other error. + */ + public abstract void copyTo(Folder folder, String destName, boolean deep) + throws LockedException, MultistatusException, ServerException, ConflictException; + + /** + * Moves this item to the destination folder under a new name. + * + * @param folder Destination folder. + * @param destName Name of the destination item. + * @throws LockedException - the source or the destination item was locked and client did not provide lock token. + * @throws ConflictException - destination folder does not exist. + * @throws MultistatusException - errors has occurred during processing of the subtree. Every processed item must have corresponding response added + * with corresponding status. + * @throws ServerException - in case of another error. + */ + public abstract void moveTo(Folder folder, String destName) + throws LockedException, ConflictException, MultistatusException, ServerException; + + /** + * Deletes this item. + * + * @throws LockedException - this item or its parent was locked and client did not provide lock token. + * @throws MultistatusException - errors has occurred during processing of the subtree. Every processed item must have corresponding response added + * to the exception with corresponding status. + * @throws ServerException - in case of another error. + */ + @Override + public abstract void delete() throws LockedException, MultistatusException, + ServerException; + + /** + * Gets the creation date of the item in repository expressed as the coordinated universal time (UTC). + * + * @return Creation date of the item. + * @throws ServerException In case of an error. + */ + @Override + public long getCreated() throws ServerException { + return created; + } + + /** + * Gets the last modification date of the item in repository expressed as the coordinated universal time (UTC). + * + * @return Modification date of the item. + * @throws ServerException In case of an error. + */ + @Override + public long getModified() throws ServerException { + return modified; + } + + /** + * Parses string to Date. + * + * @param inputDate Date in string. + * @return Date instance in UTC. + * @throws ParseException is cannot parse the Date. + */ + private Date parseDateFrom(String inputDate) throws ParseException { + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); + Date date; + date = format.parse(inputDate); + return date; + } + + /** + * Gets the name of the item in repository. + * + * @return Name of this item. + * @throws ServerException In case of an error. + */ + @Override + public String getName() throws ServerException { + return name; + } + + /** + * Set {@link HierarchyItemImpl} name. + * + * @param name {@link HierarchyItemImpl} name. + */ + void setName(String name) { + this.name = name; + } + + /** + * Unique item path in the repository relative to storage root. + * + * @return Item path relative to storage root. + * @throws ServerException In case of an error. + */ + @Override + public String getPath() throws ServerException { + return path; + } + + /** + * Gets values of all properties or selected properties for this item. + * + * @return List of properties with values set. If property cannot be found it shall be omitted from the result. + * @throws ServerException In case of an error. + */ + // <<<< getPropertiesImpl + @Override + public List getProperties(Property[] props) throws ServerException { + List l = getPropertyNames(); + List result; + if (props == null) { + return l; + } + Set propNames = Arrays.stream(props).map(Property::getName).collect(Collectors.toSet()); + result = l.stream().filter(x -> propNames.contains(x.getName())).collect(Collectors.toList()); + Property snippet = Arrays.stream(props).filter(x -> propNames.contains(SNIPPET)).findFirst().orElse(null); + if (snippet != null && this instanceof FileImpl) { + result.add(Property.create(snippet.getNamespace(), snippet.getName(), ((FileImpl) this).getSnippet())); + } + return result; + } + // getPropertiesImpl >>>> + + + private List getProperties() throws ServerException { + if (properties == null) { + String propertiesJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE); + properties = SerializationUtils.deserializeList(Property.class, propertiesJson); + } + return properties; + } + + /** + * Gets names of all properties for this item. + * + * @return List of all property names for this item. + * @throws ServerException In case of an error. + */ + // <<<< getPropertyNamesImpl + @Override + public List getPropertyNames() throws ServerException { + if (ExtendedAttributesExtension.hasExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE)) { + String propJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE); + return SerializationUtils.deserializeList(Property.class, propJson); + } + return new LinkedList<>(); + } + // getPropertyNamesImpl >>>> + + /** + * Check whether client is the lock owner. + * + * @throws LockedException in case if not owner. + * @throws ServerException other errors. + */ + void ensureHasToken() throws LockedException, ServerException { + if (!clientHasToken()) + throw new LockedException(); + } + + /** + * Check whether client is the lock owner. + * + * @return True if owner, false otherwise. + * @throws ServerException in case of errors. + */ + private boolean clientHasToken() throws ServerException { + getActiveLocks(); + if (activeLocks.isEmpty()) { + return true; + } + List clientLockTokens = DavContext.currentRequest().getClientLockTokens(); + return activeLocks.stream().anyMatch(x -> clientLockTokens.contains(x.getToken())); + } + + /** + * Modifies and removes properties for this item. + * + * @param setProps Array of properties to be set. + * @param delProps Array of properties to be removed. {@link Property#value} field is ignored. + * Specifying the removal of a property that does not exist is not an error. + * @throws LockedException this item was locked and client did not provide lock token. + * @throws MultistatusException If update fails for a property, this exception shall be thrown and contain + * result of the operation for each property. + * @throws ServerException In case of other error. + */ + // <<<< updatePropertiesImpl + @Override + public void updateProperties(Property[] setProps, Property[] delProps) + throws LockedException, MultistatusException, ServerException { + ensureHasToken(); + for (final Property prop : setProps) { + String basicAttributeNS = "urn:schemas-microsoft-com:"; + // Microsoft Mini-redirector may update file creation date, modification date and access time passing properties: + // Thu, 28 Mar 2013 20:15:34 GMT + // Thu, 28 Mar 2013 20:36:24 GMT + // Thu, 28 Mar 2013 20:36:24 GMT + // In this case update creation and modified date in your storage or do not save this properties at all, otherwise + // Windows Explorer will display creation and modification date from this props and it will differ from the values + // in the Created and Modified fields in your storage + // String basicAttributeNS = "urn:schemas-microsoft-com:"; + if (prop.getNamespace().equals(basicAttributeNS)) { + updateBasicProperties(prop.getXmlValueRaw(), prop.getName()); + } else { + properties = getProperties(); + Property existingProp = properties.stream().filter(x -> x.getName().equals(prop.getName())).findFirst().orElse(null); + if (existingProp != null) { + existingProp.setXmlValueRaw(prop.getXmlValueRaw()); + } else { + properties.add(prop); + } + } + } + properties = getProperties(); + Set propNamesToDel = Arrays.stream(delProps).map(Property::getName).collect(Collectors.toSet()); + properties = properties.stream() + .filter(e -> !propNamesToDel.contains(e.getName())) + .collect(Collectors.toList()); + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE, SerializationUtils.serialize(properties)); + getEngine().getWebSocketServer().notifyUpdated(getPath(), getWebSocketID()); + } + // updatePropertiesImpl >>>> + + /** + * Updates basic file times in the following format - Thu, 28 Mar 2013 20:15:34 GMT. + * + * @param date Date to update + * @param field Field to update + */ + private void updateBasicProperties(String date, String field) { + BasicFileAttributeView attributes = Files.getFileAttributeView(getFullPath(), BasicFileAttributeView.class); + try { + String propertyCreatedName = "Win32CreationTime"; + String propertyModifiedName = "Win32LastModifiedTime"; + String propertyAccessedName = "Win32LastAccessTime"; + if (field.equals(propertyCreatedName) || field.equals(propertyModifiedName) || field.equals(propertyAccessedName)) { + FileTime time = date == null ? null : FileTime.fromMillis(parseDateFrom(date).getTime()); + if (field.equals(propertyModifiedName)) { + attributes.setTimes(time, null, null); + } + if (field.equals(propertyAccessedName)) { + attributes.setTimes(null, time, null); + } + if (field.equals(propertyCreatedName)) { + // For some reason Windows Explorer caches created time so for some period of time it may return wrong creation time + attributes.setTimes(null, null, time); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Returns File System engine. + * + * @return File System engine. + */ + WebDavEngine getEngine() { + return engine; + } + + /** + * Returns full path in the File System to the {@link HierarchyItemImpl}. + * + * @return Full path in the File System to the {@link HierarchyItemImpl}. + */ + Path getFullPath() { + String fullPath = ""; + try { + fullPath = getRootFolder() + HierarchyItemImpl.decodeAndConvertToPath(getPath()); + } catch (ServerException ignored) { + } + return Paths.get(fullPath); + } + + /** + * Locks this item. + * + * @param shared Indicates whether a lock is shared or exclusive. + * @param deep Indicates whether a lock is enforceable on the subtree. + * @param timeout Lock expiration time in seconds. Negative value means never. + * @param owner Provides information about the principal taking out a lock. + * @return Actually applied lock (Server may modify timeout). + * @throws LockedException The item is locked, so the method has been rejected. + * @throws MultistatusException Errors have occurred during processing of the subtree. + * @throws ServerException In case of an error. + */ + // <<<< lockImpl + @Override + public LockResult lock(boolean shared, boolean deep, long timeout, String owner) + throws LockedException, MultistatusException, ServerException { + if (hasLock(shared)) { + throw new LockedException(); + } + String token = UUID.randomUUID().toString(); + if (timeout < 0 || timeout == Long.MAX_VALUE) { + // If timeout is absent or infinity timeout requested, + // grant 5 minute lock. + timeout = 300; + } + long expires = System.currentTimeMillis() + timeout * 1000; + LockInfo lockInfo = new LockInfo(shared, deep, token, expires, owner); + activeLocks.add(lockInfo); + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), activeLocksAttribute, SerializationUtils.serialize(activeLocks)); + getEngine().getWebSocketServer().notifyLocked(getPath(), getWebSocketID()); + return new LockResult(token, timeout); + } + // lockImpl >>>> + + /** + * Checks whether {@link HierarchyItemImpl} has a lock and whether it is shared. + * + * @param skipShared Indicates whether to skip shared. + * @return True if item has lock and skipShared is true, false otherwise. + * @throws ServerException in case of errors. + */ + private boolean hasLock(boolean skipShared) throws ServerException { + getActiveLocks(); + return !activeLocks.isEmpty() && !(skipShared && activeLocks.get(0).isShared()); + } + + /** + * Gets the array of all locks for this item. + * + * @return Array of locks. + * @throws ServerException In case of an error. + */ + // <<<< getActiveLocksImpl + @Override + public List getActiveLocks() throws ServerException { + if (activeLocks == null) { + String activeLocksJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), activeLocksAttribute); + activeLocks = new ArrayList<>(SerializationUtils.deserializeList(LockInfo.class, activeLocksJson)); + } else { + activeLocks = new LinkedList<>(); + } + return activeLocks.stream() + .filter(x -> System.currentTimeMillis() < x.getTimeout()) + .map(lock -> new LockInfo( + lock.isShared(), + lock.isDeep(), + lock.getToken(), + (lock.getTimeout() < 0 || lock.getTimeout() == Long.MAX_VALUE) ? lock.getTimeout() : (lock.getTimeout() - System.currentTimeMillis()) / 1000, + lock.getOwner())) + .collect(Collectors.toList()); + } + // getActiveLocksImpl >>>> + + /** + * Removes lock with the specified token from this item. + * + * @param lockToken Lock with this token should be removed from the item. + * @throws PreconditionFailedException Included lock token was not enforceable on this item. + * @throws ServerException In case of an error. + */ + // <<<< unlockImpl + @Override + public void unlock(String lockToken) throws PreconditionFailedException, + ServerException { + getActiveLocks(); + LockInfo lock = activeLocks.stream().filter(x -> x.getToken().equals(lockToken)).findFirst().orElse(null); + if (lock != null) { + activeLocks.remove(lock); + if (!activeLocks.isEmpty()) { + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), activeLocksAttribute, SerializationUtils.serialize(activeLocks)); + } else { + ExtendedAttributesExtension.deleteExtendedAttribute(getFullPath().toString(), activeLocksAttribute); + } + getEngine().getWebSocketServer().notifyUnlocked(getPath(), getWebSocketID()); + } else { + throw new PreconditionFailedException(); + } + } + // unlockImpl >>>> + + /** + * Updates lock timeout information on this item. + * + * @param token The lock token associated with a lock. + * @param timeout Lock expiration time in seconds. Negative value means never. + * @return Actually applied lock (Server may modify timeout). + * @throws PreconditionFailedException Included lock token was not enforceable on this item. + * @throws ServerException In case of an error. + */ + // <<<< refreshLockImpl + @Override + public RefreshLockResult refreshLock(String token, long timeout) + throws PreconditionFailedException, ServerException { + getActiveLocks(); + LockInfo lockInfo = activeLocks.stream().filter(x -> x.getToken().equals(token)).findFirst().orElse(null); + if (lockInfo == null) { + throw new PreconditionFailedException(); + } + if (timeout < 0 || timeout == Long.MAX_VALUE) { + // If timeout is absent or infinity timeout requested, + // grant 5 minute lock. + timeout = 300; + } + long expires = System.currentTimeMillis() + timeout * 1000; + lockInfo.setTimeout(expires); + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), activeLocksAttribute, SerializationUtils.serialize(activeLocks)); + getEngine().getWebSocketServer().notifyLocked(getPath(), getWebSocketID()); + return new RefreshLockResult(lockInfo.isShared(), lockInfo.isDeep(), + timeout, lockInfo.getOwner()); + } + // refreshLockImpl >>>> + + /** + * Returns instance ID from header + * @return InstanceId + */ + protected String getWebSocketID() { + return DavContext.currentRequest().getHeader(WebSocketServer.INSTANCE_HEADER_NAME); + } +} diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SearchFacade.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SearchFacade.java new file mode 100644 index 0000000..057ee7c --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SearchFacade.java @@ -0,0 +1,476 @@ +package com.ithit.webdav.samples.fsstorageservlet; + +import com.ithit.webdav.server.HierarchyItem; +import com.ithit.webdav.server.Logger; +import com.ithit.webdav.server.search.SearchOptions; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.standard.StandardAnalyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.StringField; +import org.apache.lucene.document.TextField; +import org.apache.lucene.index.*; +import org.apache.lucene.queryparser.classic.ParseException; +import org.apache.lucene.queryparser.classic.QueryParser; +import org.apache.lucene.search.*; +import org.apache.lucene.search.highlight.*; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.FSDirectory; +import org.apache.tika.Tika; +import org.apache.tika.exception.ZeroByteFileException; +import org.apache.tika.io.TikaInputStream; +import org.apache.tika.metadata.Metadata; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.RecursiveAction; +import java.util.regex.Pattern; + +import static com.ithit.webdav.samples.fsstorageservlet.SearchFacade.Indexer.MAX_CONTENT_LENGTH; + +/** + * Facade that incapsulates all functionality regarding indexing and searching + */ +class SearchFacade { + protected static final StandardAnalyzer ANALYZER = new StandardAnalyzer(); + private Indexer indexer; + private Searcher searcher; + private final WebDavEngine engine; + private final Logger logger; + + SearchFacade(WebDavEngine webDavEngine, Logger logger) { + engine = webDavEngine; + this.logger = logger; + } + + /** + * Returns Indexer instance + * + * @return Indexer instance + */ + Indexer getIndexer() { + return indexer; + } + + /** + * Returns Searcher instance + * + * @return Searcher instance + */ + Searcher getSearcher() { + return searcher; + } + + /** + * This task is running in background and indexes all folder mapped for WebDav asynchronously. + * So there uis a chance that in case of big folder there will be some delay while this task + * will finish indexation. + */ + private class IndexTask extends TimerTask { + + private final String dataFolder; + private final String indexFolder; + private final Integer interval; + + /** + * Build initial index of root folder. + * + * @param dataFolder Root folder. + * @param indexFolder Index folder. + * @param interval Daemon commit interval. + */ + IndexTask(String dataFolder, String indexFolder, Integer interval) { + this.dataFolder = dataFolder; + this.indexFolder = indexFolder; + this.interval = interval; + } + + /** + * The action to be performed by this timer task. + */ + @Override + public void run() { + ForkJoinPool forkJoinPool = new ForkJoinPool(4); + Directory fsDir; + try { + List filesToIndex = new ArrayList<>(); + File data = new File(dataFolder); + searcher = new Searcher(indexFolder, ANALYZER, logger); + getFilesToIndex(data.listFiles(), filesToIndex, dataFolder); + fsDir = FSDirectory.open(Paths.get(indexFolder)); + IndexWriterConfig conf = new IndexWriterConfig(ANALYZER); + conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); + IndexWriter indexWriter = new IndexWriter(fsDir, conf); + Tika tika = new Tika(); + tika.setMaxStringLength(MAX_CONTENT_LENGTH); + indexer = new Indexer(indexWriter, filesToIndex, logger, tika, dataFolder); + forkJoinPool.execute(indexer); + indexWriter.commit(); + new Indexer.CommitTask(indexWriter, logger).schedule(interval); + } catch (Throwable e) { + logger.logError("Cannot initialize Lucene", e); + } + } + + void schedule() { + Timer timer = new Timer(true); + timer.schedule(this, 0); + } + } + + /** + * Build initial index of root folder. + * + * @param dataFolder Root folder. + * @param indexFolder Index folder. + * @param interval Daemon commit interval. + */ + void indexRootFolder(String dataFolder, String indexFolder, Integer interval) { + new IndexTask(dataFolder, indexFolder, interval).schedule(); + } + + /** + * Builds list of the all files (including files in child folders) in the data folder. + * + * @param files List of files in root folder. + * @param result List to be populated with results. + * @param dataFolder Root folder absolute location. + */ + void getFilesToIndex(File[] files, List result, String dataFolder) { + for (File f : files) { + if (f.isDirectory() && f.canRead() && !f.isHidden()) { + addFileToTheList(result, dataFolder, f); + getFilesToIndex(f.listFiles(), result, dataFolder); + } else { + if (f.canRead() && !f.isHidden()) { + addFileToTheList(result, dataFolder, f); + } + } + } + } + + private void addFileToTheList(List result, String dataFolder, File f) { + String quote = Pattern.quote(dataFolder); + try { + String context = f.getAbsolutePath().replaceAll("(?i)" + quote, ""); + context = context.replace("\\", "/"); + if (f.isDirectory()) { + context += "/"; + } + result.add(engine.getHierarchyItem(context)); + } catch (Throwable e) { + logger.logDebug("Cannot add file to the list: " + f.getAbsolutePath()); + } + } + + + /** + * Indexes files in storage using Apache Lucene engine for indexing and Apache Tika. + */ + static class Indexer extends RecursiveAction { + static final int MAX_CONTENT_LENGTH = 10 * 1024 * 1024; + private static final int TASK_INTERVAL = 30 * 1000; + static final String PATH = "path"; + static final String NAME = "name"; + static final String PARENT_NAME = "parent_name"; + static final String CONTENTS = "contents"; + private final IndexWriter indexWriter; + private final List files; + private final Logger logger; + private final Tika tika; + private final String dataRoot; + private static final int BATCH_SIZE = 100; + + /** + * Create instance of Indexer file. + * + * @param iw {@link IndexWriter} Lucene index writer. + * @param files List of the file to index. + * @param logger {@link Logger}. + * @param tika {@link Tika} to read content. + * @param dataRoot Files location root folder. + */ + private Indexer(IndexWriter iw, List files, Logger logger, Tika tika, String dataRoot) { + this.indexWriter = iw; + this.files = files; + this.logger = logger; + this.tika = tika; + this.dataRoot = dataRoot; + } + + @Override + protected void compute() { + if (files.size() > BATCH_SIZE) { + List tasks = new ArrayList<>(); + List> partitioned = chopped(files, BATCH_SIZE); + for (List sublist : partitioned) { + tasks.add(new Indexer(indexWriter, sublist, logger, tika, dataRoot)); + } + invokeAll(tasks); + } else { + for (HierarchyItem f : files) { + try { + indexFile(f.getName(), f.getPath(), null, f); + } catch (Throwable e) { + logger.logDebug("Cannot find path for this file."); + } + } + } + } + + private static List> chopped(List list, final int l) { + List> parts = new ArrayList<>(); + final int n = list.size(); + for (int i = 0; i < n; i += l) { + parts.add(new ArrayList<>( + list.subList(i, Math.min(n, i + l))) + ); + } + return parts; + } + + /** + * Indexes file. + * + * @param fileName File name to add to index. + * @param currentPath Current relative path of the file. + * @param oldPath Old relative path of the file if it was moved. + */ + void indexFile(String fileName, String currentPath, String oldPath, HierarchyItem item) { + Path fullPath = Paths.get(dataRoot, currentPath); + try { + Metadata metadata = new Metadata(); + Document doc = new Document(); + String parentFolder = currentPath.replace(fileName, "").replace("/", ""); + Field pathField = new StringField(PATH, currentPath, Field.Store.YES); + Field parentField = new TextField(PARENT_NAME, parentFolder, Field.Store.YES); + Field nameField = new TextField(NAME, fileName, Field.Store.YES); + doc.add(pathField); + doc.add(parentField); + doc.add(nameField); + if (item instanceof FileImpl) { + try (TikaInputStream stream = TikaInputStream.get(fullPath, metadata)) { + String content = tika.parseToString(stream, metadata, MAX_CONTENT_LENGTH); + doc.add(new TextField(CONTENTS, content, Field.Store.YES)); + } catch (Throwable e) { + if (!(e instanceof ZeroByteFileException)) { + logger.logError("Error while indexing content: " + fullPath, e); + } + } + } + if (indexWriter.getConfig().getOpenMode() == IndexWriterConfig.OpenMode.CREATE) { + indexWriter.addDocument(doc); + } else { + indexWriter.updateDocument(new Term(PATH, oldPath != null ? oldPath : currentPath), doc); + } + } catch (Throwable e) { + logger.logError("Error while indexing file: " + fullPath, e); + } + } + + /** + * Close index and release lock + */ + void stop() { + try { + indexWriter.close(); + } catch (Throwable e) { + logger.logError("Cannot release index resources", e); + } + } + + /** + * Deletes specified file information from the index. + * + * @param file {@link FileImpl} to delete from index. + */ + void deleteIndex(HierarchyItem file) { + try { + indexWriter.deleteDocuments(new Term(PATH, file.getPath())); + } catch (Throwable e) { + logger.logError("Cannot delete index for the file.", e); + } + } + + /** + * Timer task implementation to commit index changes from time to time. + */ + static class CommitTask extends TimerTask { + + private final IndexWriter indexWriter; + private final Logger logger; + + /** + * Creates instance of {@link CommitTask}. + * + * @param indexWriter {@link IndexWriter} Lucene index writer. + * @param logger {@link Logger}. + */ + CommitTask(IndexWriter indexWriter, Logger logger) { + this.indexWriter = indexWriter; + this.logger = logger; + } + + /** + * The action to be performed by this timer task. + */ + @Override + public void run() { + try { + indexWriter.commit(); + } catch (Throwable e) { + logger.logError("Cannot commit.", e); + } + } + + /** + * Schedule timer executions at the specified Interval. + * + * @param interval Timer interval. + */ + void schedule(Integer interval) { + Timer timer = new Timer(true); + timer.scheduleAtFixedRate(this, 0, interval == null ? TASK_INTERVAL : interval * 1000); + } + } + } + + /** + * Search files information in Lucene index. + */ + static class Searcher { + + private final String indexFolder; + private final QueryParser nameParser; + private final QueryParser contentParser; + private final QueryParser parentParser; + private final Logger logger; + private IndexSearcher indexSearcher; + + /** + * Creates instance of {@link Searcher}. + * + * @param indexFolder Index folder absolute location. + * @param standardAnalyzer Lucene {@link StandardAnalyzer}. + * @param logger {@link Logger}. + */ + private Searcher(String indexFolder, StandardAnalyzer standardAnalyzer, Logger logger) { + this.indexFolder = indexFolder; + nameParser = new QueryParser(Indexer.NAME, standardAnalyzer); + nameParser.setAllowLeadingWildcard(true); + contentParser = new QueryParser(Indexer.CONTENTS, standardAnalyzer); + contentParser.setAllowLeadingWildcard(true); + parentParser = new QueryParser(Indexer.PARENT_NAME, standardAnalyzer); + parentParser.setAllowLeadingWildcard(true); + this.logger = logger; + } + + /** + * Searches files by search line either in file name or in content. + *

+ * Ajax File Browser accepts regular wild cards used in most OS: + *

+ * ‘*’ – to indicate one or more character. + * ‘?’ – to indicate exactly one character. + * The ‘*’ and ‘?’ characters are replaced with ‘%’ and ‘_’ characters to comply with DASL standard when submitted to the server. + *

+ * If ‘%’, ‘_’ or ‘\’ characters are used in search phrase they are escaped with ‘\%’, ‘\_’ and ‘\\’. + *

+ * To make the search behave similarly to how file system search functions Ajax File Browser + * will automatically add ‘%’ character at the end of the search phrase. To search for the exact match wrap the search phrase in double quotes: “my file”. + * + * @param searchLine Line to search. + * @param options {@link SearchOptions} indicates where to search. + * @param parent Folder location in which to search. + * @return Map of paths to found items. + */ + Map search(String searchLine, SearchOptions options, String parent, boolean snippet) { + searchLine = StringEscapeUtils.escapeJava(searchLine); + searchLine = searchLine.replace("%", "*"); + searchLine = searchLine.replace("_", "?"); + Map paths = new LinkedHashMap<>(); + try (IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexFolder)))) { + indexSearcher = new IndexSearcher(reader); + if (options.isSearchContent()) { + paths.putAll(searchContent(searchLine, parent, snippet, reader)); + } + if (options.isSearchName()) { + paths.putAll(searchName(searchLine, parent)); + } + } catch (Throwable e) { + logger.logError("Error while doing index search.", e); + } + return paths; + } + + // Searches files by search line in file name + private Map searchName(String searchLine, String parent) throws Exception { + Query query = nameParser.parse(searchLine); + BooleanQuery.Builder finalQuery = addParentQuery(parent, query); + return search(finalQuery.build()); + } + + // Searches files by search line in file content + private Map searchContent(String searchLine, String parent, boolean withSnippet, IndexReader indexReader) throws Exception { + Query query = contentParser.parse(searchLine); + BooleanQuery.Builder finalQuery = addParentQuery(parent, query); + BooleanQuery booleanQuery = finalQuery.build(); + if (withSnippet) { + return searchWithSnippet(indexReader, booleanQuery); + } + return search(booleanQuery); + } + + // Searches files by search line in file name and adds highlights for found words + private Map searchWithSnippet(IndexReader indexReader, Query query) throws Exception { + QueryScorer queryScorer = new QueryScorer(query, Indexer.CONTENTS); + Fragmenter fragmenter = new SimpleSpanFragmenter(queryScorer); + SimpleHTMLFormatter htmlFormatter = new SimpleHTMLFormatter(); + Highlighter highlighter = new Highlighter(htmlFormatter, queryScorer); + highlighter.setTextFragmenter(fragmenter); + + ScoreDoc[] scoreDocs = indexSearcher.search(query, 100).scoreDocs; + Map result = new LinkedHashMap<>(); + for (ScoreDoc scoreDoc : scoreDocs) { + Document document = indexSearcher.doc(scoreDoc.doc); + String text = document.get(Indexer.CONTENTS); + String path = document.get(Indexer.PATH); + TokenStream tokenStream = TokenSources.getAnyTokenStream(indexReader, + scoreDoc.doc, Indexer.CONTENTS, document, ANALYZER); + String fragment = highlighter.getBestFragment(tokenStream, text); + result.put(path, fragment == null ? "" : fragment); + } + return result; + } + + // Adds parent folder to the query to make search only in this folder + private BooleanQuery.Builder addParentQuery(String parent, Query query) throws ParseException { + BooleanQuery.Builder finalQuery = new BooleanQuery.Builder(); + finalQuery.add(query, BooleanClause.Occur.MUST); // MUST implies that the keyword must occur. + String searchString = parent.replace("/", "") + "*"; + if (!Objects.equals(parent, "/")) { + Query parentQuery = parentParser.parse(searchString); + finalQuery.add(parentQuery, BooleanClause.Occur.MUST); + } + return finalQuery; + } + + // Searches files by search query either in file name or in content. + private Map search(Query query) throws IOException { + TopDocs search = indexSearcher.search(query, 100); + ScoreDoc[] hits = search.scoreDocs; + Map paths = new LinkedHashMap<>(); + for (ScoreDoc hit : hits) { + Document doc = indexSearcher.doc(hit.doc); + String path = doc.get(Indexer.PATH); + paths.put(path, ""); + } + return paths; + } + } +} \ No newline at end of file diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SerializationUtils.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SerializationUtils.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SerializationUtils.java rename to Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SerializationUtils.java diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavEngine.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavEngine.java new file mode 100644 index 0000000..8d19013 --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavEngine.java @@ -0,0 +1,113 @@ +package com.ithit.webdav.samples.fsstorageservlet; + +import com.ithit.webdav.samples.fsstorageservlet.websocket.WebSocketServer; +import com.ithit.webdav.server.Engine; +import com.ithit.webdav.server.HierarchyItem; +import com.ithit.webdav.server.Logger; +import com.ithit.webdav.server.exceptions.ServerException; + +import java.util.Set; + +/** + * Implementation if {@link Engine}. + * Resolves hierarchy items by paths. + */ +public class WebDavEngine extends Engine { + + private final Logger logger; + private final String license; + private final Set maskRequestHeaders; + private SearchFacade searchFacade; + + /** + * Initializes a new instance of the WebDavEngine class. + * + * @param logger Where to log messages. + * @param license License string. + */ + WebDavEngine(Logger logger, String license, Set maskRequestHeaders) { + this.logger = logger; + this.license = license; + this.maskRequestHeaders = maskRequestHeaders; + } + + /** + * Creates {@link HierarchyItem} instance by path. + * + * @param contextPath Item relative path including query string. + * @return Instance of corresponding {@link HierarchyItem} or null if item is not found. + * @throws ServerException in case if engine cannot read file attributes. + */ + // <<<< getHierarchyItemEngine + @Override + public HierarchyItem getHierarchyItem(String contextPath) throws ServerException { + int i = contextPath.indexOf('?'); + if (i >= 0) { + contextPath = contextPath.substring(0, i); + } + HierarchyItemImpl item; + item = FolderImpl.getFolder(contextPath, this); + if (item != null) { + return item; + } + item = FileImpl.getFile(contextPath, this); + if (item != null) { + return item; + } + getLogger().logDebug("Could not find item that corresponds to path: " + contextPath); + return null; // no hierarchy item corresponds to path parameter was found in the repository + } + // getHierarchyItemEngine >>>> + + /** + * Returns logger that will be used by engine. + * + * @return Instance of {@link Logger}. + */ + @Override + public Logger getLogger() { + return logger; + } + + /** + * Returns license string. + * + * @return license string. + */ + @Override + public String getLicense() { + return license; + } + + @Override + public Set getMaskRequestHeaders() { + return maskRequestHeaders; + } + + /** + * Returns web socket server instance + * + * @return web socket server instance + */ + WebSocketServer getWebSocketServer() { + return WebSocketServer.getInstance(); + } + + /** + * Returns SearchFacade instance + * + * @return SearchFacade instance + */ + SearchFacade getSearchFacade() { + return searchFacade; + } + + /** + * Sets SearchFacade instance + * + * @param searchFacade SearchFacade instance + */ + void setSearchFacade(SearchFacade searchFacade) { + this.searchFacade = searchFacade; + } +} diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavServlet.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavServlet.java new file mode 100644 index 0000000..14c3db2 --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavServlet.java @@ -0,0 +1,210 @@ +package com.ithit.webdav.samples.fsstorageservlet; + +import com.ithit.webdav.integration.servlet.HttpServletDavRequest; +import com.ithit.webdav.integration.servlet.HttpServletDavResponse; +import com.ithit.webdav.integration.servlet.HttpServletLoggerImpl; +import com.ithit.webdav.samples.fsstorageservlet.extendedattributes.ExtendedAttributesExtension; +import com.ithit.webdav.server.Engine; +import com.ithit.webdav.server.Logger; +import com.ithit.webdav.server.exceptions.DavException; +import com.ithit.webdav.server.exceptions.WebDavStatus; +import com.ithit.webdav.server.util.StringUtil; +import org.apache.commons.io.FileUtils; + +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * This servlet processes WEBDAV requests. + */ +public class WebDavServlet extends HttpServlet { + + private static final long serialVersionUID = 4668224632937178086L; + private static final String DEFAULT_ROOT_PATH = "WEB-INF/Storage"; + private static final String DEFAULT_INDEX_PATH = "WEB-INF/Index"; + private static String realPath; + private static String servletContext; + private static String rootLocalPath; + private static boolean supportsUserDefinedAttributes; + private Logger logger; + private boolean showExceptions; + private SearchFacade searchFacade; + private String license; + static final String START_TIME = "" + System.currentTimeMillis(); + private Set localMaskRequestHeaders; + + /** + * Returns root folder for the WebDav. + * + * @return Root folder. + */ + static String getRootLocalPath() { + return rootLocalPath; + } + + /** + * Return path of servlet location in file system to load resources. + * + * @return Real path. + */ + static String getRealPath() { + return realPath; + } + + /** + * Returns servlet URL context path. + * + * @return Context path. + */ + static String getContext() { + return servletContext; + } + + /** + * Returns whether file system registered for the root folder supports User Defined Attributes. + * + * @return True if file system registered for root folder support User Defined Attributes, + * false otherwise. + */ + static boolean isSupportsUserDefinedAttributes() { + return supportsUserDefinedAttributes; + } + + /** + * Servlet initialization logic. Reads license file here. Creates instance of {@link com.ithit.webdav.server.Engine}. + * + * @param servletConfig Config. + * @throws ServletException if license file not found. + */ + @Override + public void init(ServletConfig servletConfig) throws ServletException { + super.init(servletConfig); + + String licenseFile = servletConfig.getInitParameter("license"); + showExceptions = Boolean.parseBoolean(servletConfig.getInitParameter("showExceptions")); + try { + license = FileUtils.readFileToString(new File(licenseFile), StandardCharsets.UTF_8); + } catch (IOException e) { + license = ""; + } + logger = new HttpServletLoggerImpl(servletConfig.getServletContext()); + realPath = servletConfig.getServletContext().getRealPath("/"); + servletContext = servletConfig.getServletContext().getContextPath(); + rootLocalPath = servletConfig.getInitParameter("root"); + localMaskRequestHeaders = toSet(servletConfig.getInitParameter("maskRequestHeaders")); + checkRootPath(rootLocalPath); + String indexLocalPath = createIndexPath(); + supportsUserDefinedAttributes = ExtendedAttributesExtension.isExtendedAttributesSupported(Paths.get(getRootLocalPath()).toString()); + WebDavEngine engine = new WebDavEngine(logger, license, localMaskRequestHeaders); + String indexInterval = servletConfig.getInitParameter("index-interval"); + Integer interval = null; + if (indexInterval != null) { + try { + interval = Integer.valueOf(indexInterval); + } catch (NumberFormatException ignored) {} + } + if (rootLocalPath != null && indexLocalPath != null) { + searchFacade = new SearchFacade(engine, logger); + searchFacade.indexRootFolder(rootLocalPath, indexLocalPath, interval); + } + } + + /** + * Release all resources when stop the servlet + */ + @Override + public void destroy() { + searchFacade.getIndexer().stop(); + } + + private void checkRootPath(String rootPath) { + Path path = Paths.get(realPath, DEFAULT_ROOT_PATH); + if (StringUtil.isNullOrEmpty(rootPath)) { + rootLocalPath = path.toString(); + } else { + if (Files.exists(Paths.get(rootPath))) { + return; + } + try { + if (Files.exists(Paths.get(realPath, rootPath))) { + rootLocalPath = Paths.get(realPath, rootPath).toString(); + } else { + rootLocalPath = path.toString(); + } + } catch (Exception ignored) { + rootLocalPath = path.toString(); + } + } + } + + /** + * Creates index folder if not exists. + * + * @return Absolute location of index folder. + */ + private String createIndexPath() { + Path indexLocalPath = Paths.get(realPath, DEFAULT_INDEX_PATH); + if (Files.notExists(indexLocalPath)) { + try { + Files.createDirectory(indexLocalPath); + } catch (IOException e) { + return null; + } + } + return indexLocalPath.toString(); + } + + /** + * Sets customs handlers. Gives control to {@link com.ithit.webdav.server.Engine}. + * + * @param httpServletRequest Servlet request. + * @param httpServletResponse Servlet response. + * @throws ServletException in case of unexpected exceptions. + * @throws IOException in case of read write exceptions. + */ + // <<<< registerMethodHandlerUsage + @Override + protected void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + WebDavEngine engine = new WebDavEngine(logger, license, localMaskRequestHeaders); + HttpServletDavRequest davRequest = new HttpServletDavRequest(httpServletRequest); + HttpServletDavResponse davResponse = new HttpServletDavResponse(httpServletResponse); + CustomFolderGetHandler handler = new CustomFolderGetHandler(engine.getResponseCharacterEncoding(), Engine.getVersion()); + CustomFolderGetHandler handlerHead = new CustomFolderGetHandler(engine.getResponseCharacterEncoding(), Engine.getVersion()); + handler.setPreviousHandler(engine.registerMethodHandler("GET", handler)); + handlerHead.setPreviousHandler(engine.registerMethodHandler("HEAD", handlerHead)); + engine.setSearchFacade(searchFacade); + + try { + engine.service(davRequest, davResponse); + } catch (DavException e) { + if (e.getStatus() == WebDavStatus.INTERNAL_ERROR) { + logger.logError("Exception during request processing", e); + if (showExceptions) + e.printStackTrace(new PrintStream(davResponse.getOutputStream())); + } + } + } + // registerMethodHandlerUsage >>>> + + private Set toSet(String parameters) { + if (parameters == null) { + return new HashSet<>(); + } + final String[] pars = parameters.split(","); + return new HashSet<>(Arrays.asList(pars)); + } +} diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/DefaultExtendedAttribute.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/DefaultExtendedAttribute.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/DefaultExtendedAttribute.java rename to Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/DefaultExtendedAttribute.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttribute.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttribute.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttribute.java rename to Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttribute.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributeFactory.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributeFactory.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributeFactory.java rename to Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributeFactory.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributesExtension.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributesExtension.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributesExtension.java rename to Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributesExtension.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/OSXExtendedAttribute.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/OSXExtendedAttribute.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/OSXExtendedAttribute.java rename to Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/OSXExtendedAttribute.java diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/staticresourceservlet/FileServlet.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/staticresourceservlet/FileServlet.java new file mode 100644 index 0000000..d67871d --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/staticresourceservlet/FileServlet.java @@ -0,0 +1,626 @@ +/* + * Copyright 2018 OmniFaces + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.ithit.webdav.samples.fsstorageservlet.staticresourceservlet; + +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; +import java.util.zip.GZIPOutputStream; + + +/** + * Servlet which processes static resources if root context is mapped to WebDAV servlet + */ +public class FileServlet extends HttpServlet { + + // Constants ------------------------------------------------------------------------------------------------------ + + private static final long serialVersionUID = 1L; + private static final int DEFAULT_STREAM_BUFFER_SIZE = 10240; + private static final Long DEFAULT_EXPIRE_TIME_IN_SECONDS = TimeUnit.DAYS.toSeconds(1); + private static final long ONE_SECOND_IN_MILLIS = TimeUnit.SECONDS.toMillis(1); + private static final String ETAG = "W/\"%s-%s\""; + private static final Pattern RANGE_PATTERN = Pattern.compile("^bytes=[0-9]*-[0-9]*(,[0-9]*-[0-9]*)*$"); + private static final String MULTIPART_BOUNDARY = UUID.randomUUID().toString(); + private static final Set DEFAULT_MIMETYPES = new HashSet<>(Arrays.asList("text/plain", "text/html", "text/xml", "text/css", "text/javascript", "text/csv", "text/rtf", + "application/xml", "application/xhtml+xml", "application/javascript", "application/json", + "image/svg+xml")); + private File folder; + + // Actions -------------------------------------------------------------------------------------------------------- + + public void init(ServletConfig servletConfig) { + folder = new File(servletConfig.getServletContext().getRealPath("/"), "WEB-INF"); + } + + @Override + protected void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException { + doRequest(request, response, true); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + doRequest(request, response, false); + } + + private void doRequest(HttpServletRequest request, HttpServletResponse response, boolean head) throws IOException { + response.reset(); + Resource resource; + + try { + resource = new Resource(getFile(request)); + } catch (IllegalArgumentException e) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + if (resource.file == null) { + handleFileNotFound(response); + return; + } + + if (preconditionFailed(request, resource)) { + response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); + return; + } + + setCacheHeaders(response, resource, getExpireTime()); + + if (notModified(request, resource)) { + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return; + } + + List ranges = getRanges(request, resource); + + if (ranges == null) { + response.setHeader("Content-Range", "bytes */" + resource.length); + response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE); + return; + } + + if (!ranges.isEmpty()) { + response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); + } else { + ranges.add(new Range(0, resource.length - 1)); // Full content. + } + + String contentType = setContentHeaders(request, response, resource, ranges); + + if (head) { + return; + } + // Checking if client supports gzip + boolean acceptsGzip = false; + if (DEFAULT_MIMETYPES.contains(contentType.split(";", 2)[0])) { + String acceptEncoding = request.getHeader("Accept-Encoding"); + acceptsGzip = acceptEncoding != null && accepts(acceptEncoding, "gzip"); + contentType += ";charset=UTF-8"; + } + writeContent(response, resource, ranges, contentType, acceptsGzip); + } + + /** + * Returns the file associated with the given HTTP servlet request. + * If this method throws {@link IllegalArgumentException}, then the servlet will return a HTTP 400 error. + * If this method returns null, or if {@link File#isFile()} returns false, then the + * servlet will invoke {@link #handleFileNotFound(HttpServletResponse)}. + * @param request The involved HTTP servlet request. + * @return The file associated with the given HTTP servlet request. + * @throws IllegalArgumentException When the request is mangled in such way that it's not recognizable as a valid + * file request. The servlet will then return a HTTP 400 error. + */ + private File getFile(HttpServletRequest request) throws IllegalArgumentException { + String servletPath = request.getServletPath(); + String pathInfo = request.getPathInfo(); + + if (servletPath == null || servletPath.isEmpty() || pathInfo == null || pathInfo.isEmpty() || "/".equals(pathInfo)) { + throw new IllegalArgumentException(); + } + return Paths.get(folder.getAbsolutePath(), servletPath, pathInfo).toFile(); + } + + /** + * Handles the case when the file is not found. + *

+ * The default implementation sends a HTTP 404 error. + * @param response The involved HTTP servlet response. + * @throws IOException When something fails at I/O level. + */ + private void handleFileNotFound(HttpServletResponse response) throws IOException { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } + + /** + * Returns how long the resource may be cached by the client before it expires, in seconds. + *

+ * The default implementation returns 30 days in seconds. + * @return The client cache expire time in seconds (not milliseconds!). + */ + private long getExpireTime() { + return DEFAULT_EXPIRE_TIME_IN_SECONDS; + } + + /** + * Returns the content type associated with the given HTTP servlet request and file. + *

+ * The default implementation delegates {@link File#getName()} to {@link jakarta.servlet.ServletContext#getMimeType(String)} with a + * fallback default value of application/octet-stream. + * @param request The involved HTTP servlet request. + * @param file The involved file. + * @return The content type associated with the given HTTP servlet request and file. + */ + private String getContentType(HttpServletRequest request, File file) { + return coalesce(request.getServletContext().getMimeType(file.getName()), "application/octet-stream"); + } + + /** + * Returns true if we must force a "Save As" dialog based on the given HTTP servlet request and content + * type as obtained from {@link #getContentType(HttpServletRequest, File)}. + *

+ * The default implementation will return true if the content type does not start with + * text or image, and the Accept request header is either null + * or does not match the given content type. + * @param request The involved HTTP servlet request. + * @param contentType The content type of the involved file. + * @return true if we must force a "Save As" dialog based on the given HTTP servlet request and content + * type. + */ + private boolean isAttachment(HttpServletRequest request, String contentType) { + String accept = request.getHeader("Accept"); + return !startsWithOneOf(contentType, "text", "image") && (accept == null || !accepts(accept, contentType)); + } + + /** + * Returns the file name to be used in Content-Disposition header. + * This does not need to be URL-encoded as this will be taken care of. + *

+ * The default implementation returns {@link File#getName()}. + * @param file The involved file. + * @return The file name to be used in Content-Disposition header. + */ + private String getAttachmentName(File file) { + return file.getName(); + } + + // Sub-actions ---------------------------------------------------------------------------------------------------- + + /** + * Returns true if it's a conditional request which must return 412. + */ + private boolean preconditionFailed(HttpServletRequest request, Resource resource) { + String match = request.getHeader("If-Match"); + long unmodified = request.getDateHeader("If-Unmodified-Since"); + return (match != null) ? !matches(match, resource.eTag) : (unmodified != -1 && modified(unmodified, resource.lastModified)); + } + + /** + * Set cache headers. + */ + private void setCacheHeaders(HttpServletResponse response, Resource resource, long expires) { + setCacheHeaders(response, expires); + response.setHeader("ETag", resource.eTag); + response.setDateHeader("Last-Modified", resource.lastModified); + } + + /** + * Returns true if it's a conditional request which must return 304. + */ + private boolean notModified(HttpServletRequest request, Resource resource) { + String noMatch = request.getHeader("If-None-Match"); + long modified = request.getDateHeader("If-Modified-Since"); + return (noMatch != null) ? matches(noMatch, resource.eTag) : (modified != -1 && !modified(modified, resource.lastModified)); + } + + /** + * Get requested ranges. If this is null, then we must return 416. If this is empty, then we must return full file. + */ + private List getRanges(HttpServletRequest request, Resource resource) { + List ranges = new ArrayList<>(1); + String rangeHeader = request.getHeader("Range"); + + if (rangeHeader == null) { + return ranges; + } else if (!RANGE_PATTERN.matcher(rangeHeader).matches()) { + return Collections.emptyList(); // Syntax error. + } + + String ifRange = request.getHeader("If-Range"); + + if (ifRange != null && !ifRange.equals(resource.eTag)) { + try { + long ifRangeTime = request.getDateHeader("If-Range"); + + if (ifRangeTime != -1 && modified(ifRangeTime, resource.lastModified)) { + return ranges; + } + } catch (IllegalArgumentException ifRangeHeaderIsInvalid) { + return ranges; + } + } + + for (String rangeHeaderPart : rangeHeader.split("=")[1].split(",")) { + Range range = parseRange(rangeHeaderPart, resource.length); + + if (range == null) { + return Collections.emptyList(); // Logic error. + } + + ranges.add(range); + } + + return ranges; + } + + /** + * Parse range header part. Returns null if there's a logic error (i.e. start after end). + */ + private Range parseRange(String range, long length) { + long start = sublong(range, 0, range.indexOf('-')); + long end = sublong(range, range.indexOf('-') + 1, range.length()); + + if (start == -1) { + start = length - end; + end = length - 1; + } else if (end == -1 || end > length - 1) { + end = length - 1; + } + + if (start > end) { + return null; // Logic error. + } + + return new Range(start, end); + } + + /** + * Set content headers. + */ + private String setContentHeaders(HttpServletRequest request, HttpServletResponse response, Resource resource, List ranges) { + String contentType = getContentType(request, resource.file); + String filename = getAttachmentName(resource.file); + boolean attachment = isAttachment(request, contentType); + response.setHeader("Content-Disposition", formatContentDispositionHeader(filename, attachment)); + response.setHeader("Accept-Ranges", "bytes"); + + if (ranges.size() == 1) { + Range range = ranges.get(0); + response.setContentType(contentType); + if (response.getStatus() == HttpServletResponse.SC_PARTIAL_CONTENT) { + response.setHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + resource.length); + } + } else { + response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY); + } + + return contentType; + } + + /** + * Write given file to response with given content type and ranges. + */ + private void writeContent(HttpServletResponse response, Resource resource, List ranges, String contentType, boolean acceptsGzip) throws IOException { + ServletOutputStream output = response.getOutputStream(); + + if (ranges.size() == 1) { + Range range = ranges.get(0); + if (acceptsGzip) { + // The browser accepts GZIP, so GZIP the content. + response.setHeader("Content-Encoding", "gzip"); + stream(resource.file, new GZIPOutputStream(output, DEFAULT_STREAM_BUFFER_SIZE), range.start, range.length); + } else { + response.setHeader("Content-Length", String.valueOf(range.length)); + stream(resource.file, output, range.start, range.length); + } + } else { + for (Range range : ranges) { + output.println(); + output.println("--" + MULTIPART_BOUNDARY); + output.println("Content-Type: " + contentType); + output.println("Content-Range: bytes " + range.start + "-" + range.end + "/" + resource.length); + stream(resource.file, output, range.start, range.length); + } + + output.println(); + output.println("--" + MULTIPART_BOUNDARY + "--"); + } + } + + // Helpers -------------------------------------------------------------------------------------------------------- + + /** + * Returns true if the given match header matches the given ETag value. + */ + private static boolean matches(String matchHeader, String eTag) { + String[] matchValues = matchHeader.split("\\s*,\\s*"); + Arrays.sort(matchValues); + return Arrays.binarySearch(matchValues, eTag) > -1 + || Arrays.binarySearch(matchValues, "*") > -1; + } + + /** + * Returns true if the given modified header is older than the given last modified value. + */ + private static boolean modified(long modifiedHeader, long lastModified) { + return (modifiedHeader + ONE_SECOND_IN_MILLIS <= lastModified); // That second is because the header is in seconds, not millis. + } + + /** + * Returns a substring of the given string value from the given begin index to the given end index as a long. + * If the substring is empty, then -1 will be returned. + */ + private static long sublong(String value, int beginIndex, int endIndex) { + String substring = value.substring(beginIndex, endIndex); + return substring.isEmpty() ? -1 : Long.parseLong(substring); + } + + /** + * Returns true if the given accept header accepts the given value. + */ + private static boolean accepts(String acceptHeader, String toAccept) { + String[] acceptValues = acceptHeader.split("\\s*(,|;)\\s*"); + Arrays.sort(acceptValues); + return Arrays.binarySearch(acceptValues, toAccept) > -1 + || Arrays.binarySearch(acceptValues, toAccept.replaceAll("/.*$", "/*")) > -1 + || Arrays.binarySearch(acceptValues, "*/*") > -1; + } + + /** + * Returns the first non-null object of the argument list, or null if there is no such + * element. + * @param The generic object type. + * @param objects The argument list of objects to be tested for non-null. + * @return The first non-null object of the argument list, or null if there is no such + * element. + */ + @SafeVarargs + private final T coalesce(T... objects) { + for (T object : objects) { + if (object != null) { + return object; + } + } + return null; + } + + /** + * URL-encode the given string using UTF-8. + * @param string The string to be URL-encoded using UTF-8. + * @return The given string, URL-encoded using UTF-8, or null if null was given. + * @throws UnsupportedOperationException When this platform does not support UTF-8. + */ + private static String encodeURL(String string) { + if (string == null) { + return null; + } + try { + return URLEncoder.encode(string, StandardCharsets.UTF_8.name()); + } + catch (UnsupportedEncodingException e) { + throw new UnsupportedOperationException("UTF-8 is apparently not supported on this platform.", e); + } + } + + /** + * Returns true if the given string starts with one of the given prefixes. + * @param string The object to be checked if it starts with one of the given prefixes. + * @param prefixes The argument list of prefixes to be checked + * @return true if the given string starts with one of the given prefixes. + */ + private boolean startsWithOneOf(String string, String... prefixes) { + for (String prefix : prefixes) { + if (string.startsWith(prefix)) { + return true; + } + } + return false; + } + + /** + *

Set the cache headers. If the expires argument is larger than 0 seconds, then the following headers + * will be set: + *

+ *

Else the method will delegate to {@link #setNoCacheHeaders(HttpServletResponse)}. + * @param response The HTTP servlet response to set the headers on. + * @param expires The expire time in seconds (not milliseconds!). + */ + private void setCacheHeaders(HttpServletResponse response, long expires) { + if (expires > 0) { + response.setHeader("Cache-Control", "public,max-age=" + expires + ",must-revalidate"); + response.setDateHeader("Expires", System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expires)); + response.setHeader("Pragma", ""); // Explicitly set pragma to prevent container from overriding it. + } + else { + setNoCacheHeaders(response); + } + } + + /** + *

Set the no-cache headers. The following headers will be set: + *

+ * Set the no-cache headers. + * @param response The HTTP servlet response to set the headers on. + */ + private void setNoCacheHeaders(HttpServletResponse response) { + response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate"); + response.setDateHeader("Expires", 0); + response.setHeader("Pragma", "no-cache"); // Backwards compatibility for HTTP 1.0. + } + + /** + *

Format an UTF-8 compatible content disposition header for the given filename and whether it's an attachment. + * @param filename The filename to appear in "Save As" dialogue. + * @param attachment Whether the content should be provided as an attachment or inline. + * @return An UTF-8 compatible content disposition header. + */ + private String formatContentDispositionHeader(String filename, boolean attachment) { + return String.format("%s;filename=\"%2$s\"; filename*=UTF-8''%2$s", (attachment ? "attachment" : "inline"), encodeURI(filename)); + } + + /** + * URI-encode the given string using UTF-8. URIs (paths and filenames) have different encoding rules as compared to + * URL query string parameters. {@link URLEncoder} is actually only for www (HTML) form based query string parameter + * values (as used when a webbrowser submits a HTML form). URI encoding has a lot in common with URL encoding, but + * the space has to be %20 and some chars doesn't necessarily need to be encoded. + * @param string The string to be URI-encoded using UTF-8. + * @return The given string, URI-encoded using UTF-8, or null if null was given. + * @throws UnsupportedOperationException When this platform does not support UTF-8. + */ + private String encodeURI(String string) { + if (string == null) { + return null; + } + return encodeURL(string) + .replace("+", "%20") + .replace("%21", "!") + .replace("%27", "'") + .replace("%28", "(") + .replace("%29", ")") + .replace("%7E", "~"); + } + + /** + * Stream the given input to the given output via NIO {@link Channels} and a directly allocated NIO + * {@link ByteBuffer}. Both the input and output streams will implicitly be closed after streaming, + * regardless of whether an exception is been thrown or not. + * @param input The input stream. + * @param output The output stream. + * @return The length of the written bytes. + * @throws IOException When an I/O error occurs. + */ + private long stream(InputStream input, OutputStream output) throws IOException { + try (ReadableByteChannel inputChannel = Channels.newChannel(input); + WritableByteChannel outputChannel = Channels.newChannel(output)) + { + ByteBuffer buffer = ByteBuffer.allocateDirect(DEFAULT_STREAM_BUFFER_SIZE); + long size = 0; + + while (inputChannel.read(buffer) != -1) { + buffer.flip(); + size += outputChannel.write(buffer); + buffer.clear(); + } + + return size; + } + } + + /** + * Stream a specified range of the given file to the given output via NIO {@link Channels} and a directly allocated + * NIO {@link ByteBuffer}. The output stream will only implicitly be closed after streaming when the specified range + * represents the whole file, regardless of whether an exception is been thrown or not. + * @param file The file. + * @param output The output stream. + * @param start The start position (offset). + * @param length The (intented) length of written bytes. + * @return The (actual) length of the written bytes. This may be smaller when the given length is too large. + * @throws IOException When an I/O error occurs. + */ + private long stream(File file, OutputStream output, long start, long length) throws IOException { + if (start == 0 && length >= file.length()) { + return stream(new FileInputStream(file), output); + } + + try (FileChannel fileChannel = (FileChannel) Files.newByteChannel(file.toPath(), StandardOpenOption.READ)) { + WritableByteChannel outputChannel = Channels.newChannel(output); + ByteBuffer buffer = ByteBuffer.allocateDirect(DEFAULT_STREAM_BUFFER_SIZE); + long size = 0; + + while (fileChannel.read(buffer, start + size) != -1) { + buffer.flip(); + + if (size + buffer.limit() > length) { + buffer.limit((int) (length - size)); + } + + size += outputChannel.write(buffer); + + if (size >= length) { + break; + } + + buffer.clear(); + } + + return size; + } + } + + + // Nested classes ------------------------------------------------------------------------------------------------- + + /** + * Convenience class for a file resource. + */ + private static class Resource { + private final File file; + private final long length; + private final long lastModified; + private final String eTag; + + public Resource(File file) { + if (file != null && file.isFile()) { + this.file = file; + length = file.length(); + lastModified = file.lastModified(); + eTag = String.format(ETAG, encodeURL(file.getName()), lastModified); + } else { + this.file = null; + length = 0; + lastModified = 0; + eTag = null; + } + } + + } + + /** + * Convenience class for a byte range. + */ + private static class Range { + private final long start; + private final long end; + private final long length; + + public Range(long start, long end) { + this.start = start; + this.end = end; + length = end - start + 1; + } + + } + +} diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/GetHttpSessionConfigurator.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/GetHttpSessionConfigurator.java new file mode 100644 index 0000000..00ef0a5 --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/GetHttpSessionConfigurator.java @@ -0,0 +1,26 @@ +package com.ithit.webdav.samples.fsstorageservlet.websocket; + +import jakarta.websocket.HandshakeResponse; +import jakarta.websocket.server.HandshakeRequest; +import jakarta.websocket.server.ServerEndpointConfig; + +import static com.ithit.webdav.samples.fsstorageservlet.websocket.WebSocketServer.INSTANCE_HEADER_NAME; + +public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator { + @Override + public void modifyHandshake(ServerEndpointConfig config, + HandshakeRequest request, + HandshakeResponse response) { + config.getUserProperties().put(INSTANCE_HEADER_NAME, request.getHeaders() + .entrySet() + .stream() + .filter(x -> x.getKey().equalsIgnoreCase(INSTANCE_HEADER_NAME)) + .findFirst().map(x -> { + if (!x.getValue().isEmpty()) { + return x.getValue().get(0); + } + return ""; + }) + .orElse("")); + } +} diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/NotificationEncoder.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/NotificationEncoder.java new file mode 100644 index 0000000..6003870 --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/NotificationEncoder.java @@ -0,0 +1,31 @@ +package com.ithit.webdav.samples.fsstorageservlet.websocket; + +import jakarta.websocket.EncodeException; +import jakarta.websocket.Encoder; +import jakarta.websocket.EndpointConfig; + +/** + * Encodes notification object to the JSON + */ +public class NotificationEncoder implements Encoder.Text { + + @Override + public void init(EndpointConfig config) { + } + + @Override + public void destroy() { + } + + @Override + public String encode(WebSocketServer.Notification notification) throws EncodeException { + String target = ""; + if (notification instanceof WebSocketServer.MovedNotification) { + target = "\"TargetPath\" : \"" + ((WebSocketServer.MovedNotification) notification).getTargetPath() + "\" ,"; + } + return "{" + target + + "\"ItemPath\" : \"" + notification.getItemPath() + "\" ," + + "\"EventType\" : \"" + notification.getOperation() + "\"" + + "}"; + } +} diff --git a/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/WebSocketServer.java b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/WebSocketServer.java new file mode 100644 index 0000000..9ac9467 --- /dev/null +++ b/Java/jakarta/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/WebSocketServer.java @@ -0,0 +1,184 @@ +package com.ithit.webdav.samples.fsstorageservlet.websocket; + +import com.ithit.webdav.server.util.StringUtil; + +import jakarta.websocket.*; +import jakarta.websocket.server.ServerEndpoint; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * WebSocket server, creates web socket endpoint, handles client's sessions + */ +@ServerEndpoint(value = "/", + encoders = {NotificationEncoder.class}, configurator = GetHttpSessionConfigurator.class) +public class WebSocketServer { + + public static final String INSTANCE_HEADER_NAME = "InstanceId"; + private static final Map SESSIONS = new HashMap<>(); + private static WebSocketServer instance; + + public static WebSocketServer getInstance() { + return instance; + } + + public static void setInstance(WebSocketServer instance) { + WebSocketServer.instance = instance; + } + + @OnOpen + public void onOpen(Session session, EndpointConfig config) { + SESSIONS.put(session.getId(), new WebSocketClient((String) config.getUserProperties().get(INSTANCE_HEADER_NAME), session)); + setInstance(this); + } + + @OnMessage + public String onMessage(String message) { + return message; + } + + @OnClose + public void onClose(Session session) { + SESSIONS.remove(session.getId()); + setInstance(this); + } + + /** + * Send notification to the client + * + * @param itemPath File/Folder path. + * @param operation Operation name: created/updated/deleted/moved + * @param clientId Current clientId. + */ + private void send(String itemPath, String operation, String clientId) { + itemPath = StringUtil.trimEnd(StringUtil.trimStart(itemPath, "/"), "/"); + final Notification notification = new Notification(itemPath, operation); + for (WebSocketClient s : + StringUtil.isNullOrEmpty(clientId) + ? SESSIONS.values() + : SESSIONS.values().stream().filter(webSocketClient -> !webSocketClient.instanceId.equals(clientId)).collect(Collectors.toSet())) { + if (s.session.isOpen()) { + s.session.getAsyncRemote().sendObject(notification); + } + } + } + + /** + * Notifies client that file/folder was created. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyCreated(String itemPath, String clientId) { + send(itemPath, "created", clientId); + } + + /** + * Notifies client that file/folder was updated. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyUpdated(String itemPath, String clientId) { + send(itemPath, "updated", clientId); + } + + /** + * Notifies client that file/folder was deleted. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyDeleted(String itemPath, String clientId) { + send(itemPath, "deleted", clientId); + } + + /** + * Notifies client that file/folder was locked. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyLocked(String itemPath, String clientId) { + send(itemPath, "locked", clientId); + } + + /** + * Notifies client that file/folder was unlocked. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyUnlocked(String itemPath, String clientId) { + send(itemPath, "unlocked", clientId); + } + + /** + * Notifies client that file/folder was moved. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyMoved(String itemPath, String targetPath, String clientId) { + itemPath = StringUtil.trimEnd(StringUtil.trimStart(itemPath, "/"), "/"); + targetPath = StringUtil.trimEnd(StringUtil.trimStart(targetPath, "/"), "/"); + final MovedNotification movedNotification = new MovedNotification(itemPath, "moved", targetPath); + for (WebSocketClient s : + clientId != null ? + SESSIONS.values().stream().filter(webSocketClient -> !webSocketClient.instanceId.equals(clientId)).collect(Collectors.toSet()) : + SESSIONS.values()) { + if (s.session.isOpen()) { + s.session.getAsyncRemote().sendObject(movedNotification); + } + } + } + + /** + * Represents VO to exchange between client and server + */ + static class Notification { + private final String itemPath; + private final String operation; + + Notification(String itemPath, String operation) { + this.itemPath = itemPath; + this.operation = operation; + } + + String getItemPath() { + return itemPath; + } + + String getOperation() { + return operation; + } + } + + /** + * Represents VO to exchange between client and server for move type + */ + static class MovedNotification extends Notification { + private final String targetPath; + + MovedNotification(String itemPath, String operation, String targetPath) { + super(itemPath, operation); + this.targetPath = targetPath; + } + + String getTargetPath() { + return targetPath; + } + + } + + private static class WebSocketClient { + private final String instanceId; + private final Session session; + + public WebSocketClient(String instanceId, Session session) { + this.instanceId = instanceId; + this.session = session; + } + } +} diff --git a/Java/collectionsync/src/main/storageresources/Storage/Document.pages b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Document.pages similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Document.pages rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Document.pages diff --git a/Java/collectionsync/src/main/storageresources/Storage/General.docx b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/General.docx similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/General.docx rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/General.docx diff --git a/Java/collectionsync/src/main/storageresources/Storage/Introduction.pptx b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Introduction.pptx similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Introduction.pptx rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Introduction.pptx diff --git a/Java/collectionsync/src/main/storageresources/Storage/Library/Content.txt b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/Content.txt similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Library/Content.txt rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/Content.txt diff --git a/Java/collectionsync/src/main/storageresources/Storage/Library/General.doc b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/General.doc similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Library/General.doc rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/General.doc diff --git a/Java/collectionsync/src/main/storageresources/Storage/Library/Introduction.ppt b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/Introduction.ppt similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Library/Introduction.ppt rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/Introduction.ppt diff --git a/Java/collectionsync/src/main/storageresources/Storage/Library/Stat.xls b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/Stat.xls similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Library/Stat.xls rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/Stat.xls diff --git a/Java/collectionsync/src/main/storageresources/Storage/Library/Vision.mpp b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/Vision.mpp similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Library/Vision.mpp rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Library/Vision.mpp diff --git a/Java/collectionsync/src/main/storageresources/Storage/My Directory/Notes.txt b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/My Directory/Notes.txt similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/My Directory/Notes.txt rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/My Directory/Notes.txt diff --git a/Java/collectionsync/src/main/storageresources/Storage/Notes.txt b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Notes.txt similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Notes.txt rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Notes.txt diff --git a/Java/collectionsync/src/main/storageresources/Storage/Presentation.key b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Presentation.key similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Presentation.key rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Presentation.key diff --git a/Java/collectionsync/src/main/storageresources/Storage/Products/General.doc b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Products/General.doc similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Products/General.doc rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Products/General.doc diff --git a/Java/collectionsync/src/main/storageresources/Storage/Products/General.vsd b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Products/General.vsd similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Products/General.vsd rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Products/General.vsd diff --git a/Java/collectionsync/src/main/storageresources/Storage/Products/Product.mpp b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Products/Product.mpp similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Products/Product.mpp rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Products/Product.mpp diff --git a/Java/collectionsync/src/main/storageresources/Storage/Project.pdf b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Project.pdf similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Project.pdf rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Project.pdf diff --git a/Java/collectionsync/src/main/storageresources/Storage/Sales/Australia/Plan.doc b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Plan.doc similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Sales/Australia/Plan.doc rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Plan.doc diff --git a/Java/collectionsync/src/main/storageresources/Storage/Sales/Australia/Prices.xls b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Prices.xls similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Sales/Australia/Prices.xls rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Prices.xls diff --git a/Java/collectionsync/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt diff --git a/Java/collectionsync/src/main/storageresources/Storage/Sales/Canada/Prices.xls b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Prices.xls similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Sales/Canada/Prices.xls rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Prices.xls diff --git a/Java/collectionsync/src/main/storageresources/Storage/Sales/Canada/Product.mpp b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Product.mpp similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Sales/Canada/Product.mpp rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Product.mpp diff --git a/Java/collectionsync/src/main/storageresources/Storage/Sales/Canada/Stat.xls b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Stat.xls similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Sales/Canada/Stat.xls rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Stat.xls diff --git a/Java/collectionsync/src/main/storageresources/Storage/Sales/Europe/Stat.xls b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Europe/Stat.xls similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Sales/Europe/Stat.xls rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/Europe/Stat.xls diff --git a/Java/collectionsync/src/main/storageresources/Storage/Sales/USA/Vision.mpp b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/USA/Vision.mpp similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Sales/USA/Vision.mpp rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Sales/USA/Vision.mpp diff --git a/Java/collectionsync/src/main/storageresources/Storage/Spreadsheet.numbers b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Spreadsheet.numbers similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Spreadsheet.numbers rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Spreadsheet.numbers diff --git a/Java/collectionsync/src/main/storageresources/Storage/Stat.xlsx b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Stat.xlsx similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Stat.xlsx rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Stat.xlsx diff --git a/Java/collectionsync/src/main/storageresources/Storage/Templates/readme.txt b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Templates/readme.txt similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Templates/readme.txt rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Templates/readme.txt diff --git a/Java/collectionsync/src/main/storageresources/Storage/Templates/template2013.dotx b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.dotx similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Templates/template2013.dotx rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.dotx diff --git a/Java/collectionsync/src/main/storageresources/Storage/Templates/template2013.potx b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.potx similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Templates/template2013.potx rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.potx diff --git a/Java/collectionsync/src/main/storageresources/Storage/Templates/template2013.xltx b/Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.xltx similarity index 100% rename from Java/collectionsync/src/main/storageresources/Storage/Templates/template2013.xltx rename to Java/jakarta/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.xltx diff --git a/Java/collectionsync/src/main/webapp/META-INF/context.xml b/Java/jakarta/filesystemstorage/src/main/webapp/META-INF/context.xml similarity index 100% rename from Java/collectionsync/src/main/webapp/META-INF/context.xml rename to Java/jakarta/filesystemstorage/src/main/webapp/META-INF/context.xml diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/MyCustomHandlerPage.html b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/MyCustomHandlerPage.html rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/attributesErrorPage.html b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/attributesErrorPage.html rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/glassfish-web.xml b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/glassfish-web.xml rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/jboss-web.xml b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/jboss-web.xml rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/web.xml b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/web.xml rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/web.xml diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/weblogic.xml b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/weblogic.xml rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/copy.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/copy.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/cut.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/cut.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/delete.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/delete.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/download.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/download.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/edit.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/edit.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/folder.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/folder.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/home.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/home.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/locked.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/locked.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/logo.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/logo.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/paste.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/paste.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/print.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/print.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/reload.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/reload.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/rename.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/rename.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/search.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/search.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/upload.svg b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/upload.svg rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json similarity index 52% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json index 5c75f6d..6032a70 100644 --- a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json +++ b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json @@ -9,16 +9,16 @@ } }, "node_modules/webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } }, "dependencies": { "webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } } } diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package.json b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package.json rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js b/Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js rename to Java/jakarta/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js diff --git a/Java/springbootfsstorage/.mvn/wrapper/maven-wrapper.properties b/Java/jakarta/springboot3fsstorage/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from Java/springbootfsstorage/.mvn/wrapper/maven-wrapper.properties rename to Java/jakarta/springboot3fsstorage/.mvn/wrapper/maven-wrapper.properties diff --git a/Java/springbootfsstorage/README.md b/Java/jakarta/springboot3fsstorage/README.md similarity index 100% rename from Java/springbootfsstorage/README.md rename to Java/jakarta/springboot3fsstorage/README.md diff --git a/Java/springbootfsstorage/mvnw b/Java/jakarta/springboot3fsstorage/mvnw similarity index 100% rename from Java/springbootfsstorage/mvnw rename to Java/jakarta/springboot3fsstorage/mvnw diff --git a/Java/springbootfsstorage/mvnw.cmd b/Java/jakarta/springboot3fsstorage/mvnw.cmd similarity index 100% rename from Java/springbootfsstorage/mvnw.cmd rename to Java/jakarta/springboot3fsstorage/mvnw.cmd diff --git a/Java/jakarta/springboot3fsstorage/pom.xml b/Java/jakarta/springboot3fsstorage/pom.xml new file mode 100644 index 0000000..997679f --- /dev/null +++ b/Java/jakarta/springboot3fsstorage/pom.xml @@ -0,0 +1,243 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.1.2 + + + com.ithit.webdav.samples + springboot3fsstorage + 6.3.9510-Beta + springboot3fsstorage + Demo project for Spring Boot 3 + + + 5.3.0 + 17 + 7.5.0 + 1.28.5 + + + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-websocket + + + com.azure.spring + spring-cloud-azure-starter-active-directory + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.projectlombok + lombok + true + + + + + com.ithit.webdav + webdav-server + 6.3.9510-Beta + + + com.ithit.webdav.integration + jakarta-integration + 6.3.9510-Beta + + + + + net.java.dev.jna + jna-platform + 5.13.0 + + + + + com.google.code.gson + gson + 2.8.9 + compile + + + + commons-io + commons-io + 2.7 + compile + + + + + org.apache.lucene + lucene-core + ${lucene-core.version} + + + org.apache.lucene + lucene-queryparser + ${lucene-core.version} + + + org.apache.lucene + lucene-highlighter + ${lucene-core.version} + + + org.apache.tika + tika-core + ${tika-core.version} + + + org.apache.tika + tika-parsers + ${tika-core.version} + + + cxf-core + org.apache.cxf + + + cxf-rt-rs-client + org.apache.cxf + + + httpservices + edu.ucar + + + maven-scm-provider-svnexe + org.apache.maven.scm + + + maven-scm-api + org.apache.maven.scm + + + slf4j-log4j12 + org.slf4j + + + c3p0 + c3p0 + + + httpclient + org.apache.httpcomponents + + + grib + edu.ucar + + + cdm + edu.ucar + + + unit-api + javax.measure + + + activation + javax.activation + + + org.apache.sis.storage + sis-netcdf + + + + + org.jdom + jdom2 + 2.0.6.1 + + + + + + + com.github.eirslett + frontend-maven-plugin + 1.12.1 + + + install node and npm + + install-node-and-npm + + + ${java.io.tmpdir} + v16.14.2 + 8.7.0 + + + + npm update + + npm + + generate-resources + + update + src/main/resources/wwwroot/js + ${java.io.tmpdir} + + + + npm install + + npm + + generate-resources + + install + src/main/resources/wwwroot/js + ${java.io.tmpdir} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + + + + com.azure.spring + spring-cloud-azure-dependencies + ${spring-cloud-azure.version} + pom + import + + + + diff --git a/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/SpringBoot3SampleApplication.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/SpringBoot3SampleApplication.java new file mode 100644 index 0000000..a97bfc9 --- /dev/null +++ b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/SpringBoot3SampleApplication.java @@ -0,0 +1,14 @@ +package com.ithit.webdav.samples.springbootfs; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; + +@SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) +public class SpringBoot3SampleApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBoot3SampleApplication.class, args); + } + +} diff --git a/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/common/ResourceReader.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/common/ResourceReader.java new file mode 100644 index 0000000..781ec94 --- /dev/null +++ b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/common/ResourceReader.java @@ -0,0 +1,37 @@ +package com.ithit.webdav.samples.springbootfs.common; + +import com.ithit.webdav.samples.springbootfs.SpringBoot3SampleApplication; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.system.ApplicationHome; +import org.springframework.boot.system.ApplicationTemp; +import org.springframework.stereotype.Component; + +import java.nio.file.Paths; + +import static lombok.AccessLevel.PRIVATE; + +@Slf4j +@FieldDefaults(level = PRIVATE, makeFinal = true) +@RequiredArgsConstructor +@Component +public class ResourceReader { + + private static final String STORAGE_FOLDER = "Storage"; + private static final String INDEX_FOLDER = "Index"; + + public String getRootFolder() { + ApplicationHome home = new ApplicationHome(SpringBoot3SampleApplication.class); + return home.getDir().getAbsolutePath(); + } + + public String getDefaultIndexFolder() { + ApplicationTemp temp = new ApplicationTemp(SpringBoot3SampleApplication.class); + return temp.getDir(INDEX_FOLDER).getAbsolutePath(); + } + + public String getDefaultPath() { + return Paths.get(getRootFolder(), STORAGE_FOLDER).toString(); + } +} diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfiguration.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfiguration.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfiguration.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfiguration.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfigurationProperties.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfigurationProperties.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfigurationProperties.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfigurationProperties.java diff --git a/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/DavFilter.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/DavFilter.java new file mode 100644 index 0000000..3faace0 --- /dev/null +++ b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/DavFilter.java @@ -0,0 +1,39 @@ +package com.ithit.webdav.samples.springbootfs.controller; + +import com.ithit.webdav.samples.springbootfs.configuration.WebDavConfigurationProperties; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; + + +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class DavFilter implements Filter { + + WebDavConfigurationProperties properties; + + @Override + public void doFilter( + ServletRequest request, + ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + HttpServletRequest req = (HttpServletRequest) request; + if ((req.getMethod().equalsIgnoreCase("PROPFIND") || req.getMethod().equalsIgnoreCase("OPTIONS")) + && properties.getRootContext().contains(req.getRequestURI()) + && properties.getRootContext().length() - 2 > req.getRequestURI().length()) { + request.getRequestDispatcher(properties.getRootContext()).include(request, response); + } else { + chain.doFilter(request, response); + } + } +} diff --git a/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/SamplesController.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/SamplesController.java new file mode 100644 index 0000000..7742f0e --- /dev/null +++ b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/SamplesController.java @@ -0,0 +1,60 @@ +package com.ithit.webdav.samples.springbootfs.controller; + +import com.ithit.webdav.integration.servlet.HttpServletDavRequest; +import com.ithit.webdav.integration.servlet.HttpServletDavResponse; +import com.ithit.webdav.samples.springbootfs.impl.WebDavEngine; +import com.ithit.webdav.server.exceptions.DavException; +import com.ithit.webdav.server.exceptions.WebDavStatus; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintStream; + + +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +@RestController +@CrossOrigin("*") +public class SamplesController { + + WebDavEngine engine; + + @RequestMapping(path = "${webdav.rootContext}**", produces = MediaType.ALL_VALUE, headers = "Connection!=Upgrade") + public void webdav(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException { + performDavRequest(httpServletRequest, httpServletResponse); + } + + @RequestMapping(path = "${webdav.rootContext}**", produces = MediaType.ALL_VALUE, method = {RequestMethod.OPTIONS}, headers = "Connection!=Upgrade") + public void options(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException { + performDavRequest(httpServletRequest, httpServletResponse); + } + + private void performDavRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException { + HttpServletDavRequest davRequest = new HttpServletDavRequest(httpServletRequest) { + @Override + public String getServerPath() { + return "/"; + } + }; + HttpServletDavResponse davResponse = new HttpServletDavResponse(httpServletResponse); + try { + engine.service(davRequest, davResponse); + } catch (DavException e) { + if (e.getStatus() == WebDavStatus.INTERNAL_ERROR) { + engine.getLogger().logError("Exception during request processing", e); + if (engine.isShowExceptions()) + e.printStackTrace(new PrintStream(davResponse.getOutputStream())); + } + } + } + +} diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/DefaultExtendedAttribute.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/DefaultExtendedAttribute.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/DefaultExtendedAttribute.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/DefaultExtendedAttribute.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttribute.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttribute.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttribute.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttribute.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributeFactory.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributeFactory.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributeFactory.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributeFactory.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributesExtension.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributesExtension.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributesExtension.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributesExtension.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/OSXExtendedAttribute.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/OSXExtendedAttribute.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/OSXExtendedAttribute.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/OSXExtendedAttribute.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/CustomFolderGetHandler.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/CustomFolderGetHandler.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/CustomFolderGetHandler.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/CustomFolderGetHandler.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FileImpl.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FileImpl.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FileImpl.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FileImpl.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FolderImpl.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FolderImpl.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FolderImpl.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FolderImpl.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/HierarchyItemImpl.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/HierarchyItemImpl.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/HierarchyItemImpl.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/HierarchyItemImpl.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SearchFacade.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SearchFacade.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SearchFacade.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SearchFacade.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SerializationUtils.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SerializationUtils.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SerializationUtils.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SerializationUtils.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SpringBootLogger.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SpringBootLogger.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SpringBootLogger.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SpringBootLogger.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/WebDavEngine.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/WebDavEngine.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/WebDavEngine.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/WebDavEngine.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/HandshakeHeadersInterceptor.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/HandshakeHeadersInterceptor.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/HandshakeHeadersInterceptor.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/HandshakeHeadersInterceptor.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/SocketHandler.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/SocketHandler.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/SocketHandler.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/SocketHandler.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/WebSocketServer.java b/Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/WebSocketServer.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/WebSocketServer.java rename to Java/jakarta/springboot3fsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/WebSocketServer.java diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Document.pages b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Document.pages similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Document.pages rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Document.pages diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/General.docx b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/General.docx similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/General.docx rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/General.docx diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Introduction.pptx b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Introduction.pptx similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Introduction.pptx rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Introduction.pptx diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Library/Content.txt b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/Content.txt similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Library/Content.txt rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/Content.txt diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Library/General.doc b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/General.doc similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Library/General.doc rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/General.doc diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Library/Introduction.ppt b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/Introduction.ppt similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Library/Introduction.ppt rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/Introduction.ppt diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Library/Stat.xls b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/Stat.xls similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Library/Stat.xls rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/Stat.xls diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Library/Vision.mpp b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/Vision.mpp similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Library/Vision.mpp rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Library/Vision.mpp diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/My Directory/Notes.txt b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/My Directory/Notes.txt similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/My Directory/Notes.txt rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/My Directory/Notes.txt diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Notes.txt b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Notes.txt similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Notes.txt rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Notes.txt diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Presentation.key b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Presentation.key similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Presentation.key rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Presentation.key diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Products/General.doc b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Products/General.doc similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Products/General.doc rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Products/General.doc diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Products/General.vsd b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Products/General.vsd similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Products/General.vsd rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Products/General.vsd diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Products/Product.mpp b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Products/Product.mpp similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Products/Product.mpp rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Products/Product.mpp diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Project.pdf b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Project.pdf similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Project.pdf rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Project.pdf diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Plan.doc b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Australia/Plan.doc similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Plan.doc rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Australia/Plan.doc diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Prices.xls b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Australia/Prices.xls similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Prices.xls rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Australia/Prices.xls diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Canada/Introduction.ppt similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Canada/Introduction.ppt diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Prices.xls b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Canada/Prices.xls similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Prices.xls rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Canada/Prices.xls diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Product.mpp b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Canada/Product.mpp similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Product.mpp rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Canada/Product.mpp diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Stat.xls b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Canada/Stat.xls similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Stat.xls rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Canada/Stat.xls diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Sales/Europe/Stat.xls b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Europe/Stat.xls similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Sales/Europe/Stat.xls rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/Europe/Stat.xls diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Sales/USA/Vision.mpp b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/USA/Vision.mpp similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Sales/USA/Vision.mpp rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Sales/USA/Vision.mpp diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Spreadsheet.numbers b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Spreadsheet.numbers similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Spreadsheet.numbers rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Spreadsheet.numbers diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Stat.xlsx b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Stat.xlsx similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Stat.xlsx rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Stat.xlsx diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Templates/readme.txt b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Templates/readme.txt similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Templates/readme.txt rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Templates/readme.txt diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.dotx b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Templates/template2013.dotx similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.dotx rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Templates/template2013.dotx diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.potx b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Templates/template2013.potx similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.potx rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Templates/template2013.potx diff --git a/Java/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.xltx b/Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Templates/template2013.xltx similarity index 100% rename from Java/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.xltx rename to Java/jakarta/springboot3fsstorage/src/main/resources/Storage/Templates/template2013.xltx diff --git a/Java/jakarta/springboot3fsstorage/src/main/resources/application.properties b/Java/jakarta/springboot3fsstorage/src/main/resources/application.properties new file mode 100644 index 0000000..e0f7923 --- /dev/null +++ b/Java/jakarta/springboot3fsstorage/src/main/resources/application.properties @@ -0,0 +1,19 @@ +# Spring related settings. +server.port=8181 +spring.mvc.dispatch-options-request=true + +# WebDAV specific settings. +# Path to the license file. +webdav.license=D:/License.lic + +# Whether to print exception stacktrace in the response. +webdav.showExceptions=true + +# Here you map you filesystem folder to be root for WebDAV. If not provided default structure will be created for the testing. +webdav.rootFolder= + +# Your WebDAV server is available at the context specified in this variable. There must be trailing slash ("/"). +webdav.rootContext=/DAV/ + +# WebSockets are available at this endpoint. WebSockets are used in the default GET page. +webdav.rootWebSocket=/ diff --git a/Java/springbootfsstorage/src/main/resources/handler/MyCustomHandlerPage.html b/Java/jakarta/springboot3fsstorage/src/main/resources/handler/MyCustomHandlerPage.html similarity index 100% rename from Java/springbootfsstorage/src/main/resources/handler/MyCustomHandlerPage.html rename to Java/jakarta/springboot3fsstorage/src/main/resources/handler/MyCustomHandlerPage.html diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html b/Java/jakarta/springboot3fsstorage/src/main/resources/handler/attributesErrorPage.html similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html rename to Java/jakarta/springboot3fsstorage/src/main/resources/handler/attributesErrorPage.html diff --git a/Java/springbootfsstorage/src/main/resources/logback-spring.xml b/Java/jakarta/springboot3fsstorage/src/main/resources/logback-spring.xml similarity index 100% rename from Java/springbootfsstorage/src/main/resources/logback-spring.xml rename to Java/jakarta/springboot3fsstorage/src/main/resources/logback-spring.xml diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/AjaxFileBrowser.html diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/AjaxIntegrationTests.html diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/css/webdav-layout.css similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/css/webdav-layout.css diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/cancel-button.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/cancel-button.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/check-square.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/check-square.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/copy.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/copy.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/copy.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/copy.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/create-folder.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/create-folder.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/cut.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/cut.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/cut.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/cut.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/delete.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/delete.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/delete.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/delete.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/download.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/download.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/download.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/download.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/edit-associated.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/edit-associated.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/edit.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/edit.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/edit.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/edit.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/file-archive-icon.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/file-archive-icon.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/file-default-icon.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/file-default-icon.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/file-image-icon.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/file-image-icon.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/file-pdf-icon.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/file-pdf-icon.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/folder.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/folder.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/folder.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/folder.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/home.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/home.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/home.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/home.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/locked.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/locked.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/locked.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/locked.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/logo.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/logo.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/logo.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/logo.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/menu-edit.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/menu-edit.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/microsoft-edit.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/microsoft-edit.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/open-folder.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/open-folder.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/paste.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/paste.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/paste.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/paste.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/pause-button.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/pause-button.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/play-button.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/play-button.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/print.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/print.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/print.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/print.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/reload.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/reload.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/reload.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/reload.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/rename.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/rename.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/rename.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/rename.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/search.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/search.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/search.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/search.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/up-one-level.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/up-one-level.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/upload.svg b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/upload.svg similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/images/upload.svg rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/images/upload.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/package.json b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/package.json similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/package.json rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/package.json diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/webdav-common.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/webdav-common.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/webdav-gridview.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/webdav-gridview.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/webdav-uploader.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/webdav-uploader.js diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js b/Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/webdav-websocket.js similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js rename to Java/jakarta/springboot3fsstorage/src/main/resources/wwwroot/js/webdav-websocket.js diff --git a/Java/collectionsync/README.md b/Java/javax/collectionsync/README.md similarity index 100% rename from Java/collectionsync/README.md rename to Java/javax/collectionsync/README.md diff --git a/Java/collectionsync/pom.xml b/Java/javax/collectionsync/pom.xml similarity index 95% rename from Java/collectionsync/pom.xml rename to Java/javax/collectionsync/pom.xml index 329d2a8..fc554db 100644 --- a/Java/collectionsync/pom.xml +++ b/Java/javax/collectionsync/pom.xml @@ -6,7 +6,7 @@ com.ithit.webdav.samples collectionsync - 6.2.9090-Beta + 6.3.9510-Beta war @@ -34,7 +34,7 @@ com.ithit.webdav.integration servlet-integration - 6.2.9090-Beta + 6.3.9510-Beta commons-io @@ -142,7 +142,7 @@ com.ithit.webdav webdav-server - 6.2.9090-Beta + 6.3.9510-Beta net.java.dev.jna @@ -160,15 +160,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - - org.apache.maven.plugins maven-war-plugin @@ -228,7 +219,7 @@ filesystem 11021 / - target/collectionsync-6.2.9090-Beta + target/collectionsync-6.3.9510-Beta diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/CustomFolderGetHandler.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/CustomFolderGetHandler.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/CustomFolderGetHandler.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/CustomFolderGetHandler.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/DavChanges.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/DavChanges.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/DavChanges.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/DavChanges.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/FileImpl.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/FileImpl.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/FileImpl.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/FileImpl.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/FolderImpl.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/FolderImpl.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/FolderImpl.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/FolderImpl.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/HierarchyItemImpl.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/HierarchyItemImpl.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/HierarchyItemImpl.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/HierarchyItemImpl.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/SearchFacade.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/SearchFacade.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/SearchFacade.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/SearchFacade.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/SerializationUtils.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/SerializationUtils.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/SerializationUtils.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/SerializationUtils.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/WebDavEngine.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/WebDavEngine.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/WebDavEngine.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/WebDavEngine.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/WebDavServlet.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/WebDavServlet.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/WebDavServlet.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/WebDavServlet.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/DefaultExtendedAttribute.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/DefaultExtendedAttribute.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/DefaultExtendedAttribute.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/DefaultExtendedAttribute.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttribute.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttribute.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttribute.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttribute.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttributeFactory.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttributeFactory.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttributeFactory.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttributeFactory.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttributesExtension.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttributesExtension.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttributesExtension.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/ExtendedAttributesExtension.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/OSXExtendedAttribute.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/OSXExtendedAttribute.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/OSXExtendedAttribute.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/extendedattributes/OSXExtendedAttribute.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/FileSystemExtension.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/FileSystemExtension.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/FileSystemExtension.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/FileSystemExtension.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/Kernel32.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/Kernel32.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/Kernel32.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/Kernel32.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/WindowsFileSystemItem.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/WindowsFileSystemItem.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/WindowsFileSystemItem.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/WindowsFileSystemItem.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/WindowsFileSystemItemId.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/WindowsFileSystemItemId.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/WindowsFileSystemItemId.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/filesystem/winapi/WindowsFileSystemItemId.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/staticresourceservlet/FileServlet.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/staticresourceservlet/FileServlet.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/staticresourceservlet/FileServlet.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/staticresourceservlet/FileServlet.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/GetHttpSessionConfigurator.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/GetHttpSessionConfigurator.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/GetHttpSessionConfigurator.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/GetHttpSessionConfigurator.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/NotificationEncoder.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/NotificationEncoder.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/NotificationEncoder.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/NotificationEncoder.java diff --git a/Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/WebSocketServer.java b/Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/WebSocketServer.java similarity index 100% rename from Java/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/WebSocketServer.java rename to Java/javax/collectionsync/src/main/java/com/ithit/webdav/samples/collectionsync/websocket/WebSocketServer.java diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Document.pages b/Java/javax/collectionsync/src/main/storageresources/Storage/Document.pages similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Document.pages rename to Java/javax/collectionsync/src/main/storageresources/Storage/Document.pages diff --git a/Java/springbootfsstorage/src/main/resources/Storage/General.docx b/Java/javax/collectionsync/src/main/storageresources/Storage/General.docx similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/General.docx rename to Java/javax/collectionsync/src/main/storageresources/Storage/General.docx diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Introduction.pptx b/Java/javax/collectionsync/src/main/storageresources/Storage/Introduction.pptx similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Introduction.pptx rename to Java/javax/collectionsync/src/main/storageresources/Storage/Introduction.pptx diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Library/Content.txt b/Java/javax/collectionsync/src/main/storageresources/Storage/Library/Content.txt similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Library/Content.txt rename to Java/javax/collectionsync/src/main/storageresources/Storage/Library/Content.txt diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Library/General.doc b/Java/javax/collectionsync/src/main/storageresources/Storage/Library/General.doc similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Library/General.doc rename to Java/javax/collectionsync/src/main/storageresources/Storage/Library/General.doc diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Library/Introduction.ppt b/Java/javax/collectionsync/src/main/storageresources/Storage/Library/Introduction.ppt similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Library/Introduction.ppt rename to Java/javax/collectionsync/src/main/storageresources/Storage/Library/Introduction.ppt diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Library/Stat.xls b/Java/javax/collectionsync/src/main/storageresources/Storage/Library/Stat.xls similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Library/Stat.xls rename to Java/javax/collectionsync/src/main/storageresources/Storage/Library/Stat.xls diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Library/Vision.mpp b/Java/javax/collectionsync/src/main/storageresources/Storage/Library/Vision.mpp similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Library/Vision.mpp rename to Java/javax/collectionsync/src/main/storageresources/Storage/Library/Vision.mpp diff --git a/Java/springbootfsstorage/src/main/resources/Storage/My Directory/Notes.txt b/Java/javax/collectionsync/src/main/storageresources/Storage/My Directory/Notes.txt similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/My Directory/Notes.txt rename to Java/javax/collectionsync/src/main/storageresources/Storage/My Directory/Notes.txt diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Notes.txt b/Java/javax/collectionsync/src/main/storageresources/Storage/Notes.txt similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Notes.txt rename to Java/javax/collectionsync/src/main/storageresources/Storage/Notes.txt diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Presentation.key b/Java/javax/collectionsync/src/main/storageresources/Storage/Presentation.key similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Presentation.key rename to Java/javax/collectionsync/src/main/storageresources/Storage/Presentation.key diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Products/General.doc b/Java/javax/collectionsync/src/main/storageresources/Storage/Products/General.doc similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Products/General.doc rename to Java/javax/collectionsync/src/main/storageresources/Storage/Products/General.doc diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Products/General.vsd b/Java/javax/collectionsync/src/main/storageresources/Storage/Products/General.vsd similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Products/General.vsd rename to Java/javax/collectionsync/src/main/storageresources/Storage/Products/General.vsd diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Products/Product.mpp b/Java/javax/collectionsync/src/main/storageresources/Storage/Products/Product.mpp similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Products/Product.mpp rename to Java/javax/collectionsync/src/main/storageresources/Storage/Products/Product.mpp diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Project.pdf b/Java/javax/collectionsync/src/main/storageresources/Storage/Project.pdf similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Project.pdf rename to Java/javax/collectionsync/src/main/storageresources/Storage/Project.pdf diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Plan.doc b/Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Australia/Plan.doc similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Plan.doc rename to Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Australia/Plan.doc diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Prices.xls b/Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Australia/Prices.xls similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Prices.xls rename to Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Australia/Prices.xls diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Introduction.ppt b/Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Introduction.ppt rename to Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Prices.xls b/Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Canada/Prices.xls similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Prices.xls rename to Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Canada/Prices.xls diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Product.mpp b/Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Canada/Product.mpp similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Product.mpp rename to Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Canada/Product.mpp diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Stat.xls b/Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Canada/Stat.xls similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Stat.xls rename to Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Canada/Stat.xls diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Sales/Europe/Stat.xls b/Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Europe/Stat.xls similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Sales/Europe/Stat.xls rename to Java/javax/collectionsync/src/main/storageresources/Storage/Sales/Europe/Stat.xls diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Sales/USA/Vision.mpp b/Java/javax/collectionsync/src/main/storageresources/Storage/Sales/USA/Vision.mpp similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Sales/USA/Vision.mpp rename to Java/javax/collectionsync/src/main/storageresources/Storage/Sales/USA/Vision.mpp diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Spreadsheet.numbers b/Java/javax/collectionsync/src/main/storageresources/Storage/Spreadsheet.numbers similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Spreadsheet.numbers rename to Java/javax/collectionsync/src/main/storageresources/Storage/Spreadsheet.numbers diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Stat.xlsx b/Java/javax/collectionsync/src/main/storageresources/Storage/Stat.xlsx similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Stat.xlsx rename to Java/javax/collectionsync/src/main/storageresources/Storage/Stat.xlsx diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Templates/readme.txt b/Java/javax/collectionsync/src/main/storageresources/Storage/Templates/readme.txt similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Templates/readme.txt rename to Java/javax/collectionsync/src/main/storageresources/Storage/Templates/readme.txt diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Templates/template2013.dotx b/Java/javax/collectionsync/src/main/storageresources/Storage/Templates/template2013.dotx similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Templates/template2013.dotx rename to Java/javax/collectionsync/src/main/storageresources/Storage/Templates/template2013.dotx diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Templates/template2013.potx b/Java/javax/collectionsync/src/main/storageresources/Storage/Templates/template2013.potx similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Templates/template2013.potx rename to Java/javax/collectionsync/src/main/storageresources/Storage/Templates/template2013.potx diff --git a/Java/springbootfsstorage/src/main/resources/Storage/Templates/template2013.xltx b/Java/javax/collectionsync/src/main/storageresources/Storage/Templates/template2013.xltx similarity index 100% rename from Java/springbootfsstorage/src/main/resources/Storage/Templates/template2013.xltx rename to Java/javax/collectionsync/src/main/storageresources/Storage/Templates/template2013.xltx diff --git a/Java/filesystemstorage/src/main/webapp/META-INF/context.xml b/Java/javax/collectionsync/src/main/webapp/META-INF/context.xml similarity index 100% rename from Java/filesystemstorage/src/main/webapp/META-INF/context.xml rename to Java/javax/collectionsync/src/main/webapp/META-INF/context.xml diff --git a/Java/deltav/src/main/webapp/WEB-INF/MyCustomHandlerPage.html b/Java/javax/collectionsync/src/main/webapp/WEB-INF/MyCustomHandlerPage.html similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/MyCustomHandlerPage.html rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/MyCustomHandlerPage.html diff --git a/Java/springbootfsstorage/src/main/resources/handler/attributesErrorPage.html b/Java/javax/collectionsync/src/main/webapp/WEB-INF/attributesErrorPage.html similarity index 100% rename from Java/springbootfsstorage/src/main/resources/handler/attributesErrorPage.html rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/attributesErrorPage.html diff --git a/Java/deltav/src/main/webapp/WEB-INF/glassfish-web.xml b/Java/javax/collectionsync/src/main/webapp/WEB-INF/glassfish-web.xml similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/glassfish-web.xml rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/glassfish-web.xml diff --git a/Java/deltav/src/main/webapp/WEB-INF/jboss-web.xml b/Java/javax/collectionsync/src/main/webapp/WEB-INF/jboss-web.xml similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/jboss-web.xml rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/jboss-web.xml diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/web.xml b/Java/javax/collectionsync/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from Java/collectionsync/src/main/webapp/WEB-INF/web.xml rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/web.xml diff --git a/Java/deltav/src/main/webapp/WEB-INF/weblogic.xml b/Java/javax/collectionsync/src/main/webapp/WEB-INF/weblogic.xml similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/weblogic.xml rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/weblogic.xml diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/copy.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/copy.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/cut.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/cut.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/delete.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/delete.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/download.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/download.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/edit.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/edit.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/folder.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/folder.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/home.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/home.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/locked.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/locked.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/logo.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/logo.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/paste.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/paste.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/print.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/print.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/reload.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/reload.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/rename.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/rename.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/search.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/search.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/upload.svg similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/images/upload.svg diff --git a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json similarity index 52% rename from Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json index 5c75f6d..6032a70 100644 --- a/Java/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json +++ b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json @@ -9,16 +9,16 @@ } }, "node_modules/webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } }, "dependencies": { "webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } } } diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package.json similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/package.json diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js b/Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js rename to Java/javax/collectionsync/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js diff --git a/Java/deltav/README.md b/Java/javax/deltav/README.md similarity index 100% rename from Java/deltav/README.md rename to Java/javax/deltav/README.md diff --git a/Java/deltav/pom.xml b/Java/javax/deltav/pom.xml similarity index 95% rename from Java/deltav/pom.xml rename to Java/javax/deltav/pom.xml index 0cec775..8270163 100644 --- a/Java/deltav/pom.xml +++ b/Java/javax/deltav/pom.xml @@ -6,7 +6,7 @@ com.ithit.webdav.samples deltav - 6.2.9090-Beta + 6.3.9510-Beta war @@ -23,7 +23,7 @@ com.ithit.webdav.integration servlet-integration - 6.2.9090-Beta + 6.3.9510-Beta commons-dbcp @@ -125,7 +125,7 @@ com.ithit.webdav webdav-server - 6.2.9090-Beta + 6.3.9510-Beta @@ -144,15 +144,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - - org.apache.maven.plugins maven-resources-plugin @@ -165,7 +156,7 @@ copy-resources - ${project.build.directory}/deltav-6.2.9090-Beta/META-INF + ${project.build.directory}/deltav-6.3.9510-Beta/META-INF true @@ -244,7 +235,7 @@ filesystem 11021 / - target/deltav-6.2.9090-Beta + target/deltav-6.3.9510-Beta diff --git a/Java/deltav/src/main/dbresources/db/deltav.sql b/Java/javax/deltav/src/main/dbresources/db/deltav.sql similarity index 100% rename from Java/deltav/src/main/dbresources/db/deltav.sql rename to Java/javax/deltav/src/main/dbresources/db/deltav.sql diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/CustomFolderGetHandler.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/CustomFolderGetHandler.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/CustomFolderGetHandler.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/CustomFolderGetHandler.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/DataAccess.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/DataAccess.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/DataAccess.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/DataAccess.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/DownloadUtil.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/DownloadUtil.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/DownloadUtil.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/DownloadUtil.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/FileImpl.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/FileImpl.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/FileImpl.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/FileImpl.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/FolderImpl.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/FolderImpl.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/FolderImpl.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/FolderImpl.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/HierarchyItemImpl.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/HierarchyItemImpl.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/HierarchyItemImpl.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/HierarchyItemImpl.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/ItemType.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/ItemType.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/ItemType.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/ItemType.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/SearchFacade.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/SearchFacade.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/SearchFacade.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/SearchFacade.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/VersionHistory.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/VersionHistory.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/VersionHistory.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/VersionHistory.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/VersionImpl.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/VersionImpl.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/VersionImpl.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/VersionImpl.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/WebDavEngine.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/WebDavEngine.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/WebDavEngine.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/WebDavEngine.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/WebDavServlet.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/WebDavServlet.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/WebDavServlet.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/WebDavServlet.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/staticresourceservlet/FileServlet.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/staticresourceservlet/FileServlet.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/staticresourceservlet/FileServlet.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/staticresourceservlet/FileServlet.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/GetHttpSessionConfigurator.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/GetHttpSessionConfigurator.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/GetHttpSessionConfigurator.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/GetHttpSessionConfigurator.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/NotificationEncoder.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/NotificationEncoder.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/NotificationEncoder.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/NotificationEncoder.java diff --git a/Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/WebSocketServer.java b/Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/WebSocketServer.java similarity index 100% rename from Java/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/WebSocketServer.java rename to Java/javax/deltav/src/main/java/com/ithit/webdav/samples/deltavservlet/websocket/WebSocketServer.java diff --git a/Java/deltav/src/main/tomcat/context.xml b/Java/javax/deltav/src/main/tomcat/context.xml similarity index 100% rename from Java/deltav/src/main/tomcat/context.xml rename to Java/javax/deltav/src/main/tomcat/context.xml diff --git a/Java/deltav/src/main/webapp/META-INF/context.xml b/Java/javax/deltav/src/main/webapp/META-INF/context.xml similarity index 100% rename from Java/deltav/src/main/webapp/META-INF/context.xml rename to Java/javax/deltav/src/main/webapp/META-INF/context.xml diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html b/Java/javax/deltav/src/main/webapp/WEB-INF/MyCustomHandlerPage.html similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html rename to Java/javax/deltav/src/main/webapp/WEB-INF/MyCustomHandlerPage.html diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml b/Java/javax/deltav/src/main/webapp/WEB-INF/glassfish-web.xml similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml rename to Java/javax/deltav/src/main/webapp/WEB-INF/glassfish-web.xml diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml b/Java/javax/deltav/src/main/webapp/WEB-INF/jboss-web.xml similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml rename to Java/javax/deltav/src/main/webapp/WEB-INF/jboss-web.xml diff --git a/Java/deltav/src/main/webapp/WEB-INF/web.xml b/Java/javax/deltav/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from Java/deltav/src/main/webapp/WEB-INF/web.xml rename to Java/javax/deltav/src/main/webapp/WEB-INF/web.xml diff --git a/Java/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml b/Java/javax/deltav/src/main/webapp/WEB-INF/weblogic.xml similarity index 100% rename from Java/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml rename to Java/javax/deltav/src/main/webapp/WEB-INF/weblogic.xml diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/copy.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/copy.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/cut.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/cut.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/delete.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/delete.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/download.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/download.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/edit.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/edit.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/folder.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/folder.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/home.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/home.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/locked.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/locked.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/logo.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/logo.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/paste.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/paste.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/print.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/print.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/reload.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/reload.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/rename.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/rename.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/search.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/search.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/upload.svg similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/images/upload.svg diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json similarity index 52% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json index 5c75f6d..6032a70 100644 --- a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json +++ b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json @@ -9,16 +9,16 @@ } }, "node_modules/webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } }, "dependencies": { "webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } } } diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package.json b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/package.json similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package.json rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/package.json diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js b/Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js rename to Java/javax/deltav/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js diff --git a/Kotlin/filesystemstorage/README.md b/Java/javax/filesystemstorage/README.md similarity index 100% rename from Kotlin/filesystemstorage/README.md rename to Java/javax/filesystemstorage/README.md diff --git a/Java/filesystemstorage/pom.xml b/Java/javax/filesystemstorage/pom.xml similarity index 87% rename from Java/filesystemstorage/pom.xml rename to Java/javax/filesystemstorage/pom.xml index 1832748..22d6cf0 100644 --- a/Java/filesystemstorage/pom.xml +++ b/Java/javax/filesystemstorage/pom.xml @@ -6,11 +6,13 @@ com.ithit.webdav.samples filesystemstorage - 6.2.9090-Beta + 6.3.9510-Beta war UTF-8 + 1.8 + 1.8 @@ -34,7 +36,7 @@ com.ithit.webdav.integration servlet-integration - 6.2.9090-Beta + 6.3.9510-Beta commons-io @@ -43,22 +45,9 @@ compile - commons-dbcp - commons-dbcp - 1.2.2 - provided - - - commons-pool - commons-pool - 1.4 - provided - - - com.oracle.database.jdbc - ojdbc8 - 23.2.0.0 - provided + commons-lang + commons-lang + 2.6 org.apache.lucene @@ -142,7 +131,7 @@ com.ithit.webdav webdav-server - 6.2.9090-Beta + 6.3.9510-Beta net.java.dev.jna @@ -151,24 +140,8 @@ - - - nuxeo - https://maven.nuxeo.org/nexus/content/groups/public - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - - org.apache.maven.plugins maven-war-plugin @@ -178,9 +151,6 @@ src/main/storageresources WEB-INF - - **/pom.xml - @@ -228,7 +198,7 @@ filesystem 11021 / - target/filesystemstorage-6.2.9090-Beta + target/filesystemstorage-6.3.9510-Beta diff --git a/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/CustomFolderGetHandler.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/CustomFolderGetHandler.java new file mode 100644 index 0000000..d0c4705 --- /dev/null +++ b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/CustomFolderGetHandler.java @@ -0,0 +1,110 @@ +package com.ithit.webdav.samples.fsstorageservlet; + +import com.ithit.webdav.server.*; +import com.ithit.webdav.server.exceptions.DavException; +import org.apache.commons.io.FileUtils; + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * This handler processes GET requests to folders returning custom HTML page. + */ +public class CustomFolderGetHandler implements MethodHandler { + + private MethodHandler previousHandler; + private final String charset; + private final String version; + private final String pathToHTML = "WEB-INF/MyCustomHandlerPage.html"; + private final String pathToErrorHTML = "WEB-INF/attributesErrorPage.html"; + + public CustomFolderGetHandler(String charset, String version) { + this.charset = charset; + this.version = version; + } + + @Override + public void processRequest(DavRequest request, DavResponse response, HierarchyItem item) + throws DavException, IOException { + if (item instanceof Folder) { + PrintStream stream = new PrintStream(response.getOutputStream(), true, charset); + response.setCharacterEncoding(charset); + response.setContentType("text/html"); + if (!WebDavServlet.isSupportsUserDefinedAttributes()) { + Path path = Paths.get(WebDavServlet.getRealPath(), pathToErrorHTML); + String lines = FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8); + stream.println(lines); + } else { + Path path = Paths.get(WebDavServlet.getRealPath(), pathToHTML); + String context = WebDavServlet.getContext() + "/"; + String wsContext = context.replaceFirst("/", ""); + int ind = wsContext.lastIndexOf('/'); + if (ind >= 0) { + wsContext = new StringBuilder(wsContext).replace(ind, ind + 1, "\\/").toString(); + } + for (String line : Files.readAllLines(path, StandardCharsets.UTF_8)) { + String contextRootString = "<%context root%>"; + if (line.contains(contextRootString)) { + line = line.replace(contextRootString, context); + } + String versionNumber = "<%version%>"; + if (line.contains(versionNumber)) { + line = line.replace(versionNumber, version); + } + String ws = "<%ws root%>"; + if (line.contains(ws)) { + line = line.replace(ws, wsContext); + } + String startTime = "<%startTime%>"; + if (line.contains(startTime)) { + line = line.replace(startTime, WebDavServlet.START_TIME); + } + stream.println(line); + } + } + stream.flush(); + } else { + previousHandler.processRequest(request, response, item); + } + } + + /** + * Determines whether request body shall be logged. + * + * @return {@code true} if request body shall be logged. + */ + public boolean getLogInput() { + return false; + } + + /** + * Determines whether response body shall be logged. + * + * @return {@code true} if response body shall be logged. + */ + public boolean getLogOutput() { + return false; + } + + /** + * Determines whether response content length shall be calculated by engine. + * + * @return {@code true} if content length shall be calculated by engine. + */ + public boolean getCalculateContentLength() { + return false; + } + + /** + * Set previous handler fo GET operation. + * + * @param methodHandler previous handler. + */ + void setPreviousHandler(MethodHandler methodHandler) { + previousHandler = methodHandler; + } +} diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FileImpl.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FileImpl.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FileImpl.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FileImpl.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FolderImpl.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FolderImpl.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FolderImpl.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/FolderImpl.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/HierarchyItemImpl.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/HierarchyItemImpl.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/HierarchyItemImpl.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/HierarchyItemImpl.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SearchFacade.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SearchFacade.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SearchFacade.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SearchFacade.java diff --git a/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SerializationUtils.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SerializationUtils.java new file mode 100644 index 0000000..a0f743c --- /dev/null +++ b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/SerializationUtils.java @@ -0,0 +1,46 @@ +package com.ithit.webdav.samples.fsstorageservlet; + + +import com.google.gson.Gson; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Utility class to perform serialization of objects. + */ +final class SerializationUtils { + + private SerializationUtils() { + } + + /** + * Serializes object to JSON string. + * + * @param object Object to serialize. + * @return String in JSON format + */ + static String serialize(T object) { + Gson gson = new Gson(); + return gson.toJson(object); + } + + /** + * Deserialize JSON string to object list. + * + * @param clazz Type of objects in the list to deserialize. + * @param json JSON string to deserialize. + * @return List of objects. + */ + @SuppressWarnings("unchecked") + static List deserializeList(final Class clazz, final String json) { + T[] array = (T[]) java.lang.reflect.Array.newInstance(clazz, 1); + array = new Gson().fromJson(json, (Type) array.getClass()); + if (array == null) { + return new ArrayList<>(); + } + return new ArrayList<>(Arrays.asList(array)); + } +} diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavEngine.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavEngine.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavEngine.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavEngine.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavServlet.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavServlet.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavServlet.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/WebDavServlet.java diff --git a/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/DefaultExtendedAttribute.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/DefaultExtendedAttribute.java new file mode 100644 index 0000000..b34d976 --- /dev/null +++ b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/DefaultExtendedAttribute.java @@ -0,0 +1,69 @@ +package com.ithit.webdav.samples.fsstorageservlet.extendedattributes; + +import java.io.IOException; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileTime; +import java.nio.file.attribute.UserDefinedFileAttributeView; +import java.util.List; + +/** + * ExtendedAttribute for most platforms using Java's UserDefinedFileAttributeView + * for extended file attributes. + */ +class DefaultExtendedAttribute implements ExtendedAttribute { + + /** + * {@inheritDoc} + */ + @Override + public void setExtendedAttribute(String path, String attribName, String attribValue) throws IOException { + final Path sysPath = Paths.get(path); + FileTime lastWriteTime = Files.getLastModifiedTime(sysPath, LinkOption.NOFOLLOW_LINKS); + + UserDefinedFileAttributeView view = Files + .getFileAttributeView(sysPath, UserDefinedFileAttributeView.class); + view.write(attribName, Charset.defaultCharset().encode(attribValue)); + + // File modification date should not change when locking and unlocking. Otherwise, client application may think that the file was changed. + // Preserve last modification date. + Files.setLastModifiedTime(sysPath, lastWriteTime); + } + + /** + * {@inheritDoc} + */ + @Override + public String getExtendedAttribute(String path, String attribName) throws IOException { + UserDefinedFileAttributeView view = Files.getFileAttributeView(Paths.get(path), UserDefinedFileAttributeView.class); + + List attrNames = view.list(); + for (String existAttrName : attrNames) { + if (existAttrName.equals(attribName)) { + ByteBuffer buf = ByteBuffer.allocate(view.size(attribName)); + view.read(attribName, buf); + // Workaround for https://openjdk.org/jeps/247 + ((Buffer) buf).flip(); + return Charset.defaultCharset().decode(buf).toString(); + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public void deleteExtendedAttribute(String path, String attribName) throws IOException { + UserDefinedFileAttributeView view = Files + .getFileAttributeView(Paths.get(path), UserDefinedFileAttributeView.class); + view.delete(attribName); + } + +} diff --git a/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttribute.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttribute.java new file mode 100644 index 0000000..de63138 --- /dev/null +++ b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttribute.java @@ -0,0 +1,59 @@ +package com.ithit.webdav.samples.fsstorageservlet.extendedattributes; + +import java.io.IOException; + +/** + * Provides support for reading, writing and removing of extended attributes. + */ +public interface ExtendedAttribute { + + String TEST_PROPERTY = "test"; + + /** + * Determines whether extended attributes are supported. + * + * @param path File or folder path to check attribute support. + * @return True if extended attributes are supported, false otherwise. + */ + default boolean isExtendedAttributeSupported(String path) { + boolean supports = true; + try { + setExtendedAttribute(path, TEST_PROPERTY, TEST_PROPERTY); + deleteExtendedAttribute(path, TEST_PROPERTY); + } catch (Exception e) { + supports = false; + } + return supports; + } + + /** + * Write the extended attribute to the file. + * + * @param path File or folder path to write attribute. + * @param attribName Attribute name. + * @param attribValue Attribute value. + * @throws IOException If file is not available or write attribute was unsuccessful. + */ + void setExtendedAttribute(String path, String attribName, String attribValue) throws IOException; + + /** + * Reads extended attribute. + * + * @param path File or folder path to read extended attribute. + * @param attribName Attribute name. + * @return Attribute value or null if attribute doesn't exist. + * @throws IOException If file is not available or read attribute was unsuccessful. + */ + String getExtendedAttribute(String path, String attribName) throws IOException; + + + /** + * Deletes extended attribute. + * + * @param path File or folder path to remove extended attribute. + * @param attribName Attribute name. + * @throws IOException If file is not available or delete attribute was unsuccessful. + */ + void deleteExtendedAttribute(String path, String attribName) throws IOException; + +} diff --git a/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributeFactory.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributeFactory.java new file mode 100644 index 0000000..2015c2e --- /dev/null +++ b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributeFactory.java @@ -0,0 +1,30 @@ +package com.ithit.webdav.samples.fsstorageservlet.extendedattributes; + +/** + * Factory-singleton which creates a ExtendedAttribute instance. + * Instance is valid for the current platform. + */ +final class ExtendedAttributeFactory { + + private ExtendedAttributeFactory() { + } + + private static ExtendedAttribute extendedAttribute; + + /** + * Builds a specific ExtendedAttribute for the current platform. + * + * @return Platform specific instance of ExtendedAttribute. + */ + static synchronized ExtendedAttribute buildFileExtendedAttributeSupport() { + if (extendedAttribute == null) { + if (System.getProperty("os.name").toLowerCase().contains("mac")) { + extendedAttribute = new OSXExtendedAttribute(); + } else { + extendedAttribute = new DefaultExtendedAttribute(); + } + } + return extendedAttribute; + } + +} diff --git a/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributesExtension.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributesExtension.java new file mode 100644 index 0000000..185a227 --- /dev/null +++ b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/ExtendedAttributesExtension.java @@ -0,0 +1,92 @@ +package com.ithit.webdav.samples.fsstorageservlet.extendedattributes; + +import com.ithit.webdav.server.exceptions.ServerException; + +import java.io.IOException; + +/** + * Helper extension methods for custom attributes. + */ +public final class ExtendedAttributesExtension { + + private ExtendedAttributesExtension() { + } + + /** + * Reads extended attribute. + * + * @param path File or folder path to read extended attribute. + * @param attribName Attribute name. + * @return Attribute value or null if attribute doesn't exist. + * @throws ServerException If file is not available or read attribute was unsuccessful. + */ + public static String getExtendedAttribute(String path, String attribName) throws ServerException { + try { + return getExtendedAttributeSupport().getExtendedAttribute(path, attribName); + } catch (IOException e) { + throw new ServerException(e.getMessage()); + } + } + + /** + * Write the extended attribute to the file. + * + * @param path File or folder path to write attribute. + * @param attribName Attribute name. + * @param attribValue Attribute value. + * @throws ServerException If file is not available or write attribute was unsuccessful. + */ + public static void setExtendedAttribute(String path, String attribName, String attribValue) throws ServerException { + try { + getExtendedAttributeSupport().setExtendedAttribute(path, attribName, attribValue); + } catch (IOException e) { + throw new ServerException(e.getMessage()); + } + } + + /** + * Checks extended attribute existence. + * + * @param path File or folder path to read extended attribute. + * @param attribName Attribute name. + * @return True if attribute exist, false otherwise. + * @throws ServerException If file is not available or read attribute was unsuccessful. + */ + public static boolean hasExtendedAttribute(String path, String attribName) throws ServerException { + try { + return getExtendedAttributeSupport().getExtendedAttribute(path, attribName) != null; + } catch (IOException e) { + throw new ServerException(e.getMessage()); + } + } + + /** + * Deletes extended attribute. + * + * @param path File or folder path to delete extended attributes. + * @param attribName Attribute name. + * @throws ServerException If file is not available or delete attribute was unsuccessful. + */ + public static void deleteExtendedAttribute(String path, String attribName) throws ServerException { + try { + getExtendedAttributeSupport().deleteExtendedAttribute(path, attribName); + } catch (IOException e) { + throw new ServerException(e.getMessage()); + } + } + + /** + * Determines whether extended attributes are supported. + * + * @param path File or folder path to check extended attributes support. + * @return True if extended attributes or NTFS file alternative streams are supported, false otherwise. + */ + public static boolean isExtendedAttributesSupported(String path) { + return getExtendedAttributeSupport().isExtendedAttributeSupported(path); + } + + private static ExtendedAttribute getExtendedAttributeSupport() { + return ExtendedAttributeFactory.buildFileExtendedAttributeSupport(); + } + +} diff --git a/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/OSXExtendedAttribute.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/OSXExtendedAttribute.java new file mode 100644 index 0000000..2b2ee1f --- /dev/null +++ b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/extendedattributes/OSXExtendedAttribute.java @@ -0,0 +1,48 @@ +package com.ithit.webdav.samples.fsstorageservlet.extendedattributes; + +import com.sun.jna.platform.mac.XAttrUtil; + +import java.io.IOException; + +/** + * OS X extended attribute support using native API. + */ +class OSXExtendedAttribute implements ExtendedAttribute { + + /** + * {@inheritDoc} + */ + @Override + public void setExtendedAttribute(String path, String attribName, String attribValue) throws IOException { + int result = XAttrUtil.setXAttr(path, attribName, attribValue); + if (result == -1) { + throw new IOException( + String.format("Writing attribute '%s' with value '%s' to file '%s' failed.", attribName, attribValue, path)); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String getExtendedAttribute(String path, String attribName) throws IOException { + try { + return XAttrUtil.getXAttr(path, attribName); + } catch (Exception e) { + throw new IOException( + String.format("Reading attribute '%s' from file '%s' failed.", attribName, path)); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void deleteExtendedAttribute(String path, String attribName) throws IOException { + int result = XAttrUtil.removeXAttr(path, attribName); + if (result == -1) { + throw new IOException( + String.format("Removing attribute '%s' from file '%s' failed.", attribName, path)); + } + } +} diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/staticresourceservlet/FileServlet.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/staticresourceservlet/FileServlet.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/staticresourceservlet/FileServlet.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/staticresourceservlet/FileServlet.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/GetHttpSessionConfigurator.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/GetHttpSessionConfigurator.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/GetHttpSessionConfigurator.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/GetHttpSessionConfigurator.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/NotificationEncoder.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/NotificationEncoder.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/NotificationEncoder.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/NotificationEncoder.java diff --git a/Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/WebSocketServer.java b/Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/WebSocketServer.java similarity index 100% rename from Java/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/WebSocketServer.java rename to Java/javax/filesystemstorage/src/main/java/com/ithit/webdav/samples/fsstorageservlet/websocket/WebSocketServer.java diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Document.pages b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Document.pages similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Document.pages rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Document.pages diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/General.docx b/Java/javax/filesystemstorage/src/main/storageresources/Storage/General.docx similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/General.docx rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/General.docx diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Introduction.pptx b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Introduction.pptx similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Introduction.pptx rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Introduction.pptx diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/Content.txt b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/Content.txt similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/Content.txt rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/Content.txt diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/General.doc b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/General.doc similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/General.doc rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/General.doc diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/Introduction.ppt b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/Introduction.ppt similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/Introduction.ppt rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/Introduction.ppt diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/Stat.xls b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/Stat.xls similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/Stat.xls rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/Stat.xls diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/Vision.mpp b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/Vision.mpp similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Library/Vision.mpp rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Library/Vision.mpp diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/My Directory/Notes.txt b/Java/javax/filesystemstorage/src/main/storageresources/Storage/My Directory/Notes.txt similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/My Directory/Notes.txt rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/My Directory/Notes.txt diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Notes.txt b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Notes.txt similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Notes.txt rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Notes.txt diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Presentation.key b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Presentation.key similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Presentation.key rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Presentation.key diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Products/General.doc b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Products/General.doc similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Products/General.doc rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Products/General.doc diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Products/General.vsd b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Products/General.vsd similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Products/General.vsd rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Products/General.vsd diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Products/Product.mpp b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Products/Product.mpp similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Products/Product.mpp rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Products/Product.mpp diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Project.pdf b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Project.pdf similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Project.pdf rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Project.pdf diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Plan.doc b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Plan.doc similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Plan.doc rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Plan.doc diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Prices.xls b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Prices.xls similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Prices.xls rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Australia/Prices.xls diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Introduction.ppt diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Prices.xls b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Prices.xls similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Prices.xls rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Prices.xls diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Product.mpp b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Product.mpp similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Product.mpp rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Product.mpp diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Stat.xls b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Stat.xls similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Stat.xls rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Canada/Stat.xls diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Europe/Stat.xls b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Europe/Stat.xls similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/Europe/Stat.xls rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/Europe/Stat.xls diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/USA/Vision.mpp b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/USA/Vision.mpp similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Sales/USA/Vision.mpp rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Sales/USA/Vision.mpp diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Spreadsheet.numbers b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Spreadsheet.numbers similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Spreadsheet.numbers rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Spreadsheet.numbers diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Stat.xlsx b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Stat.xlsx similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Stat.xlsx rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Stat.xlsx diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Templates/readme.txt b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Templates/readme.txt similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Templates/readme.txt rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Templates/readme.txt diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.dotx b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.dotx similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.dotx rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.dotx diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.potx b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.potx similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.potx rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.potx diff --git a/Kotlin/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.xltx b/Java/javax/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.xltx similarity index 100% rename from Kotlin/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.xltx rename to Java/javax/filesystemstorage/src/main/storageresources/Storage/Templates/template2013.xltx diff --git a/Kotlin/filesystemstorage/src/main/webapp/META-INF/context.xml b/Java/javax/filesystemstorage/src/main/webapp/META-INF/context.xml similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/META-INF/context.xml rename to Java/javax/filesystemstorage/src/main/webapp/META-INF/context.xml diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html diff --git a/Java/springboots3storage/src/main/resources/handler/attributesErrorPage.html b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html similarity index 100% rename from Java/springboots3storage/src/main/resources/handler/attributesErrorPage.html rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/glassfish-web.xml b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/glassfish-web.xml rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/jboss-web.xml b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/jboss-web.xml rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml diff --git a/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/web.xml b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..cfc2995 --- /dev/null +++ b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,105 @@ + + + + + FileServlet + com.ithit.webdav.samples.fsstorageservlet.staticresourceservlet.FileServlet + + + FileServlet + /wwwroot/* + + + + WebDav servlet + com.ithit.webdav.samples.fsstorageservlet.WebDavServlet + + license + D:\License.lic + + + showExceptions + true + + + root + + + + index-interval + 2 + + + maskRequestHeaders + accept-language,accept-encoding + + + + WebDav servlet + /* + + + + + + + + + + + + diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/weblogic.xml b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/weblogic.xml rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/AjaxFileBrowser.html b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/AjaxFileBrowser.html rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/AjaxIntegrationTests.html b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/AjaxIntegrationTests.html rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/css/webdav-layout.css b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/css/webdav-layout.css rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/cancel-button.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/cancel-button.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/check-square.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/check-square.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/copy.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/copy.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/create-folder.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/create-folder.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/cut.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/cut.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/delete.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/delete.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/download.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/download.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/edit-associated.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/edit-associated.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/edit.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/edit.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/file-archive-icon.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/file-archive-icon.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/file-default-icon.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/file-default-icon.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/file-image-icon.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/file-image-icon.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/file-pdf-icon.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/file-pdf-icon.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/folder.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/folder.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/home.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/home.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/locked.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/locked.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/logo.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/logo.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/menu-edit.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/menu-edit.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/microsoft-edit.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/microsoft-edit.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/open-folder.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/open-folder.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/paste.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/paste.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/pause-button.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/pause-button.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/play-button.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/play-button.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/print.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/print.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/reload.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/reload.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/rename.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/rename.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/search.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/search.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/up-one-level.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/up-one-level.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/images/upload.svg b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/images/upload.svg rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg diff --git a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json similarity index 52% rename from Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json index 5c75f6d..6032a70 100644 --- a/Java/deltav/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json +++ b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json @@ -9,16 +9,16 @@ } }, "node_modules/webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } }, "dependencies": { "webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } } } diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/package.json b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/package.json rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/webdav-common.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/webdav-common.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/webdav-gridview.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/webdav-gridview.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/webdav-uploader.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/webdav-uploader.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js diff --git a/Java/springbootfsstorage/src/main/resources/wwwroot/js/webdav-websocket.js b/Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js similarity index 100% rename from Java/springbootfsstorage/src/main/resources/wwwroot/js/webdav-websocket.js rename to Java/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js diff --git a/Java/oraclestorage/README.md b/Java/javax/oraclestorage/README.md similarity index 100% rename from Java/oraclestorage/README.md rename to Java/javax/oraclestorage/README.md diff --git a/Java/oraclestorage/pom.xml b/Java/javax/oraclestorage/pom.xml similarity index 95% rename from Java/oraclestorage/pom.xml rename to Java/javax/oraclestorage/pom.xml index d526822..5d54032 100644 --- a/Java/oraclestorage/pom.xml +++ b/Java/javax/oraclestorage/pom.xml @@ -6,7 +6,7 @@ com.ithit.webdav.samples oraclestorage - 6.2.9090-Beta + 6.3.9510-Beta war @@ -23,7 +23,7 @@ com.ithit.webdav.integration servlet-integration - 6.2.9090-Beta + 6.3.9510-Beta commons-dbcp @@ -125,7 +125,7 @@ com.ithit.webdav webdav-server - 6.2.9090-Beta + 6.3.9510-Beta @@ -144,15 +144,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - - org.apache.maven.plugins maven-resources-plugin @@ -165,7 +156,7 @@ copy-resources - ${project.build.directory}/oraclestorage-6.2.9090-Beta/META-INF + ${project.build.directory}/oraclestorage-6.3.9510-Beta/META-INF true @@ -244,7 +235,7 @@ filesystem 11021 / - target/oraclestorage-6.2.9090-Beta + target/oraclestorage-6.3.9510-Beta diff --git a/Java/oraclestorage/src/main/dbresources/db/OracleStorage.sql b/Java/javax/oraclestorage/src/main/dbresources/db/OracleStorage.sql similarity index 100% rename from Java/oraclestorage/src/main/dbresources/db/OracleStorage.sql rename to Java/javax/oraclestorage/src/main/dbresources/db/OracleStorage.sql diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/CustomFolderGetHandler.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/CustomFolderGetHandler.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/CustomFolderGetHandler.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/CustomFolderGetHandler.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/DataAccess.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/DataAccess.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/DataAccess.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/DataAccess.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/FileImpl.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/FileImpl.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/FileImpl.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/FileImpl.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/FolderImpl.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/FolderImpl.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/FolderImpl.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/FolderImpl.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/HierarchyItemImpl.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/HierarchyItemImpl.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/HierarchyItemImpl.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/HierarchyItemImpl.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/ItemType.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/ItemType.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/ItemType.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/ItemType.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/SearchFacade.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/SearchFacade.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/SearchFacade.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/SearchFacade.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/WebDavEngine.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/WebDavEngine.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/WebDavEngine.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/WebDavEngine.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/WebDavServlet.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/WebDavServlet.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/WebDavServlet.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/WebDavServlet.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/staticresourceservlet/FileServlet.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/staticresourceservlet/FileServlet.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/staticresourceservlet/FileServlet.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/staticresourceservlet/FileServlet.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/GetHttpSessionConfigurator.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/GetHttpSessionConfigurator.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/GetHttpSessionConfigurator.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/GetHttpSessionConfigurator.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/NotificationEncoder.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/NotificationEncoder.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/NotificationEncoder.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/NotificationEncoder.java diff --git a/Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/WebSocketServer.java b/Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/WebSocketServer.java similarity index 100% rename from Java/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/WebSocketServer.java rename to Java/javax/oraclestorage/src/main/java/com/ithit/webdav/samples/oraclestorageservlet/websocket/WebSocketServer.java diff --git a/Java/oraclestorage/src/main/tomcat/context.xml b/Java/javax/oraclestorage/src/main/tomcat/context.xml similarity index 100% rename from Java/oraclestorage/src/main/tomcat/context.xml rename to Java/javax/oraclestorage/src/main/tomcat/context.xml diff --git a/Java/oraclestorage/src/main/webapp/META-INF/context.xml b/Java/javax/oraclestorage/src/main/webapp/META-INF/context.xml similarity index 100% rename from Java/oraclestorage/src/main/webapp/META-INF/context.xml rename to Java/javax/oraclestorage/src/main/webapp/META-INF/context.xml diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/MyCustomHandlerPage.html diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/glassfish-web.xml similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/glassfish-web.xml diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/jboss-web.xml similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/jboss-web.xml diff --git a/Java/oraclestorage/src/main/webapp/WEB-INF/web.xml b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from Java/oraclestorage/src/main/webapp/WEB-INF/web.xml rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/web.xml diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/weblogic.xml similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/weblogic.xml diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/AjaxFileBrowser.html b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/AjaxFileBrowser.html rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/AjaxIntegrationTests.html b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/AjaxIntegrationTests.html rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/css/webdav-layout.css b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/css/webdav-layout.css rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/cancel-button.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/cancel-button.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/check-square.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/check-square.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/copy.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/copy.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/create-folder.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/create-folder.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/cut.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/cut.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/delete.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/delete.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/download.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/download.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/edit-associated.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/edit-associated.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/edit.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/edit.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/file-archive-icon.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/file-archive-icon.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/file-default-icon.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/file-default-icon.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/file-image-icon.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/file-image-icon.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/file-pdf-icon.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/file-pdf-icon.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/folder.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/folder.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/home.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/home.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/locked.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/locked.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/logo.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/logo.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/menu-edit.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/menu-edit.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/microsoft-edit.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/microsoft-edit.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/open-folder.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/open-folder.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/paste.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/paste.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/pause-button.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/pause-button.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/play-button.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/play-button.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/print.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/print.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/reload.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/reload.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/rename.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/rename.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/search.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/search.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/up-one-level.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/up-one-level.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/images/upload.svg b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/images/upload.svg rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg diff --git a/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json new file mode 100644 index 0000000..6032a70 --- /dev/null +++ b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json @@ -0,0 +1,24 @@ +{ + "name": "js", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "webdav.client": "*" + } + }, + "node_modules/webdav.client": { + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" + } + }, + "dependencies": { + "webdav.client": { + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" + } + } +} diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/package.json b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package.json similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/package.json rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/package.json diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-common.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-common.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-gridview.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-gridview.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-uploader.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-uploader.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js diff --git a/Java/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-websocket.js b/Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-websocket.js rename to Java/javax/oraclestorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js diff --git a/Java/springbootoraclestorage/.mvn/wrapper/maven-wrapper.properties b/Java/javax/springbootfsstorage/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from Java/springbootoraclestorage/.mvn/wrapper/maven-wrapper.properties rename to Java/javax/springbootfsstorage/.mvn/wrapper/maven-wrapper.properties diff --git a/Java/javax/springbootfsstorage/README.md b/Java/javax/springbootfsstorage/README.md new file mode 100644 index 0000000..f7914e7 --- /dev/null +++ b/Java/javax/springbootfsstorage/README.md @@ -0,0 +1,81 @@ + +

Spring Boot WebDAV Server Example with File System Back-end, Java

+

This sample provides a WebDAV server running on the Spring Boot framework with files being stored in the file system. The WebDAV requests are processed in a dedicated context, while the rest of the website processes regular HTTP requests, serving web pages. Documents are being published from the file system while the locks and custom attributes are being stored in Alternating Data Streams (in case of NTFS) or in Extended Attributes (in case of Linux and macOS). 

+

This sample can be downloaded in the product download area as well as it is published on GitHub.

+

This sample is using IT Hit WebDAV Ajax Library to display and browse server content on a default web page as well as to open documents for editing from a web page and save back directly to the server.

+

Requirements

+ +

Running the sample

+
    +
  1. Set the license. Download your license file here. To set the license, edit the webdav.license section in \springboot\src\main\resources\application.properties and specify the path to the license.lic file.
    +
    webdav.license=C:\License.lic
    +The IT Hit Java WebDAV Server Library is fully functional and does not have any limitations. However, the trial period is limited to 1 month. After the trial period expires the Java WebDAV Server will stop working.
  2. +
  3. Configure the storage folder. By default, this sample publishes documents from the springboot\src\main\resources\Storage\ folder. For the sake of configuration simplicity, documents are extracted from project resources during the first run. You can publish documents from any other folder specifying a path in the webdav.rootFolder section in application.properties:
    +
    webdav.rootFolder=C:\Storage
    +
  4. +
  5. Configure the application server. Here we will configure the WebDAV server to run on the website non-root context (https://server/DAV/). This setting is located in the webdav.rootContext section in the \springboot\src\main\resources\application.properties.
    +
    webdav.rootContext=/DAV/
    +Note: Some WebDAV clients (such as some old versions or Mini-redirector, Microsoft Web Folders, and MS Office 2007 and earlier) will fail to connect to a non-root server. They submit configuration requests to server root and if they do not get the response they will not be able to connect. For this reason, this sample processes OPTIONS and PROPFIND requests on all folders, including on the site root (https://server/). See also Making Microsoft Office to Work with WebDAV Server and Opening Microsoft Office Documents and Other Types of Files for Editing From a Web Page.
    This Spring Boot sample supports those configuration requests and works properly on a non-root context.
  6. +
  7. Running the springboot sample. To start the sample, change the directory to springboot and execute the following command: +
    mvnw spring-boot:run
    +

    If everything was set up properly you should see a sample web page on  https://server/DAV/ URL with a list of sample files and folders from your storge folder in the file system, configured in step 2. Now you can open documents for editing, manage documents, as well as connect to the server with any WebDAV client.

    +

    If anything goes wrong examine the log file. For Spring Boot, the log file is usually located at springboot/log/engine.log. You may also need to capture and examine the HTTP requests. See this article for more details. 

    +
  8. +
+

Authentication

+

This sample supports Anonymous access as well as MS-OFBA authentication against Azure ADBy default, the authentication is disabled and this sample allows full anonymous access.

+

To enable the MS-OFBA, uncomment MS-OFBA settings block in the application.properties file of the sample.

+
## This is Azure security configuration section.
+## If you want to use Azure login - uncomment configurations bellow.
+# Specifies your Active Directory ID:
+#azure.activedirectory.tenant-id=
+# Specifies your App Registration's Application ID:
+#azure.activedirectory.client-id=
+# Specifies your App Registration's secret key:
+#azure.activedirectory.client-secret=
+

To get these properties you must register new (or use existing) application under your Azure Active Directory. To register the new Azure AD application follow these steps:

+
    +
  1. +

    Navigate to Azure Active Directory -> App Registrations. Select New Registration.

    +

    New application registration in Azure AD

    +
  2. +
  3. +

    Enter the app name. You MUST also enter the Redirect URI. Confirm registration.

    +

    Specify the Redirect URI.

    +
  4. +
  5. +

    Open the newly created app registration.

    +

    Copy the Application (client) ID and Directory (tenant) ID into settings.

    +

    Copy the Application (client) ID and Directory (tenant) ID fields and paste them into client-id and tenant-id settings in the application.properties file.

    +
  6. +
  7. +

    Navigate to Certificates & secrets. Select New client secret. Enter the secret name and confirm the client secret creation.

    +

    Create new client secret

    +

    Copy the newly created secret value and past it into client-secret setting in the application.properties file.

    +

    Copy the newly created secret value and past it into client-secret setting.

    +
  8. +
+

 

+

After getting all data put it in properties file and run the sample. You will get Azure login screen on attemp to access WebDAV page. 

+

The Project Classes

+

On the diagram below you can see the classes in the WebDAV SpringBoot sample:

+

Class diagram of the sample Java WebDAV Server running on Spring Boot

+

To adapt the sample to your needs, you will modify these classes to read and write data from and into your storage. You can find more about this in Creating a Class 1 WebDAV Server and Creating Class 2 WebDAV Server article as well as in the class reference documentation.

+

 

+

See Also:

+ +

 

+

Next Article:

+Spring Boot WebDAV Server Example with Oracle Back-end, Java + diff --git a/Java/springbootoraclestorage/mvnw b/Java/javax/springbootfsstorage/mvnw similarity index 100% rename from Java/springbootoraclestorage/mvnw rename to Java/javax/springbootfsstorage/mvnw diff --git a/Java/springbootoraclestorage/mvnw.cmd b/Java/javax/springbootfsstorage/mvnw.cmd similarity index 100% rename from Java/springbootoraclestorage/mvnw.cmd rename to Java/javax/springbootfsstorage/mvnw.cmd diff --git a/Java/springbootfsstorage/pom.xml b/Java/javax/springbootfsstorage/pom.xml similarity index 98% rename from Java/springbootfsstorage/pom.xml rename to Java/javax/springbootfsstorage/pom.xml index 16e0ecc..3176d25 100644 --- a/Java/springbootfsstorage/pom.xml +++ b/Java/javax/springbootfsstorage/pom.xml @@ -9,7 +9,7 @@ com.ithit.webdav.samples springbootfsstorage - 6.2.9090-Beta + 6.3.9510-Beta springbootfsstorage Demo project for Spring Boot @@ -52,12 +52,12 @@ com.ithit.webdav webdav-server - 6.2.9090-Beta + 6.3.9510-Beta com.ithit.webdav.integration servlet-integration - 6.2.9090-Beta + 6.3.9510-Beta diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/SpringBootSampleApplication.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/SpringBootSampleApplication.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/SpringBootSampleApplication.java rename to Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/SpringBootSampleApplication.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/common/ResourceReader.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/common/ResourceReader.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/common/ResourceReader.java rename to Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/common/ResourceReader.java diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfiguration.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfiguration.java new file mode 100644 index 0000000..2b312b3 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfiguration.java @@ -0,0 +1,177 @@ +package com.ithit.webdav.samples.springbootfs.configuration; + +import com.ithit.webdav.samples.springbootfs.common.ResourceReader; +import com.ithit.webdav.samples.springbootfs.extendedattributes.ExtendedAttributesExtension; +import com.ithit.webdav.samples.springbootfs.impl.CustomFolderGetHandler; +import com.ithit.webdav.samples.springbootfs.impl.SearchFacade; +import com.ithit.webdav.samples.springbootfs.impl.WebDavEngine; +import com.ithit.webdav.samples.springbootfs.websocket.HandshakeHeadersInterceptor; +import com.ithit.webdav.samples.springbootfs.websocket.SocketHandler; +import com.ithit.webdav.samples.springbootfs.websocket.WebSocketServer; +import com.ithit.webdav.server.Engine; +import com.ithit.webdav.server.util.StringUtil; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.experimental.FieldDefaults; +import org.apache.commons.io.FileUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.util.StreamUtils; +import org.springframework.web.context.annotation.RequestScope; +import org.springframework.web.context.request.RequestContextListener; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; + +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PRIVATE) +@EnableConfigurationProperties(WebDavConfigurationProperties.class) +@EnableWebSocket +@Configuration +public class WebDavConfiguration extends WebMvcConfigurationSupport implements WebSocketConfigurer { + final WebDavConfigurationProperties properties; + final ResourceReader resourceReader; + @Value("classpath:handler/MyCustomHandlerPage.html") + Resource customGetHandler; + @Value("classpath:handler/attributesErrorPage.html") + Resource errorPage; + private final SocketHandler socketHandler = new SocketHandler(); + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(Collections.singletonList("*")); + configuration.setAllowedMethods(Arrays.asList("PROPFIND", "PROPPATCH", "COPY", "MOVE", "DELETE", "MKCOL", "LOCK", "UNLOCK", "PUT", "GETLIB", "VERSION-CONTROL", "CHECKIN", "CHECKOUT", "UNCHECKOUT", "REPORT", "UPDATE", "CANCELUPLOAD", "HEAD", "OPTIONS", "GET", "POST")); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } + + @Bean + public RequestContextListener requestContextListener() { + return new RequestContextListener(); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // -1 will allow to process static resources if main controller is running on the root. + registry.setOrder(-1); + registry.addResourceHandler("/wwwroot/**") + .addResourceLocations("classpath:/wwwroot/", "/wwwroot/"); + } + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(socketHandler, properties.getRootWebSocket()).addInterceptors(new HandshakeHeadersInterceptor()).setAllowedOrigins("*"); + } + + @RequestScope + @Bean + public WebDavEngine engine() { + String rootLocalPath = rootLocalPath(); + String license; + try { + license = FileUtils.readFileToString(new File(properties.getLicense()), StandardCharsets.UTF_8); + } catch (IOException e) { + license = ""; + } + final WebDavEngine webDavEngine = new WebDavEngine(license, rootLocalPath, properties.isShowExceptions(), properties.getRootContext()); + final boolean extendedAttributesSupported = ExtendedAttributesExtension.isExtendedAttributesSupported(rootLocalPath); + CustomFolderGetHandler handler = new CustomFolderGetHandler(webDavEngine.getResponseCharacterEncoding(), Engine.getVersion(), extendedAttributesSupported, customGetHandler(), errorPage(), properties.getRootContext()); + CustomFolderGetHandler handlerHead = new CustomFolderGetHandler(webDavEngine.getResponseCharacterEncoding(), Engine.getVersion(), extendedAttributesSupported, customGetHandler(), errorPage(), properties.getRootContext()); + handler.setPreviousHandler(webDavEngine.registerMethodHandler("GET", handler)); + handlerHead.setPreviousHandler(webDavEngine.registerMethodHandler("HEAD", handlerHead)); + String indexLocalPath = createIndexPath(); + if (rootLocalPath != null && indexLocalPath != null) { + SearchFacade searchFacade = SearchFacade.getInstance(webDavEngine, webDavEngine.getLogger()); + searchFacade.indexRootFolder(rootLocalPath, indexLocalPath, 2); + webDavEngine.setSearchFacade(searchFacade); + } + webDavEngine.setWebSocketServer(new WebSocketServer(socketHandler.getSessions())); + return webDavEngine; + } + + @Bean + public String rootLocalPath() { + return checkRootPath(properties.getRootFolder(), Paths.get(properties.getRootFolder()).normalize().toString()); + } + + @Bean + public String customGetHandler() { + return getStreamAsString(customGetHandler); + } + + @Bean + public String errorPage() { + return getStreamAsString(errorPage); + } + + @SneakyThrows + private String getStreamAsString(Resource customGetHandler) { + try (InputStream is = customGetHandler.getInputStream()) { + return StreamUtils.copyToString(is, StandardCharsets.UTF_8); + } + } + + private String checkRootPath(String rootPath, String path) { + String realPath = resourceReader.getRootFolder(); + if (StringUtil.isNullOrEmpty(rootPath)) { + path = createDefaultPath(); + } else { + if (Files.exists(Paths.get(rootPath))) { + return path; + } + try { + Path relative = Paths.get(realPath, rootPath); + if (Files.exists(relative)) { + path = relative.toString(); + } else { + path = createDefaultPath(); + } + } catch (Exception ignored) { + path = createDefaultPath(); + } + } + return path; + } + + private String createDefaultPath() { + return resourceReader.getDefaultPath(); + } + + /** + * Creates index folder if not exists. + * + * @return Absolute location of index folder. + */ + private String createIndexPath() { + Path indexLocalPath = Paths.get(resourceReader.getDefaultIndexFolder()); + if (Files.notExists(indexLocalPath)) { + try { + Files.createDirectory(indexLocalPath); + } catch (IOException e) { + return null; + } + } + return indexLocalPath.toString(); + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfigurationProperties.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfigurationProperties.java new file mode 100644 index 0000000..9a4ac3b --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/configuration/WebDavConfigurationProperties.java @@ -0,0 +1,19 @@ +package com.ithit.webdav.samples.springbootfs.configuration; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldDefaults; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Setter +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +@ConfigurationProperties(prefix = "webdav") +public class WebDavConfigurationProperties { + String license; + boolean showExceptions; + String rootFolder; + String rootContext; + String rootWebSocket; +} diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/DavFilter.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/DavFilter.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/DavFilter.java rename to Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/DavFilter.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/SamplesController.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/SamplesController.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/SamplesController.java rename to Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/controller/SamplesController.java diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/DefaultExtendedAttribute.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/DefaultExtendedAttribute.java new file mode 100644 index 0000000..cfcde05 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/DefaultExtendedAttribute.java @@ -0,0 +1,69 @@ +package com.ithit.webdav.samples.springbootfs.extendedattributes; + +import java.io.IOException; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileTime; +import java.nio.file.attribute.UserDefinedFileAttributeView; +import java.util.List; + +/** + * ExtendedAttribute for most platforms using Java's UserDefinedFileAttributeView + * for extended file attributes. + */ +class DefaultExtendedAttribute implements ExtendedAttribute { + + /** + * {@inheritDoc} + */ + @Override + public void setExtendedAttribute(String path, String attribName, String attribValue) throws IOException { + final Path sysPath = Paths.get(path); + FileTime lastWriteTime = Files.getLastModifiedTime(sysPath, LinkOption.NOFOLLOW_LINKS); + + UserDefinedFileAttributeView view = Files + .getFileAttributeView(sysPath, UserDefinedFileAttributeView.class); + view.write(attribName, Charset.defaultCharset().encode(attribValue)); + + // File modification date should not change when locking and unlocking. Otherwise, client application may think that the file was changed. + // Preserve last modification date. + Files.setLastModifiedTime(sysPath, lastWriteTime); + } + + /** + * {@inheritDoc} + */ + @Override + public String getExtendedAttribute(String path, String attribName) throws IOException { + UserDefinedFileAttributeView view = Files.getFileAttributeView(Paths.get(path), UserDefinedFileAttributeView.class); + + List attrNames = view.list(); + for (String existAttrName : attrNames) { + if (existAttrName.equals(attribName)) { + ByteBuffer buf = ByteBuffer.allocate(view.size(attribName)); + view.read(attribName, buf); + // Workaround for https://openjdk.org/jeps/247 + ((Buffer) buf).flip(); + return Charset.defaultCharset().decode(buf).toString(); + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public void deleteExtendedAttribute(String path, String attribName) throws IOException { + UserDefinedFileAttributeView view = Files + .getFileAttributeView(Paths.get(path), UserDefinedFileAttributeView.class); + view.delete(attribName); + } + +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttribute.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttribute.java new file mode 100644 index 0000000..37aecf6 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttribute.java @@ -0,0 +1,59 @@ +package com.ithit.webdav.samples.springbootfs.extendedattributes; + +import java.io.IOException; + +/** + * Provides support for reading, writing and removing of extended attributes. + */ +public interface ExtendedAttribute { + + String TEST_PROPERTY = "test"; + + /** + * Determines whether extended attributes are supported. + * + * @param path File or folder path to check attribute support. + * @return True if extended attributes are supported, false otherwise. + */ + default boolean isExtendedAttributeSupported(String path) { + boolean supports = true; + try { + setExtendedAttribute(path, TEST_PROPERTY, TEST_PROPERTY); + deleteExtendedAttribute(path, TEST_PROPERTY); + } catch (Exception e) { + supports = false; + } + return supports; + } + + /** + * Write the extended attribute to the file. + * + * @param path File or folder path to write attribute. + * @param attribName Attribute name. + * @param attribValue Attribute value. + * @throws IOException If file is not available or write attribute was unsuccessful. + */ + void setExtendedAttribute(String path, String attribName, String attribValue) throws IOException; + + /** + * Reads extended attribute. + * + * @param path File or folder path to read extended attribute. + * @param attribName Attribute name. + * @return Attribute value or null if attribute doesn't exist. + * @throws IOException If file is not available or read attribute was unsuccessful. + */ + String getExtendedAttribute(String path, String attribName) throws IOException; + + + /** + * Deletes extended attribute. + * + * @param path File or folder path to remove extended attribute. + * @param attribName Attribute name. + * @throws IOException If file is not available or delete attribute was unsuccessful. + */ + void deleteExtendedAttribute(String path, String attribName) throws IOException; + +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributeFactory.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributeFactory.java new file mode 100644 index 0000000..bad4014 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributeFactory.java @@ -0,0 +1,30 @@ +package com.ithit.webdav.samples.springbootfs.extendedattributes; + +/** + * Factory-singleton which creates a ExtendedAttribute instance. + * Instance is valid for the current platform. + */ +final class ExtendedAttributeFactory { + + private ExtendedAttributeFactory() { + } + + private static ExtendedAttribute extendedAttribute; + + /** + * Builds a specific ExtendedAttribute for the current platform. + * + * @return Platform specific instance of ExtendedAttribute. + */ + static synchronized ExtendedAttribute buildFileExtendedAttributeSupport() { + if (extendedAttribute == null) { + if (System.getProperty("os.name").toLowerCase().contains("mac")) { + extendedAttribute = new OSXExtendedAttribute(); + } else { + extendedAttribute = new DefaultExtendedAttribute(); + } + } + return extendedAttribute; + } + +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributesExtension.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributesExtension.java new file mode 100644 index 0000000..9facec1 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/ExtendedAttributesExtension.java @@ -0,0 +1,92 @@ +package com.ithit.webdav.samples.springbootfs.extendedattributes; + +import com.ithit.webdav.server.exceptions.ServerException; + +import java.io.IOException; + +/** + * Helper extension methods for custom attributes. + */ +public final class ExtendedAttributesExtension { + + private ExtendedAttributesExtension() { + } + + /** + * Reads extended attribute. + * + * @param path File or folder path to read extended attribute. + * @param attribName Attribute name. + * @return Attribute value or null if attribute doesn't exist. + * @throws ServerException If file is not available or read attribute was unsuccessful. + */ + public static String getExtendedAttribute(String path, String attribName) throws ServerException { + try { + return getExtendedAttributeSupport().getExtendedAttribute(path, attribName); + } catch (IOException e) { + throw new ServerException(e.getMessage()); + } + } + + /** + * Write the extended attribute to the file. + * + * @param path File or folder path to write attribute. + * @param attribName Attribute name. + * @param attribValue Attribute value. + * @throws ServerException If file is not available or write attribute was unsuccessful. + */ + public static void setExtendedAttribute(String path, String attribName, String attribValue) throws ServerException { + try { + getExtendedAttributeSupport().setExtendedAttribute(path, attribName, attribValue); + } catch (IOException e) { + throw new ServerException(e.getMessage()); + } + } + + /** + * Checks extended attribute existence. + * + * @param path File or folder path to read extended attribute. + * @param attribName Attribute name. + * @return True if attribute exist, false otherwise. + * @throws ServerException If file is not available or read attribute was unsuccessful. + */ + public static boolean hasExtendedAttribute(String path, String attribName) throws ServerException { + try { + return getExtendedAttributeSupport().getExtendedAttribute(path, attribName) != null; + } catch (IOException e) { + throw new ServerException(e.getMessage()); + } + } + + /** + * Deletes extended attribute. + * + * @param path File or folder path to delete extended attributes. + * @param attribName Attribute name. + * @throws ServerException If file is not available or delete attribute was unsuccessful. + */ + public static void deleteExtendedAttribute(String path, String attribName) throws ServerException { + try { + getExtendedAttributeSupport().deleteExtendedAttribute(path, attribName); + } catch (IOException e) { + throw new ServerException(e.getMessage()); + } + } + + /** + * Determines whether extended attributes are supported. + * + * @param path File or folder path to check extended attributes support. + * @return True if extended attributes or NTFS file alternative streams are supported, false otherwise. + */ + public static boolean isExtendedAttributesSupported(String path) { + return getExtendedAttributeSupport().isExtendedAttributeSupported(path); + } + + private static ExtendedAttribute getExtendedAttributeSupport() { + return ExtendedAttributeFactory.buildFileExtendedAttributeSupport(); + } + +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/OSXExtendedAttribute.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/OSXExtendedAttribute.java new file mode 100644 index 0000000..b28d98d --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/extendedattributes/OSXExtendedAttribute.java @@ -0,0 +1,48 @@ +package com.ithit.webdav.samples.springbootfs.extendedattributes; + +import com.sun.jna.platform.mac.XAttrUtil; + +import java.io.IOException; + +/** + * OS X extended attribute support using native API. + */ +class OSXExtendedAttribute implements ExtendedAttribute { + + /** + * {@inheritDoc} + */ + @Override + public void setExtendedAttribute(String path, String attribName, String attribValue) throws IOException { + int result = XAttrUtil.setXAttr(path, attribName, attribValue); + if (result == -1) { + throw new IOException( + String.format("Writing attribute '%s' with value '%s' to file '%s' failed.", attribName, attribValue, path)); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String getExtendedAttribute(String path, String attribName) throws IOException { + try { + return XAttrUtil.getXAttr(path, attribName); + } catch (Exception e) { + throw new IOException( + String.format("Reading attribute '%s' from file '%s' failed.", attribName, path)); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void deleteExtendedAttribute(String path, String attribName) throws IOException { + int result = XAttrUtil.removeXAttr(path, attribName); + if (result == -1) { + throw new IOException( + String.format("Removing attribute '%s' from file '%s' failed.", attribName, path)); + } + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/CustomFolderGetHandler.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/CustomFolderGetHandler.java new file mode 100644 index 0000000..4aae314 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/CustomFolderGetHandler.java @@ -0,0 +1,96 @@ +package com.ithit.webdav.samples.springbootfs.impl; + +import com.ithit.webdav.server.*; +import com.ithit.webdav.server.exceptions.DavException; + +import java.io.IOException; +import java.io.PrintStream; + +/** + * This handler processes GET requests to folders returning custom HTML page. + */ +public class CustomFolderGetHandler implements MethodHandler { + + private MethodHandler previousHandler; + private final String charset; + private final String version; + private final boolean customAttributeSupported; + private String customPage; + private final String errorPage; + private final String rootContext; + + public CustomFolderGetHandler(String charset, String version, boolean customAttributeSupported, String customPage, String errorPage, String rootContext) { + this.charset = charset; + this.version = version; + this.customAttributeSupported = customAttributeSupported; + this.customPage = customPage; + this.errorPage = errorPage; + this.rootContext = rootContext; + } + + @Override + public void processRequest(DavRequest request, DavResponse response, HierarchyItem item) + throws DavException, IOException { + if (item instanceof Folder) { + PrintStream stream = new PrintStream(response.getOutputStream(), true, charset); + response.setCharacterEncoding(charset); + response.setContentType("text/html"); + if (!customAttributeSupported) { + stream.println(errorPage); + } else { + String versionNumber = "<%version%>"; + if (customPage.contains(versionNumber)) { + customPage = customPage.replace(versionNumber, version); + } + String contextRoot = "<%context root%>"; + if (customPage.contains(contextRoot)) { + customPage = customPage.replace(contextRoot, rootContext); + } + String startTime = "<%startTime%>"; + if (customPage.contains(startTime)) { + customPage = customPage.replace(startTime, "" + System.currentTimeMillis()); + } + stream.println(customPage); + } + stream.flush(); + } else { + previousHandler.processRequest(request, response, item); + } + } + + /** + * Determines whether request body shall be logged. + * + * @return {@code true} if request body shall be logged. + */ + public boolean getLogInput() { + return false; + } + + /** + * Determines whether response body shall be logged. + * + * @return {@code true} if response body shall be logged. + */ + public boolean getLogOutput() { + return false; + } + + /** + * Determines whether response content length shall be calculated by engine. + * + * @return {@code true} if content length shall be calculated by engine. + */ + public boolean getCalculateContentLength() { + return false; + } + + /** + * Set previous handler fo GET operation. + * + * @param methodHandler previous handler. + */ + public void setPreviousHandler(MethodHandler methodHandler) { + previousHandler = methodHandler; + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FileImpl.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FileImpl.java new file mode 100644 index 0000000..80dc33a --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FileImpl.java @@ -0,0 +1,415 @@ +package com.ithit.webdav.samples.springbootfs.impl; + +import com.ithit.webdav.samples.springbootfs.extendedattributes.ExtendedAttributesExtension; +import com.ithit.webdav.server.*; +import com.ithit.webdav.server.exceptions.ConflictException; +import com.ithit.webdav.server.exceptions.LockedException; +import com.ithit.webdav.server.exceptions.MultistatusException; +import com.ithit.webdav.server.exceptions.ServerException; +import com.ithit.webdav.server.resumableupload.ResumableUpload; +import com.ithit.webdav.server.resumableupload.UploadProgress; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * Represents file in the File System repository. + */ +final class FileImpl extends HierarchyItemImpl implements File, Lock, + ResumableUpload, UploadProgress { + + private static final int BUFFER_SIZE = 1048576; // 1 Mb + + private String snippet; + + private final OpenOption[] allowedOpenFileOptions; + + /** + * Initializes a new instance of the {@link FileImpl} class. + * + * @param name Name of hierarchy item. + * @param path Relative to WebDAV root folder path. + * @param created Creation time of the hierarchy item. + * @param modified Modification time of the hierarchy item. + * @param engine Instance of current {@link WebDavEngine}. + */ + private FileImpl(String name, String path, long created, long modified, WebDavEngine engine) { + super(name, path, created, modified, engine); + + /* Mac OS X and Ubuntu doesn't work with ExtendedOpenOption.NOSHARE_DELETE */ + String systemName = System.getProperty("os.name").toLowerCase(); + this.allowedOpenFileOptions = (systemName.contains("mac") || systemName.contains("linux")) ? + (new OpenOption[]{StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.READ}) : + (new OpenOption[]{StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.READ, + noShareDeleteOption()}); + } + + /** + * Load ExtendedOpenOption with reflection without direct reference - because most of Linux/MacOS jdks don't have it and not required. + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private OpenOption noShareDeleteOption() { + try { + Class enumClass = Class.forName("com.sun.nio.file.ExtendedOpenOption"); + return (OpenOption) Enum.valueOf(enumClass, "NOSHARE_DELETE"); + } catch (ClassNotFoundException e) { + return StandardOpenOption.READ; + } + } + /** + * Returns file that corresponds to path. + * + * @param path Encoded path relative to WebDAV root. + * @param engine Instance of {@link WebDavEngine} + * @return File instance or null if physical file not found in file system. + * @throws ServerException in case of exception + */ + static FileImpl getFile(String path, WebDavEngine engine) throws ServerException { + BasicFileAttributes view = null; + Path fullPath; + String name = null; + try { + String realPath = engine.getContextAware(path); + String pathFragment = decodeAndConvertToPath(realPath); + String rootFolder = engine.getDataFolder(); + fullPath = Paths.get(rootFolder, pathFragment); + if (Files.exists(fullPath)) { + name = Paths.get(pathFragment).getFileName().toString(); + view = Files.getFileAttributeView(fullPath, BasicFileAttributeView.class).readAttributes(); + } + if (view == null) { + return null; + } + } catch (IOException e) { + throw new ServerException(); + } + long created = view.creationTime().toMillis(); + long modified = view.lastModifiedTime().toMillis(); + return new FileImpl(name, path, created, modified, engine); + } + + /** + * Array of items that are being uploaded to this item subtree. + * + * @return Return array with a single item if implemented on file items. Return all items that are being uploaded to this subtree if implemented on folder items. + * @throws ServerException - in case of an error. + */ + @Override + public List getUploadProgress() + throws ServerException { + return Collections.singletonList(this); + } + + /** + * In this method implementation you can delete partially uploaded file. + *

+ * Client do not plan to restore upload. Remove any temporary files / cleanup resources here. + * + * @throws LockedException - this item or its parent was locked and client did not provide lock token. + * @throws ServerException - in case of an error. + */ + @Override + public void cancelUpload() throws LockedException, ServerException { + ensureHasToken(); + } + + /** + * Amount of bytes successfully saved to your storage. + * + * @return Amount of bytes successfully saved. + * @throws ServerException in case of an error. + */ + @Override + public long getBytesUploaded() throws ServerException { + return getContentLength(); + } + + /** + * Indicates if item will be checked-in by the engine when last chunk of a file is uploaded + * if item was checked in when upload started. + * + * @return True if item will be checked in when upload finishes. + * @throws ServerException in case of an error. + */ + @Override + public boolean getCheckInOnFileComplete() throws ServerException { + return false; + } + + /** + * Shall store value which indicates whether file will be checked in when upload finishes. + * + * @param value True if item will be checked in when upload finishes. + * @throws ServerException in case of an error. + */ + @Override + public void setCheckInOnFileComplete(boolean value) throws ServerException { + throw new ServerException("Not implemented"); + } + + /** + * The date and time when the last chunk of file was saved in your storage. + * + * @return Time when last chunk of file was saved. + * @throws ServerException in case of an error. + */ + @Override + public long getLastChunkSaved() throws ServerException { + return getModified(); + } + + /** + * Total file size that is being uploaded. + * + * @return Total file size in bytes. + * @throws ServerException in case of an error. + */ + @Override + public long getTotalContentLength() throws ServerException { + return getContentLength(); + } + + /** + * Gets the size of the file content in bytes. + * + * @return Length of the file content in bytes. + * @throws ServerException In case of an error. + */ + @Override + public long getContentLength() throws ServerException { + Path fullPath = getFullPath(); + long size = 0; + if (Files.exists(fullPath)) { + try { + size = Files.size(fullPath); + } catch (IOException e) { + throw new ServerException(e); + } + } + return size; + } + + /** + * Gets the media type of the {@link FileImpl}. + * + * @return MIME type of the file. + * @throws ServerException In case of an error. + */ + @Override + public String getContentType() throws ServerException { + String name = this.getName(); + int periodIndex = name.lastIndexOf('.'); + String ext = name.substring(periodIndex + 1); + String contentType = MimeType.getInstance().getMimeType(ext); + if (contentType == null) + contentType = "application/octet-stream"; + return contentType; + } + + @Override + public String getEtag() throws ServerException { + return String.format("%s-%s", Long.hashCode(getModified()), getSerialNumber()); + } + + /** + * Writes the content of the file to the specified stream. + * + * @param out Output stream. + * @param startIndex Zero-based byte offset in file content at which to begin copying bytes to the output stream. + * @param count Number of bytes to be written to the output stream. + * @throws ServerException In case of an error. + */ + @Override + public void read(OutputStream out, long startIndex, long count) throws ServerException { + Path fullPath = this.getFullPath(); + byte[] buf = new byte[BUFFER_SIZE]; + int retVal; + try (InputStream in = Files.newInputStream(fullPath)) { + in.skip(startIndex); + while ((retVal = in.read(buf)) > 0) { + // Strict servlet API doesn't allow to write more bytes then content length. So we do this trick. + if (retVal > count) { + retVal = (int) count; + } + out.write(buf, 0, retVal); + startIndex += retVal; + count -= retVal; + } + } catch (IOException x) { + throw new ServerException(x); + } + } + + /** + * Saves the content of the file from the specified stream to the File System repository. + * + * @param content {@link InputStream} to read the content of the file from. + * @param contentType Indicates media type of the file. + * @param startIndex Index in file to which corresponds first byte in {@code content}. + * @param totalFileLength Total size of the file being uploaded. -1 if size is unknown. + * @return Number of bytes written. + * @throws LockedException File was locked and client did not provide lock token. + * @throws ServerException In case of an error. + * @throws IOException I/O error. + */ + @Override + public long write(InputStream content, String contentType, long startIndex, long totalFileLength) + throws LockedException, ServerException, IOException { + ensureHasToken(); + SeekableByteChannel writer = Files.newByteChannel(getFullPath(), this.allowedOpenFileOptions); + if (startIndex == 0) { + // If we override the file we must set position to 0 because writer could be at not 0 position. + writer = writer.truncate(0); + } else { + // We must set to start position in case of resume upload. + writer.position(startIndex); + } + incrementSerialNumber(); + byte[] inputBuffer = new byte[BUFFER_SIZE]; + long totalWrittenBytes = startIndex; + int readBytes; + try { + while ((readBytes = content.read(inputBuffer)) > -1) { + ByteBuffer byteBuffer; + byteBuffer = ByteBuffer.wrap(inputBuffer, 0, readBytes); + writer.write(byteBuffer); + totalWrittenBytes += readBytes; + } + + try { + getEngine().getSearchFacade().getIndexer().indexFile(getName(), decode(getContextAwarePath()), null, this); + } catch (Exception ex){ + getEngine().getLogger().logError("Errors during indexing.", ex); + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + writer.close(); + } + getEngine().getWebSocketServer().notifyUpdated(getContextAwarePath(), getWebSocketID()); + return totalWrittenBytes; + } + + private void incrementSerialNumber() { + try { + Property serialNumber = Property.create("", "SerialNumber", "1"); + String sn = getSerialNumber(); + if (!Objects.equals(sn, "0")) { + serialNumber.setValue(String.valueOf((Integer.parseInt(sn) + 1))); + } + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), "SerialNumber", SerializationUtils.serialize(Collections.singletonList(serialNumber))); + } catch (Exception ex) { + getEngine().getLogger().logError("Cannot update serial number.", ex); + } + } + + private String getSerialNumber() throws ServerException { + String serialJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), "SerialNumber"); + List properties = SerializationUtils.deserializeList(Property.class, serialJson); + if (properties.size() == 1) { + return properties.get(0).getXmlValueRaw(); + } + return "0"; + } + + + @Override + public void delete() throws LockedException, MultistatusException, ServerException { + ensureHasToken(); + try { + Files.delete(getFullPath()); + } catch (IOException e) { + getEngine().getLogger().logError("Tried to delete file in use.", e); + throw new ServerException(e); + } + getEngine().getWebSocketServer().notifyDeleted(getPath(), getWebSocketID()); + try { + getEngine().getSearchFacade().getIndexer().deleteIndex(this); + } catch (Exception ex) { + getEngine().getLogger().logError("Errors during indexing.", ex); + } + } + + @Override + public void copyTo(Folder folder, String destName, boolean deep) + throws LockedException, MultistatusException, ServerException, ConflictException { + ((FolderImpl) folder).ensureHasToken(); + String destinationFolder = Paths.get(getRootFolder(), decodeAndConvertToPath(((FolderImpl) folder).getContextAwarePath())).toString(); + if (!Files.exists(Paths.get(destinationFolder))) { + throw new ConflictException(); + } + Path newPath = Paths.get(destinationFolder, destName); + try { + Files.copy(getFullPath(), newPath); + } catch (IOException e) { + throw new ServerException(e); + } + // Locks should not be copied, delete them + if (ExtendedAttributesExtension.hasExtendedAttribute(newPath.toString(), activeLocksAttribute)) { + ExtendedAttributesExtension.deleteExtendedAttribute(newPath.toString(), activeLocksAttribute); + } + try { + String currentPath = ((FolderImpl) folder).getContextAwarePath() + encode(destName); + getEngine().getWebSocketServer().notifyCreated(folder.getPath() + encode(destName), getWebSocketID()); + getEngine().getSearchFacade().getIndexer().indexFile(decode(destName), decode(currentPath), null, this); + } catch (Exception ex) { + getEngine().getLogger().logError("Errors during indexing.", ex); + } + } + + @Override + public void moveTo(Folder folder, String destName) throws LockedException, + ConflictException, MultistatusException, ServerException { + ensureHasToken(); + ((FolderImpl) folder).ensureHasToken(); + String destinationFolder = Paths.get(getRootFolder(), decodeAndConvertToPath(((FolderImpl) folder).getContextAwarePath())).toString(); + if (!Files.exists(Paths.get(destinationFolder))) { + throw new ConflictException(); + } + Path newPath = Paths.get(destinationFolder, destName); + try { + Files.move(getFullPath(), newPath, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new ServerException(e); + } + setName(destName); + // Locks should not be copied, delete them + if (ExtendedAttributesExtension.hasExtendedAttribute(newPath.toString(), activeLocksAttribute)) { + ExtendedAttributesExtension.deleteExtendedAttribute(newPath.toString(), activeLocksAttribute); + } + try { + String currentPath = ((FolderImpl) folder).getContextAwarePath() + encode(destName); + getEngine().getWebSocketServer().notifyMoved(getPath(), folder.getPath() + encode(destName), getWebSocketID()); + getEngine().getSearchFacade().getIndexer().indexFile(decode(destName), decode(currentPath), getContextAwarePath(), this); + } catch (Exception ex) { + getEngine().getLogger().logError("Errors during indexing.", ex); + } + } + + /** + * Returns snippet of file content that matches search conditions. + * + * @return Snippet of file content that matches search conditions. + */ + String getSnippet() { + return snippet; + } + + /** + * Sets snippet of file content that matches search conditions. + * + * @param snippet Snippet of file content that matches search conditions. + */ + void setSnippet(String snippet) { + this.snippet = snippet; + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FolderImpl.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FolderImpl.java new file mode 100644 index 0000000..b655e8a --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/FolderImpl.java @@ -0,0 +1,397 @@ +package com.ithit.webdav.samples.springbootfs.impl; + +import com.ithit.webdav.server.File; +import com.ithit.webdav.server.Folder; +import com.ithit.webdav.server.HierarchyItem; +import com.ithit.webdav.server.Property; +import com.ithit.webdav.server.exceptions.*; +import com.ithit.webdav.server.paging.OrderProperty; +import com.ithit.webdav.server.paging.PageResults; +import com.ithit.webdav.server.quota.Quota; +import com.ithit.webdav.server.resumableupload.ResumableUploadBase; +import com.ithit.webdav.server.search.Search; +import com.ithit.webdav.server.search.SearchOptions; +import org.apache.commons.io.FileUtils; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +/** + * Represents a folder in the File system repository. + */ +final class FolderImpl extends HierarchyItemImpl implements Folder, Search, Quota, ResumableUploadBase { + + + /** + * Initializes a new instance of the {@link FolderImpl} class. + * + * @param name Name of hierarchy item. + * @param path Relative to WebDAV root folder path. + * @param created Creation time of the hierarchy item. + * @param modified Modification time of the hierarchy item. + * @param engine Instance of current {@link WebDavEngine} + */ + private FolderImpl(String name, String path, long created, long modified, + WebDavEngine engine) { + super(name, path, created, modified, engine); + } + + /** + * Returns folder that corresponds to path. + * + * @param path Encoded path relative to WebDAV root. + * @param engine Instance of {@link WebDavEngine} + * @return Folder instance or null if physical folder not found in file system. + * @throws ServerException in case of exception + */ + static FolderImpl getFolder(String path, WebDavEngine engine) throws ServerException { + BasicFileAttributes view = null; + Path fullPath; + String name = null; + try { + String realPath = engine.getContextAware(path); + boolean root = realPath.equals("/"); + String pathFragment = decodeAndConvertToPath(realPath); + String rootFolder = engine.getDataFolder(); + fullPath = root ? Paths.get(rootFolder) : Paths.get(rootFolder, pathFragment); + if (Files.exists(fullPath)) { + name = root ? "ROOT" : Paths.get(pathFragment).getFileName().toString(); + view = Files.getFileAttributeView(fullPath, BasicFileAttributeView.class).readAttributes(); + } + if (view == null || !view.isDirectory()) { + return null; + } + } catch (IOException e) { + throw new ServerException(); + } + + long created = view.creationTime().toMillis(); + long modified = view.lastModifiedTime().toMillis(); + return new FolderImpl(name, fixPath(path), created, modified, engine); + } + + private static String fixPath(String path) { + if (!Objects.equals(path.substring(path.length() - 1), "/")) { + path += "/"; + } + return path; + } + + /** + * Creates new {@link FileImpl} file with the specified name in this folder. + * + * @param name Name of the file to create. + * @return Reference to created {@link File}. + * @throws LockedException This folder was locked. Client did not provide the lock token. + * @throws ServerException In case of an error. + */ + @Override + public FileImpl createFile(String name) throws LockedException, ServerException { + ensureHasToken(); + + Path fullPath = Paths.get(this.getFullPath().toString(), name); + if (!Files.exists(fullPath)) { + try { + Files.createFile(fullPath); + } catch (IOException e) { + throw new ServerException(e); + } + getEngine().getWebSocketServer().notifyCreated(getPath() + encode(name), getWebSocketID()); + return FileImpl.getFile(getContextAwarePath() + encode(name), getEngine()); + } + return null; + } + + /** + * Creates new {@link FolderImpl} folder with the specified name in this folder. + * + * @param name Name of the folder to create. + * @return Instance of newly created Folder. + * @throws LockedException This folder was locked. Client did not provide the lock token. + * @throws ServerException In case of an error. + */ + @Override + public Folder createFolder(String name) throws LockedException, + ServerException { + createFolderInternal(name); + getEngine().getWebSocketServer().notifyCreated(getPath() + encode(name), getWebSocketID()); + return FolderImpl.getFolder(getPath() + encode(name), getEngine()); + } + + private void createFolderInternal(String name) throws LockedException, + ServerException { + ensureHasToken(); + + Path fullPath = Paths.get(this.getFullPath().toString(), name); + if (!Files.exists(fullPath)) { + try { + Files.createDirectory(fullPath); + } catch (IOException e) { + throw new ServerException(e); + } + } + } + + /** + * Gets the array of this folder's children. + * + * @param propNames List of properties to retrieve with the children. They will be queried by the engine later. + * @param offset The number of items to skip before returning the remaining items. + * @param nResults The number of items to return. + * @param orderProps List of order properties requested by the client. + * @return Instance of {@link PageResults} class that contains items on a requested page and total number of items in a folder. + * @throws ServerException In case of an error. + */ + @Override + public PageResults getChildren(List propNames, Long offset, Long nResults, List orderProps) throws ServerException { + String decodedPath = HierarchyItemImpl.decodeAndConvertToPath(getContextAwarePath()); + Path fullFolderPath = Paths.get(getRootFolder() + decodedPath); + List children = new ArrayList<>(); + Long total = null; + try (DirectoryStream ds = Files.newDirectoryStream(fullFolderPath)) { + List paths = StreamSupport.stream(ds.spliterator(), false).collect(Collectors.toList()); + paths = sortChildren(paths, orderProps); + for (Path p : paths) { + String childPath = getPath() + encode(p.getFileName().toString()); + HierarchyItemImpl item = (HierarchyItemImpl) getEngine().getHierarchyItem(childPath); + children.add(item); + } + total = (long) paths.size(); + if (offset != null && nResults != null) + { + children = children.stream().skip(offset).limit(nResults).collect(Collectors.toList()); + } + } catch (IOException e) { + getEngine().getLogger().logError(e.getMessage(), e); + } + return new PageResults(children, total); + } + + @Override + public void delete() throws LockedException, + ServerException { + ensureHasToken(); + try { + removeIndex(getFullPath(), this); + FileUtils.deleteDirectory(getFullPath().toFile()); + } catch (IOException e) { + throw new ServerException(e); + } + getEngine().getWebSocketServer().notifyDeleted(getPath(), getWebSocketID()); + } + + @Override + public void copyTo(Folder folder, String destName, boolean deep) + throws LockedException, MultistatusException, ServerException { + ((FolderImpl) folder).ensureHasToken(); + + String relUrl = HierarchyItemImpl.decodeAndConvertToPath(((FolderImpl) folder).getContextAwarePath()); + String destinationFolder = Paths.get(getRootFolder(), relUrl).toString(); + if (isRecursive(relUrl)) { + throw new ServerException("Cannot copy to subfolder", WebDavStatus.FORBIDDEN); + } + if (!Files.exists(Paths.get(destinationFolder))) + throw new ServerException(); + try { + Path sourcePath = this.getFullPath(); + Path destinationFullPath = Paths.get(destinationFolder, destName); + FileUtils.copyDirectory(sourcePath.toFile(), destinationFullPath.toFile()); + addIndex(destinationFullPath, ((FolderImpl) folder).getContextAwarePath() + destName, destName); + } catch (IOException e) { + throw new ServerException(e); + } + setName(destName); + getEngine().getWebSocketServer().notifyCreated(((FolderImpl) folder).getContextAwarePath() + encode(destName), getWebSocketID()); + } + + /** + * Check whether current folder is the parent to the destination. + * + * @param destFolder Path to the destination folder. + * @return True if current folder is parent for the destination, false otherwise. + * @throws ServerException in case of any server exception. + */ + private boolean isRecursive(String destFolder) throws ServerException { + return destFolder.startsWith(getContextAwarePath().replace("/", java.io.File.separator)); + } + + /** + * Sorts array of FileSystemInfo according to the specified order. + * @param paths Array of files and folders to sort. + * @param orderProps Sorting order. + * @return Sorted list of files and folders. + */ + private List sortChildren(List paths, List orderProps) { + if (orderProps != null && !orderProps.isEmpty()) { + int index = 0; + Comparator comparator = null; + for (OrderProperty orderProperty : + orderProps) { + Comparator tempComp = null; + if ("is-directory".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> item.toFile().isDirectory(); + tempComp = Comparator.comparing(sortFunc); + } + if ("quota-used-bytes".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> item.toFile().length(); + tempComp = Comparator.comparing(sortFunc); + } + if ("getlastmodified".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> item.toFile().lastModified(); + tempComp = Comparator.comparing(sortFunc); + } + if ("displayname".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> item.getFileName().toString(); + tempComp = Comparator.comparing(sortFunc); + } + if ("getcontenttype".equals(orderProperty.getProperty().getName())) { + Function sortFunc = item -> getExtension(item.getFileName().toString()); + tempComp = Comparator.comparing(sortFunc); + } + if (tempComp != null) { + if (index++ == 0) { + if (orderProperty.isAscending()) { + comparator = tempComp; + } else { + comparator = tempComp.reversed(); + } + } else { + if (orderProperty.isAscending()) { + comparator = comparator != null ? comparator.thenComparing(tempComp) : tempComp; + } else { + comparator = comparator != null ? comparator.thenComparing(tempComp.reversed()) : tempComp.reversed(); + } + } + } + } + if (comparator != null) { + paths = paths.stream().sorted(comparator).collect(Collectors.toList()); + } + } + return paths; + } + + private String getExtension(String name) { + int periodIndex = name.lastIndexOf('.'); + return periodIndex == -1 ? "" : name.substring(periodIndex + 1); + + } + + @Override + public void moveTo(Folder folder, String destName) throws LockedException, + ConflictException, ServerException { + ensureHasToken(); + ((FolderImpl) folder).ensureHasToken(); + String destinationFolder = Paths.get(getRootFolder(), HierarchyItemImpl.decodeAndConvertToPath(((FolderImpl) folder).getContextAwarePath())).toString(); + if (!Files.exists(Paths.get(destinationFolder))) + throw new ConflictException(); + Path sourcePath = this.getFullPath(); + Path destinationFullPath = Paths.get(destinationFolder, destName); + try { + removeIndex(getFullPath(), this); + FileUtils.moveDirectory(sourcePath.toFile(), destinationFullPath.toFile()); + addIndex(destinationFullPath, ((FolderImpl) folder).getContextAwarePath() + destName, destName); + } catch (IOException e) { + throw new ServerException(e); + } + setName(destName); + getEngine().getWebSocketServer().notifyMoved(getContextAwarePath(), ((FolderImpl) folder).getContextAwarePath() + encode(destName), getWebSocketID()); + } + + /** + * Returns list of items that correspond to search request. + * + * @param searchString A phrase to search. + * @param options Search parameters. + * @param propNames List of properties to retrieve with the children. They will be queried by the engine later. + * @param offset The number of items to skip before returning the remaining items. + * @param nResults The number of items to return. + * @return Instance of {@link PageResults} class that contains items on a requested page and total number of items in search results. + */ + @Override + public PageResults search(String searchString, SearchOptions options, List propNames, Long offset, Long nResults) { + List results = new LinkedList<>(); + SearchFacade.Searcher searcher = getEngine().getSearchFacade().getSearcher(); + if (searcher == null) { + return new PageResults(results, (long) 0); + } + boolean snippet = propNames.stream().anyMatch(x -> SNIPPET.equalsIgnoreCase(x.getName())); + Map searchResult; + try { + String decodedPath = decode(getContextAwarePath()); + searchResult = searcher.search(searchString, options, decodedPath, snippet); + for (Map.Entry entry : searchResult.entrySet()) { + try { + HierarchyItem item = getEngine().getHierarchyItem(entry.getKey()); + if (item != null) { + if (snippet && item instanceof FileImpl) { + ((FileImpl) item).setSnippet(entry.getValue()); + } + results.add(item); + } + } catch (Exception ex) { + getEngine().getLogger().logError("Error during search.", ex); + } + } + } catch (ServerException e) { + getEngine().getLogger().logError("Error during search.", e); + } + return new PageResults((offset != null && nResults != null) ? results.stream().skip(offset).limit(nResults).collect(Collectors.toList()) : results, (long) results.size()); + } + + /** + * Returns free bytes available to current user. + * + * @return Returns free bytes available to current user. + */ + @Override + public long getAvailableBytes() { + return getFullPath().toFile().getFreeSpace(); + } + + /** + * Returns used bytes by current user. + * + * @return Returns used bytes by current user. + */ + @Override + public long getUsedBytes() { + long total = getFullPath().toFile().getTotalSpace(); + return total - getAvailableBytes(); + } + + private void removeIndex(Path sourcePath, FolderImpl itSelf) { + List filesToDelete = new ArrayList<>(); + getEngine().getSearchFacade().getFilesToIndex(sourcePath.toFile().listFiles(), filesToDelete, getRootFolder()); + filesToDelete.add(itSelf); + for (HierarchyItem hi : filesToDelete) { + try { + getEngine().getSearchFacade().getIndexer().deleteIndex(hi); + } catch (Exception e) { + getEngine().getLogger().logError("Cannot delete index.", e); + } + } + } + + private void addIndex(Path sourcePath, String path, String name) { + List filesToIndex = new ArrayList<>(); + getEngine().getSearchFacade().getFilesToIndex(sourcePath.toFile().listFiles(), filesToIndex, getRootFolder()); + getEngine().getSearchFacade().getIndexer().indexFile(name, decode(path), null, null); + for (HierarchyItem hi : filesToIndex) { + try { + getEngine().getSearchFacade().getIndexer().indexFile(hi.getName(), decode(hi.getPath()), null, hi); + } catch (Exception e) { + getEngine().getLogger().logError("Cannot index.", e); + } + } + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/HierarchyItemImpl.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/HierarchyItemImpl.java new file mode 100644 index 0000000..7c9cf7c --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/HierarchyItemImpl.java @@ -0,0 +1,516 @@ +package com.ithit.webdav.samples.springbootfs.impl; + +import com.ithit.webdav.samples.springbootfs.extendedattributes.ExtendedAttributesExtension; +import com.ithit.webdav.samples.springbootfs.websocket.WebSocketServer; +import com.ithit.webdav.server.*; +import com.ithit.webdav.server.exceptions.*; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.FileTime; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Base class for WebDAV items (folders, files, etc). + */ +abstract class HierarchyItemImpl implements HierarchyItem, Lock { + + static final String SNIPPET = "snippet"; + private final String path; + private final long created; + private final long modified; + private final WebDavEngine engine; + private String name; + String activeLocksAttribute = "Locks"; + private static final String PROPERTIES_ATTRIBUTE = "Properties"; + private List properties; + private List activeLocks; + + /** + * Initializes a new instance of the {@link HierarchyItemImpl} class. + * + * @param name name of hierarchy item + * @param path Relative to WebDAV root folder path. + * @param created creation time of the hierarchy item + * @param modified modification time of the hierarchy item + * @param engine instance of current {@link WebDavEngine} + */ + HierarchyItemImpl(String name, String path, long created, long modified, WebDavEngine engine) { + this.name = name; + this.path = path; + this.created = created; + this.modified = modified; + this.engine = engine; + } + + /** + * Decodes URL and converts it to proper path string. + * + * @param url URL to decode. + * @return Path. + */ + static String decodeAndConvertToPath(String url) { + String path = decode(url); + return path.replace("/", File.separator); + } + + /** + * Decodes URL. + * + * @param url URL to decode. + * @return Path. + */ + static String decode(String url) { + try { + return URLDecoder.decode(url.replace("+", "%2B"), "UTF-8"); + } catch (UnsupportedEncodingException e) { + return URLDecoder.decode(url.replace("+", "%2B")); + } + } + + /** + * Encodes string to safe characters. + * + * @param val String to encode. + * @return Encoded string. + */ + String encode(String val) { + try { + return URLEncoder.encode(val, "UTF-8").replace("+", "%20"); + } catch (UnsupportedEncodingException e) { + return URLEncoder.encode(val).replace("+", "%20"); + } + } + + /** + * Returns path to the folder in File System which will be the root for the WebDav storage. + * + * @return Path to the folder in File System which will be the root for the WebDav storage. + */ + public String getRootFolder() { + return getEngine().getDataFolder(); + } + + /** + * Creates a copy of this item with a new name in the destination folder. + * + * @param folder Destination folder. + * @param destName Name of the destination item. + * @param deep Indicates whether to copy entire subtree. + * @throws LockedException - the destination item was locked and client did not provide lock token. + * @throws ConflictException - destination folder does not exist. + * @throws MultistatusException - errors has occurred during processing of the subtree. + * Every item that has been either successfully copied or failed to copy must be present in exception with corresponding status. + * @throws ServerException - In case of other error. + */ + public abstract void copyTo(Folder folder, String destName, boolean deep) + throws LockedException, MultistatusException, ServerException, ConflictException; + + /** + * Moves this item to the destination folder under a new name. + * + * @param folder Destination folder. + * @param destName Name of the destination item. + * @throws LockedException - the source or the destination item was locked and client did not provide lock token. + * @throws ConflictException - destination folder does not exist. + * @throws MultistatusException - errors has occurred during processing of the subtree. Every processed item must have corresponding response added + * with corresponding status. + * @throws ServerException - in case of another error. + */ + public abstract void moveTo(Folder folder, String destName) + throws LockedException, ConflictException, MultistatusException, ServerException; + + /** + * Deletes this item. + * + * @throws LockedException - this item or its parent was locked and client did not provide lock token. + * @throws MultistatusException - errors has occurred during processing of the subtree. Every processed item must have corresponding response added + * to the exception with corresponding status. + * @throws ServerException - in case of another error. + */ + @Override + public abstract void delete() throws LockedException, MultistatusException, + ServerException; + + /** + * Gets the creation date of the item in repository expressed as the coordinated universal time (UTC). + * + * @return Creation date of the item. + */ + @Override + public long getCreated() { + return created; + } + + /** + * Gets the last modification date of the item in repository expressed as the coordinated universal time (UTC). + * + * @return Modification date of the item. + */ + @Override + public long getModified() { + return modified; + } + + /** + * Parses string to Date. + * + * @param inputDate Date in string. + * @return Date instance in UTC. + * @throws ParseException is cannot parse the Date. + */ + private Date parseDateFrom(String inputDate) throws ParseException { + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH); + Date date; + date = format.parse(inputDate); + return date; + } + + /** + * Gets the name of the item in repository. + * + * @return Name of this item. + */ + @Override + public String getName() { + return name; + } + + /** + * Set {@link HierarchyItemImpl} name. + * + * @param name {@link HierarchyItemImpl} name. + */ + void setName(String name) { + this.name = name; + } + + /** + * Unique item path in the repository relative to storage root. + * + * @return Item path relative to storage root. + */ + @Override + public String getPath() throws ServerException { + return path; + } + + /** + * Unique item path in the repository relative to storage root considering the context root. + * @return Item path relative to storage root considering the context root. + */ + public String getContextAwarePath() throws ServerException { + return engine.getContextAware(getPath()); + } + + /** + * Gets values of all properties or selected properties for this item. + * + * @return List of properties with values set. If property cannot be found it shall be omitted from the result. + * @throws ServerException In case of an error. + */ + @Override + public List getProperties(Property[] props) throws ServerException { + List l = getPropertyNames(); + List result; + if (props == null) { + return l; + } + Set propNames = Arrays.stream(props).map(Property::getName).collect(Collectors.toSet()); + result = l.stream().filter(x -> propNames.contains(x.getName())).collect(Collectors.toList()); + Property snippet = Arrays.stream(props).filter(x -> propNames.contains(SNIPPET)).findFirst().orElse(null); + if (snippet != null && this instanceof FileImpl) { + result.add(Property.create(snippet.getNamespace(), snippet.getName(), ((FileImpl) this).getSnippet())); + } + return result; + } + + + private List getProperties() throws ServerException { + if (properties == null) { + String propertiesJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE); + properties = SerializationUtils.deserializeList(Property.class, propertiesJson); + } + return properties; + } + + /** + * Gets names of all properties for this item. + * + * @return List of all property names for this item. + * @throws ServerException In case of an error. + */ + @Override + public List getPropertyNames() throws ServerException { + if (ExtendedAttributesExtension.hasExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE)) { + String propJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE); + return SerializationUtils.deserializeList(Property.class, propJson); + } + return new LinkedList<>(); + } + + /** + * Check whether client is the lock owner. + * + * @throws LockedException in case if not owner. + * @throws ServerException other errors. + */ + void ensureHasToken() throws LockedException, ServerException { + if (!clientHasToken()) + throw new LockedException(); + } + + /** + * Check whether client is the lock owner. + * + * @return True if owner, false otherwise. + * @throws ServerException in case of errors. + */ + private boolean clientHasToken() throws ServerException { + getActiveLocks(); + if (activeLocks.isEmpty()) { + return true; + } + List clientLockTokens = DavContext.currentRequest().getClientLockTokens(); + return activeLocks.stream().anyMatch(x -> clientLockTokens.contains(x.getToken())); + } + + /** + * Modifies and removes properties for this item. + * + * @param setProps Array of properties to be set. + * @param delProps Array of properties to be removed. {@link Property#getXmlValueRaw()} field is ignored. + * Specifying the removal of a property that does not exist is not an error. + * @throws LockedException this item was locked and client did not provide lock token. + * @throws ServerException In case of other error. + */ + @Override + public void updateProperties(Property[] setProps, Property[] delProps) + throws LockedException, ServerException { + ensureHasToken(); + for (final Property prop : setProps) { + String basicAttributeNS = "urn:schemas-microsoft-com:"; + // Microsoft Mini-redirector may update file creation date, modification date and access time passing properties: + // Thu, 28 Mar 2013 20:15:34 GMT + // Thu, 28 Mar 2013 20:36:24 GMT + // Thu, 28 Mar 2013 20:36:24 GMT + // In this case update creation and modified date in your storage or do not save this properties at all, otherwise + // Windows Explorer will display creation and modification date from this props and it will differ from the values + // in the Created and Modified fields in your storage + // String basicAttributeNS = "urn:schemas-microsoft-com:"; + if (prop.getNamespace().equals(basicAttributeNS)) { + updateBasicProperties(prop.getXmlValueRaw(), prop.getName()); + } else { + properties = getProperties(); + Property existingProp = properties.stream().filter(x -> x.getName().equals(prop.getName())).findFirst().orElse(null); + if (existingProp != null) { + existingProp.setXmlValueRaw(prop.getXmlValueRaw()); + } else { + properties.add(prop); + } + } + } + properties = getProperties(); + Set propNamesToDel = Arrays.stream(delProps).map(Property::getName).collect(Collectors.toSet()); + properties = properties.stream() + .filter(e -> !propNamesToDel.contains(e.getName())) + .collect(Collectors.toList()); + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE, SerializationUtils.serialize(properties)); + getEngine().getWebSocketServer().notifyUpdated(getContextAwarePath(), getWebSocketID()); + } + + /** + * Updates basic file times in the following format - Thu, 28 Mar 2013 20:15:34 GMT. + * + * @param date Date to update + * @param field Field to update + */ + private void updateBasicProperties(String date, String field) { + BasicFileAttributeView attributes = Files.getFileAttributeView(getFullPath(), BasicFileAttributeView.class); + try { + String propertyCreatedName = "Win32CreationTime"; + String propertyModifiedName = "Win32LastModifiedTime"; + String propertyAccessedName = "Win32LastAccessTime"; + if (field.equals(propertyCreatedName) || field.equals(propertyModifiedName) || field.equals(propertyAccessedName)) { + FileTime time = date == null ? null : FileTime.fromMillis(parseDateFrom(date).getTime()); + if (field.equals(propertyModifiedName)) { + attributes.setTimes(time, null, null); + } + if (field.equals(propertyAccessedName)) { + attributes.setTimes(null, time, null); + } + if (field.equals(propertyCreatedName)) { + // For some reason Windows Explorer caches created time so for some period of time it may return wrong creation time + attributes.setTimes(null, null, time); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Returns File System engine. + * + * @return File System engine. + */ + WebDavEngine getEngine() { + return engine; + } + + /** + * Returns full path in the File System to the {@link HierarchyItemImpl}. + * + * @return Full path in the File System to the {@link HierarchyItemImpl}. + */ + Path getFullPath() { + String fullPath = ""; + try { + fullPath = getRootFolder() + HierarchyItemImpl.decodeAndConvertToPath(getContextAwarePath()); + } catch (ServerException ignored) { + } + return Paths.get(fullPath); + } + + /** + * Locks this item. + * + * @param shared Indicates whether a lock is shared or exclusive. + * @param deep Indicates whether a lock is enforceable on the subtree. + * @param timeout Lock expiration time in seconds. Negative value means never. + * @param owner Provides information about the principal taking out a lock. + * @return Actually applied lock (Server may modify timeout). + * @throws LockedException The item is locked, so the method has been rejected. + * @throws ServerException In case of an error. + */ + @Override + public LockResult lock(boolean shared, boolean deep, long timeout, String owner) + throws LockedException, ServerException { + if (hasLock(shared)) { + throw new LockedException(); + } + String token = UUID.randomUUID().toString(); + if (timeout < 0 || timeout == Long.MAX_VALUE) { + // If timeout is absent or infinity timeout requested, + // grant 5 minute lock. + timeout = 300; + } + long expires = System.currentTimeMillis() + timeout * 1000; + LockInfo lockInfo = new LockInfo(shared, deep, token, expires, owner); + activeLocks.add(lockInfo); + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), activeLocksAttribute, SerializationUtils.serialize(activeLocks)); + getEngine().getWebSocketServer().notifyLocked(getPath(), getWebSocketID()); + return new LockResult(token, timeout); + } + + /** + * Checks whether {@link HierarchyItemImpl} has a lock and whether it is shared. + * + * @param skipShared Indicates whether to skip shared. + * @return True if item has lock and skipShared is true, false otherwise. + * @throws ServerException in case of errors. + */ + private boolean hasLock(boolean skipShared) throws ServerException { + getActiveLocks(); + return !activeLocks.isEmpty() && !(skipShared && activeLocks.get(0).isShared()); + } + + /** + * Gets the array of all locks for this item. + * + * @return Array of locks. + * @throws ServerException In case of an error. + */ + @Override + public List getActiveLocks() throws ServerException { + if (activeLocks == null) { + String activeLocksJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), activeLocksAttribute); + activeLocks = new ArrayList<>(SerializationUtils.deserializeList(LockInfo.class, activeLocksJson)); + } else { + activeLocks = new LinkedList<>(); + } + return activeLocks + .stream() + .filter(x -> System.currentTimeMillis() < x.getTimeout()) + .map(lock -> new LockInfo( + lock.isShared(), + lock.isDeep(), + lock.getToken(), + (lock.getTimeout() < 0 || lock.getTimeout() == Long.MAX_VALUE) ? lock.getTimeout() : (lock.getTimeout() - System.currentTimeMillis()) / 1000, + lock.getOwner()) + ) + .collect(Collectors.toList()); + } + + /** + * Removes lock with the specified token from this item. + * + * @param lockToken Lock with this token should be removed from the item. + * @throws PreconditionFailedException Included lock token was not enforceable on this item. + * @throws ServerException In case of an error. + */ + @Override + public void unlock(String lockToken) throws PreconditionFailedException, + ServerException { + getActiveLocks(); + LockInfo lock = activeLocks.stream().filter(x -> x.getToken().equals(lockToken)).findFirst().orElse(null); + if (lock != null) { + activeLocks.remove(lock); + if (!activeLocks.isEmpty()) { + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), activeLocksAttribute, SerializationUtils.serialize(activeLocks)); + } else { + ExtendedAttributesExtension.deleteExtendedAttribute(getFullPath().toString(), activeLocksAttribute); + } + getEngine().getWebSocketServer().notifyUnlocked(getPath(), getWebSocketID()); + } else { + throw new PreconditionFailedException(); + } + } + + /** + * Updates lock timeout information on this item. + * + * @param token The lock token associated with a lock. + * @param timeout Lock expiration time in seconds. Negative value means never. + * @return Actually applied lock (Server may modify timeout). + * @throws PreconditionFailedException Included lock token was not enforceable on this item. + * @throws ServerException In case of an error. + */ + @Override + public RefreshLockResult refreshLock(String token, long timeout) + throws PreconditionFailedException, ServerException { + getActiveLocks(); + LockInfo lockInfo = activeLocks.stream().filter(x -> x.getToken().equals(token)).findFirst().orElse(null); + if (lockInfo == null) { + throw new PreconditionFailedException(); + } + if (timeout < 0 || timeout == Long.MAX_VALUE) { + // If timeout is absent or infinity timeout requested, + // grant 5 minute lock. + timeout = 300; + } + long expires = System.currentTimeMillis() + timeout * 1000; + lockInfo.setTimeout(expires); + ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), activeLocksAttribute, SerializationUtils.serialize(activeLocks)); + getEngine().getWebSocketServer().notifyLocked(getPath(), getWebSocketID()); + return new RefreshLockResult(lockInfo.isShared(), lockInfo.isDeep(), + timeout, lockInfo.getOwner()); + } + + /** + * Returns instance ID from header + * @return InstanceId + */ + protected String getWebSocketID() { + return DavContext.currentRequest().getHeader(WebSocketServer.INSTANCE_HEADER_NAME); + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SearchFacade.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SearchFacade.java new file mode 100644 index 0000000..09aaf41 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SearchFacade.java @@ -0,0 +1,486 @@ +package com.ithit.webdav.samples.springbootfs.impl; + +import com.ithit.webdav.server.HierarchyItem; +import com.ithit.webdav.server.Logger; +import com.ithit.webdav.server.search.SearchOptions; +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.standard.StandardAnalyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.document.StringField; +import org.apache.lucene.document.TextField; +import org.apache.lucene.index.*; +import org.apache.lucene.queryparser.classic.ParseException; +import org.apache.lucene.queryparser.classic.QueryParser; +import org.apache.lucene.search.*; +import org.apache.lucene.search.highlight.*; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.FSDirectory; +import org.apache.tika.Tika; +import org.apache.tika.exception.ZeroByteFileException; +import org.apache.tika.io.TikaInputStream; +import org.apache.tika.metadata.Metadata; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.RecursiveAction; +import java.util.regex.Pattern; + +/** + * Facade that encapsulates all functionality regarding indexing and searching + */ +public final class SearchFacade { + private static final StandardAnalyzer ANALYZER = new StandardAnalyzer(); + private Indexer indexer; + private Searcher searcher; + private final WebDavEngine engine; + private final Logger logger; + private static SearchFacade instance; + private boolean indexed; + + private SearchFacade(WebDavEngine webDavEngine, Logger logger) { + engine = webDavEngine; + this.logger = logger; + } + + public static synchronized SearchFacade getInstance(WebDavEngine webDavEngine, Logger logger) { + if (instance == null) { + instance = new SearchFacade(webDavEngine, logger); + } + return instance; + } + + /** + * Returns Indexer instance + * + * @return Indexer instance + */ + Indexer getIndexer() { + return indexer; + } + + /** + * Returns Searcher instance + * + * @return Searcher instance + */ + Searcher getSearcher() { + return searcher; + } + + /** + * This task is running in background and indexes all folder mapped for WebDav asynchronously. + * So there is a chance in case of big folder there will be some delays while this task + * will finish indexation. + */ + private class IndexTask extends TimerTask { + + private final String dataFolder; + private final String indexFolder; + private final Integer interval; + + /** + * Build initial index of root folder. + * + * @param dataFolder Root folder. + * @param indexFolder Index folder. + * @param interval Daemon commit interval. + */ + IndexTask(String dataFolder, String indexFolder, Integer interval) { + this.dataFolder = dataFolder; + this.indexFolder = indexFolder; + this.interval = interval; + } + + /** + * The action to be performed by this timer task. + */ + @Override + public void run() { + ForkJoinPool forkJoinPool = new ForkJoinPool(4); + Directory fsDir; + try { + List filesToIndex = new ArrayList<>(); + File data = new File(dataFolder); + searcher = new Searcher(indexFolder, ANALYZER, logger); + getFilesToIndex(data.listFiles(), filesToIndex, dataFolder); + fsDir = FSDirectory.open(Paths.get(indexFolder)); + IndexWriterConfig conf = new IndexWriterConfig(ANALYZER); + conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); + IndexWriter indexWriter = new IndexWriter(fsDir, conf); + Tika tika = new Tika(); + tika.setMaxStringLength(Indexer.MAX_CONTENT_LENGTH); + indexer = new Indexer(indexWriter, filesToIndex, logger, tika, dataFolder); + forkJoinPool.execute(indexer); + indexWriter.commit(); + new Indexer.CommitTask(indexWriter, logger).schedule(interval); + } catch (Throwable e) { + logger.logError("Cannot initialize Lucene", e); + } + } + + void schedule() { + Timer timer = new Timer(true); + timer.schedule(this, 0); + } + } + + /** + * Build initial index of root folder. + * + * @param dataFolder Root folder. + * @param indexFolder Index folder. + * @param interval Daemon commit interval. + */ + public void indexRootFolder(String dataFolder, String indexFolder, Integer interval) { + if (!indexed) { + indexed = true; + new IndexTask(dataFolder, indexFolder, interval).schedule(); + } + } + + /** + * Builds list of the all files (including files in child folders) in the data folder. + * + * @param files List of files in root folder. + * @param result List to be populated with results. + * @param dataFolder Root folder absolute location. + */ + void getFilesToIndex(File[] files, List result, String dataFolder) { + for (File f : files) { + if (f.isDirectory() && f.canRead() && !f.isHidden()) { + addFileToTheList(result, dataFolder, f); + getFilesToIndex(f.listFiles(), result, dataFolder); + } else { + if (f.canRead() && !f.isHidden()) { + addFileToTheList(result, dataFolder, f); + } + } + } + } + + private void addFileToTheList(List result, String dataFolder, File f) { + String quote = Pattern.quote(dataFolder); + try { + String context = f.getAbsolutePath().replaceAll("(?i)" + quote, ""); + context = context.replace("\\", "/"); + if (f.isDirectory()) { + context += "/"; + } + result.add(engine.getHierarchyItem(context)); + } catch (Throwable e) { + logger.logDebug("Cannot add a file to the list: " + f.getAbsolutePath()); + } + } + + + /** + * Index files in storage using Apache Lucene engine for indexing and Apache Tika. + */ + static class Indexer extends RecursiveAction { + static final int MAX_CONTENT_LENGTH = 10 * 1024 * 1024; + private static final int TASK_INTERVAL = 30 * 1000; + static final String PATH = "path"; + static final String NAME = "name"; + static final String PARENT_NAME = "parent_name"; + static final String CONTENTS = "contents"; + private final IndexWriter indexWriter; + private final List files; + private final Logger logger; + private final Tika tika; + private final String dataRoot; + private static final int BATCH_SIZE = 100; + + /** + * Create an instance of Indexer file. + * + * @param iw {@link IndexWriter} Lucene index writer. + * @param files List of the file to index. + * @param logger {@link Logger}. + * @param tika {@link Tika} to read content. + * @param dataRoot Files location root folder. + */ + private Indexer(IndexWriter iw, List files, Logger logger, Tika tika, String dataRoot) { + this.indexWriter = iw; + this.files = files; + this.logger = logger; + this.tika = tika; + this.dataRoot = dataRoot; + } + + @Override + protected void compute() { + if (files.size() > BATCH_SIZE) { + List tasks = new ArrayList<>(); + List> partitioned = chopped(files, BATCH_SIZE); + for (List sublist : partitioned) { + tasks.add(new Indexer(indexWriter, sublist, logger, tika, dataRoot)); + } + invokeAll(tasks); + } else { + for (HierarchyItem f : files) { + try { + indexFile(f.getName(), f.getPath(), null, f); + } catch (Throwable e) { + logger.logDebug("Cannot find path for this file."); + } + } + } + } + + private static List> chopped(List list, final int l) { + List> parts = new ArrayList<>(); + final int n = list.size(); + for (int i = 0; i < n; i += l) { + parts.add(new ArrayList<>( + list.subList(i, Math.min(n, i + l))) + ); + } + return parts; + } + + /** + * Indexes file. + * + * @param fileName File name to add to index. + * @param currentPath Current relative path of the file. + * @param oldPath Old relative path of the file if it was moved. + */ + void indexFile(String fileName, String currentPath, String oldPath, HierarchyItem item) { + Path fullPath = Paths.get(dataRoot, currentPath); + try { + Metadata metadata = new Metadata(); + Document doc = new Document(); + String parentFolder = currentPath.replace(fileName, "").replace("/", ""); + Field pathField = new StringField(PATH, currentPath, Field.Store.YES); + Field parentField = new TextField(PARENT_NAME, parentFolder, Field.Store.YES); + Field nameField = new TextField(NAME, fileName, Field.Store.YES); + doc.add(pathField); + doc.add(parentField); + doc.add(nameField); + if (item instanceof FileImpl) { + try (TikaInputStream stream = TikaInputStream.get(fullPath, metadata)) { + String content = tika.parseToString(stream, metadata, MAX_CONTENT_LENGTH); + doc.add(new TextField(CONTENTS, content, Field.Store.YES)); + } catch (Throwable e) { + if (!(e instanceof ZeroByteFileException)) { + logger.logError("Error while indexing content: " + fullPath, e); + } + } + } + if (indexWriter.getConfig().getOpenMode() == IndexWriterConfig.OpenMode.CREATE) { + indexWriter.addDocument(doc); + } else { + indexWriter.updateDocument(new Term(PATH, oldPath != null ? oldPath : currentPath), doc); + } + } catch (Throwable e) { + logger.logError("Error while indexing file: " + fullPath, e); + } + } + + /** + * Close index and release lock + */ + void stop() { + try { + indexWriter.close(); + } catch (Throwable e) { + logger.logError("Cannot release index resources", e); + } + } + + /** + * Deletes specified file information from the index. + * + * @param file {@link FileImpl} to delete from index. + */ + void deleteIndex(HierarchyItem file) { + try { + indexWriter.deleteDocuments(new Term(PATH, file.getPath())); + } catch (Throwable e) { + logger.logError("Cannot delete index for the file.", e); + } + } + + /** + * Timer task implementation to commit index changes from time to time. + */ + static class CommitTask extends TimerTask { + + private final IndexWriter indexWriter; + private final Logger logger; + + /** + * Creates instance of {@link CommitTask}. + * + * @param indexWriter {@link IndexWriter} Lucene index writer. + * @param logger {@link Logger}. + */ + CommitTask(IndexWriter indexWriter, Logger logger) { + this.indexWriter = indexWriter; + this.logger = logger; + } + + /** + * The action to be performed by this timer task. + */ + @Override + public void run() { + try { + indexWriter.commit(); + } catch (Throwable e) { + logger.logError("Cannot commit.", e); + } + } + + /** + * Schedule timer executions at the specified Interval. + * + * @param interval Timer interval. + */ + void schedule(Integer interval) { + Timer timer = new Timer(true); + timer.scheduleAtFixedRate(this, 0, interval == null ? TASK_INTERVAL : interval * 1000); + } + } + } + + /** + * Search files information in Lucene index. + */ + static class Searcher { + + private final String indexFolder; + private final QueryParser nameParser; + private final QueryParser contentParser; + private final QueryParser parentParser; + private final Logger logger; + private IndexSearcher indexSearcher; + + /** + * Creates instance of {@link Searcher}. + * + * @param indexFolder Index folder absolute location. + * @param standardAnalyzer Lucene {@link StandardAnalyzer}. + * @param logger {@link Logger}. + */ + private Searcher(String indexFolder, StandardAnalyzer standardAnalyzer, Logger logger) { + this.indexFolder = indexFolder; + nameParser = new QueryParser(Indexer.NAME, standardAnalyzer); + nameParser.setAllowLeadingWildcard(true); + contentParser = new QueryParser(Indexer.CONTENTS, standardAnalyzer); + contentParser.setAllowLeadingWildcard(true); + parentParser = new QueryParser(Indexer.PARENT_NAME, standardAnalyzer); + parentParser.setAllowLeadingWildcard(true); + this.logger = logger; + } + + /** + * Searches files by search line either in file name or in content. + *

+ * Ajax File Browser accepts regular wild cards used in most OS: + *

+ * ‘*’ – to indicate one or more character. + * ‘?’ – to indicate exactly one character. + * The ‘*’ and ‘?’ characters are replaced with ‘%’ and ‘_’ characters to comply with DASL standard when submitted to the server. + *

+ * If ‘%’, ‘_’ or ‘\’ characters are used in search phrase they are escaped with ‘\%’, ‘\_’ and ‘\\’. + *

+ * To make the search behave similarly to how file system search functions Ajax File Browser + * will automatically add ‘%’ character at the end of the search phrase. To search for the exact match wrap the search phrase in double quotes: “my file”. + * + * @param searchLine Line to search. + * @param options {@link SearchOptions} indicates where to search. + * @param parent Folder location in which to search. + * @return Map of paths to found items. + */ + Map search(String searchLine, SearchOptions options, String parent, boolean snippet) { + searchLine = StringEscapeUtils.escapeJava(searchLine); + searchLine = searchLine.replace("%", "*"); + searchLine = searchLine.replace("_", "?"); + Map paths = new LinkedHashMap<>(); + try (IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexFolder)))) { + indexSearcher = new IndexSearcher(reader); + if (options.isSearchContent()) { + paths.putAll(searchContent(searchLine, parent, snippet, reader)); + } + if (options.isSearchName()) { + paths.putAll(searchName(searchLine, parent)); + } + } catch (Throwable e) { + logger.logError("Error while doing index search.", e); + } + return paths; + } + + // Searches files by search line in file name + private Map searchName(String searchLine, String parent) throws Exception { + Query query = nameParser.parse(searchLine); + BooleanQuery.Builder finalQuery = addParentQuery(parent, query); + return search(finalQuery.build()); + } + + // Searches files by search line in file content + private Map searchContent(String searchLine, String parent, boolean withSnippet, IndexReader indexReader) throws Exception { + Query query = contentParser.parse(searchLine); + BooleanQuery.Builder finalQuery = addParentQuery(parent, query); + BooleanQuery booleanQuery = finalQuery.build(); + if (withSnippet) { + return searchWithSnippet(indexReader, booleanQuery); + } + return search(booleanQuery); + } + + // Searches files by search line in file name and adds highlights for found words + private Map searchWithSnippet(IndexReader indexReader, Query query) throws Exception { + QueryScorer queryScorer = new QueryScorer(query, Indexer.CONTENTS); + Fragmenter fragmenter = new SimpleSpanFragmenter(queryScorer); + SimpleHTMLFormatter htmlFormatter = new SimpleHTMLFormatter(); + Highlighter highlighter = new Highlighter(htmlFormatter, queryScorer); + highlighter.setTextFragmenter(fragmenter); + + ScoreDoc[] scoreDocs = indexSearcher.search(query, 100).scoreDocs; + Map result = new LinkedHashMap<>(); + for (ScoreDoc scoreDoc : scoreDocs) { + Document document = indexSearcher.doc(scoreDoc.doc); + String text = document.get(Indexer.CONTENTS); + String path = document.get(Indexer.PATH); + TokenStream tokenStream = TokenSources.getAnyTokenStream(indexReader, + scoreDoc.doc, Indexer.CONTENTS, document, ANALYZER); + String fragment = highlighter.getBestFragment(tokenStream, text); + result.put(path, fragment == null ? "" : fragment); + } + return result; + } + + // Adds parent folder to the query to make search only in this folder + private BooleanQuery.Builder addParentQuery(String parent, Query query) throws ParseException { + BooleanQuery.Builder finalQuery = new BooleanQuery.Builder(); + finalQuery.add(query, BooleanClause.Occur.MUST); // MUST implies that the keyword must occur. + String searchString = parent.replace("/", "") + "*"; + if (!Objects.equals(parent, "/")) { + Query parentQuery = parentParser.parse(searchString); + finalQuery.add(parentQuery, BooleanClause.Occur.MUST); + } + return finalQuery; + } + + // Searches files by search query either in file name or in content. + private Map search(Query query) throws IOException { + TopDocs search = indexSearcher.search(query, 100); + ScoreDoc[] hits = search.scoreDocs; + Map paths = new LinkedHashMap<>(); + for (ScoreDoc hit : hits) { + Document doc = indexSearcher.doc(hit.doc); + String path = doc.get(Indexer.PATH); + paths.put(path, ""); + } + return paths; + } + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SerializationUtils.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SerializationUtils.java new file mode 100644 index 0000000..6e14c68 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SerializationUtils.java @@ -0,0 +1,46 @@ +package com.ithit.webdav.samples.springbootfs.impl; + + +import com.google.gson.Gson; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Utility class to perform serialization of objects. + */ +final class SerializationUtils { + + private SerializationUtils() { + } + + /** + * Serializes object to JSON string. + * + * @param object Object to serialize. + * @return String in JSON format + */ + static String serialize(T object) { + Gson gson = new Gson(); + return gson.toJson(object); + } + + /** + * Deserialize JSON string to object list. + * + * @param clazz Type of objects in the list to deserialize. + * @param json JSON string to deserialize. + * @return List of objects. + */ + @SuppressWarnings("unchecked") + static List deserializeList(final Class clazz, final String json) { + T[] array = (T[]) java.lang.reflect.Array.newInstance(clazz, 1); + array = new Gson().fromJson(json, (Type) array.getClass()); + if (array == null) { + return new ArrayList<>(); + } + return new ArrayList<>(Arrays.asList(array)); + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SpringBootLogger.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SpringBootLogger.java new file mode 100644 index 0000000..d595626 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/SpringBootLogger.java @@ -0,0 +1,27 @@ +package com.ithit.webdav.samples.springbootfs.impl; + +import com.ithit.webdav.server.Logger; + +public class SpringBootLogger implements Logger { + + private final org.slf4j.Logger logger; + + public SpringBootLogger(org.slf4j.Logger logger) { + this.logger = logger; + } + + @Override + public void logDebug(String message) { + logger.debug(message); + } + + @Override + public void logError(String message, Throwable ex) { + logger.error(message, ex); + } + + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/WebDavEngine.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/WebDavEngine.java new file mode 100644 index 0000000..d290b57 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/impl/WebDavEngine.java @@ -0,0 +1,153 @@ +package com.ithit.webdav.samples.springbootfs.impl; + +import com.ithit.webdav.samples.springbootfs.websocket.WebSocketServer; +import com.ithit.webdav.server.Engine; +import com.ithit.webdav.server.HierarchyItem; +import com.ithit.webdav.server.Logger; +import com.ithit.webdav.server.exceptions.ServerException; +import com.ithit.webdav.server.util.StringUtil; +import lombok.extern.slf4j.Slf4j; + + +/** + * Implementation if {@link Engine}. + * Resolves hierarchy items by paths. + */ +@Slf4j +public class WebDavEngine extends Engine { + + private final Logger logger; + private final String license; + private final String dataFolder; + private final boolean showExceptions; + private final String rootContext; + private SearchFacade searchFacade; + private WebSocketServer webSocketServer; + + /** + * Initializes a new instance of the WebDavEngine class. + * + * @param license License string. + * @param dataFolder Path to the root folder to map to DAV. + * @param showExceptions True if you want to print exceptions in the response. + * @param rootContext Context path where webdav service is working. + */ + public WebDavEngine(String license, String dataFolder, boolean showExceptions, String rootContext) { + this.dataFolder = dataFolder; + this.showExceptions = showExceptions; + this.rootContext = StringUtil.trimEnd(rootContext, "/"); + this.logger = new SpringBootLogger(log); + this.license = license; + } + + /** + * Creates {@link HierarchyItem} instance by path. + * + * @param contextPath Item relative path including query string. + * @return Instance of corresponding {@link HierarchyItem} or null if item is not found. + * @throws ServerException in case if engine cannot read file attributes. + */ + @Override + public HierarchyItem getHierarchyItem(String contextPath) throws ServerException { + int i = contextPath.indexOf('?'); + if (i >= 0) { + contextPath = contextPath.substring(0, i); + } + HierarchyItemImpl item; + item = FolderImpl.getFolder(contextPath, this); + if (item != null) { + return item; + } + item = FileImpl.getFile(contextPath, this); + if (item != null) { + return item; + } + getLogger().logDebug("Could not find item that corresponds to path: " + contextPath); + return null; // no hierarchy item corresponds to path parameter was found in the repository + } + + /** + * Returns logger that will be used by engine. + * + * @return Instance of {@link Logger}. + */ + @Override + public Logger getLogger() { + return logger; + } + + /** + * Returns folder where data will be sourced for WebDAV + * @return data folder. + */ + public String getDataFolder() { + return dataFolder; + } + + /** + * Returns license string. + * + * @return license string. + */ + @Override + public String getLicense() { + return license; + } + + /** + * Returns flag if exception should be printed to response. + * @return true if exception should be printed to response. + */ + public boolean isShowExceptions() { + return showExceptions; + } + + /** + * Returns SearchFacade instance + * + * @return SearchFacade instance + */ + SearchFacade getSearchFacade() { + return searchFacade; + } + + /** + * Sets SearchFacade instance + * + * @param searchFacade SearchFacade instance + */ + public void setSearchFacade(SearchFacade searchFacade) { + this.searchFacade = searchFacade; + } + + /** + * Sets web socket server instance + * + * @param webSocketServer web socket server instance + */ + public void setWebSocketServer(WebSocketServer webSocketServer) { + this.webSocketServer = webSocketServer; + } + + /** + * Returns web socket server instance + * + * @return web socket server instance + */ + WebSocketServer getWebSocketServer() { + return webSocketServer; + } + + /** + * Returns real path considering context which may vary. + * @param path context aware path. + * @return real path. + */ + public String getContextAware(String path) { + if (path != null && path.startsWith(rootContext)) { + String contextAware = path.replaceFirst(rootContext, "/"); + return contextAware.replace("//", "/"); + } + return path; + } +} diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/MSOFBAFilter.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/MSOFBAFilter.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/MSOFBAFilter.java rename to Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/MSOFBAFilter.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/SecurityAutoConfiguration.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/SecurityAutoConfiguration.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/SecurityAutoConfiguration.java rename to Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/SecurityAutoConfiguration.java diff --git a/Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/SecurityConfig.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/SecurityConfig.java similarity index 100% rename from Java/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/SecurityConfig.java rename to Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/msofba/SecurityConfig.java diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/HandshakeHeadersInterceptor.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/HandshakeHeadersInterceptor.java new file mode 100644 index 0000000..fd25f1f --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/HandshakeHeadersInterceptor.java @@ -0,0 +1,34 @@ +package com.ithit.webdav.samples.springbootfs.websocket; + +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.server.HandshakeInterceptor; + +import java.util.Map; + +import static com.ithit.webdav.samples.springbootfs.websocket.WebSocketServer.INSTANCE_HEADER_NAME; + +public class HandshakeHeadersInterceptor implements HandshakeInterceptor { + + @Override + public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map map) throws Exception { + map.put(INSTANCE_HEADER_NAME, serverHttpRequest.getHeaders() + .entrySet() + .stream() + .filter(x -> x.getKey().equalsIgnoreCase(INSTANCE_HEADER_NAME)) + .findFirst().map(x -> { + if (!x.getValue().isEmpty()) { + return x.getValue().get(0); + } + return ""; + }) + .orElse("")); + return true; + } + + @Override + public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) { + + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/SocketHandler.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/SocketHandler.java new file mode 100644 index 0000000..bb8b3e5 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/SocketHandler.java @@ -0,0 +1,29 @@ +package com.ithit.webdav.samples.springbootfs.websocket; + +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class SocketHandler extends TextWebSocketHandler { + + private final List sessions = new CopyOnWriteArrayList<>(); + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + sessions.add(session); + super.afterConnectionEstablished(session); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { + sessions.remove(session); + super.afterConnectionClosed(session, status); + } + + public List getSessions() { + return sessions; + } +} diff --git a/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/WebSocketServer.java b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/WebSocketServer.java new file mode 100644 index 0000000..2a8db5d --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/java/com/ithit/webdav/samples/springbootfs/websocket/WebSocketServer.java @@ -0,0 +1,158 @@ +package com.ithit.webdav.samples.springbootfs.websocket; + +import com.ithit.webdav.server.util.StringUtil; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * WebSocket server, creates web socket endpoint, handles client's sessions + */ +public class WebSocketServer { + + public static final String INSTANCE_HEADER_NAME = "InstanceId"; + private final List sessions; + + public WebSocketServer(List sessions) { + this.sessions = sessions; + } + + /** + * Send notification to the client + * + * @param itemPath File/Folder path. + * @param operation Operation name: created/updated/deleted/moved + * @param clientId Current clientId. + */ + private void send(String itemPath, String operation, String clientId) { + itemPath = StringUtil.trimEnd(StringUtil.trimStart(itemPath, "/"), "/"); + final TextMessage textMessage = new TextMessage(new Notification(itemPath, operation).toString()); + send(clientId, textMessage); + } + + /** + * Notifies client that file/folder was created. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyCreated(String itemPath, String clientId) { + send(itemPath, "created", clientId); + } + + /** + * Notifies client that file/folder was updated. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyUpdated(String itemPath, String clientId) { + send(itemPath, "updated", clientId); + } + + /** + * Notifies client that file/folder was deleted. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyDeleted(String itemPath, String clientId) { + send(itemPath, "deleted", clientId); + } + + /** + * Notifies client that file/folder was locked. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyLocked(String itemPath, String clientId) { + send(itemPath, "locked", clientId); + } + + /** + * Notifies client that file/folder was unlocked. + * + * @param itemPath file/folder. + * @param clientId Current clientId. + */ + public void notifyUnlocked(String itemPath, String clientId) { + send(itemPath, "unlocked", clientId); + } + + /** + * Notifies client that file/folder was moved. + * + * @param itemPath file/folder. + * @param targetPath file/folder. + * @param clientId Current clientId. + */ + public void notifyMoved(String itemPath, String targetPath, String clientId) { + itemPath = StringUtil.trimEnd(StringUtil.trimStart(itemPath, "/"), "/"); + targetPath = StringUtil.trimEnd(StringUtil.trimStart(targetPath, "/"), "/"); + final TextMessage textMessage = new TextMessage(new MovedNotification(itemPath, "moved", targetPath).toString()); + send(clientId, textMessage); + } + + /** + * Send TextMessage to all sessions but initiator + * @param clientId Id of the initiator + * @param textMessage Message + */ + private void send(String clientId, TextMessage textMessage) { + for (WebSocketSession session: StringUtil.isNullOrEmpty(clientId) + ? sessions + : sessions.stream().filter(x -> !x.getAttributes().get(INSTANCE_HEADER_NAME).equals(clientId)).collect(Collectors.toSet())) { + try { + session.sendMessage(textMessage); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * Represents VO to exchange between client and server + */ + static class Notification { + protected final String itemPath; + protected final String operation; + + Notification(String itemPath, String operation) { + this.itemPath = itemPath; + this.operation = operation; + } + + @Override + public String toString() { + return "{" + + "\"ItemPath\" : \"" + itemPath + "\" ," + + "\"EventType\" : \"" + operation + "\"" + + "}"; + } + } + + /** + * Represents VO to exchange between client and server for move type + */ + static class MovedNotification extends Notification { + private final String targetPath; + + MovedNotification(String itemPath, String operation, String targetPath) { + super(itemPath, operation); + this.targetPath = targetPath; + } + + @Override + public String toString() { + return "{" + + "\"ItemPath\" : \"" + itemPath + "\" ," + + "\"TargetPath\" : \"" + targetPath + "\" ," + + "\"EventType\" : \"" + operation + "\"" + + "}"; + } + + } +} diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Document.pages b/Java/javax/springbootfsstorage/src/main/resources/Storage/Document.pages new file mode 100644 index 0000000..6a9c349 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Document.pages differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/General.docx b/Java/javax/springbootfsstorage/src/main/resources/Storage/General.docx new file mode 100644 index 0000000..e69de29 diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Introduction.pptx b/Java/javax/springbootfsstorage/src/main/resources/Storage/Introduction.pptx new file mode 100644 index 0000000..598ad12 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Introduction.pptx differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Content.txt b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Content.txt new file mode 100644 index 0000000..3338049 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Content.txt @@ -0,0 +1 @@ +My content file text \ No newline at end of file diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/General.doc b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/General.doc new file mode 100644 index 0000000..916c579 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/General.doc differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Introduction.ppt b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Introduction.ppt new file mode 100644 index 0000000..726b1ba Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Introduction.ppt differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Stat.xls b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Stat.xls new file mode 100644 index 0000000..7c838e3 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Stat.xls differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Vision.mpp b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Vision.mpp new file mode 100644 index 0000000..37466bc Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Library/Vision.mpp differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/My Directory/Notes.txt b/Java/javax/springbootfsstorage/src/main/resources/Storage/My Directory/Notes.txt new file mode 100644 index 0000000..45a4503 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/resources/Storage/My Directory/Notes.txt @@ -0,0 +1 @@ +My notes file text \ No newline at end of file diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Notes.txt b/Java/javax/springbootfsstorage/src/main/resources/Storage/Notes.txt new file mode 100644 index 0000000..45a4503 --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/resources/Storage/Notes.txt @@ -0,0 +1 @@ +My notes file text \ No newline at end of file diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Presentation.key b/Java/javax/springbootfsstorage/src/main/resources/Storage/Presentation.key new file mode 100644 index 0000000..838782a Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Presentation.key differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Products/General.doc b/Java/javax/springbootfsstorage/src/main/resources/Storage/Products/General.doc new file mode 100644 index 0000000..916c579 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Products/General.doc differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Products/General.vsd b/Java/javax/springbootfsstorage/src/main/resources/Storage/Products/General.vsd new file mode 100644 index 0000000..e69de29 diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Products/Product.mpp b/Java/javax/springbootfsstorage/src/main/resources/Storage/Products/Product.mpp new file mode 100644 index 0000000..37466bc Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Products/Product.mpp differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Project.pdf b/Java/javax/springbootfsstorage/src/main/resources/Storage/Project.pdf new file mode 100644 index 0000000..c82e775 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Project.pdf differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Plan.doc b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Plan.doc new file mode 100644 index 0000000..916c579 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Plan.doc differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Prices.xls b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Prices.xls new file mode 100644 index 0000000..7c838e3 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Australia/Prices.xls differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Introduction.ppt b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Introduction.ppt new file mode 100644 index 0000000..726b1ba Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Introduction.ppt differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Prices.xls b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Prices.xls new file mode 100644 index 0000000..7c838e3 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Prices.xls differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Product.mpp b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Product.mpp new file mode 100644 index 0000000..37466bc Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Product.mpp differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Stat.xls b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Stat.xls new file mode 100644 index 0000000..7c838e3 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Canada/Stat.xls differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Europe/Stat.xls b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Europe/Stat.xls new file mode 100644 index 0000000..7c838e3 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/Europe/Stat.xls differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/USA/Vision.mpp b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/USA/Vision.mpp new file mode 100644 index 0000000..37466bc Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Sales/USA/Vision.mpp differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Spreadsheet.numbers b/Java/javax/springbootfsstorage/src/main/resources/Storage/Spreadsheet.numbers new file mode 100644 index 0000000..433e419 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Spreadsheet.numbers differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Stat.xlsx b/Java/javax/springbootfsstorage/src/main/resources/Storage/Stat.xlsx new file mode 100644 index 0000000..e1ee183 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Stat.xlsx differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/readme.txt b/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/readme.txt new file mode 100644 index 0000000..d110c9a --- /dev/null +++ b/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/readme.txt @@ -0,0 +1 @@ +This folder contains templates used by Microsoft Office to create documents via New Document menu in AJAX File Browser. \ No newline at end of file diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/template2013.dotx b/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/template2013.dotx new file mode 100644 index 0000000..e69de29 diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/template2013.potx b/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/template2013.potx new file mode 100644 index 0000000..62bb025 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/template2013.potx differ diff --git a/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/template2013.xltx b/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/template2013.xltx new file mode 100644 index 0000000..3f1f4b9 Binary files /dev/null and b/Java/javax/springbootfsstorage/src/main/resources/Storage/Templates/template2013.xltx differ diff --git a/Java/springbootfsstorage/src/main/resources/application.properties b/Java/javax/springbootfsstorage/src/main/resources/application.properties similarity index 100% rename from Java/springbootfsstorage/src/main/resources/application.properties rename to Java/javax/springbootfsstorage/src/main/resources/application.properties diff --git a/Java/springbootoraclestorage/src/main/resources/handler/MyCustomHandlerPage.html b/Java/javax/springbootfsstorage/src/main/resources/handler/MyCustomHandlerPage.html similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/handler/MyCustomHandlerPage.html rename to Java/javax/springbootfsstorage/src/main/resources/handler/MyCustomHandlerPage.html diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html b/Java/javax/springbootfsstorage/src/main/resources/handler/attributesErrorPage.html similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html rename to Java/javax/springbootfsstorage/src/main/resources/handler/attributesErrorPage.html diff --git a/Java/springboots3storage/src/main/resources/logback-spring.xml b/Java/javax/springbootfsstorage/src/main/resources/logback-spring.xml similarity index 100% rename from Java/springboots3storage/src/main/resources/logback-spring.xml rename to Java/javax/springbootfsstorage/src/main/resources/logback-spring.xml diff --git a/Java/springboots3storage/src/main/resources/wwwroot/AjaxFileBrowser.html b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/AjaxFileBrowser.html rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/AjaxFileBrowser.html diff --git a/Java/springboots3storage/src/main/resources/wwwroot/AjaxIntegrationTests.html b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/AjaxIntegrationTests.html rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/AjaxIntegrationTests.html diff --git a/Java/springboots3storage/src/main/resources/wwwroot/css/webdav-layout.css b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/css/webdav-layout.css similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/css/webdav-layout.css rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/css/webdav-layout.css diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/cancel-button.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/cancel-button.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/cancel-button.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/cancel-button.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/check-square.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/check-square.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/check-square.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/check-square.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/copy.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/copy.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/copy.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/copy.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/create-folder.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/create-folder.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/create-folder.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/create-folder.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/cut.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/cut.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/cut.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/cut.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/delete.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/delete.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/delete.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/delete.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/download.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/download.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/download.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/download.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/edit-associated.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/edit-associated.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/edit-associated.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/edit-associated.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/edit.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/edit.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/edit.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/edit.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/file-archive-icon.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/file-archive-icon.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/file-archive-icon.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/file-archive-icon.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/file-default-icon.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/file-default-icon.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/file-default-icon.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/file-default-icon.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/file-image-icon.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/file-image-icon.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/file-image-icon.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/file-image-icon.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/file-pdf-icon.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/file-pdf-icon.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/file-pdf-icon.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/file-pdf-icon.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/folder.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/folder.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/folder.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/folder.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/home.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/home.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/home.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/home.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/locked.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/locked.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/locked.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/locked.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/logo.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/logo.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/logo.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/logo.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/menu-edit.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/menu-edit.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/menu-edit.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/menu-edit.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/microsoft-edit.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/microsoft-edit.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/microsoft-edit.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/microsoft-edit.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/open-folder.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/open-folder.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/open-folder.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/open-folder.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/paste.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/paste.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/paste.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/paste.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/pause-button.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/pause-button.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/pause-button.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/pause-button.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/play-button.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/play-button.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/play-button.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/play-button.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/print.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/print.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/print.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/print.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/reload.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/reload.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/reload.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/reload.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/rename.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/rename.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/rename.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/rename.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/search.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/search.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/search.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/search.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/up-one-level.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/up-one-level.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/up-one-level.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/up-one-level.svg diff --git a/Java/springboots3storage/src/main/resources/wwwroot/images/upload.svg b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/upload.svg similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/images/upload.svg rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/images/upload.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/package.json similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/package.json diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/webdav-common.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/webdav-common.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/webdav-common.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/webdav-common.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/webdav-gridview.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/webdav-gridview.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/webdav-gridview.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/webdav-gridview.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/webdav-uploader.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/webdav-uploader.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/webdav-uploader.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/webdav-uploader.js diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/webdav-websocket.js b/Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/webdav-websocket.js similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/webdav-websocket.js rename to Java/javax/springbootfsstorage/src/main/resources/wwwroot/js/webdav-websocket.js diff --git a/Java/springboots3storage/.mvn/wrapper/maven-wrapper.properties b/Java/javax/springbootoraclestorage/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from Java/springboots3storage/.mvn/wrapper/maven-wrapper.properties rename to Java/javax/springbootoraclestorage/.mvn/wrapper/maven-wrapper.properties diff --git a/Java/springbootoraclestorage/README.md b/Java/javax/springbootoraclestorage/README.md similarity index 100% rename from Java/springbootoraclestorage/README.md rename to Java/javax/springbootoraclestorage/README.md diff --git a/Java/springboots3storage/mvnw b/Java/javax/springbootoraclestorage/mvnw similarity index 100% rename from Java/springboots3storage/mvnw rename to Java/javax/springbootoraclestorage/mvnw diff --git a/Java/springboots3storage/mvnw.cmd b/Java/javax/springbootoraclestorage/mvnw.cmd similarity index 100% rename from Java/springboots3storage/mvnw.cmd rename to Java/javax/springbootoraclestorage/mvnw.cmd diff --git a/Java/springbootoraclestorage/pom.xml b/Java/javax/springbootoraclestorage/pom.xml similarity index 98% rename from Java/springbootoraclestorage/pom.xml rename to Java/javax/springbootoraclestorage/pom.xml index a98b85d..692f346 100644 --- a/Java/springbootoraclestorage/pom.xml +++ b/Java/javax/springbootoraclestorage/pom.xml @@ -9,7 +9,7 @@ com.ithit.webdav.samples springbootoraclestorage - 6.2.9090-Beta + 6.3.9510-Beta springbootoraclestorage Demo project for Spring Boot @@ -54,12 +54,12 @@ com.ithit.webdav webdav-server - 6.2.9090-Beta + 6.3.9510-Beta com.ithit.webdav.integration servlet-integration - 6.2.9090-Beta + 6.3.9510-Beta diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/SpringBootOracleSampleApplication.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/SpringBootOracleSampleApplication.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/SpringBootOracleSampleApplication.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/SpringBootOracleSampleApplication.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/configuration/WebDavConfiguration.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/configuration/WebDavConfiguration.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/configuration/WebDavConfiguration.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/configuration/WebDavConfiguration.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/configuration/WebDavConfigurationProperties.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/configuration/WebDavConfigurationProperties.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/configuration/WebDavConfigurationProperties.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/configuration/WebDavConfigurationProperties.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/controller/DavFilter.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/controller/DavFilter.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/controller/DavFilter.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/controller/DavFilter.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/controller/SamplesController.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/controller/SamplesController.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/controller/SamplesController.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/controller/SamplesController.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/CustomFolderGetHandler.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/CustomFolderGetHandler.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/CustomFolderGetHandler.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/CustomFolderGetHandler.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/DataAccess.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/DataAccess.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/DataAccess.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/DataAccess.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/FileImpl.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/FileImpl.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/FileImpl.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/FileImpl.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/FolderImpl.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/FolderImpl.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/FolderImpl.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/FolderImpl.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/HierarchyItemImpl.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/HierarchyItemImpl.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/HierarchyItemImpl.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/HierarchyItemImpl.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/ItemType.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/ItemType.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/ItemType.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/ItemType.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/SearchFacade.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/SearchFacade.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/SearchFacade.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/SearchFacade.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/SpringBootLogger.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/SpringBootLogger.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/SpringBootLogger.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/SpringBootLogger.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/WebDavEngine.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/WebDavEngine.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/WebDavEngine.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/impl/WebDavEngine.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/HandshakeHeadersInterceptor.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/HandshakeHeadersInterceptor.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/HandshakeHeadersInterceptor.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/HandshakeHeadersInterceptor.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/SocketHandler.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/SocketHandler.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/SocketHandler.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/SocketHandler.java diff --git a/Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/WebSocketServer.java b/Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/WebSocketServer.java similarity index 100% rename from Java/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/WebSocketServer.java rename to Java/javax/springbootoraclestorage/src/main/java/com/ithit/webdav/samples/springbootoracle/websocket/WebSocketServer.java diff --git a/Java/springbootoraclestorage/src/main/resources/application.properties b/Java/javax/springbootoraclestorage/src/main/resources/application.properties similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/application.properties rename to Java/javax/springbootoraclestorage/src/main/resources/application.properties diff --git a/Java/springbootoraclestorage/src/main/resources/db/OracleStorage.sql b/Java/javax/springbootoraclestorage/src/main/resources/db/OracleStorage.sql similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/db/OracleStorage.sql rename to Java/javax/springbootoraclestorage/src/main/resources/db/OracleStorage.sql diff --git a/Java/springboots3storage/src/main/resources/handler/MyCustomHandlerPage.html b/Java/javax/springbootoraclestorage/src/main/resources/handler/MyCustomHandlerPage.html similarity index 100% rename from Java/springboots3storage/src/main/resources/handler/MyCustomHandlerPage.html rename to Java/javax/springbootoraclestorage/src/main/resources/handler/MyCustomHandlerPage.html diff --git a/Java/springbootoraclestorage/src/main/resources/logback-spring.xml b/Java/javax/springbootoraclestorage/src/main/resources/logback-spring.xml similarity index 100% rename from Java/springbootoraclestorage/src/main/resources/logback-spring.xml rename to Java/javax/springbootoraclestorage/src/main/resources/logback-spring.xml diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/AjaxFileBrowser.html similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/AjaxFileBrowser.html diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/AjaxIntegrationTests.html similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/AjaxIntegrationTests.html diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/css/webdav-layout.css similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/css/webdav-layout.css diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/cancel-button.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/cancel-button.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/check-square.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/check-square.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/copy.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/copy.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/create-folder.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/create-folder.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/cut.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/cut.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/delete.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/delete.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/download.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/download.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/edit-associated.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/edit-associated.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/edit.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/edit.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/file-archive-icon.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/file-archive-icon.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/file-default-icon.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/file-default-icon.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/file-image-icon.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/file-image-icon.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/file-pdf-icon.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/file-pdf-icon.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/folder.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/folder.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/home.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/home.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/locked.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/locked.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/logo.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/logo.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/menu-edit.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/menu-edit.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/microsoft-edit.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/microsoft-edit.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/open-folder.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/open-folder.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/paste.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/paste.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/pause-button.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/pause-button.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/play-button.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/play-button.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/print.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/print.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/reload.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/reload.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/rename.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/rename.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/search.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/search.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/up-one-level.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/up-one-level.svg diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/upload.svg similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/images/upload.svg diff --git a/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/package-lock.json b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/package-lock.json new file mode 100644 index 0000000..6032a70 --- /dev/null +++ b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/package-lock.json @@ -0,0 +1,24 @@ +{ + "name": "js", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "webdav.client": "*" + } + }, + "node_modules/webdav.client": { + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" + } + }, + "dependencies": { + "webdav.client": { + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" + } + } +} diff --git a/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/package.json b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/package.json new file mode 100644 index 0000000..7eb3652 --- /dev/null +++ b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "webdav.client": "*" + } +} diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-common.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-common.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-gridview.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-gridview.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-uploader.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-uploader.js diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js b/Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-websocket.js similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-websocket.js rename to Java/javax/springbootoraclestorage/src/main/resources/wwwroot/js/webdav-websocket.js diff --git a/Java/javax/springboots3storage/.mvn/wrapper/maven-wrapper.properties b/Java/javax/springboots3storage/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..b7cb93e --- /dev/null +++ b/Java/javax/springboots3storage/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/Java/springboots3storage/README.md b/Java/javax/springboots3storage/README.md similarity index 100% rename from Java/springboots3storage/README.md rename to Java/javax/springboots3storage/README.md diff --git a/Java/javax/springboots3storage/mvnw b/Java/javax/springboots3storage/mvnw new file mode 100644 index 0000000..8a8fb22 --- /dev/null +++ b/Java/javax/springboots3storage/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/Java/javax/springboots3storage/mvnw.cmd b/Java/javax/springboots3storage/mvnw.cmd new file mode 100644 index 0000000..1d8ab01 --- /dev/null +++ b/Java/javax/springboots3storage/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/Java/springboots3storage/pom.xml b/Java/javax/springboots3storage/pom.xml similarity index 97% rename from Java/springboots3storage/pom.xml rename to Java/javax/springboots3storage/pom.xml index 59b5e3e..b4bbd66 100644 --- a/Java/springboots3storage/pom.xml +++ b/Java/javax/springboots3storage/pom.xml @@ -9,7 +9,7 @@ com.ithit.webdav.samples springboots3storage - 6.2.9090-Beta + 6.3.9510-Beta springboots3storage Demo project for Spring Boot S3 integration @@ -42,12 +42,12 @@ com.ithit.webdav webdav-server - 6.2.9090-Beta + 6.3.9510-Beta com.ithit.webdav.integration servlet-integration - 6.2.9090-Beta + 6.3.9510-Beta diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/SpringBootS3Application.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/SpringBootS3Application.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/SpringBootS3Application.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/SpringBootS3Application.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/configuration/WebDavConfiguration.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/configuration/WebDavConfiguration.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/configuration/WebDavConfiguration.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/configuration/WebDavConfiguration.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/configuration/WebDavConfigurationProperties.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/configuration/WebDavConfigurationProperties.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/configuration/WebDavConfigurationProperties.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/configuration/WebDavConfigurationProperties.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/controller/DavFilter.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/controller/DavFilter.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/controller/DavFilter.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/controller/DavFilter.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/controller/SamplesController.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/controller/SamplesController.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/controller/SamplesController.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/controller/SamplesController.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/CustomFolderGetHandler.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/CustomFolderGetHandler.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/CustomFolderGetHandler.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/CustomFolderGetHandler.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/FileImpl.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/FileImpl.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/FileImpl.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/FileImpl.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/FolderImpl.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/FolderImpl.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/FolderImpl.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/FolderImpl.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/HierarchyItemImpl.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/HierarchyItemImpl.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/HierarchyItemImpl.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/HierarchyItemImpl.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/SerializationUtils.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/SerializationUtils.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/SerializationUtils.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/SerializationUtils.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/SpringBootLogger.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/SpringBootLogger.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/SpringBootLogger.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/SpringBootLogger.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/WebDavEngine.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/WebDavEngine.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/WebDavEngine.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/impl/WebDavEngine.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/s3/DataClient.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/s3/DataClient.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/s3/DataClient.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/s3/DataClient.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/HandshakeHeadersInterceptor.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/HandshakeHeadersInterceptor.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/HandshakeHeadersInterceptor.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/HandshakeHeadersInterceptor.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/SocketHandler.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/SocketHandler.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/SocketHandler.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/SocketHandler.java diff --git a/Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/WebSocketServer.java b/Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/WebSocketServer.java similarity index 100% rename from Java/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/WebSocketServer.java rename to Java/javax/springboots3storage/src/main/java/com/ithit/webdav/samples/springboots3/websocket/WebSocketServer.java diff --git a/Java/springboots3storage/src/main/resources/application.properties b/Java/javax/springboots3storage/src/main/resources/application.properties similarity index 100% rename from Java/springboots3storage/src/main/resources/application.properties rename to Java/javax/springboots3storage/src/main/resources/application.properties diff --git a/Java/javax/springboots3storage/src/main/resources/handler/MyCustomHandlerPage.html b/Java/javax/springboots3storage/src/main/resources/handler/MyCustomHandlerPage.html new file mode 100644 index 0000000..40e06a9 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/handler/MyCustomHandlerPage.html @@ -0,0 +1,453 @@ + + + + IT Hit WebDAV Server Engine + + + + + + + +

+ + +
+
+
+
+ +
+ +
+
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+ Uploaded 0 % + + +
+
+ +
+
+
+
+ Files upload + +
+
+ +
+
+ + + +
+
+
+
+
+
+
Drag files here
+
+
+ + + + + + + + + + + + + +
+ Display NameTypeSizeModified
+
+
+
+
+
+ +
+
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/handler/attributesErrorPage.html b/Java/javax/springboots3storage/src/main/resources/handler/attributesErrorPage.html new file mode 100644 index 0000000..2e33150 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/handler/attributesErrorPage.html @@ -0,0 +1,25 @@ + + IT Hit WebDAV Server Engine + + + + +

Your file system doesn't support User Defined Attributes or they are not enabled

+

Information below will help you to find whether your file system supports User Defined Attributes:

+ + + \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/logback-spring.xml b/Java/javax/springboots3storage/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..e755c20 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/logback-spring.xml @@ -0,0 +1,26 @@ + + + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + log/engine.log + + %date %level [%thread] %logger{10} [%file : %line] %msg%n + + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/AjaxFileBrowser.html b/Java/javax/springboots3storage/src/main/resources/wwwroot/AjaxFileBrowser.html new file mode 100644 index 0000000..0b3ecba --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/AjaxFileBrowser.html @@ -0,0 +1,149 @@ + + + IT Hit Ajax File Browser + + + + + + + + + + +
+ + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/AjaxIntegrationTests.html b/Java/javax/springboots3storage/src/main/resources/wwwroot/AjaxIntegrationTests.html new file mode 100644 index 0000000..7b0a3f5 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/AjaxIntegrationTests.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/css/webdav-layout.css b/Java/javax/springboots3storage/src/main/resources/wwwroot/css/webdav-layout.css new file mode 100644 index 0000000..6ffeaaf --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/css/webdav-layout.css @@ -0,0 +1,1292 @@ +/*Start Common styles*/ +.ellipsis { + position: relative; +} + + .ellipsis:before { + content: ' '; + visibility: hidden; + } + + .ellipsis span, .ellipsis a { + position: absolute; + left: 8px; + right: 8px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + +.bg-dark { + color: white; +} + + .bg-dark h3 { + font-size: 20px; + line-height: 27px; + } + + .bg-dark p { + font-size: 16px; + line-height: 21px; + } + +a.disabled { + pointer-events: none; +} + +.custom-checkbox, .custom-radiobtn { + display: block; + position: relative; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + width: 23px; + height: 23px; + margin: 0px; +} + +.custom-radiobtn { + display: inline-block; + top: 9px; + left: 7px; +} + + .custom-checkbox input, .custom-radiobtn input { + position: absolute; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; + } + + .custom-checkbox .checkmark, .custom-radiobtn .checkmark { + display: block; + position: absolute; + top: 0; + left: 0; + width: 21px; + height: 21px; + border: 2px solid #DEE2E6; + border-radius: 4px; + } + + .custom-radiobtn .checkmark { + border-radius: 12px; + border: 3px solid #DEE2E6; + box-sizing: border-box; + } + +.custom-checkbox input:checked ~ .checkmark { + background-image: url(../images/check-square.svg); + border: none; + width: 22px; + height: 22px; +} + +.custom-radiobtn input:checked ~ .checkmark:before { + content: ""; + display: block; + background-color: #007BFF; + width: 9px; + height: 9px; + position: absolute; + top: 3px; + left: 3px; + border-radius: 5px; +} + +@media (max-width: 1280px) { + .custom-hidden { + display: none !important; + } +} + +button.btn.btn-transparent { + background-color: transparent; + border: none; + padding: 2px 8px; + min-width: initial; + color: #337ab7; +} + +.alert-danger { + margin-top: 15px; +} + +p.error-message { + margin: 0; +} + +.btn-info { + padding: 0px 5px !important; + line-height: 1.2; + margin-top: -3px; +} + +.btn-label { + display: inline-block; + padding: 4px 9px; + background: rgba(0,0,0,0.15); + border-radius: 6px 0 0 6px; +} + +.btn-labeled { + padding: 0; +} + + .btn-labeled span:last-child { + padding: 0 10px 0 5px; + vertical-align: text-bottom; + min-width: 42px; + } + +.btn-edit-label { + padding-left: 5px; +} + +.dropdown-menu-radio-btns { + margin-left: -10px; +} + +.table-hover tbody tr.active, .table-hover tbody tr.active + tr.tr-snippet-url { + background-color: rgba(0,0,0,.075); +} + +.split { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + overflow-y: auto; + overflow-x: hidden; +} + +.gutter { + z-index: 2; + background-color: transparent; + background-repeat: no-repeat; + background-position: 10px 50%; +} + + .gutter.gutter-horizontal { + cursor: col-resize; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAA1CAYAAAB4HnrFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAF/SURBVHgB7VXLUcMwEJUcJVdSgkvIPZOQVABUgKkAOoB0QAeIDkwFduLxPSWoBHP1l/dkicmJiU8mM9nLvpVWO89Pu7LMsmwjpUwEDF4vl8sn4sPhoIMgeCTuum4biDNN1XVdTKdT4+Jvv4HqBZwRF2TSyfNhAym/IM8LMdbfEd+59QflDoTO3/gK0G6OBLvetu38bB0vwWSe5wv4ZxfvIY8mwHoEd0tcluVO8dMhQ2RPSUlnE5um2fg2U0p9DmqzI05sGVRVZfwGKvJmNDFzxHgmkyQJwTFigEY4rtfrmBjDdQ+OC8dRI0eFWHjlAuTQcLErwkQvTzpMnslkYmcZFcwvJ0iDy0iJIZUR45mVBxw3NgDH1WqVEnPoIFdIDI6xl8dPoYaziUiKfPewwCB5DKruGECO0y6JUdUQMEeMZ5RnDo62S/CVBYbL8nRdFYqeI6dALfwbLvrBsvcObd9OumfYG25ms5l28d5voGIK11l+/Xv+701ef3F/2Yi/uB95ycM47B+AqAAAAABJRU5ErkJggg=='); + } + + .split.split-horizontal, .gutter.gutter-horizontal { + float: left; + } + +@media (max-width: 575px) { + #leftPanel { + display: block; + flex-basis: 100% !important; + } + + #rightPanel { + display: none; + } + + .gutter { + display: none; + } +} + +#leftPanel, #rightPanel { + overflow: hidden; +} + +#leftPanel { + position: initial; +} + +#rightPanel { + position: relative; +} + + #rightPanel.disable-iframe-events:before { + content: ""; + display: block; + position: absolute; + background-color: transparent; + height: 100%; + width: 100%; + top: 0; + z-index: 1; + } +#leftPanel.extra-large-point .d-xxl-inline { + display: none !important; +} +#leftPanel.large-point .d-xl-table-cell { + display: none !important; +} + +#leftPanel.medium-point .d-lg-table-cell, +#leftPanel.medium-point .d-xl-table-cell, +#leftPanel.medium-point .d-lg-inline { + display: none !important; +} + +.versions { + font-size: 14px; + line-height: 19px; + color: rgba(0, 0, 0, 0.5); + margin-bottom: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.file-name { + position: absolute; + right: 0px; + top: 13px; + font-size: 16px; + line-height: 27px; + color: #212529; +} + +.modal-footer button { + min-width: 75px; +} + +/*End Common styles*/ + +/*Start Header styles*/ +header { + margin-bottom: 15px; +} + + header p { + word-break: break-word; + } + +.navbar-toggler .burger-icon { + width: 23px; + height: 20px; + position: relative; + margin: 0px; + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + transition: 0.5s ease-in-out; + cursor: pointer; +} + +header .logo { + margin-right: 10px; + position: absolute; + left: 0px; + top: 2px; +} + +.navbar-toggler .burger-icon span { + background: #fff; + display: block; + position: absolute; + height: 2px; + width: 100%; + border-radius: 9px; + opacity: 1; + left: 0; + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + transition: 0.25s ease-in-out; +} + +header .versions { + color: white; + padding-right: 0 !important; +} + +@media (prefers-reduced-motion: reduce) { + .navbar-toggler .burger-icon span { + transition: none; + } + + .navbar-toggler .burger-icon { + transition: none; + } +} + +.navbar-toggler .burger-icon span:nth-child(1) { + top: 1px; +} + +.navbar-toggler .burger-icon span:nth-child(2) { + top: 8px; +} + +.navbar-toggler .burger-icon span:nth-child(3) { + top: 16px; +} + +.navbar-toggler[aria-expanded="true"] .burger-icon span:nth-child(1) { + top: 11px; + -moz-transform: rotate(135deg); + -o-transform: rotate(135deg); + -ms-transform: rotate(135deg); + -webkit-transform: rotate(135deg); + transform: rotate(135deg); +} + +.navbar-toggler[aria-expanded="true"] .burger-icon span:nth-child(2) { + opacity: 0; + left: -60px; +} + +.navbar-toggler[aria-expanded="true"] .burger-icon span:nth-child(3) { + top: 11px; + -moz-transform: rotate(-135deg); + -o-transform: rotate(-135deg); + -ms-transform: rotate(-135deg); + -webkit-transform: rotate(-135deg); + transform: rotate(-135deg); +} + +.navbar-toggler, .navbar-toggler:focus { + border: none; + outline: 0; +} + +.navbar-header h1 { + height: auto; + padding: 15px; + margin: 0; + font-weight: normal; + font-size: 18px; + line-height: 20px; + color: #9d9d9d; +} + +.navbar-brand.ellipsis { + width: calc(100% - 48px); + margin-right: 0; + cursor: pointer; +} + + .navbar-brand.ellipsis span { + left: 45px; + top: 5px; + } + +.navbar { + overflow: hidden; +} + + .navbar .nav-link { + margin-right: 0.5rem; + } + +.navbar-dark .navbar-nav .nav-link { + color: #fff; +} + +@media (max-width: 767px) { + .navbar .nav-link { + margin-right: 0; + margin-bottom: 0.5rem; + } + + .navbar .navbar-collapse { + margin-top: 0.5rem; + } +} + +.header-content { + padding: .5rem 1rem 1.5rem 1rem; +} + + .header-content .col > p { + padding-right: 5rem; + } + + + .header-content a { + font-weight: bold; + color: white; + text-decoration: underline; + } + + .header-content .flex-column { + position: relative; + padding-bottom: 48px; + } + + .header-content .flex-column .btn { + position: absolute; + bottom: 10px; + } +/*End Header styles*/ + +/*Start Main layout styles*/ +.btn-up-one-level { + color: #007BFF; + border: none; + background: none; + cursor: pointer; + margin: 9px 10px 9px 6px; + opacity: 0.9; + display: inline-block; +} + + .btn-up-one-level:hover, .btn-up-one-level:focus { + opacity: 1 + } + + .btn-up-one-level.disabled { + opacity: 0.5; + cursor: not-allowed; + } + + .btn-up-one-level.disabled:hover, .btn-up-one-level.disabled:focus { + opacity: 0.5; + } + + .btn-up-one-level:hover, .btn-up-one-level:focus { + opacity: 1 + } + .btn-up-one-level:before { + content: ""; + display: inline-block; + width: 24px; + height: 24px; + position: relative; + background-repeat: no-repeat; + text-align: center; + background-position: center; + vertical-align: bottom; + background-image: url(../images/up-one-level.svg); + } + + +.breadcrumb { + background: none; + padding: 10px 7px; + margin-bottom: 15px; +} + +ol.breadcrumb li .icon-home { + background-image: url('../images/home.svg'); + display: inline-block; + height: 16px; + width: 14px; + margin-top: 3px; + margin-left: 2px; +} + +/*Start Right Panel styles*/ +.nav-tabs { + border-bottom: 1px solid #007BFF; +} + + .nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { + border-color: #007BFF #007BFF #007BFF; + } + + .nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active { + border-color: #007BFF #007BFF #fff; + } + + .nav-tabs .nav-item { + line-height: 31px; + min-width: 90px; + text-align: center; + } + +.tab-content > .active { + display: block; + border: 1px solid #007BFF; + border-top: none; +} + +.gsuite-container #gSuitePreview, .gsuite-container #gSuiteEdit { + height: 714px; + margin: 0px -8px 25px -8px; +} + + .gsuite-container #gSuitePreview .inner-container, .gsuite-container #gSuiteEdit .inner-container { + height: 714px; + } + +.gsuite-container { + position: relative; +} + + .gsuite-container .background { + position: absolute; + top: calc(50% - 20px); + left: 0; + bottom: 0; + right: 0; + z-index: -1; + overflow: hidden; + text-align: center; + } +/*End Right Panel styles*/ + +/*Start Left Panel styles*/ + +/*Toolbar*/ +.ithit-grid-toolbar { + margin-top: 7px; + padding: 0 10px; +} + + .ithit-grid-toolbar .first-section { + padding: 0 5px; + } + + .ithit-grid-toolbar button, .ithit-grid-toolbar label.btn-upload-items { + color: #007BFF; + border: none; + background: none; + cursor: pointer; + padding: 0; + margin-left: 6px; + opacity: 0.9; + } + + .ithit-grid-toolbar button.btn-create-folder { + white-space: nowrap + } + + .ithit-grid-toolbar button:before, .ithit-grid-toolbar label.btn-upload-items:before { + content: ""; + display: inline-block; + width: 24px; + height: 24px; + margin-right: 10px; + position: relative; + background-repeat: no-repeat; + text-align: center; + background-position: center; + vertical-align: bottom; + } + + .ithit-grid-toolbar button:disabled { + opacity: 0.5; + cursor: not-allowed; + } + + + .ithit-grid-toolbar button:disabled:hover, .ithit-grid-toolbar button:disabled:focus { + opacity: 0.5; + } + + .ithit-grid-toolbar button:hover, .ithit-grid-toolbar button:focus { + opacity: 1 + } + + .ithit-grid-toolbar button.btn-create-folder:before { + background-image: url(../images/create-folder.svg); + } + + .ithit-grid-toolbar label.btn-upload-items:before { + background-image: url(../images/upload.svg); + } + + .ithit-grid-toolbar button.btn-copy-items:before { + margin: 0 4px; + background-image: url(../images/copy.svg); + } + + .ithit-grid-toolbar button.btn-cut-items:before { + margin: 0 4px; + background-image: url(../images/cut.svg); + } + + .ithit-grid-toolbar button.btn-paste-items:before { + margin: 0 4px; + background-image: url(../images/paste.svg); + } + + .ithit-grid-toolbar button.btn-reload-items:before { + margin: 0 4px; + background-image: url(../images/reload.svg); + } + + .ithit-grid-toolbar button.btn-rename-item:before { + background-image: url(../images/rename.svg); + } + + .ithit-grid-toolbar button.btn-download-items:before { + background-image: url(../images/download.svg); + } + + .ithit-grid-toolbar button.btn-print-items:before { + background-image: url(../images/print.svg); + } + + .ithit-grid-toolbar button.btn-delete-items:before { + background-image: url(../images/delete.svg); + } + + .ithit-grid-toolbar button:hover:before, .ithit-grid-toolbar button:focus:before { + opacity: 1; + } + +/*Search Panel*/ +.ithit-search-container { + position: relative; + height: 50px; +} + + .ithit-search-container input.tt-input[disabled], + .ithit-search-container input.tt-input[readonly] { + cursor: default; + } + + .ithit-search-container .twitter-typeahead { + position: relative; + width: 100%; + margin-bottom: 15px; + } + + .ithit-search-container .twitter-typeahead:before { + position: absolute; + top: 9px; + left: 7px; + content: ""; + background-image: url(../images/search.svg); + display: block; + width: 20px; + height: 20px; + z-index: 1; + } + + .ithit-search-container .twitter-typeahead input { + padding: .4rem .75rem .4rem 40px; + } + + .ithit-search-container button { + position: absolute; + top: 0; + right: 0; + width: 85px; + } + +.tt-suggestion .snippet, .ithit-grid-container .snippet { + overflow: hidden; + font-size: 12px; + line-height: 18px; + color: #999; +} + +.tt-suggestion .breadcrumb, .ithit-grid-container .breadcrumb { + font-size: 12px; + color: #999; + word-break: break-word; +} + +.ithit-grid-container ol.breadcrumb, .tt-suggestion ol.breadcrumb { + list-style: none; + background-color: transparent; + padding: 0 0 0 8px; + margin: 0; +} + +.tt-suggestion ol.breadcrumb { + padding: 0; +} + + .tt-suggestion ol.breadcrumb li:first-child, .ithit-grid-container ol.breadcrumb li:first-child { + display: none; + } + + .ithit-grid-container ol.breadcrumb li, .tt-suggestion ol.breadcrumb li { + display: inline-block; + } + + .ithit-grid-container ol.breadcrumb li:nth-of-type(2):before, + .tt-suggestion ol.breadcrumb li:nth-of-type(2):before { + display: none; + } + + .ithit-grid-container ol.breadcrumb li:before, .tt-suggestion ol.breadcrumb li:before { + padding-right: .3rem; + padding-left: .3rem; + } + + + +.tt-suggestion .snippet b, .ithit-grid-container .snippet b { + color: #555; +} + +.tt-hint { + color: #999; +} + +.tt-menu { + width: 100%; + right: 100px; + margin: 1px 0; + padding: 6px 0; + background-color: #fff; + border: 1px solid #ccc; + -webkit-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} + +.tt-suggestion { + padding: 3px 20px; + line-height: 1.7; +} + + .tt-suggestion:hover { + cursor: pointer; + background-color: #eee; + } + + .tt-suggestion.tt-cursor { + background-color: #eee; + } + +table tr.tr-snippet-url td { + padding: 0px; + border-top: none; +} + + table tr.tr-snippet-url td > div { + padding-left: 8px; + } + + table tr.tr-snippet-url td > div:last-child { + margin-bottom: 8px; + padding-right: 8px; + } + +/*Grid Items*/ +.ithit-grid-container { + width: 100%; + /*margin-top: 20px;*/ + overflow-y: hidden; +} + +.ithit-grid-container .icon-folder { + background-image: url(../images/folder.svg); + display: inline-block; + height: 14px; + width: 16px; +} + +.ithit-grid-container .icon-open-folder, .ithit-grid-container .icon-edit, +.ithit-grid-container .icon-microsoft-edit, .icon-gsuite-edit, +.ithit-grid-container .icon-edit-associated { + background-image: url(../images/open-folder.svg); + background-repeat: no-repeat; + display: inline-block; + height: 19px; + width: 19px; + position: relative; + top: 5px; +} + +.ithit-grid-container .icon-edit { + background-image: url(../images/edit.svg); + top: 2px; +} + +.ithit-grid-container .icon-microsoft-edit, .ithit-grid-container .icon-gsuite-edit { + background: none; + -webkit-mask-image: url(../images/menu-microsoft-edit.svg); + mask-image: url(../images/menu-microsoft-edit.svg); + background-color: white; + -webkit-mask-size: cover; + top: 2px; +} + +.ithit-grid-container .icon-gsuite-edit { + -webkit-mask-image: url(../images/menu-gsuit-edit.svg); + mask-image: url(../images/menu-gsuit-edit.svg); +} + +.ithit-grid-container th.sort { + position: relative; + cursor: pointer; +} + + .ithit-grid-container th.sort.ascending, th.sort.descending { + padding-right: 15px; + } + + .ithit-grid-container th.sort.ascending:after, th.sort.descending:after { + content: ""; + display: inline-block; + position: absolute; + left: -5px; + width: 0px; + height: 0px; + margin-top: 6px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #2f2f2f; + } + + .ithit-grid-container th.sort.descending:after { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #2f2f2f; + border-bottom: none; + margin-top: 13px; + } + + .ithit-grid-container th.sort.disabled { + pointer-events: none; + } + + .ithit-grid-container th.sort.disabled:after { + display: none; + } + +.ithit-grid-container .column-action { + text-align: right; + padding-left: 0; + padding-right: 0; +} + + .ithit-grid-container .column-action a { + display: inline-block; + padding: 2px 8px; + } + + .ithit-grid-container .column-action a:last-child { + margin-right: 0; + } + + .ithit-grid-container .column-action button.browse-lnk span:last-child { + margin-right: 10px; + } + + .ithit-grid-container .column-action button span { + vertical-align: middle; + } + +.ithit-grid-container .badge { + left: 22px; + font-size: 55%; + position: absolute; + top: 27px; + background: #FFFFFF; + border: 1px solid #409CFF; + box-sizing: border-box; + border-radius: 6px; + padding: 1px 5px; + color: #212529; +} + +table.ithit-grid-container > tbody > tr > td { + vertical-align: middle; + white-space: nowrap; + cursor: default; +} + + table.ithit-grid-container > thead > tr > th:nth-child(1), + table.ithit-grid-container > tbody > tr > td:nth-child(1) { + text-align: right; + } + + table.ithit-grid-container > thead > tr > th:nth-child(2), + table.ithit-grid-container > tbody > tr > td:nth-child(2) { + min-width: 46px; + text-align: center; + position: relative; + } + + table.ithit-grid-container > thead > tr > th:nth-child(4), + table.ithit-grid-container > tbody > tr > td:nth-child(4) { + min-width: 120px; + max-width: 120px; + } + + table.ithit-grid-container > thead > tr > th:nth-child(5), + table.ithit-grid-container > tbody > tr > td:nth-child(5) { + min-width: 100px; + max-width: 100px; + } + + table.ithit-grid-container > tbody > tr > td:nth-child(3) { + width: 100%; + } + + table.ithit-grid-container > tbody > tr > td button:last-child { + margin-left: 5px; + } + + table.ithit-grid-container > tbody > tr > td button.btn-delete .btn-label { + padding-left: 5px; + } + +@media (max-width: 320px) { + table.ithit-grid-container > thead > tr > th:nth-child(5), + table.ithit-grid-container > tbody > tr > td:nth-child(5) { + display: none; + } +} + +.ithit-grid-icon-locked { + background-image: url(../images/locked.svg); + width: 17px; + height: 22px; + display: inline-block; +} + +.ithit-grid-container button.btn-labeled { + border-radius: 5px; +} + +.ithit-grid-container .actions input[type=radio] { + position: relative; + top: 0; + left: 0; + width: 20px; + height: 20px; + z-index: 3; +} + +.ithit-grid-container .actions .icon-edit, .ithit-grid-container .actions .icon-microsoft-edit, +.ithit-grid-container .actions .icon-gsuite-edit, +.ithit-grid-container .actions .icon-edit-associated { + display: inline-block; + background-image: url(../images/menu-edit.svg); + width: 28px; + height: 24px; + vertical-align: middle; + margin-top: -10px; + margin-right: 10px; +} + +.ithit-grid-container .actions .icon-edit-associated { + background-image: url(../images/edit-associated.svg); + width: 27px; + height: 30px; + margin-top: -17px; +} + +.ithit-grid-container .actions .dropdown-item { + padding-top: 10px; + padding-bottom: 10px; +} + + .ithit-grid-container .actions .dropdown-item.desktop-app { + padding-left: 61px; + } + +.ithit-grid-container .actions.dropdown-menu-radio-btns .dropdown-item.desktop-app { + padding-left: 76px; +} + +.ithit-grid-container .actions .dropdown-radio { + margin-top: -28px; + z-index: 2; + padding-left: 40px; +} + +.ithit-grid-container .actions .icon-microsoft-edit, .ithit-grid-container .actions .icon-gsuite-edit { + background-image: url(../images/menu-microsoft-edit.svg); + width: 25px; + height: 26px; + margin-top: -9px; +} + +.ithit-grid-container .actions .icon-gsuite-edit { + background-image: url(../images/menu-gsuit-edit.svg); +} + +table tr.hover, table tr:hover, table tr:hover + table tr.tr-snippet-url { + background-color: rgba(0,0,0,.075); +} + +.table td, .table th { + padding: 0.5rem; +} + +.table-responsive { + border: none; +} + +/*Uploader Grid*/ +.progress-wrapper { + padding: 3px 0; +} + + .progress-wrapper:hover ~ .uploading-block { + visibility: visible; + opacity: 1; + } +.progress { + height: 3px +} + +.progress-bar { + background-color: #007BFF; + box-shadow: 0px 0px 8px rgba(0, 123, 255, 0.5); +} + +.ithit-grid-uploads { + margin-top: 20px; +} + + .ithit-grid-uploads button:not(:disabled):not(.disabled) { + cursor: pointer; + } + + + +.uploading-block, +.uploading-details { + display: inline-block; + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 4px; + margin-top: 0px; +} + +.uploading-block { + min-width: 208px; + + visibility: hidden; + opacity: 0; + transition: visibility 0.5s, opacity 0.5s linear; +} + + .uploading-block:hover, .uploading-block.show { + visibility: visible; + opacity: 1; + } + + .uploading-block.hide { + visibility: hidden !important; + opacity: 0; + transition: visibility 0.5s, opacity 0.5s linear; + } + + .uploading-block .uploading-controls { + padding: 12px 14px; + line-height: 28px + } + + .uploading-block .uploading-controls .persent { + color: #007BFF + } + + .uploading-block .btn.btn-primary { + border-radius: 0 0 4px 4px; + width: 100% + } + +@media (max-width: 575px) { + .uploading-details { + left: 15px; + right: 15px; + } +} +@media (min-width: 576px) { + .uploading-details { + min-width: 479px; + } +} + + .uploading-details .details-header { + padding: 8px + } + + .uploading-details .details-header .details-title { + font-size: 16px; + line-height: 21px; + padding: 5px; + } + +.uploading-items { + max-height: 300px; + overflow-y: auto; + padding: 0 30px 15px 10px +} + +.uploading-item { + align-items: center; + margin: 0; + padding: 9px 0 +} + + .uploading-item .item-progress, + .uploading-item .item-size, + .uploading-item .item-speed { + font-size: 12px; + line-height: 16px; + color: #b3b3b3 + } + + .uploading-item .item-name span { + padding: 0 7px; + } + + .uploading-item .file-icon { + position: relative; + width: 38px; + height: 49px; + background: url(../images/file-default-icon.svg) no-repeat + } + + .uploading-item .file-icon { + position: relative; + width: 38px; + height: 49px; + background: url(../images/file-default-icon.svg) no-repeat + } + + .uploading-item .file-icon.file-7z, + .uploading-item .file-icon.file-gz, + .uploading-item .file-icon.file-rar, + .uploading-item .file-icon.file-tar, + .uploading-item .file-icon.file-zip { + background: url(../images/file-archive-icon.svg) no-repeat + } + + .uploading-item .file-icon.file-gif, + .uploading-item .file-icon.file-jpeg, + .uploading-item .file-icon.file-jpg, + .uploading-item .file-icon.file-png, + .uploading-item .file-icon.file-svg { + background: url(../images/file-image-icon.svg) no-repeat + } + + .uploading-item .file-icon.file-pdf { + background: url(../images/file-pdf-icon.svg) no-repeat + } + + .uploading-item .file-icon .file-extension { + font-family: Arial, Helvetica, sans-serif; + color: #fff; + font-size: 12px; + position: absolute; + bottom: 0; + line-height: 1.1; + left: 50%; + transform: translate(-50%) + } + +button.cancel-button, +button.close-button, +button.pause-button, +button.play-button { + padding: 0; + border: none; + background-color: transparent; + text-align: center +} + + button.cancel-button:before, + button.close-button:before, + button.pause-button:before, + button.play-button:before { + content: ""; + display: block; + width: 28px; + height: 28px; + background-repeat: no-repeat; + background-position: 50% + } + + button.pause-button:before { + background-image: url(../images/pause-button.svg) + } + + button.play-button:before { + background-image: url(../images/play-button.svg) + } + + button.close-button:before { + background-image: url(../images/cancel-button.svg) + } + + button.cancel-button:before { + background-image: url(../images/cancel-button.svg) + } + +button.cancel-all-button { + margin: 15px 30px 15px 10px +} + +.ithit-grid-wrapper { + margin: 20px 0px; + border: 2px solid transparent; + position: relative; +} + .ithit-grid-wrapper .table-responsive { + min-height: 300px; + } + + .ithit-grid-wrapper .drop-files-header { + display: none; + } + +.dropzone .ithit-grid-wrapper { + border: 2px solid #007BFF; +} + + .dropzone .ithit-grid-wrapper .drop-files-header { + display: block; + position: absolute; + left: 0; + right: 0; + top: 0; + height: 42px; + width: 100%; + z-index: 2; + background-color: white; + border-bottom: 1px solid #007BFF; + color: #007BFF; + text-align: center; + } + + .dropzone .ithit-grid-wrapper .drop-files-header .drop-files-title { + margin-top: 7px; + font-size: 20px; + line-height: 27px; + } + + .dropzone .ithit-grid-wrapper .drop-files-header .drop-files-title:before { + content: ""; + display: inline-block; + width: 24px; + height: 24px; + margin-right: 10px; + position: relative; + background-repeat: no-repeat; + text-align: center; + background-position: center; + vertical-align: bottom; + background-image: url(../images/upload.svg); + } + + .dropzone .ithit-grid-wrapper tr { + opacity: 0.4; + } + +.more-lnk { + margin: 15px 0; + display: inline-block; +} + +.more-pnl { + padding-left: 15px; + display: none; +} + +.ui-draggable { + cursor: move; +} +/*End Main layout styles*/ diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/cancel-button.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/cancel-button.svg new file mode 100644 index 0000000..8e13466 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/cancel-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/check-square.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/check-square.svg new file mode 100644 index 0000000..f61913d --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/check-square.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/copy.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/copy.svg new file mode 100644 index 0000000..5ac0b67 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/copy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/create-folder.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/create-folder.svg new file mode 100644 index 0000000..0b1f205 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/create-folder.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/cut.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/cut.svg new file mode 100644 index 0000000..bc0b4d3 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/cut.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/delete.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/delete.svg new file mode 100644 index 0000000..7e16e63 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/delete.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/download.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/download.svg new file mode 100644 index 0000000..194382d --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/download.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/edit-associated.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/edit-associated.svg new file mode 100644 index 0000000..ec19cce --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/edit-associated.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/edit.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/edit.svg new file mode 100644 index 0000000..1540872 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/edit.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-archive-icon.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-archive-icon.svg new file mode 100644 index 0000000..6343516 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-archive-icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-default-icon.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-default-icon.svg new file mode 100644 index 0000000..56bcace --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-default-icon.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-image-icon.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-image-icon.svg new file mode 100644 index 0000000..ade2b79 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-image-icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-pdf-icon.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-pdf-icon.svg new file mode 100644 index 0000000..dcb1b85 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/file-pdf-icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/folder.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/folder.svg new file mode 100644 index 0000000..d900027 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/folder.svg @@ -0,0 +1,3 @@ + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/home.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/home.svg new file mode 100644 index 0000000..f63b4f6 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/home.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/locked.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/locked.svg new file mode 100644 index 0000000..d68efcf --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/locked.svg @@ -0,0 +1,3 @@ + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/logo.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/logo.svg new file mode 100644 index 0000000..7e321fc --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-edit.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-edit.svg new file mode 100644 index 0000000..3ef3edc --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-edit.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg new file mode 100644 index 0000000..730dd8b --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-gsuit-edit.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg new file mode 100644 index 0000000..d5116ef --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/menu-microsoft-edit.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/microsoft-edit.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/microsoft-edit.svg new file mode 100644 index 0000000..fb2da8c --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/microsoft-edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/open-folder.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/open-folder.svg new file mode 100644 index 0000000..5fea104 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/open-folder.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/paste.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/paste.svg new file mode 100644 index 0000000..1f1a062 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/paste.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/pause-button.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/pause-button.svg new file mode 100644 index 0000000..6b1d021 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/pause-button.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/play-button.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/play-button.svg new file mode 100644 index 0000000..6cce171 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/play-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/print.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/print.svg new file mode 100644 index 0000000..378b072 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/print.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/reload.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/reload.svg new file mode 100644 index 0000000..b70ad9e --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/reload.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/rename.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/rename.svg new file mode 100644 index 0000000..b1cee21 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/rename.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/search.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/search.svg new file mode 100644 index 0000000..62df0f4 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/up-one-level.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/up-one-level.svg new file mode 100644 index 0000000..1f45bd4 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/up-one-level.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/images/upload.svg b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/upload.svg new file mode 100644 index 0000000..4605326 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/images/upload.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/package-lock.json b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/package-lock.json similarity index 53% rename from Java/springboots3storage/src/main/resources/wwwroot/js/package-lock.json rename to Java/javax/springboots3storage/src/main/resources/wwwroot/js/package-lock.json index e5c0203..2ec1786 100644 --- a/Java/springboots3storage/src/main/resources/wwwroot/js/package-lock.json +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/package-lock.json @@ -9,16 +9,16 @@ } }, "node_modules/webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } }, "dependencies": { "webdav.client": { - "version": "5.21.5941", - "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5941.tgz", - "integrity": "sha512-REQLPRbIDFAI4gHhj9W5N+i2/Q3fJen8lNGflPaN0VI8v9iacZIPh6VnfhQQ5TS/K6wdugdC17MfKunLt8vLzA==" + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" } } } diff --git a/Java/springboots3storage/src/main/resources/wwwroot/js/package.json b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/package.json similarity index 100% rename from Java/springboots3storage/src/main/resources/wwwroot/js/package.json rename to Java/javax/springboots3storage/src/main/resources/wwwroot/js/package.json diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js new file mode 100644 index 0000000..2e18e7a --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-basebutton.js @@ -0,0 +1,34 @@ +/** + * This class represents button that occurred on client. + * @class + * @param {string} sName - The name of button. + * @param {string} cssClass - This cssClass will be inserted into html. + * @property {string} Name + * @property {string} CssClass + */ +function BaseButton(sName, cssClass) { + this.Name = sName; + this.CssClass = cssClass; + this.InnerHtmlContent = ""; + + this.Create = function ($toolbarContainer) { + $toolbarContainer.append(''); + this.$Button = $('.' + this.CssClass); + } + + this.Disable = function () { + this.$Button.attr('disabled', true); + } + + this.Activate = function () { + this.$Button.attr('disabled', false); + } + + this.HideOnMobile = function () { + this.$Button.addClass('d-none d-md-inline'); + } + + this.ShowOnMobile = function () { + this.$Button.removeClass('d-none d-md-inline'); + } +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js new file mode 100644 index 0000000..a2411e4 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-copypastecutbuttons.js @@ -0,0 +1,179 @@ +const sCopyItemsErrorMessage = "Copy items error."; +const sCutItemsErrorMessage = "Cut items error."; +const sCutItemsSameNameErrorMessage = "The source and destination file names are the same."; +const sCutItemsLockedErrorMessage = "Items are locked."; + +function HerarhyItemsCopyPasteController(toolbar, storedItems) { + //Copied or cut items + this.storedItems = storedItems; + this.isCopiedItems = false; + this.Toolbar = toolbar; +} + +HerarhyItemsCopyPasteController.prototype = { + /** + * Copies files or folders. + */ + Copy: function (oItem, oItemName, fCallback) { + oItem.CopyToAsync(this.Toolbar.WebDAV.CurrentFolder, oItemName, true, null, null, function (oAsyncResult) { + fCallback(oAsyncResult); + }); + }, + + /** + * Moves files or folders. + */ + Move: function (oItem, fCallback) { + oItem.MoveToAsync(this.Toolbar.WebDAV.CurrentFolder, oItem.DisplayName, null, null, function (oAsyncResult) { + fCallback(oAsyncResult); + }); + }, + + /** + * Adds items to storeItems array. + */ + _PushStoreItems: function () { + var self = this; + if (self.storedItems.length != 0) { + $.each(self.storedItems, function (index) { + self.storedItems.pop(this); + }); + } + $.each(self.Toolbar.FolderGrid.selectedItems, function (index) { + self.storedItems.push(self.Toolbar.FolderGrid.selectedItems[index]); + }); + + self.Toolbar.UpdateToolbarButtons(); + }, + + /** + * Moves or pastes files or folders. + */ + _MoveOrPasteItems: function () { + var self = this; + if (self.isCopiedItems) { + $.each(self.storedItems, function (index) { + self._ExecuteCopy(self.storedItems[index]); + }); + } else { + $.each(self.storedItems, function (index) { + self.Move(self.storedItems[index], function (oAsyncResult) { + if (!oAsyncResult.IsSuccess) { + if (oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.ForbiddenException) { + WebdavCommon.ErrorModal.Show(sCutItemsSameNameErrorMessage, oAsyncResult.Error); + } + else if (oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.LockedException) { + WebdavCommon.ErrorModal.Show(sCutItemsLockedErrorMessage, oAsyncResult.Error); + } + else { + WebdavCommon.ErrorModal.Show(sCutItemsErrorMessage, oAsyncResult.Error); + } + } + }); + }); + $.each(self.storedItems, function (index) { + self.storedItems.pop(this); + }); + } + this.Toolbar.UpdateToolbarButtons(); + }, + + _ExecuteCopy: function (oItem) { + var self = this; + self._DoCopy(oItem, self._GetCopySuffix(oItem.DisplayName, false)); + }, + + /** + * Copies files or folders or shows error modal. + */ + _DoCopy: function (oItem, oItemName) { + var self = this; + self.Copy(oItem, oItemName, function (oAsyncResult) { + if (!oAsyncResult.IsSuccess) { + if ( + oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.PreconditionFailedException || + oAsyncResult.Error instanceof window.ITHit.WebDAV.Client.Exceptions.ForbiddenException) { + self._DoCopy(oItem, self._GetCopySuffix(oItemName, true)); + } + else { + WebdavCommon.ErrorModal.Show(sCopyItemsErrorMessage, oAsyncResult.Error); + } + } + }); + }, + + /** + * Gets 'Copy' suffix. + */ + _GetCopySuffix: function (oItemName, bWithCopySuffix) { + var sCopyPrefixName = 'Copy'; + + var aExtensionMatches = /\.[^\.]+$/.exec(oItemName); + var sName = aExtensionMatches !== null ? oItemName.replace(aExtensionMatches[0], '') : oItemName; + var sDotAndExtension = aExtensionMatches !== null ? aExtensionMatches[0] : ''; + + var sLangCopy = sCopyPrefixName; + var oSuffixPattern = new RegExp('- ' + sLangCopy + '( \\(([0-9]+)\\))?$', 'i'); + + var aSuffixMatches = oSuffixPattern.exec(sName); + if (aSuffixMatches === null && bWithCopySuffix) { + sName += " - " + sLangCopy; + } else if (aSuffixMatches !== null && !aSuffixMatches[1]) { + sName += " (2)"; + } else if (aSuffixMatches !== null) { + var iNextNumber = parseInt(aSuffixMatches[2]) + 1; + sName = sName.replace( + oSuffixPattern, + "- " + sLangCopy + " (" + iNextNumber + ")" + ); + } + + oItemName = sName + sDotAndExtension; + return oItemName; + }, +} + +function CopyPasteButtonsControl(toolbar) { + this.CopyButton = new BaseButton('Copy', 'btn-copy-items', toolbar); + this.PasteButton = new BaseButton('Paste', 'btn-paste-items', toolbar); + this.CutButton = new BaseButton('Cut', 'btn-cut-items', toolbar); + this.storedItems = []; + + var oHerarhyItemsCopyPasteController = new HerarhyItemsCopyPasteController(toolbar, this.storedItems); + + this.Create = function (tolbarSection) { + + this.CopyButton.Create(tolbarSection); + this.CutButton.Create(tolbarSection); + this.PasteButton.Create(tolbarSection); + } + this.Disable = function () { + this.CopyButton.Disable(); + this.CutButton.Disable(); + this.PasteButton.Disable(); + } + + this.Activate = function () { + this.CopyButton.Activate(); + this.CutButton.Activate(); + this.PasteButton.Activate(); + } + + this.Render = function () { + this.CopyButton.$Button.on('click', function () { + oHerarhyItemsCopyPasteController.isCopiedItems = true; + oHerarhyItemsCopyPasteController._PushStoreItems(); + }) + + this.CutButton.$Button.on('click', function () { + oHerarhyItemsCopyPasteController.isCopiedItems = false; + oHerarhyItemsCopyPasteController._PushStoreItems(); + }) + + this.PasteButton.$Button.on('click', function () { + oHerarhyItemsCopyPasteController._MoveOrPasteItems(); + }) + } + + +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js new file mode 100644 index 0000000..c51debb --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-createfolderbutton.js @@ -0,0 +1,71 @@ +function CreateFolderController(toolbar) { + this.Toolbar = toolbar; +} + +CreateFolderController.prototype = { + CreateFolder: function (sFolderName, fCallback) { + this.Toolbar.WebDAV.CurrentFolder.CreateFolderAsync(sFolderName, null, null, function (oAsyncResult) { + fCallback(oAsyncResult); + }); + }, +} + +/////////////////// +// Create Folder Bootstrap Modal +function CreateFolderModal(modalSelector, createFolderController) { + var sCreateFolderErrorMessage = "Create folder error."; + + var self = this; + this.$modal = $(modalSelector); + this.$txt = $(modalSelector).find('input[type="text"]'); + this.$submitButton = $(modalSelector).find('.btn-submit'); + this.$alert = $(modalSelector).find('.alert-danger'); + + this.$modal.on('shown.bs.modal', function () { + self.$txt.focus(); + }) + this.$modal.find('form').submit(function () { + self.$alert.addClass('d-none'); + if (self.$txt.val() !== null && self.$txt.val().match(/^ *$/) === null) { + var oValidationMessage = WebdavCommon.Validators.ValidateName(self.$txt.val()); + if (oValidationMessage) { + self.$alert.removeClass('d-none').text(oValidationMessage); + return false; + } + + self.$txt.blur(); + self.$submitButton.attr('disabled', 'disabled'); + createFolderController.CreateFolder(self.$txt.val().trim(), function (oAsyncResult) { + if (!oAsyncResult.IsSuccess) { + if (oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.MethodNotAllowedException) { + self.$alert.removeClass('d-none').text(oAsyncResult.Error.Error.Description ? oAsyncResult.Error.Error.Description : 'Folder already exists.'); + } + else { + WebdavCommon.ErrorModal.Show(sCreateFolderErrorMessage, oAsyncResult.Error); + } + } + else { + self.$modal.modal('hide'); + } + self.$submitButton.removeAttr('disabled'); + }); + } + else { + self.$alert.removeClass('d-none').text('Name is required!'); + } + return false; + }); +} + +function ToolbarCreateFolderButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + var oCreateFolderModal = new CreateFolderModal('#CreateFolderModal', new CreateFolderController(toolbar)); + this.InnerHtmlContent = 'Create Folder'; + this.Render = function () { + this.$Button.on('click', function () { + oCreateFolderModal.$txt.val(''); + oCreateFolderModal.$alert.addClass('d-none'); + oCreateFolderModal.$modal.modal('show'); + }) + } +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js new file mode 100644 index 0000000..c8dc136 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-deletebutton.js @@ -0,0 +1,33 @@ +function HerarhyItemDeleteController(toolbar) { + this.Toolbar = toolbar; +} + +HerarhyItemDeleteController.prototype = { + Delete: function () { + var self = this; + self.Toolbar.ConfirmModal.Confirm('Are you sure want to delete selected items?', function () { + var countDeleted = 0; + self.Toolbar.WebDAV.AllowReloadGrid = false; + $.each(self.Toolbar.FolderGrid.selectedItems, function (index) { + self.Toolbar.FolderGrid.selectedItems[index].DeleteAsync(null, function () { + if (++countDeleted == self.Toolbar.FolderGrid.selectedItems.length) { + self.Toolbar.WebDAV.AllowReloadGrid = true; + self.Toolbar.WebDAV.Reload(); + self.Toolbar.ResetToolbar(); + } + }); + }); + }); + } +} + +function ToolbarDeleteButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + this.InnerHtmlContent = 'Delete'; + + this.Render = function () { + this.$Button.on('click', function () { + new HerarhyItemDeleteController(toolbar).Delete(); + }) + } +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js new file mode 100644 index 0000000..580a9c1 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-downloadbutton.js @@ -0,0 +1,43 @@ +function HerarhyItemDownloadController(toolbar) { + this.Toolbar = toolbar; +} + +HerarhyItemDownloadController.prototype = { + DownloadFiles: function () { + var self = this; + $.each(self.Toolbar.FolderGrid.selectedItems, function (index) { + if (!this.IsFolder()) { + self._Delay(index * 1000); + self._Download(this.Href + "?download", ''); + } + }); + }, + _Download: function (url, name) { + const a = document.createElement('a'); + a.download = name; + a.href = url; + a.style.display = 'none'; + document.body.append(a); + a.click(); + + // Chrome requires the timeout + this._Delay(100); + a.remove(); + }, + _Delay: function () { + return ms => new Promise(resolve => setTimeout(resolve, ms)); + } +} + + + +function ToolbarDownloadButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + this.InnerHtmlContent = 'Download'; + + this.Render = function () { + this.$Button.on('click', function () { + new HerarhyItemDownloadController(toolbar).DownloadFiles(); + }) + } +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js new file mode 100644 index 0000000..7b327ac --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-printbutton.js @@ -0,0 +1,39 @@ +function HerarhyItemPrintController(toolbar) { + this.Toolbar = toolbar; +} + +HerarhyItemPrintController.prototype = { + /** + * Print documents. + * @param {string} sDocumentUrls Array of document URLs + */ + PrintDocs: function (sDocumentUrls) { + ITHit.WebDAV.Client.DocManager.DavProtocolEditDocument(sDocumentUrls, this.Toolbar.WebDAV.GetMountUrl(), + this.Toolbar.WebDAV._ProtocolInstallMessage.bind(this.Toolbar.WebDAV), null, webDavSettings.EditDocAuth.SearchIn, + webDavSettings.EditDocAuth.CookieNames, webDavSettings.EditDocAuth.LoginUrl, 'Print'); + }, + ExecutePrint: function () { + self = this; + self.Toolbar.ConfirmModal.Confirm('Are you sure want to print selected items?', function () { + var filesUrls = []; + $.each(self.Toolbar.FolderGrid.selectedItems, function () { + if (!this.IsFolder()) { + filesUrls.push(this.Href); + } + }); + + self.PrintDocs(filesUrls); + }); + } +} + +function ToolbarPrintButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + this.InnerHtmlContent = 'Print'; + + this.Render = function () { + this.$Button.on('click', function () { + new HerarhyItemPrintController(toolbar).ExecutePrint(); + }) + } +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js new file mode 100644 index 0000000..ec3e001 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-reloadbutton.js @@ -0,0 +1,9 @@ +function ToolbarReloadButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + + this.Render = function () { + this.$Button.on('click', function () { + toolbar.WebDAV.Reload(); + }) + } +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js new file mode 100644 index 0000000..db711d5 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-renamebutton.js @@ -0,0 +1,84 @@ +const sRenameItemErrorMessage = "Rename item error."; +const sRenameItemLockedErrorMessage = "Item is locked."; + +function RenameItemController(toolbar) { + this.Toolbar = toolbar; +} + +RenameItemController.prototype = { + /** + * Renames files or folders. + */ + Rename: function (newItemName, fCallback) { + this.Toolbar.FolderGrid.selectedItems[0].MoveToAsync(this.Toolbar.WebDAV.CurrentFolder, + newItemName, null, null, function (oAsyncResult) { + fCallback(oAsyncResult); + }); + }, +} + +/////////////////// +// Create Folder Bootstrap Modal +function RenameItemModal(modalSelector, renameItemController) { + + var self = this; + this.$modal = $(modalSelector); + this.$txt = $(modalSelector).find('input[type="text"]'); + this.$submitButton = $(modalSelector).find('.btn-submit'); + this.$alert = $(modalSelector).find('.alert-danger'); + this.oldItemName = ""; + + this.$modal.on('shown.bs.modal', function () { + self.$txt.focus(); + }) + this.$modal.find('form').submit(function () { + self.$alert.addClass('d-none'); + if (self.$txt.val() == self.oldItemName) { + self.$modal.modal('hide'); + } + else if (self.$txt.val() !== null && self.$txt.val().match(/^ *$/) === null) { + var oValidationMessage = WebdavCommon.Validators.ValidateName(self.$txt.val()); + if (oValidationMessage) { + self.$alert.removeClass('d-none').text(oValidationMessage); + return false; + } + + self.$txt.blur(); + self.$submitButton.attr('disabled', 'disabled'); + renameItemController.Rename(self.$txt.val().trim(), function (oAsyncResult) { + if (!oAsyncResult.IsSuccess) { + if (oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.LockedException) { + WebdavCommon.ErrorModal.Show(sRenameItemLockedErrorMessage, oAsyncResult.Error); + } + else { + WebdavCommon.ErrorModal.Show(sRenameItemErrorMessage, oAsyncResult.Error); + } + } + self.$modal.modal('hide'); + self.$submitButton.removeAttr('disabled'); + renameItemController.Toolbar.ResetToolbar(); + self.$txt.val(''); + }); + } + else { + self.$alert.removeClass('d-none').text('Name is required!'); + } + return false; + }); + +} + +function ToolbarRenameButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + var oRenameItemModal = new RenameItemModal('#RenameItemModal', new RenameItemController(toolbar)); + this.Render = function () { + this.$Button.on('click', function () { + if (toolbar.FolderGrid.selectedItems.length) { + oRenameItemModal.$txt.val(toolbar.FolderGrid.selectedItems[0].DisplayName); + oRenameItemModal.oldItemName = toolbar.FolderGrid.selectedItems[0].DisplayName; + } + oRenameItemModal.$alert.addClass('d-none'); + oRenameItemModal.$modal.modal('show'); + }) + } +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js new file mode 100644 index 0000000..66596f6 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/toolbar/webdav-toolbar.js @@ -0,0 +1,141 @@ + function Toolbar(selectorTableToolbar, folderGrid, confirmModal, webDAVController) { + this.ToolbarName = selectorTableToolbar; + this.$Toolbar = $(selectorTableToolbar); + this.FolderGrid = folderGrid; + this.ConfirmModal = confirmModal; + this.WebDAV = webDAVController; + this.buttons = []; + + var self = this; + + if (typeof ToolbarCreateFolderButton === "function") { + var createFolderButton = new ToolbarCreateFolderButton('Create Folder', 'btn-create-folder', this); + this.buttons.push(createFolderButton); + createFolderButton.Create($(self.$Toolbar).find(".first-section")); + } + + if (typeof ToolbarDownloadButton == "function") { + var downloadButton = new ToolbarDownloadButton('Dwonload', 'btn-download-items', this); + this.buttons.push(downloadButton); + downloadButton.Create($(self.$Toolbar).find(".second-section")); + } + + if (typeof ToolbarRenameButton == "function") { + var renameButton = new ToolbarRenameButton('Rename', 'btn-rename-item', this); + this.buttons.push(renameButton); + renameButton.Create($(self.$Toolbar).find(".third-section")); + } + + if (typeof CopyPasteButtonsControl === "function") { + var copyPasteButtons = new CopyPasteButtonsControl(this) + this.buttons.push(copyPasteButtons) + copyPasteButtons.Create($(self.$Toolbar).find(".fourth-section")); + } + + if (typeof ToolbarReloadButton == "function") { + var reloadButton = new ToolbarReloadButton('Reload', 'btn-reload-items', this); + this.buttons.push(reloadButton); + reloadButton.Create($(self.$Toolbar).find(".fifth-section")); + } + + if (typeof ToolbarPrintButton === "function") { + var printButton = new ToolbarPrintButton('Print', 'btn-print-items', this) + this.buttons.push(printButton); + printButton.Create($(self.$Toolbar).find(".sixth-section")); + } + + if (typeof ToolbarDeleteButton === "function") { + var deleteButton = new ToolbarDeleteButton('Delete', 'btn-delete-items', this) + this.buttons.push(deleteButton); + deleteButton.Create($(self.$Toolbar).find(".sixth-section")); + } + + $.each(self.buttons, function (index) { + this.Render(); + }); + + this.UpdateToolbarButtons(); + } + +Toolbar.prototype = { + UpdateToolbarButtons: function () { + var self = this; + + $.each(self.buttons, function (index) { + if (typeof ToolbarCreateFolderButton === "function" && this instanceof ToolbarCreateFolderButton) { + self.FolderGrid.selectedItems.length == 0 ? this.ShowOnMobile() : this.HideOnMobile(); + } + if (typeof ToolbarDeleteButton === "function" && this instanceof ToolbarDeleteButton) { + if (self.FolderGrid.selectedItems.length == 0) { + this.Disable(); + this.HideOnMobile(); + } + else { + this.Activate(); + this.ShowOnMobile(); + } + } + if (typeof ToolbarRenameButton === "function" && this instanceof ToolbarRenameButton) { + if (self.FolderGrid.selectedItems.length == 0 || + self.FolderGrid.selectedItems.length != 1) { + this.Disable(); + this.HideOnMobile(); + } + else { + this.Activate(); + this.ShowOnMobile(); + } + } + if (typeof ToolbarDownloadButton === "function" && this instanceof ToolbarDownloadButton) { + if (self.FolderGrid.selectedItems.length == 0 || !self.FolderGrid.selectedItems.some(el => !el.IsFolder())) { + this.Disable(); + this.HideOnMobile(); + } + else { + this.Activate(); + this.ShowOnMobile(); + } + } + if (typeof CopyPasteButtonsControl === "function" && this instanceof CopyPasteButtonsControl) { + if (self.FolderGrid.selectedItems.length == 0) { + this.CopyButton.Disable(); + this.CopyButton.HideOnMobile(); + + this.CutButton.Disable(); + this.CutButton.HideOnMobile(); + } + else { + this.CopyButton.Activate(); + this.CopyButton.ShowOnMobile(); + + this.CutButton.Activate(); + this.CutButton.ShowOnMobile(); + } + + if (this.storedItems.length == 0) { + this.PasteButton.Disable(); + this.PasteButton.HideOnMobile(); + } + else { + this.PasteButton.Activate(); + this.PasteButton.ShowOnMobile(); + } + } + if (ITHit.Environment.OS == 'Windows' && typeof ToolbarPrintButton === "function" && this instanceof ToolbarPrintButton) { + if (self.FolderGrid.selectedItems.filter(function (item) { return !item.IsFolder(); }).length == 0) { + this.Disable(); + this.HideOnMobile(); + } + else { + this.Activate(); + this.ShowOnMobile(); + } + } + }); + }, + + ResetToolbar: function () { + this.FolderGrid.UncheckTableCheckboxs(); + this.UpdateToolbarButtons(); + } +} \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-common.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-common.js new file mode 100644 index 0000000..eac3835 --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-common.js @@ -0,0 +1,227 @@ + +/** + * @namespace WebdavCommon + */ +window.WebdavCommon = (function () { + var sGSuitePreviewErrorMessage = "Preview document with G Suite Online Tool error."; + var sGSuiteEditErrorMessage = "Edit document with G Suite Online Editor error."; + var sFileNameSpecialCharactersRestrictionFormat = "The name cannot contain any of the following characters: {0}"; + var sForbiddenNameChars = '\/:*?"<>|'; + + var ns = {}; + + /**@class Formatters + * @memberof! WebdavCommon + */ + var Formatters = ns.Formatters = { + + /** + * + * @param {number} iSize + * @returns {string} + */ + FileSize: function (iSize) { + if (!iSize) { + return '0.00 B'; + } + var i = Math.floor(Math.log(iSize) / Math.log(1024)); + return (iSize / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; + }, + + /** + * + * @param {Date} oDate + * @returns {string} + */ + Date: function (oDate) { + return moment(oDate).fromNow(); + }, + + + /** + * + * @param {string} html + * @returns {string} + */ + Snippet: function (html) { + if (html) { + var safePrefix = '__b__tag' + (new Date()).getTime(); + html = html.replace(//g, safePrefix + '_0').replace(/<\/b>/g, safePrefix + '_1'); + html = $('
').text(html).text(); + html = html.replace(new RegExp(safePrefix + '_0', 'g'), ''). + replace(new RegExp(safePrefix + '_1', 'g'), ''); + } + return $('
').addClass('snippet').html(html); + }, + + /** + * + * @param {string} fileName + * @returns {string} + */ + GetFileExtension: function (fileName) { + var index = fileName.lastIndexOf('.'); + return index !== -1 ? fileName.substr(index + 1).toLowerCase() : ''; + }, + + /** + * + * @param {string} fileName + * @returns {string} + */ + GetFileNameWithoutExtension: function (fileName) { + var index = fileName.lastIndexOf('.'); + return index !== -1 ? fileName.slice(0, index) : ''; + }, + + /** + * + * @param {number} iSeconds + * @returns {string} + */ + TimeSpan: function (iSeconds) { + var hours = Math.floor(iSeconds / 3600); + var minutes = Math.floor((iSeconds - hours * 3600) / 60); + var seconds = iSeconds - (hours * 3600) - (minutes * 60) + var sResult = ''; + if (hours) sResult += hours + 'h '; + if (minutes) sResult += minutes + 'm '; + sResult += seconds + 's '; + return sResult; + }, + /** + * Converts a string to an HTML-encoded string. + * @param {string} sText - The string to encode. + * @return {string} - An encoded string. + */ + HtmlEscape: function(sText) { + return String(sText) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + }; + + /** + * This class represents error that occured on client. + * @class ClientError + * @memberof! WebdavCommon + * @param {string} sMessage - The message will be displayed as error's short description. + * @param {string} sUri - This url will be displayed as item's URL caused error. + * @property {string} Message + * @property {string} Uri + */ + var ClientError = ns.ClientError = function ClientError(sMessage, sUri) { + this.Message = sMessage; + this.Uri = sUri; + }; + + /**@class Validators + * @memberof! WebdavCommon + */ + ns.Validators = /** @leads Validators */ { + + /** + * @param {string} sName - The name to check. + * @memberof Validators. + * @returns {undefined | string} - Undefined if item valid or error string. + */ + ValidateName: function(sName) { + var oRegExp = new RegExp('[' + sForbiddenNameChars + ']', 'g'); + if(oRegExp.test(sName)) { + var sMessage = WebdavCommon.PasteFormat(sFileNameSpecialCharactersRestrictionFormat, + sForbiddenNameChars.replace(/\\?(.)/g, '$1 ')); + return sMessage; + } + } + }; + + ns.PasteFormat = function pasteFormat(sPhrase) { + var callbackReplace = function(oArguments) { + this._arguments = oArguments; + }; + + callbackReplace.prototype.Replace = function(sPlaceholder) { + + var iIndex = sPlaceholder.substr(1, sPlaceholder.length - 2); + return ('undefined' !== typeof this._arguments[iIndex]) ? this._arguments[iIndex] : sPlaceholder; + }; + + if(/\{\d+?\}/.test(sPhrase)) { + var oReplace = new callbackReplace(Array.prototype.slice.call(arguments, 1)); + sPhrase = sPhrase.replace(/\{(\d+?)\}/g, function(args) { return oReplace.Replace(args); }); + } + + return sPhrase; + }; + + /** + * This class provides method for display error modal window. + * @param {string} selector - The selector of root element of modal window markup. + * @class ErrorModal + * @memberof! WebdavCommon + */ + function ErrorModal(selector) { + this.$el = $(selector); + this.$el.on('hidden.bs.modal', this._onModalHideHandler.bind(this)); + }; + + /**@lends ErrorModal.prototype */ + ErrorModal.prototype = { + + /** + * Shows modal window with message and error details. + * @method + * @param {string} sMessage - The error message. + * @param {ITHit.WebDAV.Client.Exceptions.WebDavHttpException | ClientError} oError - The error object to display. + * @param {function()} [fCallback] - The callback to be called on close. + */ + Show: function (sMessage, oError, fCallback) { + this._closeCallback = fCallback || $.noop; + this._SetErrorMessage(sMessage); + this._SetUrl(oError.Uri); + this._SetMessage(oError.Message); + + if (oError.Error) { + this._SetBody(oError.Error.Description || oError.Error.BodyText); + } else if (oError.InnerException) { + this._SetBody(oError.InnerException.toString()); + } + + this.$el.modal('show'); + }, + + _SetErrorMessage: function (sMessage) { + this.$el.find('.error-message').html(sMessage); + }, + + _SetUrl: function (sUrl) { + this.$el.find('.error-details-url').html(Formatters.HtmlEscape(sUrl)); + }, + + _SetMessage: function (sMessage) { + sMessage = Formatters.HtmlEscape(sMessage); + sMessage = String(sMessage).replace(/\n/g, '
\n').replace(/\t/g, '    '); + this.$el.find('.error-details-message').html(sMessage); + }, + + _SetBody: function (sMessage) { + var iframe = this.$el.find('iframe')[0]; + var doc = iframe.contentDocument || iframe.contentWindow.document; + + // FireFox fix, trigger a page `load` + doc.open(); + doc.close(); + + doc.body.innerHTML = sMessage; + }, + _onModalHideHandler: function () { + this._closeCallback(); + } + }; + + ns.ErrorModal = new ErrorModal('#ErrorModal'); + return ns; +})(); \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-gridview.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-gridview.js new file mode 100644 index 0000000..0ce487b --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-gridview.js @@ -0,0 +1,1132 @@ + +(function (WebdavCommon) { + var sSearchErrorMessage = "Search is not supported."; + var sSupportedFeaturesErrorMessage = "Supported Features error."; + var sProfindErrorMessage = "PROPFIND request error."; + + + /////////////////// + // Folder Grid View + var FolderGridView = function (selectorTableContainer, selectorTableToolbar) { + var self = this; + this.$el = $(selectorTableContainer); + this.selectedItems = []; + + //Copied or cut items + this.storedItems = []; + this.isCopiedItems = false; + this.selectedItem = null; + this.activeSelectedTab = 'preview'; + this.isSearchMode = false; + this._defaultEditor = 'OSEditor'; + + this.$el.on({ + mouseenter: function () { + if ($(this).hasClass('tr-snippet-url')) + $(this).addClass('hover').prev().addClass('hover'); + else + $(this).addClass('hover').next().addClass('hover'); + }, + mouseleave: function () { + if ($(this).hasClass('tr-snippet-url')) + $(this).removeClass('hover').prev().removeClass('hover'); + else + $(this).removeClass('hover').next().removeClass('hover'); + } + }, 'tr'); + + this.$el.find('th input[type="checkbox"]').change(function () { + self.selectedItems = []; + if ($(this).is(':checked')) { + self.$el.find('td input[type="checkbox"]').prop('checked', true).change(); + } + else { + oToolbar.ResetToolbar(); + self.$el.find('td input[type="checkbox"]').prop('checked', false); + } + }); + + // set timer for updating Modified field + setInterval(function () { + self.$el.find('td.modified-date').each(function () { + $(this).text(WebdavCommon.Formatters.Date($(this).data('modified-date'))); + }); + }, 3000); + }; + FolderGridView.prototype = { + Render: function (aItems, bisSearchMode) { + var self = this; + this.isSearchMode = bisSearchMode || false; + + this.$el.find('tbody').html( + aItems.map(function (oItem) { + var locked = oItem.ActiveLocks.length > 0 + ? ('' + + (oItem.ActiveLocks[0].LockScope === 'Shared' ? ('' + oItem.ActiveLocks.length + '') : '')) + : ''; + /** @type {ITHit.WebDAV.Client.HierarchyItem} oItem */ + var $customCheckbox = $(''); + $customCheckbox.find('input').on('change', function () { + if ($(this).is(':checked')) { + self._AddSelectedItem(oItem); + } + else { + self._RemoveSelectedItem(oItem); + } + }).attr('checked', this._IsSelectedItem(oItem)); + + return $('
').html([ + $('').html([ + $('').html([ + $customCheckbox + ]), + $(''). + html(oItem.IsFolder() ? ('' + locked + '') : locked), + this._RenderDisplayName(oItem), + $('').text(oItem.IsFolder() ? 'Folder' : ('File ' + WebdavCommon.Formatters.GetFileExtension(oItem.DisplayName))), + $(''). + text(!oItem.IsFolder() ? WebdavCommon.Formatters.FileSize(oItem.ContentLength) : ''). + css('text-align', 'right'), + $('').text(WebdavCommon.Formatters.Date(oItem.LastModified)).data('modified-date', oItem.LastModified), + $('').html(this._RenderActions(oItem)) + ]).on('click', function (e) { + // enable GSuite preview and edit only for files + if (!oItem.IsFolder() && !$(this).hasClass('active') && + ((e.target.nodeName.toLowerCase() === 'td' && !$(e.target).hasClass('select-disabled')) || + (e.target.nodeName.toLowerCase() !== 'td' && !$(e.target).parents('td').hasClass('select-disabled')))) { + $(this).addClass('active').siblings().removeClass('active'); + self.selectedItem = oItem; + + // render GSuite Editor + WebdavCommon.GSuiteEditor.Render(oItem); + } + }).addClass(self.selectedItem != null && oItem.Href == self.selectedItem.Href ? 'active' : ''), + $('').html([ + $(''), + $(''), + this._RenderSnippetAndUrl(oItem)])]).children(); + }.bind(this)) + ); + }, + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + **/ + _RenderLokedIconTooltip(oItem) { + var tooltipTitle = 'Exclusive lock: ' + oItem.ActiveLocks[0].Owner; + if (oItem.ActiveLocks[0].LockScope === 'Shared') { + var userNames = []; + tooltipTitle = 'Shared lock' + (oItem.ActiveLocks.length > 1 ? '(s)':'') + ': '; + for (var i = 0; i < oItem.ActiveLocks.length; i++) { + userNames.push(oItem.ActiveLocks[i].Owner); + } + tooltipTitle += userNames.join(', '); + } + return tooltipTitle; + }, + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + **/ + _RenderDisplayName: function (oItem) { + var oElement = oItem.IsFolder() ? + $('').html($('').text(oItem.DisplayName).attr('href', oItem.Href)) : + $('').html($('').text(oItem.DisplayName)); + + return oElement; + }, + + _RenderSnippetAndUrl: function (oItem) { + var oElement = $(''); + // Append path on search mode + if (this.isSearchMode) { + new BreadcrumbsView($('
    ').addClass('breadcrumb').appendTo(oElement)).SetHierarchyItem(oItem); + + // Append snippet to name + oElement.append(WebdavCommon.Formatters.Snippet(oItem.Properties.Find(oWebDAV.SnippetPropertyName))); + } + + return oElement; + }, + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + * @returns string + **/ + _RenderActions: function (oItem) { + var self = this; + var actions = []; + var isDavProtocolSupported = ITHit.WebDAV.Client.DocManager.IsDavProtocolSupported(); + var isMicrosoftOfficeDocument = ITHit.WebDAV.Client.DocManager.IsMicrosoftOfficeDocument(oItem.Href); + var isGSuiteDocument = ITHit.WebDAV.Client.DocManager.IsGSuiteDocument(oItem.Href); + + if (oItem.IsFolder()) { + actions.push($('') + .appendTo($btnGroup).on('click', function () { + var $radio = $(this).parent().find('input[type=radio]:checked'); + if ($radio.length) { + $radio.parent().next().click(); + } + else { + oWebDAV.EditDoc(oItem.Href); + } + }).prop("disabled", !isDavProtocolSupported && !isMicrosoftOfficeDocument); + + var $dropdownToggle = $('') + .appendTo($btnGroup).prop("disabled", !isDavProtocolSupported && !isMicrosoftOfficeDocument); + + this._RenderContextMenu(oItem, $btnGroup, isMicrosoftOfficeDocument, isGSuiteDocument, isDavProtocolSupported, isExclusiveLocked); + + $btnGroup.on('shown.bs.dropdown', function () { + self.ContextMenuID = oItem.Href; + }); + + $btnGroup.on('hidden.bs.dropdown', function () { + self.ContextMenuID = null; + }); + + // open context menu if it was open before update + if (self.ContextMenuID && self.ContextMenuID == oItem.Href) { + $dropdownToggle.dropdown('toggle'); + } + + actions.push($btnGroup); + } + + return actions; + }, + + _GetActionGroupBtnTooltipText: function () { + var tooltipText = 'Edit document with desktop associated application.'; + switch (this._defaultEditor) { + case 'OSEditor': + tooltipText = 'Edit with Microsoft Office Desktop.'; + break; + case 'GSuiteEditor': + tooltipText = 'Edit document in G Suite Editor.'; + break; + } + return tooltipText; + }, + + _GetDisabledGroupBtnAttribute: function (isExclusiveLocked) { + var attribute = ''; + if (this._defaultEditor == 'GSuiteEditor' && isExclusiveLocked) { + attribute = ' disabled="disabled"'; + } + return attribute; + }, + + _GetActionGroupBtnCssClass: function () { + var cssClassName = 'icon-edit'; + switch (this._defaultEditor) { + case 'OSEditor': + cssClassName = 'icon-microsoft-edit'; + break; + case 'GSuiteEditor': + cssClassName = 'icon-gsuite-edit'; + break; + } + + return cssClassName; + }, + + _RenderContextMenu: function (oItem, $btnGroup, isMicrosoftOfficeDocument, isGSuiteDocument, isDavProtocolSupported, isExclusiveLocked) { + var self = this; + var supportGSuiteFeature = oWebDAV.OptionsInfo.Features & ITHit.WebDAV.Client.Features.GSuite; + var displayRadioBtns = (isMicrosoftOfficeDocument && isGSuiteDocument); + var $dropdownMenu = $('').appendTo($btnGroup); + if (isMicrosoftOfficeDocument) { + if (displayRadioBtns) { + $('').appendTo($dropdownMenu).find('input[type=radio]').change(function () { self._ChangeContextMenuRadionBtnHandler($(this)); }); + } + $('Edit with Microsoft Office Desktop') + .appendTo($dropdownMenu).on('click', function () { + oWebDAV.EditDoc(oItem.Href); + }); + } + if (!isMicrosoftOfficeDocument) { + $('Edit with Associated Desktop Application') + .appendTo($dropdownMenu).on('click', function () { + oWebDAV.EditDoc(oItem.Href); + }); + } + + $('').appendTo($dropdownMenu); + $('Select Desktop Application') + .appendTo($dropdownMenu).on('click', function () { + oWebDAV.OpenDocWith(oItem.Href); + }); + }, + + _GetContextMenuRadioBtnCheckedProperty: function (editorName) { + return this._defaultEditor == editorName ? 'checked="checked"' : ''; + }, + + _ChangeContextMenuRadionBtnHandler: function ($radioBtn) { + var self = this; + var iconClassName = $radioBtn.parent().next().find('i:first').attr('class'); + + this._defaultEditor = $radioBtn.val(); + $('input[value="' + self._defaultEditor + '"]').prop('checked', true); + + // update button icon + $('.btn-default-edit').each(function () { + var $btn = $(this); + if ($btn.parent().find('.actions input[type=radio]').length) { + $btn.find('i:first').attr('class', iconClassName); + } + $btn.attr('title', self._GetActionGroupBtnTooltipText()); + }); + }, + + _AddSelectedItem: function (oItem) { + this.selectedItems.push(oItem); + oToolbar.UpdateToolbarButtons(); + }, + + _RemoveSelectedItem: function (oItem) { + var self = this; + $.each(this.selectedItems, function (index) { + if (self.selectedItems[index].Href === oItem.Href) { + self.selectedItems.splice(index, 1); + return false; + } + }); + + oToolbar.UpdateToolbarButtons(); + }, + + _IsSelectedItem: function (oItem) { + var self = this; + var isSelected = false; + $.each(this.selectedItems, function (index) { + if (self.selectedItems[index].Href === oItem.Href) { + isSelected = true; + return false; + } + }); + return isSelected; + }, + + UncheckTableCheckboxs: function () { + this.selectedItems = []; + this.$el.find('input[type="checkbox"]').prop('checked', false); + }, + }; + + + /////////////////// + // Search Form View + var SearchFormView = function (selector) { + this.$el = $(selector); + this.Init(); + }; + SearchFormView.prototype = { + + Init: function () { + this.$el.find('button').on('click', this._OnSubmit.bind(this)); + this.$el.find('input').typeahead({}, + { + name: 'states', + display: 'DisplayName', + limit: 6, + templates: { + suggestion: this._RenderSuggestion.bind(this) + }, + async: true, + source: this._Source.bind(this) + } + ).on('keyup', this._OnKeyUp.bind(this)).on('typeahead:select', this._OnSelect.bind(this)); + }, + + SetDisabled: function (bIsDisabled) { + this.$el.find('button').prop('disabled', bIsDisabled); + this.$el.find('input'). + prop('disabled', bIsDisabled). + attr('placeholder', !bIsDisabled ? '' : 'The server does not support search'); + }, + + GetValue: function () { + return this.$el.find('input.tt-input').val(); + }, + + LoadFromHash: function () { + this.$el.find('input.tt-input').val(oWebDAV.GetHashValue('search')); + this._RenderFolderGrid(oWebDAV.GetHashValue('search'), oWebDAV.GetHashValue('page')); + }, + + _Source: function (sPhrase, c, fCallback) { + oWebDAV.NavigateSearch(sPhrase, false, 1, false, true, function (oResult) { + if (oResult.IsSuccess) { + fCallback(oResult.Result.Page); + } else { + WebdavCommon.ErrorModal.Show(sSearchErrorMessage, oResult.Error); + } + }); + }, + + _OnKeyUp: function (oEvent) { + if (oEvent.keyCode === 13) { + this._RenderFolderGrid(oSearchForm.GetValue(), 1); + this.$el.find('input').typeahead('close'); + this._HideKeyboard(this.$el.find('input')); + } + }, + + _OnSelect: function (oEvent, oItem) { + oFolderGrid.Render([oItem], true); + oPagination.Hide(); + }, + + _OnSubmit: function () { + this._RenderFolderGrid(oSearchForm.GetValue(), 1); + }, + + _RenderFolderGrid: function (oSearchQuery, nPageNumber) { + var oSearchFormView = this; + oWebDAV.NavigateSearch(oSearchForm.GetValue(), false, nPageNumber, true, true, function (oResult) { + oFolderGrid.Render(oResult.Result.Page, true); + oPagination.Render(nPageNumber, Math.ceil(oResult.Result.TotalItems / oWebDAV.PageSize), function (pageNumber) { + oSearchFormView._RenderFolderGrid(oSearchQuery, pageNumber); + }); + + if (oResult.Result.Page.length == 0 && nPageNumber != 1) { + oSearchFormView._RenderFolderGrid(oSearchQuery, 1); + } + }); + }, + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + **/ + _RenderSuggestion: function (oItem) { + var oElement = $('
    ').text(oItem.DisplayName); + + // Append path + new BreadcrumbsView($('
      ').addClass('breadcrumb').appendTo(oElement)).SetHierarchyItem(oItem); + + // Append snippet + oElement.append(WebdavCommon.Formatters.Snippet(oItem.Properties.Find(oWebDAV.SnippetPropertyName))); + + return oElement; + }, + + /** + * @param {JQuery obeject} element + **/ + _HideKeyboard: function (element) { + element.attr('readonly', 'readonly'); // Force keyboard to hide on input field. + element.attr('disabled', 'true'); // Force keyboard to hide on textarea field. + setTimeout(function () { + element.blur(); //actually close the keyboard + // Remove readonly attribute after keyboard is hidden. + element.removeAttr('readonly'); + element.removeAttr('disabled'); + }, 100); + } + + }; + + /////////////////// + // Breadcrumbs View + var BreadcrumbsView = function (selector, upOneLevelBtn) { + this.$el = $(selector); + this.$upOneLevelBtn = $(upOneLevelBtn); + }; + BreadcrumbsView.prototype = { + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + */ + SetHierarchyItem: function (oItem) { + var aParts = oItem.Href + .split('/') + .slice(2) + .filter(function (v) { + return v; + }); + + this.$el.html(aParts.map(function (sPart, i) { + var bIsLast = aParts.length === i + 1; + var oLabel = i === 0 ? $('').addClass('icon-home') : $('').text(decodeURIComponent(sPart)); + return $('
    1. ').addClass('page-item ' + (pageNumber == 1 ? 'disabled' : '')).appendTo(this.$el)).text('<<').click(function () { + if (pageNumber != 1) + changePageCallback(pageNumber - 1); + return false; + }); + + // render pages + var firstPage = countPages > this.maxItems && (pageNumber - Math.floor(this.maxItems / 2)) > 0 ? (pageNumber - Math.floor(this.maxItems / 2)) : 1; + var lastPage = (firstPage + this.maxItems - 1) <= countPages ? (firstPage + this.maxItems - 1) : countPages; + + if (countPages > this.maxItems && lastPage - firstPage < this.maxItems) { + firstPage = lastPage - this.maxItems + 1; + } + + if (firstPage > 1 && countPages > this.maxItems) { + $('').addClass('page-link').data('page-number', 1).appendTo($('
    2. ').addClass('page-item ' + (1 == pageNumber ? 'active' : '')).appendTo(this.$el)).text(1).click(function () { + if (pageNumber != $(this).data('page-number')) { + changePageCallback($(this).data('page-number')); + } + return false; + }); + if (firstPage - 1 > 1) { + $('').addClass('page-link').data('page-number', i).appendTo($('
    3. ').addClass('page-item disabled').appendTo(this.$el)).text('...'); + } + } + + for (var i = firstPage; i <= lastPage; i++) { + $('').addClass('page-link').data('page-number', i).appendTo($('
    4. ').addClass('page-item ' + (i == pageNumber ? 'active' : '')).appendTo(this.$el)).text(i).click(function () { + if (pageNumber != $(this).data('page-number')) { + changePageCallback($(this).data('page-number')); + } + return false; + }); + } + + if (lastPage != countPages && countPages > this.maxItems) { + if (lastPage != countPages - 1) { + $('').addClass('page-link').data('page-number', i).appendTo($('
    5. ').addClass('page-item disabled').appendTo(this.$el)).text('...'); + } + $('').addClass('page-link').data('page-number', countPages).appendTo($('
    6. ').addClass('page-item ' + (countPages == pageNumber ? 'active' : '')).appendTo(this.$el)).text(countPages).click(function () { + if (pageNumber != $(this).data('page-number')) + changePageCallback($(this).data('page-number')); + return false; + }); + } + + // render Next link + $('').addClass('page-link').appendTo($('
    7. ').addClass('page-item ' + (countPages == pageNumber ? 'disabled' : '')).appendTo(this.$el)).text('>>').click(function () { + if (pageNumber != countPages) + changePageCallback(pageNumber + 1); + return false; + }); + } + }, + + Hide: function () { + this.$el.empty(); + } + } + + /////////////////// + // Table sorting View + var TableSortingView = function (selector) { + this.$headerCols = $(selector); + this.Init(); + }; + TableSortingView.prototype = { + Init: function () { + var $cols = this.$headerCols; + $cols.click(function () { + var className = 'ascending' + if ($(this).hasClass('ascending')) { + className = 'descending'; + } + + oWebDAV.Sort($(this).data('sort-column'), className == 'ascending'); + }) + }, + + Set: function (sortColumn, sortAscending) { + var $col = this.$headerCols.filter('[data-sort-column="' + sortColumn + '"]'); + this.$headerCols.removeClass('ascending descending'); + if (sortAscending) { + $col.removeClass('descending').addClass('ascending'); + } else { + $col.removeClass('ascending').addClass('descending'); + } + }, + + Disable: function () { + this.$headerCols.addClass('disabled'); + }, + + Enable: function () { + this.$headerCols.removeClass('disabled'); + } + } + + ///////////////////////// + // History Api Controller + var HistoryApiController = function (selector) { + this.$container = $(selector); + this.Init(); + }; + HistoryApiController.prototype = { + + Init: function () { + if (!this._IsBrowserSupport()) { + return; + } + + window.addEventListener('popstate', this._OnPopState.bind(this), false); + this.$container.on('click', this._OnLinkClick.bind(this)); + }, + + PushState: function () { + if (this._IsBrowserSupport()) { + history.pushState('', document.title, window.location.pathname + window.location.search); + } + }, + + _OnPopState: function (oEvent) { + if (oWebDAV.GetHashValue('search')) { + oSearchForm.LoadFromHash(); + } + else { + var sUrl = oEvent.state && oEvent.state.Url || window.location.href.split("#")[0]; + oWebDAV.NavigateFolder(sUrl, null, null, null, true); + } + }, + + _OnLinkClick: function (oEvent) { + var sUrl = $(oEvent.target).closest('a').attr('href'); + if (!sUrl) { + return; + } + + if (sUrl.indexOf((location.origin || window.location.href.split("#")[0].replace(location.pathname, ''))) !== 0) { + return; + } + + oEvent.preventDefault(); + + history.pushState({ Url: sUrl }, '', sUrl); + oWebDAV.NavigateFolder(sUrl, null, null, null, true); + }, + + _IsBrowserSupport: function () { + return !!(window.history && history.pushState); + } + + }; + + /////////////////// + // Confirm Bootstrap Modal + var ConfirmModal = function (selector) { + var self = this; + this.$el = $(selector); + this.$el.find('.btn-ok').click(function () { + if (self.successfulCallback) { + self.successfulCallback(); + } + self.$el.modal('hide'); + }); + } + ConfirmModal.prototype = { + Confirm: function (htmlMessage, successfulCallback, options) { + var $modalDialog = this.$el.find('.modal-dialog'); + this.successfulCallback = successfulCallback; + this.$el.find('.message').html(htmlMessage); + if (options && options.size == 'lg') + $modalDialog.removeClass('modal-sm').addClass('modal-lg'); + else + $modalDialog.removeClass('modal-lg').addClass('modal-sm'); + + this.$el.modal('show'); + } + } + + var WebDAVController = function () { + this.PageSize = 10; // set size items of page + this.CurrentFolder = null; + this.AllowReloadGrid = true; + this.WebDavSession = new ITHit.WebDAV.Client.WebDavSession(); + this.SnippetPropertyName = new ITHit.WebDAV.Client.PropertyName('snippet', 'ithit'); + }; + + WebDAVController.prototype = { + + Reload: function () { + if (this.CurrentFolder && this.AllowReloadGrid) { + if (this.GetHashValue('search')) { + oSearchForm.LoadFromHash(); + } + else { + this.NavigateFolder(this.CurrentFolder.Href); + } + } + }, + + NavigateFolder: function (sPath, pageNumber, sortColumn, sortAscending, resetSelectedItem, fCallback) { + var pageSize = this.PageSize, currentPageNumber = 1; + // add default sorting by file type + var sortColumns = [new ITHit.WebDAV.Client.OrderProperty(new ITHit.WebDAV.Client.PropertyName('is-directory', ITHit.WebDAV.Client.DavConstants.NamespaceUri), this.CurrentSortColumnAscending)]; + if (!sPath && this.CurrentFolder) { + sPath = this.CurrentFolder.Href; + } + + //set upload url for uploader control + if (typeof WebDAVUploaderGridView !== 'undefined') { + WebDAVUploaderGridView.SetUploadUrl(sPath); + } + + if (resetSelectedItem) { + oToolbar.ResetToolbar(); + } + + //Enable sorting + oTableSorting.Enable(); + if (sortColumn) { + this.CurrentSortColumn = sortColumn; + this.CurrentSortAscending = sortAscending; + this.SetHashValues([{ Name: 'sortcolumn', Value: sortColumn }, { Name: 'sortascending', Value: sortAscending.toString() }]); + } else if (this.GetHashValue('sortcolumn')) { + this.CurrentSortColumn = this.GetHashValue('sortcolumn'); + this.CurrentSortAscending = this.GetHashValue('sortascending') == 'true'; + oTableSorting.Set(this.CurrentSortColumn, this.CurrentSortAscending); + } else { + this.CurrentSortColumn = 'displayname'; + this.CurrentSortAscending = true; + oTableSorting.Set(this.CurrentSortColumn, this.CurrentSortAscending); + } + + // apply sorting by table column + if (this.CurrentSortColumn) { + sortColumns.push(new ITHit.WebDAV.Client.OrderProperty(new ITHit.WebDAV.Client.PropertyName(this.CurrentSortColumn, ITHit.WebDAV.Client.DavConstants.NamespaceUri), this.CurrentSortAscending)); + } + + // update page number + if (pageNumber) { + currentPageNumber = pageNumber; + } else if (this.GetHashValue('page')) { + currentPageNumber = parseInt(this.GetHashValue('page')); + } + + if (currentPageNumber != 1) { + this.SetHashValue('page', currentPageNumber); + } else { + this.SetHashValue('page', ''); + } + + this.WebDavSession.OpenFolderAsync(sPath, [], function (oResponse) { + var self = this; + if (oResponse.IsSuccess) { + self.CurrentFolder = oResponse.Result; + oBreadcrumbs.SetHierarchyItem(self.CurrentFolder); + + // Detect search support. If search is not supported - disable search field. + this.CurrentFolder.GetSupportedFeaturesAsync(function (oResult) { + /** @typedef {ITHit.WebDAV.Client.OptionsInfo} oOptionsInfo */ + + if (oResult.IsSuccess) { + self.OptionsInfo = oResult.Result; + oSearchForm.SetDisabled(!(self.OptionsInfo.Features & ITHit.WebDAV.Client.Features.Dasl)); + } else { + WebdavCommon.ErrorModal.Show(sSupportedFeaturesErrorMessage, oResult.Error); + } + }); + + this.CurrentFolder.GetPageAsync([], (currentPageNumber - 1) * pageSize, pageSize, sortColumns, function (oResult) { + /** @type {ITHit.WebDAV.Client.HierarchyItem[]} aItems */ + if (oResult.IsSuccess) { + var aItems = oResult.Result.Page; + var aCountPages = Math.ceil(oResult.Result.TotalItems / pageSize); + + oFolderGrid.Render(aItems, false); + oPagination.Render(currentPageNumber, aCountPages, function (pageNumber) { + oWebDAV.NavigateFolder(null, pageNumber, null, null, true); + }); + + if (aItems.length == 0 && pageNumber != 1) { + oWebDAV.NavigateFolder(null, 1, null, null, true); + } + + if (fCallback) + fCallback(aItems); + } else { + WebdavCommon.ErrorModal.Show(sProfindErrorMessage, oResult.Error); + } + }); + } else { + WebdavCommon.ErrorModal.Show(sProfindErrorMessage, oResponse.Error); + } + }.bind(this)); + }, + + NavigateSearch: function (sPhrase, bIsDynamic, pageNumber, updateUrlHash, resetSelectedItem, fCallback) { + var pageSize = this.PageSize, currentPageNumber = 1; + + if (!this.CurrentFolder) { + fCallback && fCallback({ Items: [], TotalItems: 0 }); + return; + } + + if (updateUrlHash) { + this.SetHashValue('search', sPhrase); + } + + if (sPhrase === '') { + this.Reload(); + return; + } + + if (resetSelectedItem) { + oToolbar.ResetToolbar(); + } + + // update page number + if (pageNumber) { + currentPageNumber = pageNumber; + } else if (this.GetHashValue('page')) { + currentPageNumber = parseInt(this.GetHashValue('page')); + } + + if (updateUrlHash && currentPageNumber != 1) { + this.SetHashValue('page', currentPageNumber); + } else { + this.SetHashValue('page', ''); + } + //Disable sorting + oTableSorting.Disable(); + + // The DASL search phrase can contain wildcard characters and escape according to DASL rules: + // ‘%’ – to indicate one or more character. + // ‘_’ – to indicate exactly one character. + // If ‘%’, ‘_’ or ‘\’ characters are used in search phrase they are escaped as ‘\%’, ‘\_’ and ‘\\’. + var searchQuery = new ITHit.WebDAV.Client.SearchQuery(); + searchQuery.Phrase = sPhrase.replace(/\\/g, '\\\\'). + replace(/\%/g, '\\%'). + replace(/\_/g, '\\_'). + replace(/\*/g, '%'). + replace(/\?/g, '_') + '%'; + searchQuery.EnableContains = !bIsDynamic; //Enable/disable search in file content. + + // Get following additional properties from server in search results: snippet - text around search phrase. + searchQuery.SelectProperties = [ + this.SnippetPropertyName + ]; + + function _getSearchPageByQuery() { + oWebDAV.CurrentFolder.GetSearchPageByQueryAsync(searchQuery, (currentPageNumber - 1) * pageSize, pageSize, function (oResult) { + /** @type {ITHit.WebDAV.Client.AsyncResult} oResult */ + /** @type {ITHit.WebDAV.Client.HierarchyItem[]} aItems */ + + if (oResult.IsSuccess) { + fCallback && fCallback(oResult); + } else { + WebdavCommon.ErrorModal.Show(sSearchErrorMessage, oResult.Error); + } + }); + } + + if (window.location.href.split("#")[0] != this.CurrentFolder.Href) { + this.WebDavSession.OpenFolderAsync(window.location.href.split("#")[0], [], function (oResponse) { + oWebDAV.CurrentFolder = oResponse.Result; + oBreadcrumbs.SetHierarchyItem(oWebDAV.CurrentFolder); + _getSearchPageByQuery(); + }); + } + else { + _getSearchPageByQuery(); + } + + + }, + + Sort: function (columnName, sortAscending) { + this.NavigateFolder(null, null, columnName, sortAscending, true); + }, + + /** + * Opens document for editing. + * @param {string} sDocumentUrl Must be full path including domain name: https://webdavserver.com/path/file.ext + */ + EditDoc: function (sDocumentUrl) { + if (['cookies', 'ms-ofba'].indexOf(webDavSettings.EditDocAuth.Authentication.toLowerCase()) != -1) { + if (webDavSettings.EditDocAuth.Authentication.toLowerCase() == 'ms-ofba' && + ITHit.WebDAV.Client.DocManager.IsMicrosoftOfficeDocument(sDocumentUrl)) { + ITHit.WebDAV.Client.DocManager.EditDocument(sDocumentUrl, this.GetMountUrl(), this._ProtocolInstallMessage.bind(this)); + } + else { + ITHit.WebDAV.Client.DocManager.DavProtocolEditDocument(sDocumentUrl, this.GetMountUrl(), this._ProtocolInstallMessage.bind(this), null, webDavSettings.EditDocAuth.SearchIn, + webDavSettings.EditDocAuth.CookieNames, webDavSettings.EditDocAuth.LoginUrl); + } + } + else { + ITHit.WebDAV.Client.DocManager.EditDocument(sDocumentUrl, this.GetMountUrl(), this._ProtocolInstallMessage.bind(this)); + } + }, + + /** + * Opens document for editing in online G Suite editor. + * @param {string} sDocumentUrl Must be full path including domain name: https://webdavserver.com/path/file.ext + * @param {DOM} gSuiteEditPanel html DOM element + * @param {function} [errorCallback] Function to call if document opening failed. + */ + GSuiteEditDoc: function (sDocumentUrl, gSuiteEditPanel, errorCallback) { + ITHit.WebDAV.Client.DocManager.GSuiteEditDocument(sDocumentUrl, gSuiteEditPanel, errorCallback); + }, + + /** + * Opens document for preview in online G Suite editor. + * @param {string} sDocumentUrl Must be full path including domain name: https://webdavserver.com/path/file.ext + * @param {DOM} gSuitePreviewPanel html DOM element + * @param {function} [errorCallback] Function to call if document opening failed. + */ + GSuitePreviewDoc: function (sDocumentUrl, gSuitePreviewPanel, errorCallback) { + ITHit.WebDAV.Client.DocManager.GSuitePreviewDocument(sDocumentUrl, gSuitePreviewPanel, errorCallback); + }, + + /** + * Opens document with. + * @param {string} sDocumentUrl Must be full path including domain name: https://webdavserver.com/path/file.ext + */ + OpenDocWith: function (sDocumentUrl) { + ITHit.WebDAV.Client.DocManager.DavProtocolEditDocument([sDocumentUrl], this.GetMountUrl(), this._ProtocolInstallMessage.bind(this), null, webDavSettings.EditDocAuth.SearchIn, + webDavSettings.EditDocAuth.CookieNames, webDavSettings.EditDocAuth.LoginUrl, 'OpenWith'); + }, + + /** + * Opens current folder in OS file manager. + */ + OpenCurrentFolderInOsFileManager: function () { + this.OpenFolderInOsFileManager(this.CurrentFolder.Href); + }, + + /** + * Opens folder in OS file manager. + * @param {string} sFolderUrl Must be full path including domain name: https://webdavserver.com/path/ + */ + OpenFolderInOsFileManager: function (sFolderUrl) { + ITHit.WebDAV.Client.DocManager.OpenFolderInOsFileManager(sFolderUrl, this.GetMountUrl(), this._ProtocolInstallMessage.bind(this), null, webDavSettings.EditDocAuth.SearchIn, + webDavSettings.EditDocAuth.CookieNames, webDavSettings.EditDocAuth.LoginUrl); + }, + + /** + * @return {string} + **/ + GetMountUrl: function () { + // Web Folders on Windows XP require port, even if it is a default port 80 or 443. + var port = window.location.port || (window.location.protocol == 'http:' ? 80 : 443); + + return window.location.protocol + '//' + window.location.hostname + ':' + port + webDavSettings.ApplicationPath; + }, + + /** + * Returns value from hash + * @return {string} + */ + GetHashValue: function (key) { + var hashConfig = this._parseUrlHash(); + + return hashConfig.hasOwnProperty(key) ? hashConfig[key] : null; + }, + + /** + * Sets values to hash + */ + SetHashValues: function (arrayValues) { + var hashValue = ''; + var params = []; + var hashConfig = this._parseUrlHash(); + + for (var i = 0; i < arrayValues.length; i++) { + hashConfig = this._addParameterToArray(arrayValues[i].Name, arrayValues[i].Value, hashConfig) + } + + for (var key in hashConfig) { + params.push(key + '=' + hashConfig[key]); + } + + hashValue = params.length > 0 ? ('#' + params.join('&')) : ''; + + if (hashValue != location.hash) { + location.hash = hashValue; + } + + if (location.href[location.href.length - 1] == '#') { + oHistoryApi.PushState(); + } + }, + + /** + * Sets value to hash + */ + SetHashValue: function (name, value) { + this.SetHashValues([{ Name: name, Value: value }]); + }, + + /** + * Returns url of app installer + */ + GetInstallerFileUrl: function () { + return webDavSettings.ApplicationProtocolsPath + ITHit.WebDAV.Client.DocManager.GetProtocolInstallFileNames()[0]; + }, + + /** + * Adds name and value to array + * @return {Array} + */ + _addParameterToArray: function (name, value, arrayParams) { + var nameExist = false; + + for (var key in arrayParams) { + if (arrayParams.hasOwnProperty(key)) { + if (key == name) { + nameExist = true; + arrayParams[key] = value; + } + + if (!arrayParams[key]) { + continue; + } + } + } + + if (!nameExist && value) { + arrayParams[name] = value; + } + + return arrayParams; + }, + + /** + * Parses hash + * @return {string} + */ + _parseUrlHash: function () { + // Parse hash + var hash = {}; + if (location.hash.length > 0) { + var hashParts = location.hash.substr(1).split('&'); + for (var i = 0, l = hashParts.length; i < l; i++) { + var param = hashParts[i].split('='); + hash[param[0]] = param[1]; + } + } + + return hash; + }, + + /** + * Function to be called when document or OS file manager failed to open. + * @private + */ + _ProtocolInstallMessage: function () { + if (ITHit.WebDAV.Client.DocManager.IsDavProtocolSupported()) { + var $currentOS = $('#DownloadProtocolModal .current-os'); + var $currentBrowser = $('#DownloadProtocolModal .current-browser'); + + // initialization browsers extension panel + if ($currentBrowser.children().length === 0) { + let isChrome = !!window['chrome'] && (!!window['chrome']['webstore'] || !!window['chrome']['runtime']); + + // Edge (based on chromium) detection + if (isChrome && (navigator.userAgent.indexOf('Edg') !== -1)) { + $('#DownloadProtocolModal .edge-chromium').appendTo($currentBrowser); + } else if (isChrome) { + $('#DownloadProtocolModal .goole-chrome').appendTo($currentBrowser); + } else if (typeof InstallTrigger !== 'undefined') { + $('#DownloadProtocolModal .mozilla-firefox').appendTo($currentBrowser); + } + else if (navigator.userAgent.indexOf("MSIE ") > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) { + $('#DownloadProtocolModal .not-required-internet-explorer').show(); + } + } + + // initialization custom protocol installers panel + if ($currentOS.children().length === 0) { + if (ITHit.DetectOS.OS === 'Windows') { + $('#DownloadProtocolModal .window').appendTo($currentOS); + } else if (ITHit.DetectOS.OS === 'Linux') { + $('#DownloadProtocolModal .linux').appendTo($currentOS); + } else if (ITHit.DetectOS.OS === 'MacOS') { + $('#DownloadProtocolModal .mac-os').appendTo($currentOS); + } + } + + $('#DownloadProtocolModal').modal('show'); + $('#DownloadProtocolModal .more-lnk').unbind().click(function () { + var $pnl = $(this).next(); + if ($pnl.is(':visible')) { + $(this).find('span').text('+'); + $pnl.hide(); + } else { + $(this).find('span').text('-'); + $pnl.show(); + } + }); + } + } + }; + var oWebDAV = window.WebDAVController = new WebDAVController(); + var oConfirmModal = new ConfirmModal('#ConfirmModal'); + var oFolderGrid = new FolderGridView('.ithit-grid-container', '.ithit-grid-toolbar'); + var oToolbar = new Toolbar('.ithit-grid-toolbar', oFolderGrid, oConfirmModal, oWebDAV); + var oSearchForm = new SearchFormView('.ithit-search-container'); + var oBreadcrumbs = new BreadcrumbsView('.ithit-breadcrumb-container .breadcrumb', '.btn-up-one-level'); + var oPagination = new PaginationView('.ithit-pagination-container'); + var oTableSorting = new TableSortingView('.ithit-grid-container th.sort'); + var oHistoryApi = new HistoryApiController('.ithit-grid-container, .ithit-breadcrumb-container'); + + + // List files on a WebDAV server using WebDAV Ajax Library + if (oWebDAV.GetHashValue('search')) { + oWebDAV.NavigateFolder(window.location.href.split("#")[0], null, null, null, true, function () { + oSearchForm.LoadFromHash(); + }); + } + else { + oWebDAV.NavigateFolder(window.location.href.split("#")[0], null, null, null, true); + } + + // Set Ajax lib version + if (ITHit.WebDAV.Client.DocManager.IsDavProtocolSupported()) { + $('.ithit-version-value').html('v' + ITHit.WebDAV.Client.WebDavSession.Version + ' (Protocol v' + ITHit.WebDAV.Client.WebDavSession.ProtocolVersion + ')'); + } + else { + $('.ithit-version-value').text('v' + ITHit.WebDAV.Client.WebDavSession.Version + ' (Protocol v' + ITHit.WebDAV.Client.WebDavSession.ProtocolVersion + ')'); + } + $('.ithit-current-folder-value').text(oWebDAV.GetMountUrl()); + +})(WebdavCommon); \ No newline at end of file diff --git a/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-uploader.js b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-uploader.js new file mode 100644 index 0000000..ab28eaa --- /dev/null +++ b/Java/javax/springboots3storage/src/main/resources/wwwroot/js/webdav-uploader.js @@ -0,0 +1,850 @@ +(function (WebdavCommon) { + var sOverwriteDialogueFormat = 'The following item(s) exist on the server:

      {0}

      Overwrite?'; + var sFailedCheckExistsMessage = "Check for already exists item failed with error."; + var sRetryMessageFormat = 'Retry in: {0}'; + var sWrongFileSizeFormat = 'File size should be less than {0}.'; + var sForbiddenExtensionFormat = 'Upload files with "{0}" extension is forbidden.'; + var sValidationError = 'Validation Error'; + var iMaxFileSize = 10485760; //10MB + var aForbiddenExtensions = ['BAT', 'BIN', 'CMD', 'COM', 'EXE']; + + + /////////////////// + // Confirm Bootstrap Modal + var ConfirmRewriteModal = function (selector) { + this.$el = $(selector); + this.$el.find('.btn-ok').click(this._onOkClickHandler.bind(this)); + this.$el.find('.btn-no').click(this._onNoClickHandler.bind(this)); + this.$el.on('hide.bs.modal', this._onModalHideHandler.bind(this)); + } + ConfirmRewriteModal.prototype = { + Confirm: function (message, successfulCallback, discardCallback, cancelCallback) { + this.isConfirmed = false; + this.successfulCallback = successfulCallback || $.noop; + this.discardCallback = discardCallback || $.noop; + this.cancelCallback = cancelCallback || $.noop; + this.$el.find('.message').html(message); + this.$el.find('.modal-dialog').addClass('modal-lg'); + this.$el.modal('show'); + }, + + _onOkClickHandler: function (e) { + this.isConfirmed = true; + this.successfulCallback(); + this.$el.modal('hide'); + }, + + _onNoClickHandler: function (e) { + this.isDiscarded = true; + this.discardCallback(); + this.$el.modal('hide'); + }, + + _onModalHideHandler: function () { + if (!this.isConfirmed && !this.isDiscarded) { + this.cancelCallback(); + } + } + }; + + /** + * This class represents error that occured on client. + * @class + * @param {string} sMessage - The message will be displayed as error's short description. + * @param {string} sUri - This url will be displayed as item's URL caused error. + * @property {string} Message + * @property {string} Uri + */ + function ClientError(sMessage, sUri) { + this.Message = sMessage; + this.Uri = sUri; + } + + //////////////// + // Uploader Grid View + /** @class */ + function UploaderGridView(sSelector) { + + this.Uploader = new ITHit.WebDAV.Client.Upload.Uploader(); + this._dropCounter = 0; + + this.Uploader.Inputs.AddById('ithit-button-input'); + this._dropZone = this.Uploader.DropZones.AddById('ithit-dropzone'); + this._dropZone.HtmlElement.addEventListener('dragenter', this._OnDragEnter.bind(this), false); + this._dropZone.HtmlElement.addEventListener('dragleave', this._OnDragLeave.bind(this), false); + this._dropZone.HtmlElement.addEventListener('drop', this._OnDrop.bind(this), false); + + this.Uploader.SetUploadUrl(ITHit.WebDAV.Client.Encoder.Decode(window.location.href.split("#")[0])); + this.Uploader.Queue.AddListener('OnQueueChanged', '_QueueChange', this); + this.Uploader.Queue.AddListener('OnUploadItemsCreated', this._OnUploadItemsCreated, this); + + var $container = this.$container = $(sSelector); + this.$uploadingBlock = this.$container.find('.uploading-block'); + this.$uploadingDetails = this.$container.find('.uploading-details'); + this.$uploadingDetails.draggable(); + + this.rows = []; + this.fileLoadCompleted = function () { + if (this.$container.find('.uploading-item').length == 0) { + this.$container.addClass('d-none'); + this.$container.find('.progress-wrapper .progress-bar').attr('aria-valuenow', 0).css('width', 0 + '%'); + this.$uploadingBlock.find('.persent').text(0 + '%'); + } + window.WebDAVController.Reload(); + } + + window.addEventListener('beforeunload', function (event) { + if ($container.find('.uploading-item').length != 0) { + var warnMessage = 'Uploader is running!'; + (event || window.event).returnValue = warnMessage; + return warnMessage; + } + }); + + this._DataBindUploaderBlock(); + }; + + UploaderGridView.prototype.SetUploadUrl = function (sPath) { + this.Uploader.SetUploadUrl(sPath); + }; + + /** Called when a user selects items for upload or drops items into a drop area. + * In this function, you can validate files selected for upload and present user interface + * if user interaction is necessary. + * You can check if each item exists on the server, submitting additional requests to the + * server, and specify if each item should be overwritten or skipped. You can also specify + * if the item should be deleted in case of upload cancelation (typically if the item did + * not exist on the server before upload). + * In addition you can validate file size, file extension, file upload path, and file name. + * + * As soon as you may perform asynchronous calls in this function you must signal that all + * asynchronous checks are completed and upload can be started calling + * UploadItemsCreated.Upload() function passing a list of UploadItems to be uploaded. + * + * @param {ITHit.WebDAV.Client.Upload.Events.UploadItemsCreated} oUploadItemsCreated - Contains + * a list of items selected by the user for upload in UploadItemsCreated.Items property. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._OnUploadItemsCreated = function (oUploadItemsCreated) { + + /* Validate file extensions, size, name, etc. here. */ + var oValidationError = this._ValidateUploadItems(oUploadItemsCreated.Items); + if (oValidationError) { + WebdavCommon.ErrorModal.Show(sValidationError, oValidationError); + return; + } + + /* Below we will check if each file exists on the server + and ask a user if files should be overwritten or skipped. */ + this._GetExistsAsync(oUploadItemsCreated.Items, function (oAsyncResult) { + if (oAsyncResult.IsSuccess && oAsyncResult.Result.length === 0) { + // No items exists on the server. + // Add all items to the upload queue. + oUploadItemsCreated.Upload(oUploadItemsCreated.Items); + return; + } + + if (!oAsyncResult.IsSuccess) { + // Some error occurred during item existence verification requests. + // Show error dialog with error description. + // Mark all items as failed and add to the upload list. + this._ShowExistsCheckError(oAsyncResult.Error, + function () { + oUploadItemsCreated.Items.forEach(function (oUploadItem) { + + // Move an item into the error state. + // Upload of this item will NOT start when added to the queue. + oUploadItem.SetFailed(oAsyncResult.Error); + }); + + // Add all items to the upload queue, so a user can start the upload later. + oUploadItemsCreated.Upload(oUploadItemsCreated.Items); + }); + return; + } + + var sItemsList = ''; // List of items to be displayed in Overwrite / Skip / Cancel dialog. + + /** @type {ITHit.WebDAV.Client.Upload.UploadItem[]} aExistsUploadItems */ + var aExistsUploadItems = []; + oAsyncResult.Result.forEach(function (oUploadItem) { + + // For the sake of simplicity folders are never deleted when upload canceled. + if (!oUploadItem.IsFolder()) { + + // File exists so we should not delete it when file's upload canceled. + oUploadItem.SetDeleteOnCancel(false); + } + + // Mark item as verified to avoid additional file existence verification requests. + oUploadItem.CustomData.FileExistanceVerified = true; + + sItemsList += decodeURI(oUploadItem.GetRelativePath()) + '
      '; + aExistsUploadItems.push(oUploadItem); + }); + + /* One or more items exists on the server. Show Overwrite / Skip / Cancel dialog.*/ + oConfirmModal.Confirm(WebdavCommon.PasteFormat(sOverwriteDialogueFormat, sItemsList), + + /* A user selected to overwrite existing files. */ + function onOverwrite() { + + // Mark all items that exist on the server with overwrite flag. + aExistsUploadItems.forEach(function (oUploadItem) { + if (oUploadItem.IsFolder()) return; + + // The file will be overwritten if it exists on the server. + oUploadItem.SetOverwrite(true); + }); + + // Add all items to the upload queue. + oUploadItemsCreated.Upload(oUploadItemsCreated.Items); + }, + + /* A user selected to skip existing files. */ + function onSkipExists() { + + // Create list of items that do not exist on the server. + /** @type {ITHit.WebDAV.Client.Upload.UploadItem[]} aNotExistsUploadItems */ + var aNotExistsUploadItems = $.grep(oUploadItemsCreated.Items, + function (oUploadItem) { + return !ITHit.Utils.Contains(aExistsUploadItems, oUploadItem); + }); + + // Add only items that do not exist on the server to the upload queue. + oUploadItemsCreated.Upload(aNotExistsUploadItems); + }); + }.bind(this)); + }; + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem[]} aUploadItems - Array of items to check. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._ValidateUploadItems = function (aUploadItems) { + for (var i = 0; i < aUploadItems.length; i++) { + var oUploadItem = aUploadItems[i]; + //Max file size validation + //var oExtensionError = this._ValidateExtension(oUploadItem); + + //File extension validation + //var oSizeError = this._ValidateSize(oUploadItem); + + //Special characters validation + //var oNameError = this._ValidateName(oUploadItem); + + //var oValidationError = oExtensionError || oSizeError || oNameError; + //if(oValidationError) { + // return oValidationError; + //} + + var oValidationError = this._ValidateName(oUploadItem); + if (oValidationError) { + return oValidationError; + } + } + }; + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - The item to check. + * @memberof UploaderGridView.prototype + * @returns {undefined | WebdavCommon.ClientError} - Undefined if item valid or error object. + */ + UploaderGridView.prototype._ValidateSize = function (oUploadItem) { + if (oUploadItem.GetSize() > iMaxFileSize) { + var sMessage = WebdavCommon.PasteFormat(sWrongFileSizeFormat, WebdavCommon.Formatters.FileSize(iMaxFileSize)); + return new ClientError(sMessage, oUploadItem.GetUrl()); + } + }; + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - The item to check. + * @memberof UploaderGridView.prototype + * @returns {undefined | WebdavCommon.ClientError} - Undefined if item valid or error object. + */ + UploaderGridView.prototype._ValidateExtension = function (oUploadItem) { + var sExtension = WebdavCommon.Formatters.GetExtension(oUploadItem.GetUrl()); + if (aForbiddenExtensions.indexOf(sExtension.toUpperCase()) >= 0) { + var sMessage = WebdavCommon.PasteFormat(sForbiddenExtensionFormat, sExtension); + return new ClientError(sMessage, oUploadItem.GetUrl()); + } + }; + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - Array of items to check. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._ValidateName = function (oUploadItem) { + var sValidationMessage = WebdavCommon.Validators.ValidateName(oUploadItem.GetName()); + if (sValidationMessage) { + return new ClientError(sValidationMessage, oUploadItem.GetUrl()); + } + }; + + + /** + * Verifies if each item in the list exists on the server and returns list of existing items. + * @callback UploaderGridView~GetExistsAsyncCallback + * @param {ITHit.WebDAV.Client.AsyncResult} oAsyncResult - The result of operation. + * @param {ITHit.WebDAV.Client.Upload.UploadItem[]} oAsyncResult.Result - The array of items + * that exists on server. + */ + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem[]} aUploadItems - Array of items to check. + * @param {UploaderGridView~GetExistsAsyncCallback} fCallback - The function to be called when + * all checks are completed. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._GetExistsAsync = function (aUploadItems, fCallback) { + this._OpenItemsCollectionAsync(aUploadItems, + function (aResultCollection) { + var oFailedResult = ITHit.Utils.FindBy(aResultCollection, + function (oResult) { + return !(oResult.AsyncResult.IsSuccess || oResult.AsyncResult.Status.Code === 404); + }, + this); + + if (oFailedResult) { + fCallback(oFailedResult.AsyncResult); + return; + } + + var aExistsItems = aResultCollection.filter(function (oResult) { + return oResult.AsyncResult.IsSuccess; + }) + .map(function (oResult) { + return oResult.UploadItem; + }); + + fCallback(new ITHit.WebDAV.Client.AsyncResult(aExistsItems, true, null)); + }); + + }; + + + /** + * @typedef {Object} UploaderGridView~OpenItemsCollectionResult + * @property {ITHit.WebDAV.Client.Upload.UploadItem} UploadItem + * @property {ITHit.WebDAV.Client.AsyncResult} oAsyncResult - The result of operation. + */ + + /** + * @callback UploaderGridView~OpenItemsCollectionAsyncCallback + * @param {UploaderGridView~OpenItemsCollectionResult[]} oResult - The result of operation. + */ + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem[]} aUploadItems - Array of items to check. + * @param {UploaderGridView~OpenItemsCollectionAsyncCallback} fCallback - The function to + * be called when all requests completed. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._OpenItemsCollectionAsync = function (aUploadItems, fCallback) { + var iCounter = aUploadItems.length; + + /**@type {UploaderGridView~OpenItemsCollectionResult} */ + var aResults = []; + if (iCounter === 0) { + fCallback(aResults); + return; + } + + aUploadItems.forEach(function (oUploadItem) { + window.WebDAVController.WebDavSession.OpenItemAsync(ITHit.EncodeURI(oUploadItem.GetUrl()), + [], + function (oAsyncResult) { + iCounter--; + aResults.push({ + UploadItem: oUploadItem, + AsyncResult: oAsyncResult + }); + + if (iCounter === 0) { + fCallback(aResults); + } + }); + }); + }; + + + /** + * Called when items are added or deleted from upload queue. + * @param {ITHit.WebDAV.Client.Upload.Queue#event:OnQueueChanged} oQueueChanged - Contains + * lists of items added to the upload queue in oQueueChanged.AddedItems property and removed + * from the upload queue in oQueueChanged.RemovedItems property. + */ + UploaderGridView.prototype._QueueChange = function (oQueueChanged) { + + // Display each ited added to the upload queue in the grid. + oQueueChanged.AddedItems.forEach(function (value) { + var row = new UploaderGridRow(value, this.fileLoadCompleted.bind(this), this._ShowExistsCheckError.bind(this), + this._DataBindAllProgress.bind(this), this._StateRowChange.bind(this)); + this.rows.push(row); + this.$container.find('.uploading-items').append(row.$el); + }.bind(this)); + + // Remove items deleted from upload queue from the grid. + oQueueChanged.RemovedItems.forEach(function (value) { + var aRows = $.grep(this.rows, function (oElem) { return value === oElem.UploadItem; }); + if (aRows.length === 0) return; + var rowIndex = this.rows.indexOf(aRows[0]); + this.rows.splice(rowIndex, 1); + aRows[0].$el.remove(); + }.bind(this)); + + if (this.rows.length == 0) { + this.$container.addClass('d-none'); + } else { + this.$container.removeClass('d-none'); + this.$uploadingBlock.addClass('show'); + var $uploading = this.$uploadingBlock; + setTimeout(function () { + $uploading.removeClass('show'); + }, 3000); + } + + this._StateRowChange(); + }; + + UploaderGridView.prototype._StateRowChange = function () { + let countPaused = 0; + let countCompleted = 0; + this.rows.forEach(function (row) { + let rowState = row.UploadItem.GetState(); + if (rowState === window.ITHit.WebDAV.Client.Upload.State.Paused) { + countPaused++; + } else if (rowState === window.ITHit.WebDAV.Client.Upload.State.Completed + || rowState === window.ITHit.WebDAV.Client.Upload.State.Canceled) { + countCompleted++; + } + }) + if (countPaused == 0) { + this._UpdateActions(false); + } else if (countPaused == (this.rows.length - countCompleted)) { + this._UpdateActions(true); + } + }; + + UploaderGridView.prototype._DataBindAllProgress = function () { + var currProgress = 0; + var count = 0; + this.rows.forEach(function (value) { + if (value.UploadItem.GetState() !== window.ITHit.WebDAV.Client.Upload.State.Canceled) { + var valueProgress = value.UploadItem.GetProgress().Completed; + if (valueProgress < 100) { + currProgress += valueProgress; + } + else { + currProgress += 100; + } + count++; + } + }); + currProgress /= count; + if (currProgress >= 0) { + var $progress = this.$container.find('.progress-wrapper .progress-bar'); + $progress.attr('aria-valuenow', currProgress).css('width', currProgress + '%'); + this.$uploadingBlock.find('.persent').text(Math.round(currProgress) + '%'); + } + } + + UploaderGridView.prototype._DataBindUploaderBlock = function () { + this.$container.find('.pause-all-button').click(this._PauseAllClickHandler.bind(this)); + this.$container.find('.play-all-button').click(this._StartAllClickHandler.bind(this)); + this.$uploadingBlock.find('.details-button').click(this._DetailsClickHandler.bind(this)); + this.$uploadingDetails.find('.close-button').click(this._CloseClickHandler.bind(this)); + this.$container.find('.cancel-all-button').click(this._CancelAllClickHandler.bind(this)); + this._UpdateActions(false); + } + + UploaderGridView.prototype._UpdateActions = function (isPaused) { + var $playButton = this.$container.find(".play-all-button"); + var $pauseButton = this.$container.find(".pause-all-button"); + if (isPaused) { + if ($playButton.hasClass('d-none')) { + $playButton.removeClass('d-none'); + + } + if (!$pauseButton.hasClass('d-none')) { + $pauseButton.addClass('d-none'); + } + } else { + if ($pauseButton.hasClass('d-none')) { + $pauseButton.removeClass('d-none'); + } + if (!$playButton.hasClass('d-none')) { + $playButton.addClass('d-none'); + } + } + }; + + UploaderGridView.prototype._DetailsClickHandler = function () { + this.$uploadingBlock.addClass('hide'); + this.$uploadingDetails.removeClass('d-none'); + this.$uploadingDetails.focus(); + } + + UploaderGridView.prototype._CloseClickHandler = function () { + this.$uploadingBlock.removeClass('hide'); + this.$uploadingDetails.addClass('d-none'); + } + + + UploaderGridView.prototype._DisableActions = function () { + this.$container.find('.cancel-all-button').attr("disabled", 'disabled'); + this.$container.find('.play-all-button').attr("disabled", 'disabled'); + this.$container.find('.pause-all-button').attr("disabled", 'disabled'); + }; + + UploaderGridView.prototype._EnableActions = function () { + this.$container.find('.cancel-all-button').removeAttr("disabled"); + this.$container.find('.play-all-button').removeAttr("disabled"); + this.$container.find('.pause-all-button').removeAttr("disabled"); + }; + + UploaderGridView.prototype._StartAllClickHandler = function () { + this._DisableActions(); + this.rows.forEach(function (value) { + if (value.UploadItem.GetState() === window.ITHit.WebDAV.Client.Upload.State.Paused) { + value._StartClickHandler(); + } + }); + this._EnableActions(); + }; + + UploaderGridView.prototype._PauseAllClickHandler = function () { + this._DisableActions(); + this.rows.forEach(function (value) { + value._PauseClickHandler(); + }); + this._EnableActions(); + }; + + UploaderGridView.prototype._CancelAllClickHandler = function () { + this._DisableActions(); + this.rows.forEach(function (value) { + value._CancelClickHandler(); + }); + this._UpdateActions(false); + this._EnableActions(); + }; + + /** + * Drag-and-Drop area visual effects. + */ + UploaderGridView.prototype._OnDragEnter = function (oEvent) { + this._dropCounter++; + $(oEvent.target).closest('#ithit-dropzone').addClass('dropzone'); + }; + + UploaderGridView.prototype._OnDragLeave = function (oEvent) { + this._dropCounter--; + if (this._dropCounter <= 0) { + this._dropCounter = 0; + oEvent.currentTarget.classList.remove('dropzone'); + } + }; + + UploaderGridView.prototype._OnDrop = function (oEvent) { + this._dropCounter = 0; + this._dropZone.HtmlElement.classList.remove('dropzone'); + this._dropZone.HtmlElement.querySelectorAll("*").forEach(function (value) { + value.classList.remove('dropzone'); + }); + }; + + UploaderGridView.prototype._ShowExistsCheckError = function (oError, fCallback) { + WebdavCommon.ErrorModal.Show(sFailedCheckExistsMessage, oError, fCallback); + }; + + /** + * Represents uploader grid row and subscribes for upload changes. + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - Upload item. + */ + function UploaderGridRow(oUploadItem, fileLoadCompletedCallback, fileUploadFailedCallback, progressChangedCallback, stateChangedCallback) { + this.$el = $('
      '); + this.UploadItem = oUploadItem; + this.UploadItem.AddListener('OnProgressChanged', '_OnProgress', this); + this.UploadItem.AddListener('OnStateChanged', '_OnStateChange', this); + this.UploadItem.AddListener('OnBeforeUploadStarted', this._OnBeforeUploadStarted, this); + this.UploadItem.AddListener('OnUploadError', this._OnUploadError, this); + this._Render(oUploadItem); + this._MaxRetry = 10; + this._CurrentRetry = 0; + this._RetryDelay = 10; + this.fileLoadCompletedCallback = fileLoadCompletedCallback; + this.fileUploadFailedCallback = fileUploadFailedCallback; + this.progressChangedCallback = progressChangedCallback; + this.stateChangedCallback = stateChangedCallback; + }; + + /** + * Creates upload row details view. + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - Upload item to render details. + */ + UploaderGridRow.prototype._Render = function (oUploadItem) { + + var $cancelBlock = $('
      ') + .append($(' +
      +
      + + +
      +
      +
      + +
      + +
      +
      +
      + +
      +
      + + +
      +
      + +
      +
      + +
      +
      + +
      +
      + +
      +
      + +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      + Uploaded 0 % + + +
      +
      + +
      +
      +
      +
      + Files upload + +
      +
      + +
      +
      + + + +
      +
      +
      +
      +
      +
      +
      Drag files here
      +
      +
      + + + + + + + + + + + + + +
      + Display NameTypeSizeModified
      +
      +
      +
      +
      +
      + +
      +
      + + + + + + +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html new file mode 100644 index 0000000..2e33150 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/attributesErrorPage.html @@ -0,0 +1,25 @@ + + IT Hit WebDAV Server Engine + + + + +

      Your file system doesn't support User Defined Attributes or they are not enabled

      +

      Information below will help you to find whether your file system supports User Defined Attributes:

      +
        +
      • In Linux, the ext2, ext3, ext4, JFS, Squashfs, Yaffs2, ReiserFS, XFS, Btrfs, OrangeFS, Lustre, OCFS2 1.6 and F2FS + support User Defined Attributes. +

        Enabling extended attributes on Linux

        +

        Go to /etc/fstab and add "user_xattr" to the options section of the line regarding the file-system you'd like to enable extended attributes on. Such a line might look like:

        +

        /dev/sda1 / ext4 errors=remount-ro,user_xattr 0 1

        +
      • +
      • In Windows only NTFS supports User Defined Attributes
      • +
      • In FreeBSD only UFS2 supports User Defined Attributes
      • +
      • In Mac OS HFS+ supports User Defined Attributes
      • +
      • Solaris version 9 and later allows files to have "extended attributes"
      • +
      + + \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml new file mode 100644 index 0000000..ca16d9a --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/glassfish-web.xml @@ -0,0 +1,6 @@ + + + + / + \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml new file mode 100644 index 0000000..8a24b22 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/jboss-web.xml @@ -0,0 +1,4 @@ + + + / + \ No newline at end of file diff --git a/Kotlin/filesystemstorage/src/main/webapp/WEB-INF/web.xml b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from Kotlin/filesystemstorage/src/main/webapp/WEB-INF/web.xml rename to Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/web.xml diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml new file mode 100644 index 0000000..839dd28 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/weblogic.xml @@ -0,0 +1,6 @@ + + + true + + / + \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html new file mode 100644 index 0000000..0b3ecba --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxFileBrowser.html @@ -0,0 +1,149 @@ + + + IT Hit Ajax File Browser + + + + + + + + + + +
      + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html new file mode 100644 index 0000000..7b0a3f5 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/AjaxIntegrationTests.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css new file mode 100644 index 0000000..6ffeaaf --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/css/webdav-layout.css @@ -0,0 +1,1292 @@ +/*Start Common styles*/ +.ellipsis { + position: relative; +} + + .ellipsis:before { + content: ' '; + visibility: hidden; + } + + .ellipsis span, .ellipsis a { + position: absolute; + left: 8px; + right: 8px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + +.bg-dark { + color: white; +} + + .bg-dark h3 { + font-size: 20px; + line-height: 27px; + } + + .bg-dark p { + font-size: 16px; + line-height: 21px; + } + +a.disabled { + pointer-events: none; +} + +.custom-checkbox, .custom-radiobtn { + display: block; + position: relative; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + width: 23px; + height: 23px; + margin: 0px; +} + +.custom-radiobtn { + display: inline-block; + top: 9px; + left: 7px; +} + + .custom-checkbox input, .custom-radiobtn input { + position: absolute; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; + } + + .custom-checkbox .checkmark, .custom-radiobtn .checkmark { + display: block; + position: absolute; + top: 0; + left: 0; + width: 21px; + height: 21px; + border: 2px solid #DEE2E6; + border-radius: 4px; + } + + .custom-radiobtn .checkmark { + border-radius: 12px; + border: 3px solid #DEE2E6; + box-sizing: border-box; + } + +.custom-checkbox input:checked ~ .checkmark { + background-image: url(../images/check-square.svg); + border: none; + width: 22px; + height: 22px; +} + +.custom-radiobtn input:checked ~ .checkmark:before { + content: ""; + display: block; + background-color: #007BFF; + width: 9px; + height: 9px; + position: absolute; + top: 3px; + left: 3px; + border-radius: 5px; +} + +@media (max-width: 1280px) { + .custom-hidden { + display: none !important; + } +} + +button.btn.btn-transparent { + background-color: transparent; + border: none; + padding: 2px 8px; + min-width: initial; + color: #337ab7; +} + +.alert-danger { + margin-top: 15px; +} + +p.error-message { + margin: 0; +} + +.btn-info { + padding: 0px 5px !important; + line-height: 1.2; + margin-top: -3px; +} + +.btn-label { + display: inline-block; + padding: 4px 9px; + background: rgba(0,0,0,0.15); + border-radius: 6px 0 0 6px; +} + +.btn-labeled { + padding: 0; +} + + .btn-labeled span:last-child { + padding: 0 10px 0 5px; + vertical-align: text-bottom; + min-width: 42px; + } + +.btn-edit-label { + padding-left: 5px; +} + +.dropdown-menu-radio-btns { + margin-left: -10px; +} + +.table-hover tbody tr.active, .table-hover tbody tr.active + tr.tr-snippet-url { + background-color: rgba(0,0,0,.075); +} + +.split { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + overflow-y: auto; + overflow-x: hidden; +} + +.gutter { + z-index: 2; + background-color: transparent; + background-repeat: no-repeat; + background-position: 10px 50%; +} + + .gutter.gutter-horizontal { + cursor: col-resize; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAA1CAYAAAB4HnrFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAF/SURBVHgB7VXLUcMwEJUcJVdSgkvIPZOQVABUgKkAOoB0QAeIDkwFduLxPSWoBHP1l/dkicmJiU8mM9nLvpVWO89Pu7LMsmwjpUwEDF4vl8sn4sPhoIMgeCTuum4biDNN1XVdTKdT4+Jvv4HqBZwRF2TSyfNhAym/IM8LMdbfEd+59QflDoTO3/gK0G6OBLvetu38bB0vwWSe5wv4ZxfvIY8mwHoEd0tcluVO8dMhQ2RPSUlnE5um2fg2U0p9DmqzI05sGVRVZfwGKvJmNDFzxHgmkyQJwTFigEY4rtfrmBjDdQ+OC8dRI0eFWHjlAuTQcLErwkQvTzpMnslkYmcZFcwvJ0iDy0iJIZUR45mVBxw3NgDH1WqVEnPoIFdIDI6xl8dPoYaziUiKfPewwCB5DKruGECO0y6JUdUQMEeMZ5RnDo62S/CVBYbL8nRdFYqeI6dALfwbLvrBsvcObd9OumfYG25ms5l28d5voGIK11l+/Xv+701ef3F/2Yi/uB95ycM47B+AqAAAAABJRU5ErkJggg=='); + } + + .split.split-horizontal, .gutter.gutter-horizontal { + float: left; + } + +@media (max-width: 575px) { + #leftPanel { + display: block; + flex-basis: 100% !important; + } + + #rightPanel { + display: none; + } + + .gutter { + display: none; + } +} + +#leftPanel, #rightPanel { + overflow: hidden; +} + +#leftPanel { + position: initial; +} + +#rightPanel { + position: relative; +} + + #rightPanel.disable-iframe-events:before { + content: ""; + display: block; + position: absolute; + background-color: transparent; + height: 100%; + width: 100%; + top: 0; + z-index: 1; + } +#leftPanel.extra-large-point .d-xxl-inline { + display: none !important; +} +#leftPanel.large-point .d-xl-table-cell { + display: none !important; +} + +#leftPanel.medium-point .d-lg-table-cell, +#leftPanel.medium-point .d-xl-table-cell, +#leftPanel.medium-point .d-lg-inline { + display: none !important; +} + +.versions { + font-size: 14px; + line-height: 19px; + color: rgba(0, 0, 0, 0.5); + margin-bottom: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.file-name { + position: absolute; + right: 0px; + top: 13px; + font-size: 16px; + line-height: 27px; + color: #212529; +} + +.modal-footer button { + min-width: 75px; +} + +/*End Common styles*/ + +/*Start Header styles*/ +header { + margin-bottom: 15px; +} + + header p { + word-break: break-word; + } + +.navbar-toggler .burger-icon { + width: 23px; + height: 20px; + position: relative; + margin: 0px; + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + transition: 0.5s ease-in-out; + cursor: pointer; +} + +header .logo { + margin-right: 10px; + position: absolute; + left: 0px; + top: 2px; +} + +.navbar-toggler .burger-icon span { + background: #fff; + display: block; + position: absolute; + height: 2px; + width: 100%; + border-radius: 9px; + opacity: 1; + left: 0; + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + transition: 0.25s ease-in-out; +} + +header .versions { + color: white; + padding-right: 0 !important; +} + +@media (prefers-reduced-motion: reduce) { + .navbar-toggler .burger-icon span { + transition: none; + } + + .navbar-toggler .burger-icon { + transition: none; + } +} + +.navbar-toggler .burger-icon span:nth-child(1) { + top: 1px; +} + +.navbar-toggler .burger-icon span:nth-child(2) { + top: 8px; +} + +.navbar-toggler .burger-icon span:nth-child(3) { + top: 16px; +} + +.navbar-toggler[aria-expanded="true"] .burger-icon span:nth-child(1) { + top: 11px; + -moz-transform: rotate(135deg); + -o-transform: rotate(135deg); + -ms-transform: rotate(135deg); + -webkit-transform: rotate(135deg); + transform: rotate(135deg); +} + +.navbar-toggler[aria-expanded="true"] .burger-icon span:nth-child(2) { + opacity: 0; + left: -60px; +} + +.navbar-toggler[aria-expanded="true"] .burger-icon span:nth-child(3) { + top: 11px; + -moz-transform: rotate(-135deg); + -o-transform: rotate(-135deg); + -ms-transform: rotate(-135deg); + -webkit-transform: rotate(-135deg); + transform: rotate(-135deg); +} + +.navbar-toggler, .navbar-toggler:focus { + border: none; + outline: 0; +} + +.navbar-header h1 { + height: auto; + padding: 15px; + margin: 0; + font-weight: normal; + font-size: 18px; + line-height: 20px; + color: #9d9d9d; +} + +.navbar-brand.ellipsis { + width: calc(100% - 48px); + margin-right: 0; + cursor: pointer; +} + + .navbar-brand.ellipsis span { + left: 45px; + top: 5px; + } + +.navbar { + overflow: hidden; +} + + .navbar .nav-link { + margin-right: 0.5rem; + } + +.navbar-dark .navbar-nav .nav-link { + color: #fff; +} + +@media (max-width: 767px) { + .navbar .nav-link { + margin-right: 0; + margin-bottom: 0.5rem; + } + + .navbar .navbar-collapse { + margin-top: 0.5rem; + } +} + +.header-content { + padding: .5rem 1rem 1.5rem 1rem; +} + + .header-content .col > p { + padding-right: 5rem; + } + + + .header-content a { + font-weight: bold; + color: white; + text-decoration: underline; + } + + .header-content .flex-column { + position: relative; + padding-bottom: 48px; + } + + .header-content .flex-column .btn { + position: absolute; + bottom: 10px; + } +/*End Header styles*/ + +/*Start Main layout styles*/ +.btn-up-one-level { + color: #007BFF; + border: none; + background: none; + cursor: pointer; + margin: 9px 10px 9px 6px; + opacity: 0.9; + display: inline-block; +} + + .btn-up-one-level:hover, .btn-up-one-level:focus { + opacity: 1 + } + + .btn-up-one-level.disabled { + opacity: 0.5; + cursor: not-allowed; + } + + .btn-up-one-level.disabled:hover, .btn-up-one-level.disabled:focus { + opacity: 0.5; + } + + .btn-up-one-level:hover, .btn-up-one-level:focus { + opacity: 1 + } + .btn-up-one-level:before { + content: ""; + display: inline-block; + width: 24px; + height: 24px; + position: relative; + background-repeat: no-repeat; + text-align: center; + background-position: center; + vertical-align: bottom; + background-image: url(../images/up-one-level.svg); + } + + +.breadcrumb { + background: none; + padding: 10px 7px; + margin-bottom: 15px; +} + +ol.breadcrumb li .icon-home { + background-image: url('../images/home.svg'); + display: inline-block; + height: 16px; + width: 14px; + margin-top: 3px; + margin-left: 2px; +} + +/*Start Right Panel styles*/ +.nav-tabs { + border-bottom: 1px solid #007BFF; +} + + .nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { + border-color: #007BFF #007BFF #007BFF; + } + + .nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active { + border-color: #007BFF #007BFF #fff; + } + + .nav-tabs .nav-item { + line-height: 31px; + min-width: 90px; + text-align: center; + } + +.tab-content > .active { + display: block; + border: 1px solid #007BFF; + border-top: none; +} + +.gsuite-container #gSuitePreview, .gsuite-container #gSuiteEdit { + height: 714px; + margin: 0px -8px 25px -8px; +} + + .gsuite-container #gSuitePreview .inner-container, .gsuite-container #gSuiteEdit .inner-container { + height: 714px; + } + +.gsuite-container { + position: relative; +} + + .gsuite-container .background { + position: absolute; + top: calc(50% - 20px); + left: 0; + bottom: 0; + right: 0; + z-index: -1; + overflow: hidden; + text-align: center; + } +/*End Right Panel styles*/ + +/*Start Left Panel styles*/ + +/*Toolbar*/ +.ithit-grid-toolbar { + margin-top: 7px; + padding: 0 10px; +} + + .ithit-grid-toolbar .first-section { + padding: 0 5px; + } + + .ithit-grid-toolbar button, .ithit-grid-toolbar label.btn-upload-items { + color: #007BFF; + border: none; + background: none; + cursor: pointer; + padding: 0; + margin-left: 6px; + opacity: 0.9; + } + + .ithit-grid-toolbar button.btn-create-folder { + white-space: nowrap + } + + .ithit-grid-toolbar button:before, .ithit-grid-toolbar label.btn-upload-items:before { + content: ""; + display: inline-block; + width: 24px; + height: 24px; + margin-right: 10px; + position: relative; + background-repeat: no-repeat; + text-align: center; + background-position: center; + vertical-align: bottom; + } + + .ithit-grid-toolbar button:disabled { + opacity: 0.5; + cursor: not-allowed; + } + + + .ithit-grid-toolbar button:disabled:hover, .ithit-grid-toolbar button:disabled:focus { + opacity: 0.5; + } + + .ithit-grid-toolbar button:hover, .ithit-grid-toolbar button:focus { + opacity: 1 + } + + .ithit-grid-toolbar button.btn-create-folder:before { + background-image: url(../images/create-folder.svg); + } + + .ithit-grid-toolbar label.btn-upload-items:before { + background-image: url(../images/upload.svg); + } + + .ithit-grid-toolbar button.btn-copy-items:before { + margin: 0 4px; + background-image: url(../images/copy.svg); + } + + .ithit-grid-toolbar button.btn-cut-items:before { + margin: 0 4px; + background-image: url(../images/cut.svg); + } + + .ithit-grid-toolbar button.btn-paste-items:before { + margin: 0 4px; + background-image: url(../images/paste.svg); + } + + .ithit-grid-toolbar button.btn-reload-items:before { + margin: 0 4px; + background-image: url(../images/reload.svg); + } + + .ithit-grid-toolbar button.btn-rename-item:before { + background-image: url(../images/rename.svg); + } + + .ithit-grid-toolbar button.btn-download-items:before { + background-image: url(../images/download.svg); + } + + .ithit-grid-toolbar button.btn-print-items:before { + background-image: url(../images/print.svg); + } + + .ithit-grid-toolbar button.btn-delete-items:before { + background-image: url(../images/delete.svg); + } + + .ithit-grid-toolbar button:hover:before, .ithit-grid-toolbar button:focus:before { + opacity: 1; + } + +/*Search Panel*/ +.ithit-search-container { + position: relative; + height: 50px; +} + + .ithit-search-container input.tt-input[disabled], + .ithit-search-container input.tt-input[readonly] { + cursor: default; + } + + .ithit-search-container .twitter-typeahead { + position: relative; + width: 100%; + margin-bottom: 15px; + } + + .ithit-search-container .twitter-typeahead:before { + position: absolute; + top: 9px; + left: 7px; + content: ""; + background-image: url(../images/search.svg); + display: block; + width: 20px; + height: 20px; + z-index: 1; + } + + .ithit-search-container .twitter-typeahead input { + padding: .4rem .75rem .4rem 40px; + } + + .ithit-search-container button { + position: absolute; + top: 0; + right: 0; + width: 85px; + } + +.tt-suggestion .snippet, .ithit-grid-container .snippet { + overflow: hidden; + font-size: 12px; + line-height: 18px; + color: #999; +} + +.tt-suggestion .breadcrumb, .ithit-grid-container .breadcrumb { + font-size: 12px; + color: #999; + word-break: break-word; +} + +.ithit-grid-container ol.breadcrumb, .tt-suggestion ol.breadcrumb { + list-style: none; + background-color: transparent; + padding: 0 0 0 8px; + margin: 0; +} + +.tt-suggestion ol.breadcrumb { + padding: 0; +} + + .tt-suggestion ol.breadcrumb li:first-child, .ithit-grid-container ol.breadcrumb li:first-child { + display: none; + } + + .ithit-grid-container ol.breadcrumb li, .tt-suggestion ol.breadcrumb li { + display: inline-block; + } + + .ithit-grid-container ol.breadcrumb li:nth-of-type(2):before, + .tt-suggestion ol.breadcrumb li:nth-of-type(2):before { + display: none; + } + + .ithit-grid-container ol.breadcrumb li:before, .tt-suggestion ol.breadcrumb li:before { + padding-right: .3rem; + padding-left: .3rem; + } + + + +.tt-suggestion .snippet b, .ithit-grid-container .snippet b { + color: #555; +} + +.tt-hint { + color: #999; +} + +.tt-menu { + width: 100%; + right: 100px; + margin: 1px 0; + padding: 6px 0; + background-color: #fff; + border: 1px solid #ccc; + -webkit-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} + +.tt-suggestion { + padding: 3px 20px; + line-height: 1.7; +} + + .tt-suggestion:hover { + cursor: pointer; + background-color: #eee; + } + + .tt-suggestion.tt-cursor { + background-color: #eee; + } + +table tr.tr-snippet-url td { + padding: 0px; + border-top: none; +} + + table tr.tr-snippet-url td > div { + padding-left: 8px; + } + + table tr.tr-snippet-url td > div:last-child { + margin-bottom: 8px; + padding-right: 8px; + } + +/*Grid Items*/ +.ithit-grid-container { + width: 100%; + /*margin-top: 20px;*/ + overflow-y: hidden; +} + +.ithit-grid-container .icon-folder { + background-image: url(../images/folder.svg); + display: inline-block; + height: 14px; + width: 16px; +} + +.ithit-grid-container .icon-open-folder, .ithit-grid-container .icon-edit, +.ithit-grid-container .icon-microsoft-edit, .icon-gsuite-edit, +.ithit-grid-container .icon-edit-associated { + background-image: url(../images/open-folder.svg); + background-repeat: no-repeat; + display: inline-block; + height: 19px; + width: 19px; + position: relative; + top: 5px; +} + +.ithit-grid-container .icon-edit { + background-image: url(../images/edit.svg); + top: 2px; +} + +.ithit-grid-container .icon-microsoft-edit, .ithit-grid-container .icon-gsuite-edit { + background: none; + -webkit-mask-image: url(../images/menu-microsoft-edit.svg); + mask-image: url(../images/menu-microsoft-edit.svg); + background-color: white; + -webkit-mask-size: cover; + top: 2px; +} + +.ithit-grid-container .icon-gsuite-edit { + -webkit-mask-image: url(../images/menu-gsuit-edit.svg); + mask-image: url(../images/menu-gsuit-edit.svg); +} + +.ithit-grid-container th.sort { + position: relative; + cursor: pointer; +} + + .ithit-grid-container th.sort.ascending, th.sort.descending { + padding-right: 15px; + } + + .ithit-grid-container th.sort.ascending:after, th.sort.descending:after { + content: ""; + display: inline-block; + position: absolute; + left: -5px; + width: 0px; + height: 0px; + margin-top: 6px; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid #2f2f2f; + } + + .ithit-grid-container th.sort.descending:after { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid #2f2f2f; + border-bottom: none; + margin-top: 13px; + } + + .ithit-grid-container th.sort.disabled { + pointer-events: none; + } + + .ithit-grid-container th.sort.disabled:after { + display: none; + } + +.ithit-grid-container .column-action { + text-align: right; + padding-left: 0; + padding-right: 0; +} + + .ithit-grid-container .column-action a { + display: inline-block; + padding: 2px 8px; + } + + .ithit-grid-container .column-action a:last-child { + margin-right: 0; + } + + .ithit-grid-container .column-action button.browse-lnk span:last-child { + margin-right: 10px; + } + + .ithit-grid-container .column-action button span { + vertical-align: middle; + } + +.ithit-grid-container .badge { + left: 22px; + font-size: 55%; + position: absolute; + top: 27px; + background: #FFFFFF; + border: 1px solid #409CFF; + box-sizing: border-box; + border-radius: 6px; + padding: 1px 5px; + color: #212529; +} + +table.ithit-grid-container > tbody > tr > td { + vertical-align: middle; + white-space: nowrap; + cursor: default; +} + + table.ithit-grid-container > thead > tr > th:nth-child(1), + table.ithit-grid-container > tbody > tr > td:nth-child(1) { + text-align: right; + } + + table.ithit-grid-container > thead > tr > th:nth-child(2), + table.ithit-grid-container > tbody > tr > td:nth-child(2) { + min-width: 46px; + text-align: center; + position: relative; + } + + table.ithit-grid-container > thead > tr > th:nth-child(4), + table.ithit-grid-container > tbody > tr > td:nth-child(4) { + min-width: 120px; + max-width: 120px; + } + + table.ithit-grid-container > thead > tr > th:nth-child(5), + table.ithit-grid-container > tbody > tr > td:nth-child(5) { + min-width: 100px; + max-width: 100px; + } + + table.ithit-grid-container > tbody > tr > td:nth-child(3) { + width: 100%; + } + + table.ithit-grid-container > tbody > tr > td button:last-child { + margin-left: 5px; + } + + table.ithit-grid-container > tbody > tr > td button.btn-delete .btn-label { + padding-left: 5px; + } + +@media (max-width: 320px) { + table.ithit-grid-container > thead > tr > th:nth-child(5), + table.ithit-grid-container > tbody > tr > td:nth-child(5) { + display: none; + } +} + +.ithit-grid-icon-locked { + background-image: url(../images/locked.svg); + width: 17px; + height: 22px; + display: inline-block; +} + +.ithit-grid-container button.btn-labeled { + border-radius: 5px; +} + +.ithit-grid-container .actions input[type=radio] { + position: relative; + top: 0; + left: 0; + width: 20px; + height: 20px; + z-index: 3; +} + +.ithit-grid-container .actions .icon-edit, .ithit-grid-container .actions .icon-microsoft-edit, +.ithit-grid-container .actions .icon-gsuite-edit, +.ithit-grid-container .actions .icon-edit-associated { + display: inline-block; + background-image: url(../images/menu-edit.svg); + width: 28px; + height: 24px; + vertical-align: middle; + margin-top: -10px; + margin-right: 10px; +} + +.ithit-grid-container .actions .icon-edit-associated { + background-image: url(../images/edit-associated.svg); + width: 27px; + height: 30px; + margin-top: -17px; +} + +.ithit-grid-container .actions .dropdown-item { + padding-top: 10px; + padding-bottom: 10px; +} + + .ithit-grid-container .actions .dropdown-item.desktop-app { + padding-left: 61px; + } + +.ithit-grid-container .actions.dropdown-menu-radio-btns .dropdown-item.desktop-app { + padding-left: 76px; +} + +.ithit-grid-container .actions .dropdown-radio { + margin-top: -28px; + z-index: 2; + padding-left: 40px; +} + +.ithit-grid-container .actions .icon-microsoft-edit, .ithit-grid-container .actions .icon-gsuite-edit { + background-image: url(../images/menu-microsoft-edit.svg); + width: 25px; + height: 26px; + margin-top: -9px; +} + +.ithit-grid-container .actions .icon-gsuite-edit { + background-image: url(../images/menu-gsuit-edit.svg); +} + +table tr.hover, table tr:hover, table tr:hover + table tr.tr-snippet-url { + background-color: rgba(0,0,0,.075); +} + +.table td, .table th { + padding: 0.5rem; +} + +.table-responsive { + border: none; +} + +/*Uploader Grid*/ +.progress-wrapper { + padding: 3px 0; +} + + .progress-wrapper:hover ~ .uploading-block { + visibility: visible; + opacity: 1; + } +.progress { + height: 3px +} + +.progress-bar { + background-color: #007BFF; + box-shadow: 0px 0px 8px rgba(0, 123, 255, 0.5); +} + +.ithit-grid-uploads { + margin-top: 20px; +} + + .ithit-grid-uploads button:not(:disabled):not(.disabled) { + cursor: pointer; + } + + + +.uploading-block, +.uploading-details { + display: inline-block; + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 4px; + margin-top: 0px; +} + +.uploading-block { + min-width: 208px; + + visibility: hidden; + opacity: 0; + transition: visibility 0.5s, opacity 0.5s linear; +} + + .uploading-block:hover, .uploading-block.show { + visibility: visible; + opacity: 1; + } + + .uploading-block.hide { + visibility: hidden !important; + opacity: 0; + transition: visibility 0.5s, opacity 0.5s linear; + } + + .uploading-block .uploading-controls { + padding: 12px 14px; + line-height: 28px + } + + .uploading-block .uploading-controls .persent { + color: #007BFF + } + + .uploading-block .btn.btn-primary { + border-radius: 0 0 4px 4px; + width: 100% + } + +@media (max-width: 575px) { + .uploading-details { + left: 15px; + right: 15px; + } +} +@media (min-width: 576px) { + .uploading-details { + min-width: 479px; + } +} + + .uploading-details .details-header { + padding: 8px + } + + .uploading-details .details-header .details-title { + font-size: 16px; + line-height: 21px; + padding: 5px; + } + +.uploading-items { + max-height: 300px; + overflow-y: auto; + padding: 0 30px 15px 10px +} + +.uploading-item { + align-items: center; + margin: 0; + padding: 9px 0 +} + + .uploading-item .item-progress, + .uploading-item .item-size, + .uploading-item .item-speed { + font-size: 12px; + line-height: 16px; + color: #b3b3b3 + } + + .uploading-item .item-name span { + padding: 0 7px; + } + + .uploading-item .file-icon { + position: relative; + width: 38px; + height: 49px; + background: url(../images/file-default-icon.svg) no-repeat + } + + .uploading-item .file-icon { + position: relative; + width: 38px; + height: 49px; + background: url(../images/file-default-icon.svg) no-repeat + } + + .uploading-item .file-icon.file-7z, + .uploading-item .file-icon.file-gz, + .uploading-item .file-icon.file-rar, + .uploading-item .file-icon.file-tar, + .uploading-item .file-icon.file-zip { + background: url(../images/file-archive-icon.svg) no-repeat + } + + .uploading-item .file-icon.file-gif, + .uploading-item .file-icon.file-jpeg, + .uploading-item .file-icon.file-jpg, + .uploading-item .file-icon.file-png, + .uploading-item .file-icon.file-svg { + background: url(../images/file-image-icon.svg) no-repeat + } + + .uploading-item .file-icon.file-pdf { + background: url(../images/file-pdf-icon.svg) no-repeat + } + + .uploading-item .file-icon .file-extension { + font-family: Arial, Helvetica, sans-serif; + color: #fff; + font-size: 12px; + position: absolute; + bottom: 0; + line-height: 1.1; + left: 50%; + transform: translate(-50%) + } + +button.cancel-button, +button.close-button, +button.pause-button, +button.play-button { + padding: 0; + border: none; + background-color: transparent; + text-align: center +} + + button.cancel-button:before, + button.close-button:before, + button.pause-button:before, + button.play-button:before { + content: ""; + display: block; + width: 28px; + height: 28px; + background-repeat: no-repeat; + background-position: 50% + } + + button.pause-button:before { + background-image: url(../images/pause-button.svg) + } + + button.play-button:before { + background-image: url(../images/play-button.svg) + } + + button.close-button:before { + background-image: url(../images/cancel-button.svg) + } + + button.cancel-button:before { + background-image: url(../images/cancel-button.svg) + } + +button.cancel-all-button { + margin: 15px 30px 15px 10px +} + +.ithit-grid-wrapper { + margin: 20px 0px; + border: 2px solid transparent; + position: relative; +} + .ithit-grid-wrapper .table-responsive { + min-height: 300px; + } + + .ithit-grid-wrapper .drop-files-header { + display: none; + } + +.dropzone .ithit-grid-wrapper { + border: 2px solid #007BFF; +} + + .dropzone .ithit-grid-wrapper .drop-files-header { + display: block; + position: absolute; + left: 0; + right: 0; + top: 0; + height: 42px; + width: 100%; + z-index: 2; + background-color: white; + border-bottom: 1px solid #007BFF; + color: #007BFF; + text-align: center; + } + + .dropzone .ithit-grid-wrapper .drop-files-header .drop-files-title { + margin-top: 7px; + font-size: 20px; + line-height: 27px; + } + + .dropzone .ithit-grid-wrapper .drop-files-header .drop-files-title:before { + content: ""; + display: inline-block; + width: 24px; + height: 24px; + margin-right: 10px; + position: relative; + background-repeat: no-repeat; + text-align: center; + background-position: center; + vertical-align: bottom; + background-image: url(../images/upload.svg); + } + + .dropzone .ithit-grid-wrapper tr { + opacity: 0.4; + } + +.more-lnk { + margin: 15px 0; + display: inline-block; +} + +.more-pnl { + padding-left: 15px; + display: none; +} + +.ui-draggable { + cursor: move; +} +/*End Main layout styles*/ diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg new file mode 100644 index 0000000..8e13466 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cancel-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg new file mode 100644 index 0000000..f61913d --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/check-square.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg new file mode 100644 index 0000000..5ac0b67 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/copy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg new file mode 100644 index 0000000..0b1f205 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/create-folder.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg new file mode 100644 index 0000000..bc0b4d3 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/cut.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg new file mode 100644 index 0000000..7e16e63 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/delete.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg new file mode 100644 index 0000000..194382d --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/download.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg new file mode 100644 index 0000000..ec19cce --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit-associated.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg new file mode 100644 index 0000000..1540872 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/edit.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg new file mode 100644 index 0000000..6343516 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-archive-icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg new file mode 100644 index 0000000..56bcace --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-default-icon.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg new file mode 100644 index 0000000..ade2b79 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-image-icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg new file mode 100644 index 0000000..dcb1b85 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/file-pdf-icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg new file mode 100644 index 0000000..d900027 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/folder.svg @@ -0,0 +1,3 @@ + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg new file mode 100644 index 0000000..f63b4f6 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/home.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg new file mode 100644 index 0000000..d68efcf --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/locked.svg @@ -0,0 +1,3 @@ + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg new file mode 100644 index 0000000..7e321fc --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg new file mode 100644 index 0000000..3ef3edc --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-edit.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg new file mode 100644 index 0000000..730dd8b --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-gsuit-edit.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg new file mode 100644 index 0000000..d5116ef --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/menu-microsoft-edit.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg new file mode 100644 index 0000000..fb2da8c --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/microsoft-edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg new file mode 100644 index 0000000..5fea104 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/open-folder.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg new file mode 100644 index 0000000..1f1a062 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/paste.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg new file mode 100644 index 0000000..6b1d021 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/pause-button.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg new file mode 100644 index 0000000..6cce171 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/play-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg new file mode 100644 index 0000000..378b072 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/print.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg new file mode 100644 index 0000000..b70ad9e --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/reload.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg new file mode 100644 index 0000000..b1cee21 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/rename.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg new file mode 100644 index 0000000..62df0f4 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg new file mode 100644 index 0000000..1f45bd4 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/up-one-level.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg new file mode 100644 index 0000000..4605326 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/images/upload.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json new file mode 100644 index 0000000..6032a70 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package-lock.json @@ -0,0 +1,24 @@ +{ + "name": "js", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "webdav.client": "*" + } + }, + "node_modules/webdav.client": { + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" + } + }, + "dependencies": { + "webdav.client": { + "version": "5.21.5945", + "resolved": "https://registry.npmjs.org/webdav.client/-/webdav.client-5.21.5945.tgz", + "integrity": "sha512-MC9FYy99pe3cspcX9hH60HqNJ3cJ/CqHXTcXReTAAefW0jMftBxjjiWnv1CqsMd61bIEyd7JYPMaF9EMIxa/sQ==" + } + } +} diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json new file mode 100644 index 0000000..7eb3652 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "webdav.client": "*" + } +} diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js new file mode 100644 index 0000000..2e18e7a --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-basebutton.js @@ -0,0 +1,34 @@ +/** + * This class represents button that occurred on client. + * @class + * @param {string} sName - The name of button. + * @param {string} cssClass - This cssClass will be inserted into html. + * @property {string} Name + * @property {string} CssClass + */ +function BaseButton(sName, cssClass) { + this.Name = sName; + this.CssClass = cssClass; + this.InnerHtmlContent = ""; + + this.Create = function ($toolbarContainer) { + $toolbarContainer.append(''); + this.$Button = $('.' + this.CssClass); + } + + this.Disable = function () { + this.$Button.attr('disabled', true); + } + + this.Activate = function () { + this.$Button.attr('disabled', false); + } + + this.HideOnMobile = function () { + this.$Button.addClass('d-none d-md-inline'); + } + + this.ShowOnMobile = function () { + this.$Button.removeClass('d-none d-md-inline'); + } +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js new file mode 100644 index 0000000..a2411e4 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-copypastecutbuttons.js @@ -0,0 +1,179 @@ +const sCopyItemsErrorMessage = "Copy items error."; +const sCutItemsErrorMessage = "Cut items error."; +const sCutItemsSameNameErrorMessage = "The source and destination file names are the same."; +const sCutItemsLockedErrorMessage = "Items are locked."; + +function HerarhyItemsCopyPasteController(toolbar, storedItems) { + //Copied or cut items + this.storedItems = storedItems; + this.isCopiedItems = false; + this.Toolbar = toolbar; +} + +HerarhyItemsCopyPasteController.prototype = { + /** + * Copies files or folders. + */ + Copy: function (oItem, oItemName, fCallback) { + oItem.CopyToAsync(this.Toolbar.WebDAV.CurrentFolder, oItemName, true, null, null, function (oAsyncResult) { + fCallback(oAsyncResult); + }); + }, + + /** + * Moves files or folders. + */ + Move: function (oItem, fCallback) { + oItem.MoveToAsync(this.Toolbar.WebDAV.CurrentFolder, oItem.DisplayName, null, null, function (oAsyncResult) { + fCallback(oAsyncResult); + }); + }, + + /** + * Adds items to storeItems array. + */ + _PushStoreItems: function () { + var self = this; + if (self.storedItems.length != 0) { + $.each(self.storedItems, function (index) { + self.storedItems.pop(this); + }); + } + $.each(self.Toolbar.FolderGrid.selectedItems, function (index) { + self.storedItems.push(self.Toolbar.FolderGrid.selectedItems[index]); + }); + + self.Toolbar.UpdateToolbarButtons(); + }, + + /** + * Moves or pastes files or folders. + */ + _MoveOrPasteItems: function () { + var self = this; + if (self.isCopiedItems) { + $.each(self.storedItems, function (index) { + self._ExecuteCopy(self.storedItems[index]); + }); + } else { + $.each(self.storedItems, function (index) { + self.Move(self.storedItems[index], function (oAsyncResult) { + if (!oAsyncResult.IsSuccess) { + if (oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.ForbiddenException) { + WebdavCommon.ErrorModal.Show(sCutItemsSameNameErrorMessage, oAsyncResult.Error); + } + else if (oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.LockedException) { + WebdavCommon.ErrorModal.Show(sCutItemsLockedErrorMessage, oAsyncResult.Error); + } + else { + WebdavCommon.ErrorModal.Show(sCutItemsErrorMessage, oAsyncResult.Error); + } + } + }); + }); + $.each(self.storedItems, function (index) { + self.storedItems.pop(this); + }); + } + this.Toolbar.UpdateToolbarButtons(); + }, + + _ExecuteCopy: function (oItem) { + var self = this; + self._DoCopy(oItem, self._GetCopySuffix(oItem.DisplayName, false)); + }, + + /** + * Copies files or folders or shows error modal. + */ + _DoCopy: function (oItem, oItemName) { + var self = this; + self.Copy(oItem, oItemName, function (oAsyncResult) { + if (!oAsyncResult.IsSuccess) { + if ( + oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.PreconditionFailedException || + oAsyncResult.Error instanceof window.ITHit.WebDAV.Client.Exceptions.ForbiddenException) { + self._DoCopy(oItem, self._GetCopySuffix(oItemName, true)); + } + else { + WebdavCommon.ErrorModal.Show(sCopyItemsErrorMessage, oAsyncResult.Error); + } + } + }); + }, + + /** + * Gets 'Copy' suffix. + */ + _GetCopySuffix: function (oItemName, bWithCopySuffix) { + var sCopyPrefixName = 'Copy'; + + var aExtensionMatches = /\.[^\.]+$/.exec(oItemName); + var sName = aExtensionMatches !== null ? oItemName.replace(aExtensionMatches[0], '') : oItemName; + var sDotAndExtension = aExtensionMatches !== null ? aExtensionMatches[0] : ''; + + var sLangCopy = sCopyPrefixName; + var oSuffixPattern = new RegExp('- ' + sLangCopy + '( \\(([0-9]+)\\))?$', 'i'); + + var aSuffixMatches = oSuffixPattern.exec(sName); + if (aSuffixMatches === null && bWithCopySuffix) { + sName += " - " + sLangCopy; + } else if (aSuffixMatches !== null && !aSuffixMatches[1]) { + sName += " (2)"; + } else if (aSuffixMatches !== null) { + var iNextNumber = parseInt(aSuffixMatches[2]) + 1; + sName = sName.replace( + oSuffixPattern, + "- " + sLangCopy + " (" + iNextNumber + ")" + ); + } + + oItemName = sName + sDotAndExtension; + return oItemName; + }, +} + +function CopyPasteButtonsControl(toolbar) { + this.CopyButton = new BaseButton('Copy', 'btn-copy-items', toolbar); + this.PasteButton = new BaseButton('Paste', 'btn-paste-items', toolbar); + this.CutButton = new BaseButton('Cut', 'btn-cut-items', toolbar); + this.storedItems = []; + + var oHerarhyItemsCopyPasteController = new HerarhyItemsCopyPasteController(toolbar, this.storedItems); + + this.Create = function (tolbarSection) { + + this.CopyButton.Create(tolbarSection); + this.CutButton.Create(tolbarSection); + this.PasteButton.Create(tolbarSection); + } + this.Disable = function () { + this.CopyButton.Disable(); + this.CutButton.Disable(); + this.PasteButton.Disable(); + } + + this.Activate = function () { + this.CopyButton.Activate(); + this.CutButton.Activate(); + this.PasteButton.Activate(); + } + + this.Render = function () { + this.CopyButton.$Button.on('click', function () { + oHerarhyItemsCopyPasteController.isCopiedItems = true; + oHerarhyItemsCopyPasteController._PushStoreItems(); + }) + + this.CutButton.$Button.on('click', function () { + oHerarhyItemsCopyPasteController.isCopiedItems = false; + oHerarhyItemsCopyPasteController._PushStoreItems(); + }) + + this.PasteButton.$Button.on('click', function () { + oHerarhyItemsCopyPasteController._MoveOrPasteItems(); + }) + } + + +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js new file mode 100644 index 0000000..c51debb --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-createfolderbutton.js @@ -0,0 +1,71 @@ +function CreateFolderController(toolbar) { + this.Toolbar = toolbar; +} + +CreateFolderController.prototype = { + CreateFolder: function (sFolderName, fCallback) { + this.Toolbar.WebDAV.CurrentFolder.CreateFolderAsync(sFolderName, null, null, function (oAsyncResult) { + fCallback(oAsyncResult); + }); + }, +} + +/////////////////// +// Create Folder Bootstrap Modal +function CreateFolderModal(modalSelector, createFolderController) { + var sCreateFolderErrorMessage = "Create folder error."; + + var self = this; + this.$modal = $(modalSelector); + this.$txt = $(modalSelector).find('input[type="text"]'); + this.$submitButton = $(modalSelector).find('.btn-submit'); + this.$alert = $(modalSelector).find('.alert-danger'); + + this.$modal.on('shown.bs.modal', function () { + self.$txt.focus(); + }) + this.$modal.find('form').submit(function () { + self.$alert.addClass('d-none'); + if (self.$txt.val() !== null && self.$txt.val().match(/^ *$/) === null) { + var oValidationMessage = WebdavCommon.Validators.ValidateName(self.$txt.val()); + if (oValidationMessage) { + self.$alert.removeClass('d-none').text(oValidationMessage); + return false; + } + + self.$txt.blur(); + self.$submitButton.attr('disabled', 'disabled'); + createFolderController.CreateFolder(self.$txt.val().trim(), function (oAsyncResult) { + if (!oAsyncResult.IsSuccess) { + if (oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.MethodNotAllowedException) { + self.$alert.removeClass('d-none').text(oAsyncResult.Error.Error.Description ? oAsyncResult.Error.Error.Description : 'Folder already exists.'); + } + else { + WebdavCommon.ErrorModal.Show(sCreateFolderErrorMessage, oAsyncResult.Error); + } + } + else { + self.$modal.modal('hide'); + } + self.$submitButton.removeAttr('disabled'); + }); + } + else { + self.$alert.removeClass('d-none').text('Name is required!'); + } + return false; + }); +} + +function ToolbarCreateFolderButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + var oCreateFolderModal = new CreateFolderModal('#CreateFolderModal', new CreateFolderController(toolbar)); + this.InnerHtmlContent = 'Create Folder'; + this.Render = function () { + this.$Button.on('click', function () { + oCreateFolderModal.$txt.val(''); + oCreateFolderModal.$alert.addClass('d-none'); + oCreateFolderModal.$modal.modal('show'); + }) + } +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js new file mode 100644 index 0000000..c8dc136 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-deletebutton.js @@ -0,0 +1,33 @@ +function HerarhyItemDeleteController(toolbar) { + this.Toolbar = toolbar; +} + +HerarhyItemDeleteController.prototype = { + Delete: function () { + var self = this; + self.Toolbar.ConfirmModal.Confirm('Are you sure want to delete selected items?', function () { + var countDeleted = 0; + self.Toolbar.WebDAV.AllowReloadGrid = false; + $.each(self.Toolbar.FolderGrid.selectedItems, function (index) { + self.Toolbar.FolderGrid.selectedItems[index].DeleteAsync(null, function () { + if (++countDeleted == self.Toolbar.FolderGrid.selectedItems.length) { + self.Toolbar.WebDAV.AllowReloadGrid = true; + self.Toolbar.WebDAV.Reload(); + self.Toolbar.ResetToolbar(); + } + }); + }); + }); + } +} + +function ToolbarDeleteButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + this.InnerHtmlContent = 'Delete'; + + this.Render = function () { + this.$Button.on('click', function () { + new HerarhyItemDeleteController(toolbar).Delete(); + }) + } +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js new file mode 100644 index 0000000..580a9c1 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-downloadbutton.js @@ -0,0 +1,43 @@ +function HerarhyItemDownloadController(toolbar) { + this.Toolbar = toolbar; +} + +HerarhyItemDownloadController.prototype = { + DownloadFiles: function () { + var self = this; + $.each(self.Toolbar.FolderGrid.selectedItems, function (index) { + if (!this.IsFolder()) { + self._Delay(index * 1000); + self._Download(this.Href + "?download", ''); + } + }); + }, + _Download: function (url, name) { + const a = document.createElement('a'); + a.download = name; + a.href = url; + a.style.display = 'none'; + document.body.append(a); + a.click(); + + // Chrome requires the timeout + this._Delay(100); + a.remove(); + }, + _Delay: function () { + return ms => new Promise(resolve => setTimeout(resolve, ms)); + } +} + + + +function ToolbarDownloadButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + this.InnerHtmlContent = 'Download'; + + this.Render = function () { + this.$Button.on('click', function () { + new HerarhyItemDownloadController(toolbar).DownloadFiles(); + }) + } +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js new file mode 100644 index 0000000..7b327ac --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-printbutton.js @@ -0,0 +1,39 @@ +function HerarhyItemPrintController(toolbar) { + this.Toolbar = toolbar; +} + +HerarhyItemPrintController.prototype = { + /** + * Print documents. + * @param {string} sDocumentUrls Array of document URLs + */ + PrintDocs: function (sDocumentUrls) { + ITHit.WebDAV.Client.DocManager.DavProtocolEditDocument(sDocumentUrls, this.Toolbar.WebDAV.GetMountUrl(), + this.Toolbar.WebDAV._ProtocolInstallMessage.bind(this.Toolbar.WebDAV), null, webDavSettings.EditDocAuth.SearchIn, + webDavSettings.EditDocAuth.CookieNames, webDavSettings.EditDocAuth.LoginUrl, 'Print'); + }, + ExecutePrint: function () { + self = this; + self.Toolbar.ConfirmModal.Confirm('Are you sure want to print selected items?', function () { + var filesUrls = []; + $.each(self.Toolbar.FolderGrid.selectedItems, function () { + if (!this.IsFolder()) { + filesUrls.push(this.Href); + } + }); + + self.PrintDocs(filesUrls); + }); + } +} + +function ToolbarPrintButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + this.InnerHtmlContent = 'Print'; + + this.Render = function () { + this.$Button.on('click', function () { + new HerarhyItemPrintController(toolbar).ExecutePrint(); + }) + } +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js new file mode 100644 index 0000000..ec3e001 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-reloadbutton.js @@ -0,0 +1,9 @@ +function ToolbarReloadButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + + this.Render = function () { + this.$Button.on('click', function () { + toolbar.WebDAV.Reload(); + }) + } +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js new file mode 100644 index 0000000..db711d5 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-renamebutton.js @@ -0,0 +1,84 @@ +const sRenameItemErrorMessage = "Rename item error."; +const sRenameItemLockedErrorMessage = "Item is locked."; + +function RenameItemController(toolbar) { + this.Toolbar = toolbar; +} + +RenameItemController.prototype = { + /** + * Renames files or folders. + */ + Rename: function (newItemName, fCallback) { + this.Toolbar.FolderGrid.selectedItems[0].MoveToAsync(this.Toolbar.WebDAV.CurrentFolder, + newItemName, null, null, function (oAsyncResult) { + fCallback(oAsyncResult); + }); + }, +} + +/////////////////// +// Create Folder Bootstrap Modal +function RenameItemModal(modalSelector, renameItemController) { + + var self = this; + this.$modal = $(modalSelector); + this.$txt = $(modalSelector).find('input[type="text"]'); + this.$submitButton = $(modalSelector).find('.btn-submit'); + this.$alert = $(modalSelector).find('.alert-danger'); + this.oldItemName = ""; + + this.$modal.on('shown.bs.modal', function () { + self.$txt.focus(); + }) + this.$modal.find('form').submit(function () { + self.$alert.addClass('d-none'); + if (self.$txt.val() == self.oldItemName) { + self.$modal.modal('hide'); + } + else if (self.$txt.val() !== null && self.$txt.val().match(/^ *$/) === null) { + var oValidationMessage = WebdavCommon.Validators.ValidateName(self.$txt.val()); + if (oValidationMessage) { + self.$alert.removeClass('d-none').text(oValidationMessage); + return false; + } + + self.$txt.blur(); + self.$submitButton.attr('disabled', 'disabled'); + renameItemController.Rename(self.$txt.val().trim(), function (oAsyncResult) { + if (!oAsyncResult.IsSuccess) { + if (oAsyncResult.Error instanceof ITHit.WebDAV.Client.Exceptions.LockedException) { + WebdavCommon.ErrorModal.Show(sRenameItemLockedErrorMessage, oAsyncResult.Error); + } + else { + WebdavCommon.ErrorModal.Show(sRenameItemErrorMessage, oAsyncResult.Error); + } + } + self.$modal.modal('hide'); + self.$submitButton.removeAttr('disabled'); + renameItemController.Toolbar.ResetToolbar(); + self.$txt.val(''); + }); + } + else { + self.$alert.removeClass('d-none').text('Name is required!'); + } + return false; + }); + +} + +function ToolbarRenameButton(name, cssClass, toolbar) { + BaseButton.call(this, name, cssClass); + var oRenameItemModal = new RenameItemModal('#RenameItemModal', new RenameItemController(toolbar)); + this.Render = function () { + this.$Button.on('click', function () { + if (toolbar.FolderGrid.selectedItems.length) { + oRenameItemModal.$txt.val(toolbar.FolderGrid.selectedItems[0].DisplayName); + oRenameItemModal.oldItemName = toolbar.FolderGrid.selectedItems[0].DisplayName; + } + oRenameItemModal.$alert.addClass('d-none'); + oRenameItemModal.$modal.modal('show'); + }) + } +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js new file mode 100644 index 0000000..66596f6 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/toolbar/webdav-toolbar.js @@ -0,0 +1,141 @@ + function Toolbar(selectorTableToolbar, folderGrid, confirmModal, webDAVController) { + this.ToolbarName = selectorTableToolbar; + this.$Toolbar = $(selectorTableToolbar); + this.FolderGrid = folderGrid; + this.ConfirmModal = confirmModal; + this.WebDAV = webDAVController; + this.buttons = []; + + var self = this; + + if (typeof ToolbarCreateFolderButton === "function") { + var createFolderButton = new ToolbarCreateFolderButton('Create Folder', 'btn-create-folder', this); + this.buttons.push(createFolderButton); + createFolderButton.Create($(self.$Toolbar).find(".first-section")); + } + + if (typeof ToolbarDownloadButton == "function") { + var downloadButton = new ToolbarDownloadButton('Dwonload', 'btn-download-items', this); + this.buttons.push(downloadButton); + downloadButton.Create($(self.$Toolbar).find(".second-section")); + } + + if (typeof ToolbarRenameButton == "function") { + var renameButton = new ToolbarRenameButton('Rename', 'btn-rename-item', this); + this.buttons.push(renameButton); + renameButton.Create($(self.$Toolbar).find(".third-section")); + } + + if (typeof CopyPasteButtonsControl === "function") { + var copyPasteButtons = new CopyPasteButtonsControl(this) + this.buttons.push(copyPasteButtons) + copyPasteButtons.Create($(self.$Toolbar).find(".fourth-section")); + } + + if (typeof ToolbarReloadButton == "function") { + var reloadButton = new ToolbarReloadButton('Reload', 'btn-reload-items', this); + this.buttons.push(reloadButton); + reloadButton.Create($(self.$Toolbar).find(".fifth-section")); + } + + if (typeof ToolbarPrintButton === "function") { + var printButton = new ToolbarPrintButton('Print', 'btn-print-items', this) + this.buttons.push(printButton); + printButton.Create($(self.$Toolbar).find(".sixth-section")); + } + + if (typeof ToolbarDeleteButton === "function") { + var deleteButton = new ToolbarDeleteButton('Delete', 'btn-delete-items', this) + this.buttons.push(deleteButton); + deleteButton.Create($(self.$Toolbar).find(".sixth-section")); + } + + $.each(self.buttons, function (index) { + this.Render(); + }); + + this.UpdateToolbarButtons(); + } + +Toolbar.prototype = { + UpdateToolbarButtons: function () { + var self = this; + + $.each(self.buttons, function (index) { + if (typeof ToolbarCreateFolderButton === "function" && this instanceof ToolbarCreateFolderButton) { + self.FolderGrid.selectedItems.length == 0 ? this.ShowOnMobile() : this.HideOnMobile(); + } + if (typeof ToolbarDeleteButton === "function" && this instanceof ToolbarDeleteButton) { + if (self.FolderGrid.selectedItems.length == 0) { + this.Disable(); + this.HideOnMobile(); + } + else { + this.Activate(); + this.ShowOnMobile(); + } + } + if (typeof ToolbarRenameButton === "function" && this instanceof ToolbarRenameButton) { + if (self.FolderGrid.selectedItems.length == 0 || + self.FolderGrid.selectedItems.length != 1) { + this.Disable(); + this.HideOnMobile(); + } + else { + this.Activate(); + this.ShowOnMobile(); + } + } + if (typeof ToolbarDownloadButton === "function" && this instanceof ToolbarDownloadButton) { + if (self.FolderGrid.selectedItems.length == 0 || !self.FolderGrid.selectedItems.some(el => !el.IsFolder())) { + this.Disable(); + this.HideOnMobile(); + } + else { + this.Activate(); + this.ShowOnMobile(); + } + } + if (typeof CopyPasteButtonsControl === "function" && this instanceof CopyPasteButtonsControl) { + if (self.FolderGrid.selectedItems.length == 0) { + this.CopyButton.Disable(); + this.CopyButton.HideOnMobile(); + + this.CutButton.Disable(); + this.CutButton.HideOnMobile(); + } + else { + this.CopyButton.Activate(); + this.CopyButton.ShowOnMobile(); + + this.CutButton.Activate(); + this.CutButton.ShowOnMobile(); + } + + if (this.storedItems.length == 0) { + this.PasteButton.Disable(); + this.PasteButton.HideOnMobile(); + } + else { + this.PasteButton.Activate(); + this.PasteButton.ShowOnMobile(); + } + } + if (ITHit.Environment.OS == 'Windows' && typeof ToolbarPrintButton === "function" && this instanceof ToolbarPrintButton) { + if (self.FolderGrid.selectedItems.filter(function (item) { return !item.IsFolder(); }).length == 0) { + this.Disable(); + this.HideOnMobile(); + } + else { + this.Activate(); + this.ShowOnMobile(); + } + } + }); + }, + + ResetToolbar: function () { + this.FolderGrid.UncheckTableCheckboxs(); + this.UpdateToolbarButtons(); + } +} \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js new file mode 100644 index 0000000..eac3835 --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-common.js @@ -0,0 +1,227 @@ + +/** + * @namespace WebdavCommon + */ +window.WebdavCommon = (function () { + var sGSuitePreviewErrorMessage = "Preview document with G Suite Online Tool error."; + var sGSuiteEditErrorMessage = "Edit document with G Suite Online Editor error."; + var sFileNameSpecialCharactersRestrictionFormat = "The name cannot contain any of the following characters: {0}"; + var sForbiddenNameChars = '\/:*?"<>|'; + + var ns = {}; + + /**@class Formatters + * @memberof! WebdavCommon + */ + var Formatters = ns.Formatters = { + + /** + * + * @param {number} iSize + * @returns {string} + */ + FileSize: function (iSize) { + if (!iSize) { + return '0.00 B'; + } + var i = Math.floor(Math.log(iSize) / Math.log(1024)); + return (iSize / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; + }, + + /** + * + * @param {Date} oDate + * @returns {string} + */ + Date: function (oDate) { + return moment(oDate).fromNow(); + }, + + + /** + * + * @param {string} html + * @returns {string} + */ + Snippet: function (html) { + if (html) { + var safePrefix = '__b__tag' + (new Date()).getTime(); + html = html.replace(//g, safePrefix + '_0').replace(/<\/b>/g, safePrefix + '_1'); + html = $('
      ').text(html).text(); + html = html.replace(new RegExp(safePrefix + '_0', 'g'), ''). + replace(new RegExp(safePrefix + '_1', 'g'), ''); + } + return $('
      ').addClass('snippet').html(html); + }, + + /** + * + * @param {string} fileName + * @returns {string} + */ + GetFileExtension: function (fileName) { + var index = fileName.lastIndexOf('.'); + return index !== -1 ? fileName.substr(index + 1).toLowerCase() : ''; + }, + + /** + * + * @param {string} fileName + * @returns {string} + */ + GetFileNameWithoutExtension: function (fileName) { + var index = fileName.lastIndexOf('.'); + return index !== -1 ? fileName.slice(0, index) : ''; + }, + + /** + * + * @param {number} iSeconds + * @returns {string} + */ + TimeSpan: function (iSeconds) { + var hours = Math.floor(iSeconds / 3600); + var minutes = Math.floor((iSeconds - hours * 3600) / 60); + var seconds = iSeconds - (hours * 3600) - (minutes * 60) + var sResult = ''; + if (hours) sResult += hours + 'h '; + if (minutes) sResult += minutes + 'm '; + sResult += seconds + 's '; + return sResult; + }, + /** + * Converts a string to an HTML-encoded string. + * @param {string} sText - The string to encode. + * @return {string} - An encoded string. + */ + HtmlEscape: function(sText) { + return String(sText) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + }; + + /** + * This class represents error that occured on client. + * @class ClientError + * @memberof! WebdavCommon + * @param {string} sMessage - The message will be displayed as error's short description. + * @param {string} sUri - This url will be displayed as item's URL caused error. + * @property {string} Message + * @property {string} Uri + */ + var ClientError = ns.ClientError = function ClientError(sMessage, sUri) { + this.Message = sMessage; + this.Uri = sUri; + }; + + /**@class Validators + * @memberof! WebdavCommon + */ + ns.Validators = /** @leads Validators */ { + + /** + * @param {string} sName - The name to check. + * @memberof Validators. + * @returns {undefined | string} - Undefined if item valid or error string. + */ + ValidateName: function(sName) { + var oRegExp = new RegExp('[' + sForbiddenNameChars + ']', 'g'); + if(oRegExp.test(sName)) { + var sMessage = WebdavCommon.PasteFormat(sFileNameSpecialCharactersRestrictionFormat, + sForbiddenNameChars.replace(/\\?(.)/g, '$1 ')); + return sMessage; + } + } + }; + + ns.PasteFormat = function pasteFormat(sPhrase) { + var callbackReplace = function(oArguments) { + this._arguments = oArguments; + }; + + callbackReplace.prototype.Replace = function(sPlaceholder) { + + var iIndex = sPlaceholder.substr(1, sPlaceholder.length - 2); + return ('undefined' !== typeof this._arguments[iIndex]) ? this._arguments[iIndex] : sPlaceholder; + }; + + if(/\{\d+?\}/.test(sPhrase)) { + var oReplace = new callbackReplace(Array.prototype.slice.call(arguments, 1)); + sPhrase = sPhrase.replace(/\{(\d+?)\}/g, function(args) { return oReplace.Replace(args); }); + } + + return sPhrase; + }; + + /** + * This class provides method for display error modal window. + * @param {string} selector - The selector of root element of modal window markup. + * @class ErrorModal + * @memberof! WebdavCommon + */ + function ErrorModal(selector) { + this.$el = $(selector); + this.$el.on('hidden.bs.modal', this._onModalHideHandler.bind(this)); + }; + + /**@lends ErrorModal.prototype */ + ErrorModal.prototype = { + + /** + * Shows modal window with message and error details. + * @method + * @param {string} sMessage - The error message. + * @param {ITHit.WebDAV.Client.Exceptions.WebDavHttpException | ClientError} oError - The error object to display. + * @param {function()} [fCallback] - The callback to be called on close. + */ + Show: function (sMessage, oError, fCallback) { + this._closeCallback = fCallback || $.noop; + this._SetErrorMessage(sMessage); + this._SetUrl(oError.Uri); + this._SetMessage(oError.Message); + + if (oError.Error) { + this._SetBody(oError.Error.Description || oError.Error.BodyText); + } else if (oError.InnerException) { + this._SetBody(oError.InnerException.toString()); + } + + this.$el.modal('show'); + }, + + _SetErrorMessage: function (sMessage) { + this.$el.find('.error-message').html(sMessage); + }, + + _SetUrl: function (sUrl) { + this.$el.find('.error-details-url').html(Formatters.HtmlEscape(sUrl)); + }, + + _SetMessage: function (sMessage) { + sMessage = Formatters.HtmlEscape(sMessage); + sMessage = String(sMessage).replace(/\n/g, '
      \n').replace(/\t/g, '    '); + this.$el.find('.error-details-message').html(sMessage); + }, + + _SetBody: function (sMessage) { + var iframe = this.$el.find('iframe')[0]; + var doc = iframe.contentDocument || iframe.contentWindow.document; + + // FireFox fix, trigger a page `load` + doc.open(); + doc.close(); + + doc.body.innerHTML = sMessage; + }, + _onModalHideHandler: function () { + this._closeCallback(); + } + }; + + ns.ErrorModal = new ErrorModal('#ErrorModal'); + return ns; +})(); \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js new file mode 100644 index 0000000..0ce487b --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-gridview.js @@ -0,0 +1,1132 @@ + +(function (WebdavCommon) { + var sSearchErrorMessage = "Search is not supported."; + var sSupportedFeaturesErrorMessage = "Supported Features error."; + var sProfindErrorMessage = "PROPFIND request error."; + + + /////////////////// + // Folder Grid View + var FolderGridView = function (selectorTableContainer, selectorTableToolbar) { + var self = this; + this.$el = $(selectorTableContainer); + this.selectedItems = []; + + //Copied or cut items + this.storedItems = []; + this.isCopiedItems = false; + this.selectedItem = null; + this.activeSelectedTab = 'preview'; + this.isSearchMode = false; + this._defaultEditor = 'OSEditor'; + + this.$el.on({ + mouseenter: function () { + if ($(this).hasClass('tr-snippet-url')) + $(this).addClass('hover').prev().addClass('hover'); + else + $(this).addClass('hover').next().addClass('hover'); + }, + mouseleave: function () { + if ($(this).hasClass('tr-snippet-url')) + $(this).removeClass('hover').prev().removeClass('hover'); + else + $(this).removeClass('hover').next().removeClass('hover'); + } + }, 'tr'); + + this.$el.find('th input[type="checkbox"]').change(function () { + self.selectedItems = []; + if ($(this).is(':checked')) { + self.$el.find('td input[type="checkbox"]').prop('checked', true).change(); + } + else { + oToolbar.ResetToolbar(); + self.$el.find('td input[type="checkbox"]').prop('checked', false); + } + }); + + // set timer for updating Modified field + setInterval(function () { + self.$el.find('td.modified-date').each(function () { + $(this).text(WebdavCommon.Formatters.Date($(this).data('modified-date'))); + }); + }, 3000); + }; + FolderGridView.prototype = { + Render: function (aItems, bisSearchMode) { + var self = this; + this.isSearchMode = bisSearchMode || false; + + this.$el.find('tbody').html( + aItems.map(function (oItem) { + var locked = oItem.ActiveLocks.length > 0 + ? ('' + + (oItem.ActiveLocks[0].LockScope === 'Shared' ? ('' + oItem.ActiveLocks.length + '') : '')) + : ''; + /** @type {ITHit.WebDAV.Client.HierarchyItem} oItem */ + var $customCheckbox = $(''); + $customCheckbox.find('input').on('change', function () { + if ($(this).is(':checked')) { + self._AddSelectedItem(oItem); + } + else { + self._RemoveSelectedItem(oItem); + } + }).attr('checked', this._IsSelectedItem(oItem)); + + return $('
      ').html([ + $('').html([ + $('').html([ + $customCheckbox + ]), + $(''). + html(oItem.IsFolder() ? ('' + locked + '') : locked), + this._RenderDisplayName(oItem), + $('').text(oItem.IsFolder() ? 'Folder' : ('File ' + WebdavCommon.Formatters.GetFileExtension(oItem.DisplayName))), + $(''). + text(!oItem.IsFolder() ? WebdavCommon.Formatters.FileSize(oItem.ContentLength) : ''). + css('text-align', 'right'), + $('').text(WebdavCommon.Formatters.Date(oItem.LastModified)).data('modified-date', oItem.LastModified), + $('').html(this._RenderActions(oItem)) + ]).on('click', function (e) { + // enable GSuite preview and edit only for files + if (!oItem.IsFolder() && !$(this).hasClass('active') && + ((e.target.nodeName.toLowerCase() === 'td' && !$(e.target).hasClass('select-disabled')) || + (e.target.nodeName.toLowerCase() !== 'td' && !$(e.target).parents('td').hasClass('select-disabled')))) { + $(this).addClass('active').siblings().removeClass('active'); + self.selectedItem = oItem; + + // render GSuite Editor + WebdavCommon.GSuiteEditor.Render(oItem); + } + }).addClass(self.selectedItem != null && oItem.Href == self.selectedItem.Href ? 'active' : ''), + $('').html([ + $(''), + $(''), + this._RenderSnippetAndUrl(oItem)])]).children(); + }.bind(this)) + ); + }, + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + **/ + _RenderLokedIconTooltip(oItem) { + var tooltipTitle = 'Exclusive lock: ' + oItem.ActiveLocks[0].Owner; + if (oItem.ActiveLocks[0].LockScope === 'Shared') { + var userNames = []; + tooltipTitle = 'Shared lock' + (oItem.ActiveLocks.length > 1 ? '(s)':'') + ': '; + for (var i = 0; i < oItem.ActiveLocks.length; i++) { + userNames.push(oItem.ActiveLocks[i].Owner); + } + tooltipTitle += userNames.join(', '); + } + return tooltipTitle; + }, + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + **/ + _RenderDisplayName: function (oItem) { + var oElement = oItem.IsFolder() ? + $('').html($('').text(oItem.DisplayName).attr('href', oItem.Href)) : + $('').html($('').text(oItem.DisplayName)); + + return oElement; + }, + + _RenderSnippetAndUrl: function (oItem) { + var oElement = $(''); + // Append path on search mode + if (this.isSearchMode) { + new BreadcrumbsView($('
        ').addClass('breadcrumb').appendTo(oElement)).SetHierarchyItem(oItem); + + // Append snippet to name + oElement.append(WebdavCommon.Formatters.Snippet(oItem.Properties.Find(oWebDAV.SnippetPropertyName))); + } + + return oElement; + }, + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + * @returns string + **/ + _RenderActions: function (oItem) { + var self = this; + var actions = []; + var isDavProtocolSupported = ITHit.WebDAV.Client.DocManager.IsDavProtocolSupported(); + var isMicrosoftOfficeDocument = ITHit.WebDAV.Client.DocManager.IsMicrosoftOfficeDocument(oItem.Href); + var isGSuiteDocument = ITHit.WebDAV.Client.DocManager.IsGSuiteDocument(oItem.Href); + + if (oItem.IsFolder()) { + actions.push($('') + .appendTo($btnGroup).on('click', function () { + var $radio = $(this).parent().find('input[type=radio]:checked'); + if ($radio.length) { + $radio.parent().next().click(); + } + else { + oWebDAV.EditDoc(oItem.Href); + } + }).prop("disabled", !isDavProtocolSupported && !isMicrosoftOfficeDocument); + + var $dropdownToggle = $('') + .appendTo($btnGroup).prop("disabled", !isDavProtocolSupported && !isMicrosoftOfficeDocument); + + this._RenderContextMenu(oItem, $btnGroup, isMicrosoftOfficeDocument, isGSuiteDocument, isDavProtocolSupported, isExclusiveLocked); + + $btnGroup.on('shown.bs.dropdown', function () { + self.ContextMenuID = oItem.Href; + }); + + $btnGroup.on('hidden.bs.dropdown', function () { + self.ContextMenuID = null; + }); + + // open context menu if it was open before update + if (self.ContextMenuID && self.ContextMenuID == oItem.Href) { + $dropdownToggle.dropdown('toggle'); + } + + actions.push($btnGroup); + } + + return actions; + }, + + _GetActionGroupBtnTooltipText: function () { + var tooltipText = 'Edit document with desktop associated application.'; + switch (this._defaultEditor) { + case 'OSEditor': + tooltipText = 'Edit with Microsoft Office Desktop.'; + break; + case 'GSuiteEditor': + tooltipText = 'Edit document in G Suite Editor.'; + break; + } + return tooltipText; + }, + + _GetDisabledGroupBtnAttribute: function (isExclusiveLocked) { + var attribute = ''; + if (this._defaultEditor == 'GSuiteEditor' && isExclusiveLocked) { + attribute = ' disabled="disabled"'; + } + return attribute; + }, + + _GetActionGroupBtnCssClass: function () { + var cssClassName = 'icon-edit'; + switch (this._defaultEditor) { + case 'OSEditor': + cssClassName = 'icon-microsoft-edit'; + break; + case 'GSuiteEditor': + cssClassName = 'icon-gsuite-edit'; + break; + } + + return cssClassName; + }, + + _RenderContextMenu: function (oItem, $btnGroup, isMicrosoftOfficeDocument, isGSuiteDocument, isDavProtocolSupported, isExclusiveLocked) { + var self = this; + var supportGSuiteFeature = oWebDAV.OptionsInfo.Features & ITHit.WebDAV.Client.Features.GSuite; + var displayRadioBtns = (isMicrosoftOfficeDocument && isGSuiteDocument); + var $dropdownMenu = $('').appendTo($btnGroup); + if (isMicrosoftOfficeDocument) { + if (displayRadioBtns) { + $('').appendTo($dropdownMenu).find('input[type=radio]').change(function () { self._ChangeContextMenuRadionBtnHandler($(this)); }); + } + $('Edit with Microsoft Office Desktop') + .appendTo($dropdownMenu).on('click', function () { + oWebDAV.EditDoc(oItem.Href); + }); + } + if (!isMicrosoftOfficeDocument) { + $('Edit with Associated Desktop Application') + .appendTo($dropdownMenu).on('click', function () { + oWebDAV.EditDoc(oItem.Href); + }); + } + + $('').appendTo($dropdownMenu); + $('Select Desktop Application') + .appendTo($dropdownMenu).on('click', function () { + oWebDAV.OpenDocWith(oItem.Href); + }); + }, + + _GetContextMenuRadioBtnCheckedProperty: function (editorName) { + return this._defaultEditor == editorName ? 'checked="checked"' : ''; + }, + + _ChangeContextMenuRadionBtnHandler: function ($radioBtn) { + var self = this; + var iconClassName = $radioBtn.parent().next().find('i:first').attr('class'); + + this._defaultEditor = $radioBtn.val(); + $('input[value="' + self._defaultEditor + '"]').prop('checked', true); + + // update button icon + $('.btn-default-edit').each(function () { + var $btn = $(this); + if ($btn.parent().find('.actions input[type=radio]').length) { + $btn.find('i:first').attr('class', iconClassName); + } + $btn.attr('title', self._GetActionGroupBtnTooltipText()); + }); + }, + + _AddSelectedItem: function (oItem) { + this.selectedItems.push(oItem); + oToolbar.UpdateToolbarButtons(); + }, + + _RemoveSelectedItem: function (oItem) { + var self = this; + $.each(this.selectedItems, function (index) { + if (self.selectedItems[index].Href === oItem.Href) { + self.selectedItems.splice(index, 1); + return false; + } + }); + + oToolbar.UpdateToolbarButtons(); + }, + + _IsSelectedItem: function (oItem) { + var self = this; + var isSelected = false; + $.each(this.selectedItems, function (index) { + if (self.selectedItems[index].Href === oItem.Href) { + isSelected = true; + return false; + } + }); + return isSelected; + }, + + UncheckTableCheckboxs: function () { + this.selectedItems = []; + this.$el.find('input[type="checkbox"]').prop('checked', false); + }, + }; + + + /////////////////// + // Search Form View + var SearchFormView = function (selector) { + this.$el = $(selector); + this.Init(); + }; + SearchFormView.prototype = { + + Init: function () { + this.$el.find('button').on('click', this._OnSubmit.bind(this)); + this.$el.find('input').typeahead({}, + { + name: 'states', + display: 'DisplayName', + limit: 6, + templates: { + suggestion: this._RenderSuggestion.bind(this) + }, + async: true, + source: this._Source.bind(this) + } + ).on('keyup', this._OnKeyUp.bind(this)).on('typeahead:select', this._OnSelect.bind(this)); + }, + + SetDisabled: function (bIsDisabled) { + this.$el.find('button').prop('disabled', bIsDisabled); + this.$el.find('input'). + prop('disabled', bIsDisabled). + attr('placeholder', !bIsDisabled ? '' : 'The server does not support search'); + }, + + GetValue: function () { + return this.$el.find('input.tt-input').val(); + }, + + LoadFromHash: function () { + this.$el.find('input.tt-input').val(oWebDAV.GetHashValue('search')); + this._RenderFolderGrid(oWebDAV.GetHashValue('search'), oWebDAV.GetHashValue('page')); + }, + + _Source: function (sPhrase, c, fCallback) { + oWebDAV.NavigateSearch(sPhrase, false, 1, false, true, function (oResult) { + if (oResult.IsSuccess) { + fCallback(oResult.Result.Page); + } else { + WebdavCommon.ErrorModal.Show(sSearchErrorMessage, oResult.Error); + } + }); + }, + + _OnKeyUp: function (oEvent) { + if (oEvent.keyCode === 13) { + this._RenderFolderGrid(oSearchForm.GetValue(), 1); + this.$el.find('input').typeahead('close'); + this._HideKeyboard(this.$el.find('input')); + } + }, + + _OnSelect: function (oEvent, oItem) { + oFolderGrid.Render([oItem], true); + oPagination.Hide(); + }, + + _OnSubmit: function () { + this._RenderFolderGrid(oSearchForm.GetValue(), 1); + }, + + _RenderFolderGrid: function (oSearchQuery, nPageNumber) { + var oSearchFormView = this; + oWebDAV.NavigateSearch(oSearchForm.GetValue(), false, nPageNumber, true, true, function (oResult) { + oFolderGrid.Render(oResult.Result.Page, true); + oPagination.Render(nPageNumber, Math.ceil(oResult.Result.TotalItems / oWebDAV.PageSize), function (pageNumber) { + oSearchFormView._RenderFolderGrid(oSearchQuery, pageNumber); + }); + + if (oResult.Result.Page.length == 0 && nPageNumber != 1) { + oSearchFormView._RenderFolderGrid(oSearchQuery, 1); + } + }); + }, + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + **/ + _RenderSuggestion: function (oItem) { + var oElement = $('
        ').text(oItem.DisplayName); + + // Append path + new BreadcrumbsView($('
          ').addClass('breadcrumb').appendTo(oElement)).SetHierarchyItem(oItem); + + // Append snippet + oElement.append(WebdavCommon.Formatters.Snippet(oItem.Properties.Find(oWebDAV.SnippetPropertyName))); + + return oElement; + }, + + /** + * @param {JQuery obeject} element + **/ + _HideKeyboard: function (element) { + element.attr('readonly', 'readonly'); // Force keyboard to hide on input field. + element.attr('disabled', 'true'); // Force keyboard to hide on textarea field. + setTimeout(function () { + element.blur(); //actually close the keyboard + // Remove readonly attribute after keyboard is hidden. + element.removeAttr('readonly'); + element.removeAttr('disabled'); + }, 100); + } + + }; + + /////////////////// + // Breadcrumbs View + var BreadcrumbsView = function (selector, upOneLevelBtn) { + this.$el = $(selector); + this.$upOneLevelBtn = $(upOneLevelBtn); + }; + BreadcrumbsView.prototype = { + + /** + * @param {ITHit.WebDAV.Client.HierarchyItem} oItem + */ + SetHierarchyItem: function (oItem) { + var aParts = oItem.Href + .split('/') + .slice(2) + .filter(function (v) { + return v; + }); + + this.$el.html(aParts.map(function (sPart, i) { + var bIsLast = aParts.length === i + 1; + var oLabel = i === 0 ? $('').addClass('icon-home') : $('').text(decodeURIComponent(sPart)); + return $('
        1. ').addClass('page-item ' + (pageNumber == 1 ? 'disabled' : '')).appendTo(this.$el)).text('<<').click(function () { + if (pageNumber != 1) + changePageCallback(pageNumber - 1); + return false; + }); + + // render pages + var firstPage = countPages > this.maxItems && (pageNumber - Math.floor(this.maxItems / 2)) > 0 ? (pageNumber - Math.floor(this.maxItems / 2)) : 1; + var lastPage = (firstPage + this.maxItems - 1) <= countPages ? (firstPage + this.maxItems - 1) : countPages; + + if (countPages > this.maxItems && lastPage - firstPage < this.maxItems) { + firstPage = lastPage - this.maxItems + 1; + } + + if (firstPage > 1 && countPages > this.maxItems) { + $('').addClass('page-link').data('page-number', 1).appendTo($('
        2. ').addClass('page-item ' + (1 == pageNumber ? 'active' : '')).appendTo(this.$el)).text(1).click(function () { + if (pageNumber != $(this).data('page-number')) { + changePageCallback($(this).data('page-number')); + } + return false; + }); + if (firstPage - 1 > 1) { + $('').addClass('page-link').data('page-number', i).appendTo($('
        3. ').addClass('page-item disabled').appendTo(this.$el)).text('...'); + } + } + + for (var i = firstPage; i <= lastPage; i++) { + $('').addClass('page-link').data('page-number', i).appendTo($('
        4. ').addClass('page-item ' + (i == pageNumber ? 'active' : '')).appendTo(this.$el)).text(i).click(function () { + if (pageNumber != $(this).data('page-number')) { + changePageCallback($(this).data('page-number')); + } + return false; + }); + } + + if (lastPage != countPages && countPages > this.maxItems) { + if (lastPage != countPages - 1) { + $('').addClass('page-link').data('page-number', i).appendTo($('
        5. ').addClass('page-item disabled').appendTo(this.$el)).text('...'); + } + $('').addClass('page-link').data('page-number', countPages).appendTo($('
        6. ').addClass('page-item ' + (countPages == pageNumber ? 'active' : '')).appendTo(this.$el)).text(countPages).click(function () { + if (pageNumber != $(this).data('page-number')) + changePageCallback($(this).data('page-number')); + return false; + }); + } + + // render Next link + $('').addClass('page-link').appendTo($('
        7. ').addClass('page-item ' + (countPages == pageNumber ? 'disabled' : '')).appendTo(this.$el)).text('>>').click(function () { + if (pageNumber != countPages) + changePageCallback(pageNumber + 1); + return false; + }); + } + }, + + Hide: function () { + this.$el.empty(); + } + } + + /////////////////// + // Table sorting View + var TableSortingView = function (selector) { + this.$headerCols = $(selector); + this.Init(); + }; + TableSortingView.prototype = { + Init: function () { + var $cols = this.$headerCols; + $cols.click(function () { + var className = 'ascending' + if ($(this).hasClass('ascending')) { + className = 'descending'; + } + + oWebDAV.Sort($(this).data('sort-column'), className == 'ascending'); + }) + }, + + Set: function (sortColumn, sortAscending) { + var $col = this.$headerCols.filter('[data-sort-column="' + sortColumn + '"]'); + this.$headerCols.removeClass('ascending descending'); + if (sortAscending) { + $col.removeClass('descending').addClass('ascending'); + } else { + $col.removeClass('ascending').addClass('descending'); + } + }, + + Disable: function () { + this.$headerCols.addClass('disabled'); + }, + + Enable: function () { + this.$headerCols.removeClass('disabled'); + } + } + + ///////////////////////// + // History Api Controller + var HistoryApiController = function (selector) { + this.$container = $(selector); + this.Init(); + }; + HistoryApiController.prototype = { + + Init: function () { + if (!this._IsBrowserSupport()) { + return; + } + + window.addEventListener('popstate', this._OnPopState.bind(this), false); + this.$container.on('click', this._OnLinkClick.bind(this)); + }, + + PushState: function () { + if (this._IsBrowserSupport()) { + history.pushState('', document.title, window.location.pathname + window.location.search); + } + }, + + _OnPopState: function (oEvent) { + if (oWebDAV.GetHashValue('search')) { + oSearchForm.LoadFromHash(); + } + else { + var sUrl = oEvent.state && oEvent.state.Url || window.location.href.split("#")[0]; + oWebDAV.NavigateFolder(sUrl, null, null, null, true); + } + }, + + _OnLinkClick: function (oEvent) { + var sUrl = $(oEvent.target).closest('a').attr('href'); + if (!sUrl) { + return; + } + + if (sUrl.indexOf((location.origin || window.location.href.split("#")[0].replace(location.pathname, ''))) !== 0) { + return; + } + + oEvent.preventDefault(); + + history.pushState({ Url: sUrl }, '', sUrl); + oWebDAV.NavigateFolder(sUrl, null, null, null, true); + }, + + _IsBrowserSupport: function () { + return !!(window.history && history.pushState); + } + + }; + + /////////////////// + // Confirm Bootstrap Modal + var ConfirmModal = function (selector) { + var self = this; + this.$el = $(selector); + this.$el.find('.btn-ok').click(function () { + if (self.successfulCallback) { + self.successfulCallback(); + } + self.$el.modal('hide'); + }); + } + ConfirmModal.prototype = { + Confirm: function (htmlMessage, successfulCallback, options) { + var $modalDialog = this.$el.find('.modal-dialog'); + this.successfulCallback = successfulCallback; + this.$el.find('.message').html(htmlMessage); + if (options && options.size == 'lg') + $modalDialog.removeClass('modal-sm').addClass('modal-lg'); + else + $modalDialog.removeClass('modal-lg').addClass('modal-sm'); + + this.$el.modal('show'); + } + } + + var WebDAVController = function () { + this.PageSize = 10; // set size items of page + this.CurrentFolder = null; + this.AllowReloadGrid = true; + this.WebDavSession = new ITHit.WebDAV.Client.WebDavSession(); + this.SnippetPropertyName = new ITHit.WebDAV.Client.PropertyName('snippet', 'ithit'); + }; + + WebDAVController.prototype = { + + Reload: function () { + if (this.CurrentFolder && this.AllowReloadGrid) { + if (this.GetHashValue('search')) { + oSearchForm.LoadFromHash(); + } + else { + this.NavigateFolder(this.CurrentFolder.Href); + } + } + }, + + NavigateFolder: function (sPath, pageNumber, sortColumn, sortAscending, resetSelectedItem, fCallback) { + var pageSize = this.PageSize, currentPageNumber = 1; + // add default sorting by file type + var sortColumns = [new ITHit.WebDAV.Client.OrderProperty(new ITHit.WebDAV.Client.PropertyName('is-directory', ITHit.WebDAV.Client.DavConstants.NamespaceUri), this.CurrentSortColumnAscending)]; + if (!sPath && this.CurrentFolder) { + sPath = this.CurrentFolder.Href; + } + + //set upload url for uploader control + if (typeof WebDAVUploaderGridView !== 'undefined') { + WebDAVUploaderGridView.SetUploadUrl(sPath); + } + + if (resetSelectedItem) { + oToolbar.ResetToolbar(); + } + + //Enable sorting + oTableSorting.Enable(); + if (sortColumn) { + this.CurrentSortColumn = sortColumn; + this.CurrentSortAscending = sortAscending; + this.SetHashValues([{ Name: 'sortcolumn', Value: sortColumn }, { Name: 'sortascending', Value: sortAscending.toString() }]); + } else if (this.GetHashValue('sortcolumn')) { + this.CurrentSortColumn = this.GetHashValue('sortcolumn'); + this.CurrentSortAscending = this.GetHashValue('sortascending') == 'true'; + oTableSorting.Set(this.CurrentSortColumn, this.CurrentSortAscending); + } else { + this.CurrentSortColumn = 'displayname'; + this.CurrentSortAscending = true; + oTableSorting.Set(this.CurrentSortColumn, this.CurrentSortAscending); + } + + // apply sorting by table column + if (this.CurrentSortColumn) { + sortColumns.push(new ITHit.WebDAV.Client.OrderProperty(new ITHit.WebDAV.Client.PropertyName(this.CurrentSortColumn, ITHit.WebDAV.Client.DavConstants.NamespaceUri), this.CurrentSortAscending)); + } + + // update page number + if (pageNumber) { + currentPageNumber = pageNumber; + } else if (this.GetHashValue('page')) { + currentPageNumber = parseInt(this.GetHashValue('page')); + } + + if (currentPageNumber != 1) { + this.SetHashValue('page', currentPageNumber); + } else { + this.SetHashValue('page', ''); + } + + this.WebDavSession.OpenFolderAsync(sPath, [], function (oResponse) { + var self = this; + if (oResponse.IsSuccess) { + self.CurrentFolder = oResponse.Result; + oBreadcrumbs.SetHierarchyItem(self.CurrentFolder); + + // Detect search support. If search is not supported - disable search field. + this.CurrentFolder.GetSupportedFeaturesAsync(function (oResult) { + /** @typedef {ITHit.WebDAV.Client.OptionsInfo} oOptionsInfo */ + + if (oResult.IsSuccess) { + self.OptionsInfo = oResult.Result; + oSearchForm.SetDisabled(!(self.OptionsInfo.Features & ITHit.WebDAV.Client.Features.Dasl)); + } else { + WebdavCommon.ErrorModal.Show(sSupportedFeaturesErrorMessage, oResult.Error); + } + }); + + this.CurrentFolder.GetPageAsync([], (currentPageNumber - 1) * pageSize, pageSize, sortColumns, function (oResult) { + /** @type {ITHit.WebDAV.Client.HierarchyItem[]} aItems */ + if (oResult.IsSuccess) { + var aItems = oResult.Result.Page; + var aCountPages = Math.ceil(oResult.Result.TotalItems / pageSize); + + oFolderGrid.Render(aItems, false); + oPagination.Render(currentPageNumber, aCountPages, function (pageNumber) { + oWebDAV.NavigateFolder(null, pageNumber, null, null, true); + }); + + if (aItems.length == 0 && pageNumber != 1) { + oWebDAV.NavigateFolder(null, 1, null, null, true); + } + + if (fCallback) + fCallback(aItems); + } else { + WebdavCommon.ErrorModal.Show(sProfindErrorMessage, oResult.Error); + } + }); + } else { + WebdavCommon.ErrorModal.Show(sProfindErrorMessage, oResponse.Error); + } + }.bind(this)); + }, + + NavigateSearch: function (sPhrase, bIsDynamic, pageNumber, updateUrlHash, resetSelectedItem, fCallback) { + var pageSize = this.PageSize, currentPageNumber = 1; + + if (!this.CurrentFolder) { + fCallback && fCallback({ Items: [], TotalItems: 0 }); + return; + } + + if (updateUrlHash) { + this.SetHashValue('search', sPhrase); + } + + if (sPhrase === '') { + this.Reload(); + return; + } + + if (resetSelectedItem) { + oToolbar.ResetToolbar(); + } + + // update page number + if (pageNumber) { + currentPageNumber = pageNumber; + } else if (this.GetHashValue('page')) { + currentPageNumber = parseInt(this.GetHashValue('page')); + } + + if (updateUrlHash && currentPageNumber != 1) { + this.SetHashValue('page', currentPageNumber); + } else { + this.SetHashValue('page', ''); + } + //Disable sorting + oTableSorting.Disable(); + + // The DASL search phrase can contain wildcard characters and escape according to DASL rules: + // ‘%’ – to indicate one or more character. + // ‘_’ – to indicate exactly one character. + // If ‘%’, ‘_’ or ‘\’ characters are used in search phrase they are escaped as ‘\%’, ‘\_’ and ‘\\’. + var searchQuery = new ITHit.WebDAV.Client.SearchQuery(); + searchQuery.Phrase = sPhrase.replace(/\\/g, '\\\\'). + replace(/\%/g, '\\%'). + replace(/\_/g, '\\_'). + replace(/\*/g, '%'). + replace(/\?/g, '_') + '%'; + searchQuery.EnableContains = !bIsDynamic; //Enable/disable search in file content. + + // Get following additional properties from server in search results: snippet - text around search phrase. + searchQuery.SelectProperties = [ + this.SnippetPropertyName + ]; + + function _getSearchPageByQuery() { + oWebDAV.CurrentFolder.GetSearchPageByQueryAsync(searchQuery, (currentPageNumber - 1) * pageSize, pageSize, function (oResult) { + /** @type {ITHit.WebDAV.Client.AsyncResult} oResult */ + /** @type {ITHit.WebDAV.Client.HierarchyItem[]} aItems */ + + if (oResult.IsSuccess) { + fCallback && fCallback(oResult); + } else { + WebdavCommon.ErrorModal.Show(sSearchErrorMessage, oResult.Error); + } + }); + } + + if (window.location.href.split("#")[0] != this.CurrentFolder.Href) { + this.WebDavSession.OpenFolderAsync(window.location.href.split("#")[0], [], function (oResponse) { + oWebDAV.CurrentFolder = oResponse.Result; + oBreadcrumbs.SetHierarchyItem(oWebDAV.CurrentFolder); + _getSearchPageByQuery(); + }); + } + else { + _getSearchPageByQuery(); + } + + + }, + + Sort: function (columnName, sortAscending) { + this.NavigateFolder(null, null, columnName, sortAscending, true); + }, + + /** + * Opens document for editing. + * @param {string} sDocumentUrl Must be full path including domain name: https://webdavserver.com/path/file.ext + */ + EditDoc: function (sDocumentUrl) { + if (['cookies', 'ms-ofba'].indexOf(webDavSettings.EditDocAuth.Authentication.toLowerCase()) != -1) { + if (webDavSettings.EditDocAuth.Authentication.toLowerCase() == 'ms-ofba' && + ITHit.WebDAV.Client.DocManager.IsMicrosoftOfficeDocument(sDocumentUrl)) { + ITHit.WebDAV.Client.DocManager.EditDocument(sDocumentUrl, this.GetMountUrl(), this._ProtocolInstallMessage.bind(this)); + } + else { + ITHit.WebDAV.Client.DocManager.DavProtocolEditDocument(sDocumentUrl, this.GetMountUrl(), this._ProtocolInstallMessage.bind(this), null, webDavSettings.EditDocAuth.SearchIn, + webDavSettings.EditDocAuth.CookieNames, webDavSettings.EditDocAuth.LoginUrl); + } + } + else { + ITHit.WebDAV.Client.DocManager.EditDocument(sDocumentUrl, this.GetMountUrl(), this._ProtocolInstallMessage.bind(this)); + } + }, + + /** + * Opens document for editing in online G Suite editor. + * @param {string} sDocumentUrl Must be full path including domain name: https://webdavserver.com/path/file.ext + * @param {DOM} gSuiteEditPanel html DOM element + * @param {function} [errorCallback] Function to call if document opening failed. + */ + GSuiteEditDoc: function (sDocumentUrl, gSuiteEditPanel, errorCallback) { + ITHit.WebDAV.Client.DocManager.GSuiteEditDocument(sDocumentUrl, gSuiteEditPanel, errorCallback); + }, + + /** + * Opens document for preview in online G Suite editor. + * @param {string} sDocumentUrl Must be full path including domain name: https://webdavserver.com/path/file.ext + * @param {DOM} gSuitePreviewPanel html DOM element + * @param {function} [errorCallback] Function to call if document opening failed. + */ + GSuitePreviewDoc: function (sDocumentUrl, gSuitePreviewPanel, errorCallback) { + ITHit.WebDAV.Client.DocManager.GSuitePreviewDocument(sDocumentUrl, gSuitePreviewPanel, errorCallback); + }, + + /** + * Opens document with. + * @param {string} sDocumentUrl Must be full path including domain name: https://webdavserver.com/path/file.ext + */ + OpenDocWith: function (sDocumentUrl) { + ITHit.WebDAV.Client.DocManager.DavProtocolEditDocument([sDocumentUrl], this.GetMountUrl(), this._ProtocolInstallMessage.bind(this), null, webDavSettings.EditDocAuth.SearchIn, + webDavSettings.EditDocAuth.CookieNames, webDavSettings.EditDocAuth.LoginUrl, 'OpenWith'); + }, + + /** + * Opens current folder in OS file manager. + */ + OpenCurrentFolderInOsFileManager: function () { + this.OpenFolderInOsFileManager(this.CurrentFolder.Href); + }, + + /** + * Opens folder in OS file manager. + * @param {string} sFolderUrl Must be full path including domain name: https://webdavserver.com/path/ + */ + OpenFolderInOsFileManager: function (sFolderUrl) { + ITHit.WebDAV.Client.DocManager.OpenFolderInOsFileManager(sFolderUrl, this.GetMountUrl(), this._ProtocolInstallMessage.bind(this), null, webDavSettings.EditDocAuth.SearchIn, + webDavSettings.EditDocAuth.CookieNames, webDavSettings.EditDocAuth.LoginUrl); + }, + + /** + * @return {string} + **/ + GetMountUrl: function () { + // Web Folders on Windows XP require port, even if it is a default port 80 or 443. + var port = window.location.port || (window.location.protocol == 'http:' ? 80 : 443); + + return window.location.protocol + '//' + window.location.hostname + ':' + port + webDavSettings.ApplicationPath; + }, + + /** + * Returns value from hash + * @return {string} + */ + GetHashValue: function (key) { + var hashConfig = this._parseUrlHash(); + + return hashConfig.hasOwnProperty(key) ? hashConfig[key] : null; + }, + + /** + * Sets values to hash + */ + SetHashValues: function (arrayValues) { + var hashValue = ''; + var params = []; + var hashConfig = this._parseUrlHash(); + + for (var i = 0; i < arrayValues.length; i++) { + hashConfig = this._addParameterToArray(arrayValues[i].Name, arrayValues[i].Value, hashConfig) + } + + for (var key in hashConfig) { + params.push(key + '=' + hashConfig[key]); + } + + hashValue = params.length > 0 ? ('#' + params.join('&')) : ''; + + if (hashValue != location.hash) { + location.hash = hashValue; + } + + if (location.href[location.href.length - 1] == '#') { + oHistoryApi.PushState(); + } + }, + + /** + * Sets value to hash + */ + SetHashValue: function (name, value) { + this.SetHashValues([{ Name: name, Value: value }]); + }, + + /** + * Returns url of app installer + */ + GetInstallerFileUrl: function () { + return webDavSettings.ApplicationProtocolsPath + ITHit.WebDAV.Client.DocManager.GetProtocolInstallFileNames()[0]; + }, + + /** + * Adds name and value to array + * @return {Array} + */ + _addParameterToArray: function (name, value, arrayParams) { + var nameExist = false; + + for (var key in arrayParams) { + if (arrayParams.hasOwnProperty(key)) { + if (key == name) { + nameExist = true; + arrayParams[key] = value; + } + + if (!arrayParams[key]) { + continue; + } + } + } + + if (!nameExist && value) { + arrayParams[name] = value; + } + + return arrayParams; + }, + + /** + * Parses hash + * @return {string} + */ + _parseUrlHash: function () { + // Parse hash + var hash = {}; + if (location.hash.length > 0) { + var hashParts = location.hash.substr(1).split('&'); + for (var i = 0, l = hashParts.length; i < l; i++) { + var param = hashParts[i].split('='); + hash[param[0]] = param[1]; + } + } + + return hash; + }, + + /** + * Function to be called when document or OS file manager failed to open. + * @private + */ + _ProtocolInstallMessage: function () { + if (ITHit.WebDAV.Client.DocManager.IsDavProtocolSupported()) { + var $currentOS = $('#DownloadProtocolModal .current-os'); + var $currentBrowser = $('#DownloadProtocolModal .current-browser'); + + // initialization browsers extension panel + if ($currentBrowser.children().length === 0) { + let isChrome = !!window['chrome'] && (!!window['chrome']['webstore'] || !!window['chrome']['runtime']); + + // Edge (based on chromium) detection + if (isChrome && (navigator.userAgent.indexOf('Edg') !== -1)) { + $('#DownloadProtocolModal .edge-chromium').appendTo($currentBrowser); + } else if (isChrome) { + $('#DownloadProtocolModal .goole-chrome').appendTo($currentBrowser); + } else if (typeof InstallTrigger !== 'undefined') { + $('#DownloadProtocolModal .mozilla-firefox').appendTo($currentBrowser); + } + else if (navigator.userAgent.indexOf("MSIE ") > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) { + $('#DownloadProtocolModal .not-required-internet-explorer').show(); + } + } + + // initialization custom protocol installers panel + if ($currentOS.children().length === 0) { + if (ITHit.DetectOS.OS === 'Windows') { + $('#DownloadProtocolModal .window').appendTo($currentOS); + } else if (ITHit.DetectOS.OS === 'Linux') { + $('#DownloadProtocolModal .linux').appendTo($currentOS); + } else if (ITHit.DetectOS.OS === 'MacOS') { + $('#DownloadProtocolModal .mac-os').appendTo($currentOS); + } + } + + $('#DownloadProtocolModal').modal('show'); + $('#DownloadProtocolModal .more-lnk').unbind().click(function () { + var $pnl = $(this).next(); + if ($pnl.is(':visible')) { + $(this).find('span').text('+'); + $pnl.hide(); + } else { + $(this).find('span').text('-'); + $pnl.show(); + } + }); + } + } + }; + var oWebDAV = window.WebDAVController = new WebDAVController(); + var oConfirmModal = new ConfirmModal('#ConfirmModal'); + var oFolderGrid = new FolderGridView('.ithit-grid-container', '.ithit-grid-toolbar'); + var oToolbar = new Toolbar('.ithit-grid-toolbar', oFolderGrid, oConfirmModal, oWebDAV); + var oSearchForm = new SearchFormView('.ithit-search-container'); + var oBreadcrumbs = new BreadcrumbsView('.ithit-breadcrumb-container .breadcrumb', '.btn-up-one-level'); + var oPagination = new PaginationView('.ithit-pagination-container'); + var oTableSorting = new TableSortingView('.ithit-grid-container th.sort'); + var oHistoryApi = new HistoryApiController('.ithit-grid-container, .ithit-breadcrumb-container'); + + + // List files on a WebDAV server using WebDAV Ajax Library + if (oWebDAV.GetHashValue('search')) { + oWebDAV.NavigateFolder(window.location.href.split("#")[0], null, null, null, true, function () { + oSearchForm.LoadFromHash(); + }); + } + else { + oWebDAV.NavigateFolder(window.location.href.split("#")[0], null, null, null, true); + } + + // Set Ajax lib version + if (ITHit.WebDAV.Client.DocManager.IsDavProtocolSupported()) { + $('.ithit-version-value').html('v' + ITHit.WebDAV.Client.WebDavSession.Version + ' (Protocol v' + ITHit.WebDAV.Client.WebDavSession.ProtocolVersion + ')'); + } + else { + $('.ithit-version-value').text('v' + ITHit.WebDAV.Client.WebDavSession.Version + ' (Protocol v' + ITHit.WebDAV.Client.WebDavSession.ProtocolVersion + ')'); + } + $('.ithit-current-folder-value').text(oWebDAV.GetMountUrl()); + +})(WebdavCommon); \ No newline at end of file diff --git a/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js new file mode 100644 index 0000000..ab28eaa --- /dev/null +++ b/Kotlin/javax/filesystemstorage/src/main/webapp/WEB-INF/wwwroot/js/webdav-uploader.js @@ -0,0 +1,850 @@ +(function (WebdavCommon) { + var sOverwriteDialogueFormat = 'The following item(s) exist on the server:

          {0}

          Overwrite?'; + var sFailedCheckExistsMessage = "Check for already exists item failed with error."; + var sRetryMessageFormat = 'Retry in: {0}'; + var sWrongFileSizeFormat = 'File size should be less than {0}.'; + var sForbiddenExtensionFormat = 'Upload files with "{0}" extension is forbidden.'; + var sValidationError = 'Validation Error'; + var iMaxFileSize = 10485760; //10MB + var aForbiddenExtensions = ['BAT', 'BIN', 'CMD', 'COM', 'EXE']; + + + /////////////////// + // Confirm Bootstrap Modal + var ConfirmRewriteModal = function (selector) { + this.$el = $(selector); + this.$el.find('.btn-ok').click(this._onOkClickHandler.bind(this)); + this.$el.find('.btn-no').click(this._onNoClickHandler.bind(this)); + this.$el.on('hide.bs.modal', this._onModalHideHandler.bind(this)); + } + ConfirmRewriteModal.prototype = { + Confirm: function (message, successfulCallback, discardCallback, cancelCallback) { + this.isConfirmed = false; + this.successfulCallback = successfulCallback || $.noop; + this.discardCallback = discardCallback || $.noop; + this.cancelCallback = cancelCallback || $.noop; + this.$el.find('.message').html(message); + this.$el.find('.modal-dialog').addClass('modal-lg'); + this.$el.modal('show'); + }, + + _onOkClickHandler: function (e) { + this.isConfirmed = true; + this.successfulCallback(); + this.$el.modal('hide'); + }, + + _onNoClickHandler: function (e) { + this.isDiscarded = true; + this.discardCallback(); + this.$el.modal('hide'); + }, + + _onModalHideHandler: function () { + if (!this.isConfirmed && !this.isDiscarded) { + this.cancelCallback(); + } + } + }; + + /** + * This class represents error that occured on client. + * @class + * @param {string} sMessage - The message will be displayed as error's short description. + * @param {string} sUri - This url will be displayed as item's URL caused error. + * @property {string} Message + * @property {string} Uri + */ + function ClientError(sMessage, sUri) { + this.Message = sMessage; + this.Uri = sUri; + } + + //////////////// + // Uploader Grid View + /** @class */ + function UploaderGridView(sSelector) { + + this.Uploader = new ITHit.WebDAV.Client.Upload.Uploader(); + this._dropCounter = 0; + + this.Uploader.Inputs.AddById('ithit-button-input'); + this._dropZone = this.Uploader.DropZones.AddById('ithit-dropzone'); + this._dropZone.HtmlElement.addEventListener('dragenter', this._OnDragEnter.bind(this), false); + this._dropZone.HtmlElement.addEventListener('dragleave', this._OnDragLeave.bind(this), false); + this._dropZone.HtmlElement.addEventListener('drop', this._OnDrop.bind(this), false); + + this.Uploader.SetUploadUrl(ITHit.WebDAV.Client.Encoder.Decode(window.location.href.split("#")[0])); + this.Uploader.Queue.AddListener('OnQueueChanged', '_QueueChange', this); + this.Uploader.Queue.AddListener('OnUploadItemsCreated', this._OnUploadItemsCreated, this); + + var $container = this.$container = $(sSelector); + this.$uploadingBlock = this.$container.find('.uploading-block'); + this.$uploadingDetails = this.$container.find('.uploading-details'); + this.$uploadingDetails.draggable(); + + this.rows = []; + this.fileLoadCompleted = function () { + if (this.$container.find('.uploading-item').length == 0) { + this.$container.addClass('d-none'); + this.$container.find('.progress-wrapper .progress-bar').attr('aria-valuenow', 0).css('width', 0 + '%'); + this.$uploadingBlock.find('.persent').text(0 + '%'); + } + window.WebDAVController.Reload(); + } + + window.addEventListener('beforeunload', function (event) { + if ($container.find('.uploading-item').length != 0) { + var warnMessage = 'Uploader is running!'; + (event || window.event).returnValue = warnMessage; + return warnMessage; + } + }); + + this._DataBindUploaderBlock(); + }; + + UploaderGridView.prototype.SetUploadUrl = function (sPath) { + this.Uploader.SetUploadUrl(sPath); + }; + + /** Called when a user selects items for upload or drops items into a drop area. + * In this function, you can validate files selected for upload and present user interface + * if user interaction is necessary. + * You can check if each item exists on the server, submitting additional requests to the + * server, and specify if each item should be overwritten or skipped. You can also specify + * if the item should be deleted in case of upload cancelation (typically if the item did + * not exist on the server before upload). + * In addition you can validate file size, file extension, file upload path, and file name. + * + * As soon as you may perform asynchronous calls in this function you must signal that all + * asynchronous checks are completed and upload can be started calling + * UploadItemsCreated.Upload() function passing a list of UploadItems to be uploaded. + * + * @param {ITHit.WebDAV.Client.Upload.Events.UploadItemsCreated} oUploadItemsCreated - Contains + * a list of items selected by the user for upload in UploadItemsCreated.Items property. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._OnUploadItemsCreated = function (oUploadItemsCreated) { + + /* Validate file extensions, size, name, etc. here. */ + var oValidationError = this._ValidateUploadItems(oUploadItemsCreated.Items); + if (oValidationError) { + WebdavCommon.ErrorModal.Show(sValidationError, oValidationError); + return; + } + + /* Below we will check if each file exists on the server + and ask a user if files should be overwritten or skipped. */ + this._GetExistsAsync(oUploadItemsCreated.Items, function (oAsyncResult) { + if (oAsyncResult.IsSuccess && oAsyncResult.Result.length === 0) { + // No items exists on the server. + // Add all items to the upload queue. + oUploadItemsCreated.Upload(oUploadItemsCreated.Items); + return; + } + + if (!oAsyncResult.IsSuccess) { + // Some error occurred during item existence verification requests. + // Show error dialog with error description. + // Mark all items as failed and add to the upload list. + this._ShowExistsCheckError(oAsyncResult.Error, + function () { + oUploadItemsCreated.Items.forEach(function (oUploadItem) { + + // Move an item into the error state. + // Upload of this item will NOT start when added to the queue. + oUploadItem.SetFailed(oAsyncResult.Error); + }); + + // Add all items to the upload queue, so a user can start the upload later. + oUploadItemsCreated.Upload(oUploadItemsCreated.Items); + }); + return; + } + + var sItemsList = ''; // List of items to be displayed in Overwrite / Skip / Cancel dialog. + + /** @type {ITHit.WebDAV.Client.Upload.UploadItem[]} aExistsUploadItems */ + var aExistsUploadItems = []; + oAsyncResult.Result.forEach(function (oUploadItem) { + + // For the sake of simplicity folders are never deleted when upload canceled. + if (!oUploadItem.IsFolder()) { + + // File exists so we should not delete it when file's upload canceled. + oUploadItem.SetDeleteOnCancel(false); + } + + // Mark item as verified to avoid additional file existence verification requests. + oUploadItem.CustomData.FileExistanceVerified = true; + + sItemsList += decodeURI(oUploadItem.GetRelativePath()) + '
          '; + aExistsUploadItems.push(oUploadItem); + }); + + /* One or more items exists on the server. Show Overwrite / Skip / Cancel dialog.*/ + oConfirmModal.Confirm(WebdavCommon.PasteFormat(sOverwriteDialogueFormat, sItemsList), + + /* A user selected to overwrite existing files. */ + function onOverwrite() { + + // Mark all items that exist on the server with overwrite flag. + aExistsUploadItems.forEach(function (oUploadItem) { + if (oUploadItem.IsFolder()) return; + + // The file will be overwritten if it exists on the server. + oUploadItem.SetOverwrite(true); + }); + + // Add all items to the upload queue. + oUploadItemsCreated.Upload(oUploadItemsCreated.Items); + }, + + /* A user selected to skip existing files. */ + function onSkipExists() { + + // Create list of items that do not exist on the server. + /** @type {ITHit.WebDAV.Client.Upload.UploadItem[]} aNotExistsUploadItems */ + var aNotExistsUploadItems = $.grep(oUploadItemsCreated.Items, + function (oUploadItem) { + return !ITHit.Utils.Contains(aExistsUploadItems, oUploadItem); + }); + + // Add only items that do not exist on the server to the upload queue. + oUploadItemsCreated.Upload(aNotExistsUploadItems); + }); + }.bind(this)); + }; + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem[]} aUploadItems - Array of items to check. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._ValidateUploadItems = function (aUploadItems) { + for (var i = 0; i < aUploadItems.length; i++) { + var oUploadItem = aUploadItems[i]; + //Max file size validation + //var oExtensionError = this._ValidateExtension(oUploadItem); + + //File extension validation + //var oSizeError = this._ValidateSize(oUploadItem); + + //Special characters validation + //var oNameError = this._ValidateName(oUploadItem); + + //var oValidationError = oExtensionError || oSizeError || oNameError; + //if(oValidationError) { + // return oValidationError; + //} + + var oValidationError = this._ValidateName(oUploadItem); + if (oValidationError) { + return oValidationError; + } + } + }; + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - The item to check. + * @memberof UploaderGridView.prototype + * @returns {undefined | WebdavCommon.ClientError} - Undefined if item valid or error object. + */ + UploaderGridView.prototype._ValidateSize = function (oUploadItem) { + if (oUploadItem.GetSize() > iMaxFileSize) { + var sMessage = WebdavCommon.PasteFormat(sWrongFileSizeFormat, WebdavCommon.Formatters.FileSize(iMaxFileSize)); + return new ClientError(sMessage, oUploadItem.GetUrl()); + } + }; + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - The item to check. + * @memberof UploaderGridView.prototype + * @returns {undefined | WebdavCommon.ClientError} - Undefined if item valid or error object. + */ + UploaderGridView.prototype._ValidateExtension = function (oUploadItem) { + var sExtension = WebdavCommon.Formatters.GetExtension(oUploadItem.GetUrl()); + if (aForbiddenExtensions.indexOf(sExtension.toUpperCase()) >= 0) { + var sMessage = WebdavCommon.PasteFormat(sForbiddenExtensionFormat, sExtension); + return new ClientError(sMessage, oUploadItem.GetUrl()); + } + }; + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - Array of items to check. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._ValidateName = function (oUploadItem) { + var sValidationMessage = WebdavCommon.Validators.ValidateName(oUploadItem.GetName()); + if (sValidationMessage) { + return new ClientError(sValidationMessage, oUploadItem.GetUrl()); + } + }; + + + /** + * Verifies if each item in the list exists on the server and returns list of existing items. + * @callback UploaderGridView~GetExistsAsyncCallback + * @param {ITHit.WebDAV.Client.AsyncResult} oAsyncResult - The result of operation. + * @param {ITHit.WebDAV.Client.Upload.UploadItem[]} oAsyncResult.Result - The array of items + * that exists on server. + */ + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem[]} aUploadItems - Array of items to check. + * @param {UploaderGridView~GetExistsAsyncCallback} fCallback - The function to be called when + * all checks are completed. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._GetExistsAsync = function (aUploadItems, fCallback) { + this._OpenItemsCollectionAsync(aUploadItems, + function (aResultCollection) { + var oFailedResult = ITHit.Utils.FindBy(aResultCollection, + function (oResult) { + return !(oResult.AsyncResult.IsSuccess || oResult.AsyncResult.Status.Code === 404); + }, + this); + + if (oFailedResult) { + fCallback(oFailedResult.AsyncResult); + return; + } + + var aExistsItems = aResultCollection.filter(function (oResult) { + return oResult.AsyncResult.IsSuccess; + }) + .map(function (oResult) { + return oResult.UploadItem; + }); + + fCallback(new ITHit.WebDAV.Client.AsyncResult(aExistsItems, true, null)); + }); + + }; + + + /** + * @typedef {Object} UploaderGridView~OpenItemsCollectionResult + * @property {ITHit.WebDAV.Client.Upload.UploadItem} UploadItem + * @property {ITHit.WebDAV.Client.AsyncResult} oAsyncResult - The result of operation. + */ + + /** + * @callback UploaderGridView~OpenItemsCollectionAsyncCallback + * @param {UploaderGridView~OpenItemsCollectionResult[]} oResult - The result of operation. + */ + + /** + * @param {ITHit.WebDAV.Client.Upload.UploadItem[]} aUploadItems - Array of items to check. + * @param {UploaderGridView~OpenItemsCollectionAsyncCallback} fCallback - The function to + * be called when all requests completed. + * @memberof UploaderGridView.prototype + */ + UploaderGridView.prototype._OpenItemsCollectionAsync = function (aUploadItems, fCallback) { + var iCounter = aUploadItems.length; + + /**@type {UploaderGridView~OpenItemsCollectionResult} */ + var aResults = []; + if (iCounter === 0) { + fCallback(aResults); + return; + } + + aUploadItems.forEach(function (oUploadItem) { + window.WebDAVController.WebDavSession.OpenItemAsync(ITHit.EncodeURI(oUploadItem.GetUrl()), + [], + function (oAsyncResult) { + iCounter--; + aResults.push({ + UploadItem: oUploadItem, + AsyncResult: oAsyncResult + }); + + if (iCounter === 0) { + fCallback(aResults); + } + }); + }); + }; + + + /** + * Called when items are added or deleted from upload queue. + * @param {ITHit.WebDAV.Client.Upload.Queue#event:OnQueueChanged} oQueueChanged - Contains + * lists of items added to the upload queue in oQueueChanged.AddedItems property and removed + * from the upload queue in oQueueChanged.RemovedItems property. + */ + UploaderGridView.prototype._QueueChange = function (oQueueChanged) { + + // Display each ited added to the upload queue in the grid. + oQueueChanged.AddedItems.forEach(function (value) { + var row = new UploaderGridRow(value, this.fileLoadCompleted.bind(this), this._ShowExistsCheckError.bind(this), + this._DataBindAllProgress.bind(this), this._StateRowChange.bind(this)); + this.rows.push(row); + this.$container.find('.uploading-items').append(row.$el); + }.bind(this)); + + // Remove items deleted from upload queue from the grid. + oQueueChanged.RemovedItems.forEach(function (value) { + var aRows = $.grep(this.rows, function (oElem) { return value === oElem.UploadItem; }); + if (aRows.length === 0) return; + var rowIndex = this.rows.indexOf(aRows[0]); + this.rows.splice(rowIndex, 1); + aRows[0].$el.remove(); + }.bind(this)); + + if (this.rows.length == 0) { + this.$container.addClass('d-none'); + } else { + this.$container.removeClass('d-none'); + this.$uploadingBlock.addClass('show'); + var $uploading = this.$uploadingBlock; + setTimeout(function () { + $uploading.removeClass('show'); + }, 3000); + } + + this._StateRowChange(); + }; + + UploaderGridView.prototype._StateRowChange = function () { + let countPaused = 0; + let countCompleted = 0; + this.rows.forEach(function (row) { + let rowState = row.UploadItem.GetState(); + if (rowState === window.ITHit.WebDAV.Client.Upload.State.Paused) { + countPaused++; + } else if (rowState === window.ITHit.WebDAV.Client.Upload.State.Completed + || rowState === window.ITHit.WebDAV.Client.Upload.State.Canceled) { + countCompleted++; + } + }) + if (countPaused == 0) { + this._UpdateActions(false); + } else if (countPaused == (this.rows.length - countCompleted)) { + this._UpdateActions(true); + } + }; + + UploaderGridView.prototype._DataBindAllProgress = function () { + var currProgress = 0; + var count = 0; + this.rows.forEach(function (value) { + if (value.UploadItem.GetState() !== window.ITHit.WebDAV.Client.Upload.State.Canceled) { + var valueProgress = value.UploadItem.GetProgress().Completed; + if (valueProgress < 100) { + currProgress += valueProgress; + } + else { + currProgress += 100; + } + count++; + } + }); + currProgress /= count; + if (currProgress >= 0) { + var $progress = this.$container.find('.progress-wrapper .progress-bar'); + $progress.attr('aria-valuenow', currProgress).css('width', currProgress + '%'); + this.$uploadingBlock.find('.persent').text(Math.round(currProgress) + '%'); + } + } + + UploaderGridView.prototype._DataBindUploaderBlock = function () { + this.$container.find('.pause-all-button').click(this._PauseAllClickHandler.bind(this)); + this.$container.find('.play-all-button').click(this._StartAllClickHandler.bind(this)); + this.$uploadingBlock.find('.details-button').click(this._DetailsClickHandler.bind(this)); + this.$uploadingDetails.find('.close-button').click(this._CloseClickHandler.bind(this)); + this.$container.find('.cancel-all-button').click(this._CancelAllClickHandler.bind(this)); + this._UpdateActions(false); + } + + UploaderGridView.prototype._UpdateActions = function (isPaused) { + var $playButton = this.$container.find(".play-all-button"); + var $pauseButton = this.$container.find(".pause-all-button"); + if (isPaused) { + if ($playButton.hasClass('d-none')) { + $playButton.removeClass('d-none'); + + } + if (!$pauseButton.hasClass('d-none')) { + $pauseButton.addClass('d-none'); + } + } else { + if ($pauseButton.hasClass('d-none')) { + $pauseButton.removeClass('d-none'); + } + if (!$playButton.hasClass('d-none')) { + $playButton.addClass('d-none'); + } + } + }; + + UploaderGridView.prototype._DetailsClickHandler = function () { + this.$uploadingBlock.addClass('hide'); + this.$uploadingDetails.removeClass('d-none'); + this.$uploadingDetails.focus(); + } + + UploaderGridView.prototype._CloseClickHandler = function () { + this.$uploadingBlock.removeClass('hide'); + this.$uploadingDetails.addClass('d-none'); + } + + + UploaderGridView.prototype._DisableActions = function () { + this.$container.find('.cancel-all-button').attr("disabled", 'disabled'); + this.$container.find('.play-all-button').attr("disabled", 'disabled'); + this.$container.find('.pause-all-button').attr("disabled", 'disabled'); + }; + + UploaderGridView.prototype._EnableActions = function () { + this.$container.find('.cancel-all-button').removeAttr("disabled"); + this.$container.find('.play-all-button').removeAttr("disabled"); + this.$container.find('.pause-all-button').removeAttr("disabled"); + }; + + UploaderGridView.prototype._StartAllClickHandler = function () { + this._DisableActions(); + this.rows.forEach(function (value) { + if (value.UploadItem.GetState() === window.ITHit.WebDAV.Client.Upload.State.Paused) { + value._StartClickHandler(); + } + }); + this._EnableActions(); + }; + + UploaderGridView.prototype._PauseAllClickHandler = function () { + this._DisableActions(); + this.rows.forEach(function (value) { + value._PauseClickHandler(); + }); + this._EnableActions(); + }; + + UploaderGridView.prototype._CancelAllClickHandler = function () { + this._DisableActions(); + this.rows.forEach(function (value) { + value._CancelClickHandler(); + }); + this._UpdateActions(false); + this._EnableActions(); + }; + + /** + * Drag-and-Drop area visual effects. + */ + UploaderGridView.prototype._OnDragEnter = function (oEvent) { + this._dropCounter++; + $(oEvent.target).closest('#ithit-dropzone').addClass('dropzone'); + }; + + UploaderGridView.prototype._OnDragLeave = function (oEvent) { + this._dropCounter--; + if (this._dropCounter <= 0) { + this._dropCounter = 0; + oEvent.currentTarget.classList.remove('dropzone'); + } + }; + + UploaderGridView.prototype._OnDrop = function (oEvent) { + this._dropCounter = 0; + this._dropZone.HtmlElement.classList.remove('dropzone'); + this._dropZone.HtmlElement.querySelectorAll("*").forEach(function (value) { + value.classList.remove('dropzone'); + }); + }; + + UploaderGridView.prototype._ShowExistsCheckError = function (oError, fCallback) { + WebdavCommon.ErrorModal.Show(sFailedCheckExistsMessage, oError, fCallback); + }; + + /** + * Represents uploader grid row and subscribes for upload changes. + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - Upload item. + */ + function UploaderGridRow(oUploadItem, fileLoadCompletedCallback, fileUploadFailedCallback, progressChangedCallback, stateChangedCallback) { + this.$el = $('
          '); + this.UploadItem = oUploadItem; + this.UploadItem.AddListener('OnProgressChanged', '_OnProgress', this); + this.UploadItem.AddListener('OnStateChanged', '_OnStateChange', this); + this.UploadItem.AddListener('OnBeforeUploadStarted', this._OnBeforeUploadStarted, this); + this.UploadItem.AddListener('OnUploadError', this._OnUploadError, this); + this._Render(oUploadItem); + this._MaxRetry = 10; + this._CurrentRetry = 0; + this._RetryDelay = 10; + this.fileLoadCompletedCallback = fileLoadCompletedCallback; + this.fileUploadFailedCallback = fileUploadFailedCallback; + this.progressChangedCallback = progressChangedCallback; + this.stateChangedCallback = stateChangedCallback; + }; + + /** + * Creates upload row details view. + * @param {ITHit.WebDAV.Client.Upload.UploadItem} oUploadItem - Upload item to render details. + */ + UploaderGridRow.prototype._Render = function (oUploadItem) { + + var $cancelBlock = $('
          ') + .append($('