🔀 Merge “release/v81” into “master” v81
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 9 Feb 2020 11:16:48 +0000 (12:16 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 9 Feb 2020 11:16:48 +0000 (12:16 +0100)
480 files changed:
.builds/jdk-1.8.yml
.gitignore
build.gradle
gradle/wrapper/gradle-wrapper.properties
src/main/java/net/pterodactylus/sone/core/Core.java
src/main/java/net/pterodactylus/sone/core/FreenetInterface.java
src/main/java/net/pterodactylus/sone/core/ImageInserter.java
src/main/java/net/pterodactylus/sone/core/Options.java
src/main/java/net/pterodactylus/sone/core/PreferencesLoader.java [deleted file]
src/main/java/net/pterodactylus/sone/core/PreferencesLoader.kt [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/core/SoneDownloaderImpl.java
src/main/java/net/pterodactylus/sone/core/SoneException.java
src/main/java/net/pterodactylus/sone/core/SoneInsertException.java
src/main/java/net/pterodactylus/sone/core/SoneInserter.java
src/main/java/net/pterodactylus/sone/core/SoneModificationDetector.java
src/main/java/net/pterodactylus/sone/core/SoneParser.java
src/main/java/net/pterodactylus/sone/core/SoneRescuer.java
src/main/java/net/pterodactylus/sone/core/SoneUri.java
src/main/java/net/pterodactylus/sone/core/UpdateChecker.java [deleted file]
src/main/java/net/pterodactylus/sone/core/WebOfTrustUpdater.java
src/main/java/net/pterodactylus/sone/core/WebOfTrustUpdaterImpl.java
src/main/java/net/pterodactylus/sone/core/event/ImageEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/ImageInsertAbortedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/ImageInsertFailedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/ImageInsertFinishedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/ImageInsertStartedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/MarkPostKnownEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/MarkPostReplyKnownEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/MarkSoneKnownEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/NewSoneFoundEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/PostEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/PostReplyEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneInsertAbortedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneInsertedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneInsertingEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneLockedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneRemovedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneUnlockedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/UpdateFoundEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/data/Album.java
src/main/java/net/pterodactylus/sone/data/Client.java
src/main/java/net/pterodactylus/sone/data/Image.java
src/main/java/net/pterodactylus/sone/data/Post.java
src/main/java/net/pterodactylus/sone/data/PostReply.java
src/main/java/net/pterodactylus/sone/data/Profile.java
src/main/java/net/pterodactylus/sone/data/Reply.java
src/main/java/net/pterodactylus/sone/data/Sone.java
src/main/java/net/pterodactylus/sone/data/TemporaryImage.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractAlbumBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractImageBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractPostBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractPostReplyBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractReplyBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AlbumBuilderImpl.java
src/main/java/net/pterodactylus/sone/data/impl/AlbumImpl.java
src/main/java/net/pterodactylus/sone/data/impl/ImageBuilderImpl.java
src/main/java/net/pterodactylus/sone/data/impl/ImageImpl.java
src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java
src/main/java/net/pterodactylus/sone/database/DatabaseException.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryDatabase.kt
src/main/java/net/pterodactylus/sone/database/memory/MemoryPost.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryPostBuilder.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryPostReply.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryPostReplyBuilder.java
src/main/java/net/pterodactylus/sone/fcp/CreatePostCommand.java
src/main/java/net/pterodactylus/sone/fcp/CreateReplyCommand.java
src/main/java/net/pterodactylus/sone/fcp/DeletePostCommand.java
src/main/java/net/pterodactylus/sone/fcp/DeleteReplyCommand.java
src/main/java/net/pterodactylus/sone/fcp/FcpInterface.java
src/main/java/net/pterodactylus/sone/fcp/GetLocalSonesCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetPostCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetPostFeedCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetPostsCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetSoneCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetSonesCommand.java
src/main/java/net/pterodactylus/sone/fcp/LikePostCommand.java
src/main/java/net/pterodactylus/sone/fcp/LikeReplyCommand.java
src/main/java/net/pterodactylus/sone/fcp/LockSoneCommand.java
src/main/java/net/pterodactylus/sone/fcp/UnlockSoneCommand.java
src/main/java/net/pterodactylus/sone/fcp/VersionCommand.java
src/main/java/net/pterodactylus/sone/freenet/Key.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/L10nFilter.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/PluginStoreConfigurationBackend.java
src/main/java/net/pterodactylus/sone/freenet/SimpleFieldSetBuilder.java
src/main/java/net/pterodactylus/sone/freenet/fcp/AbstractCommand.java
src/main/java/net/pterodactylus/sone/freenet/fcp/Command.java
src/main/java/net/pterodactylus/sone/freenet/fcp/FcpException.java
src/main/java/net/pterodactylus/sone/freenet/plugin/PluginConnector.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/plugin/PluginException.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/plugin/event/ReceivedReplyEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/Context.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/DefaultIdentity.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/DefaultOwnIdentity.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/Identity.java
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityChangeDetector.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityChangeDetector.kt [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityChangeEventSender.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityLoader.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/OwnIdentity.java
src/main/java/net/pterodactylus/sone/freenet/wot/Trust.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/WebOfTrustConnector.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/WebOfTrustException.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/IdentityAddedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/IdentityEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/IdentityRemovedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/IdentityUpdatedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/OwnIdentityAddedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/OwnIdentityEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/OwnIdentityRemovedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/main/DebugLoaders.java
src/main/java/net/pterodactylus/sone/main/DefaultLoaders.java
src/main/java/net/pterodactylus/sone/main/Loaders.java
src/main/java/net/pterodactylus/sone/main/SonePlugin.java
src/main/java/net/pterodactylus/sone/notify/ListNotification.java [deleted file]
src/main/java/net/pterodactylus/sone/notify/ListNotificationFilter.java
src/main/java/net/pterodactylus/sone/template/AlbumAccessor.java
src/main/java/net/pterodactylus/sone/template/CollectionAccessor.java
src/main/java/net/pterodactylus/sone/template/CssClassNameFilter.java
src/main/java/net/pterodactylus/sone/template/GetPagePlugin.java
src/main/java/net/pterodactylus/sone/template/HttpRequestAccessor.java
src/main/java/net/pterodactylus/sone/template/IdentityAccessor.java
src/main/java/net/pterodactylus/sone/template/ImageAccessor.java
src/main/java/net/pterodactylus/sone/template/ImageLinkFilter.java
src/main/java/net/pterodactylus/sone/template/JavascriptFilter.java
src/main/java/net/pterodactylus/sone/template/PostAccessor.java [deleted file]
src/main/java/net/pterodactylus/sone/template/ProfileAccessor.java
src/main/java/net/pterodactylus/sone/template/ReplyAccessor.java
src/main/java/net/pterodactylus/sone/template/ReplyGroupFilter.java
src/main/java/net/pterodactylus/sone/template/RequestChangeFilter.java
src/main/java/net/pterodactylus/sone/template/SoneAccessor.java
src/main/java/net/pterodactylus/sone/template/SubstringFilter.java
src/main/java/net/pterodactylus/sone/template/TrustAccessor.java
src/main/java/net/pterodactylus/sone/template/UniqueElementFilter.java
src/main/java/net/pterodactylus/sone/template/UnknownDateFilter.java
src/main/java/net/pterodactylus/sone/text/Parser.java
src/main/java/net/pterodactylus/sone/text/ParserContext.java
src/main/java/net/pterodactylus/sone/text/PostPart.java
src/main/java/net/pterodactylus/sone/text/SoneTextParserContext.java
src/main/java/net/pterodactylus/sone/text/TextFilter.java
src/main/java/net/pterodactylus/sone/utils/IntegerRangePredicate.java
src/main/java/net/pterodactylus/sone/web/AllPages.kt
src/main/java/net/pterodactylus/sone/web/WebInterface.java
src/main/java/net/pterodactylus/sone/web/page/PageToadlet.java
src/main/kotlin/net/pterodactylus/sone/core/DefaultElementLoader.kt
src/main/kotlin/net/pterodactylus/sone/core/Preferences.kt
src/main/kotlin/net/pterodactylus/sone/core/UpdateChecker.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ConfigNotRead.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/DebugActivatedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/FirstStart.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageInsertAbortedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageInsertFailedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageInsertFinishedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageInsertStartedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MarkPostKnownEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MarkPostReplyKnownEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MarkSoneKnownEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MentionOfLocalSoneFoundEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MentionOfLocalSoneRemovedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/NewPostFoundEvent.kt
src/main/kotlin/net/pterodactylus/sone/core/event/NewPostReplyFoundEvent.kt
src/main/kotlin/net/pterodactylus/sone/core/event/NewSoneFoundEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/PostEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/PostRemovedEvent.kt
src/main/kotlin/net/pterodactylus/sone/core/event/PostReplyEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/PostReplyRemovedEvent.kt
src/main/kotlin/net/pterodactylus/sone/core/event/Shutdown.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneInsertAbortedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneInsertedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneInsertingEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneLockedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneLockedOnStartup.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneRemovedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneUnlockedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/Startup.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/UpdateFoundEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/WebOfTrustAppeared.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/WebOfTrustDisappeared.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/data/Albums.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/data/Fingerprintable.kt
src/main/kotlin/net/pterodactylus/sone/data/Identified.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumBuilderFactory.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumDatabase.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumStore.kt
src/main/kotlin/net/pterodactylus/sone/database/Database.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageBuilderFactory.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageDatabase.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageStore.kt
src/main/kotlin/net/pterodactylus/sone/database/PostBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/PostBuilderFactory.kt
src/main/kotlin/net/pterodactylus/sone/database/PostDatabase.kt
src/main/kotlin/net/pterodactylus/sone/database/PostProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyBuilderFactory.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyDatabase.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyStore.kt
src/main/kotlin/net/pterodactylus/sone/database/PostStore.kt
src/main/kotlin/net/pterodactylus/sone/database/ReplyBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/SoneProvider.kt
src/main/kotlin/net/pterodactylus/sone/fcp/AbstractSoneCommand.kt
src/main/kotlin/net/pterodactylus/sone/freenet/AsyncFreenetInterface.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/BaseL10nTranslation.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/FreenetClient.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/FreenetURIs.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/L10nFilter.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/Translation.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/plugin/FredPluginConnector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/plugin/PluginConnector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/plugin/PluginException.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/plugin/PluginRespiratorFacade.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/Context.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/DefaultIdentity.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/DefaultOwnIdentity.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityChangeEventSender.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityLoader.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManager.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/PluginWebOfTrustConnector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/Trust.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/WebOfTrustConnector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/WebOfTrustException.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/WebOfTrustPinger.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/IdentityAddedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/IdentityRemovedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/IdentityUpdatedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/OwnIdentityAddedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/OwnIdentityRemovedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/main/FreenetModule.kt
src/main/kotlin/net/pterodactylus/sone/main/SoneModule.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/main/SoneModuleCreator.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/main/TickerShutdown.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/notify/ListNotification.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/notify/Notifications.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/template/DurationFormatFilter.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/template/HistogramRenderer.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/template/PostAccessor.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/text/SoneMentionDetector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/text/SoneTextParser.kt
src/main/kotlin/net/pterodactylus/sone/utils/Booleans.kt
src/main/kotlin/net/pterodactylus/sone/utils/Freenet.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/utils/Functions.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/utils/Objects.kt
src/main/kotlin/net/pterodactylus/sone/utils/Renderables.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/PageToadletRegistry.kt
src/main/kotlin/net/pterodactylus/sone/web/WebInterfaceModule.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/CreatePostAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/DistrustAjaxPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/ajax/GetNotificationsAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/GetTranslationAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/TrustAjaxPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/ajax/UntrustAjaxPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/notification/ConfigNotReadHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/FirstStartHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/ImageInsertHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/LocalPostHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/MarkPostKnownDuringFirstStartHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/MarkPostReplyKnownDuringFirstStartHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NewRemotePostHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NewSoneHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NewVersionHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NotificationHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerModule.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/SoneInsertHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/SoneLockedHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/SoneLockedOnStartupHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/SoneMentionedHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/StartupHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/WebOfTrustHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/page/FreenetPage.kt
src/main/kotlin/net/pterodactylus/sone/web/page/FreenetRequest.kt
src/main/kotlin/net/pterodactylus/sone/web/page/FreenetTemplatePage.kt
src/main/kotlin/net/pterodactylus/sone/web/page/PageToadletFactory.kt
src/main/kotlin/net/pterodactylus/sone/web/page/SoneRequest.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/BookmarkPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/CreateAlbumPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/CreatePostPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/CreateReplyPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/CreateSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DebugPage.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteAlbumPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteImagePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeletePostPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteProfileFieldPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteReplyPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DismissNotificationPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DistrustPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/pages/EditAlbumPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/EditImagePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/EditProfileFieldPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/EditProfilePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/FollowSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/LikePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/LockSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/LoginPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/LogoutPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/MarkAsKnownPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/MetricsPage.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/pages/OptionsPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/SearchPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/SoneTemplatePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/TrustPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/pages/UnbookmarkPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/UnfollowSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/UnlikePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/UnlockSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/UntrustPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/pages/UploadImagePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/ViewSonePage.kt
src/main/resources/i18n/sone.de.properties
src/main/resources/i18n/sone.en.properties
src/main/resources/i18n/sone.es.properties
src/main/resources/i18n/sone.fr.properties
src/main/resources/i18n/sone.ja.properties
src/main/resources/i18n/sone.no.properties
src/main/resources/i18n/sone.pl.properties
src/main/resources/i18n/sone.ru.properties
src/main/resources/static/css/sone.css
src/main/resources/static/javascript/jquery-1.4.2.js [deleted file]
src/main/resources/static/javascript/jquery-3.4.1.js [new file with mode: 0644]
src/main/resources/static/javascript/sone.js
src/main/resources/templates/editProfile.html
src/main/resources/templates/imageBrowser.html
src/main/resources/templates/include/head.html
src/main/resources/templates/include/soneMenu.html
src/main/resources/templates/include/viewPost.html
src/main/resources/templates/include/viewReply.html
src/main/resources/templates/knownSones.html
src/main/resources/templates/metrics.html [new file with mode: 0644]
src/main/resources/templates/notify/soneLockedOnStartupNotification.html [new file with mode: 0644]
src/main/resources/templates/options.html
src/test/java/net/pterodactylus/sone/core/ConfigurationSoneParserTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/CoreTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/FreenetInterfaceTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/PreferencesLoaderTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/SoneInserterTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/SoneParserTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/UpdateCheckerTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/WebOfTrustUpdaterTest.java
src/test/java/net/pterodactylus/sone/freenet/KeyTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/DefaultIdentityTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/DefaultOwnIdentityTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/Identities.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityChangeDetectorTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityChangeEventSenderTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityLoaderTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityManagerTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityManagerTest.kt [new file with mode: 0644]
src/test/java/net/pterodactylus/sone/freenet/wot/event/IdentityEventTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/event/OwnIdentityEventTest.java [deleted file]
src/test/java/net/pterodactylus/sone/main/DebugLoadersTest.java
src/test/java/net/pterodactylus/sone/main/DefaultLoadersTest.java
src/test/java/net/pterodactylus/sone/notify/ListNotificationTest.java [deleted file]
src/test/java/net/pterodactylus/sone/template/FilesystemTemplateTest.java [deleted file]
src/test/java/net/pterodactylus/sone/template/PostAccessorTest.java [deleted file]
src/test/java/net/pterodactylus/sone/test/Matchers.java
src/test/kotlin/net/pterodactylus/sone/core/ConfigurationSoneParserTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/CoreTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/DefaultElementLoaderTest.kt
src/test/kotlin/net/pterodactylus/sone/core/FreenetInterfaceTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/ImageInserterTest.kt
src/test/kotlin/net/pterodactylus/sone/core/PreferencesLoaderTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/PreferencesTest.kt
src/test/kotlin/net/pterodactylus/sone/core/SoneInserterTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/SoneParserTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/UpdateCheckerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/data/AlbumsTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/data/ClientTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/database/memory/MemoryDatabaseTest.kt
src/test/kotlin/net/pterodactylus/sone/fcp/CreatePostCommandTest.kt
src/test/kotlin/net/pterodactylus/sone/freenet/AsyncFreenetInterfaceTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/BaseL10nTranslationTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/FreenetClientTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/FreenetURIsTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/L10nFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/freenet/plugin/FredPluginConnectorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/plugin/PluginRespiratorFacadeTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/DefaultIdentityTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/DefaultOwnIdentityTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/Identities.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/IdentityChangeDetectorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/IdentityChangeEventSenderTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/IdentityLoaderTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/PluginWebOfTrustConnectorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/WebOfTrustPingerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/main/FreenetModuleTest.kt
src/test/kotlin/net/pterodactylus/sone/main/SoneModuleCreatorTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/main/SoneModuleTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/main/SonePluginTest.kt
src/test/kotlin/net/pterodactylus/sone/main/TickerShutdownTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/notify/ListNotificationTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/DurationFormatFilterTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/FilesystemTemplateTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/HistogramRendererTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/LinkedElementsFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/template/ParserFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/template/PostAccessorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/ProfileAccessorTest.kt
src/test/kotlin/net/pterodactylus/sone/template/ShortenFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/template/UnknownDateFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/test/Guice.kt
src/test/kotlin/net/pterodactylus/sone/test/Matchers.kt
src/test/kotlin/net/pterodactylus/sone/test/Mockotlin.kt
src/test/kotlin/net/pterodactylus/sone/test/Mocks.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/NotParallel.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/TestLoaders.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/TestPage.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/TestUtils.kt
src/test/kotlin/net/pterodactylus/sone/text/FreenetLinkPartTest.kt
src/test/kotlin/net/pterodactylus/sone/text/LinkPartTest.kt
src/test/kotlin/net/pterodactylus/sone/text/SoneMentionDetectorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/text/SonePartTest.kt
src/test/kotlin/net/pterodactylus/sone/text/SoneTextParserTest.kt
src/test/kotlin/net/pterodactylus/sone/utils/BooleansTest.kt
src/test/kotlin/net/pterodactylus/sone/utils/ObjectsTest.kt
src/test/kotlin/net/pterodactylus/sone/utils/RenderablesTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/AllPagesTest.kt
src/test/kotlin/net/pterodactylus/sone/web/PageToadletRegistryTest.kt
src/test/kotlin/net/pterodactylus/sone/web/WebInterfaceModuleTest.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/CreatePostAjaxPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/DistrustAjaxPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/ajax/TestObjects.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/TrustAjaxPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/ajax/UntrustAjaxPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/notification/ConfigNotReadHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/FirstStartHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/ImageInsertHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/LocalPostHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/MarkPostKnownDuringFirstStartHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/MarkPostReplyKnownDuringFirstStartHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NewRemotePostHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NewSoneHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NewVersionHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerModuleTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerTester.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/SoneInsertHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/SoneLockedHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/SoneLockedOnStartupHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/SoneMentionedHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/StartupHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/Testing.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/WebOfTrustHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/page/FreenetRequestTest.kt
src/test/kotlin/net/pterodactylus/sone/web/page/SoneRequestTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/CreatePostPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/DebugPageTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/pages/DeleteSonePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/DismissNotificationPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/DistrustPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/pages/EditAlbumPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/EditImagePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/EditProfileFieldPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/EditProfilePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/FollowSonePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/ImageBrowserPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/IndexPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/KnownSonesPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/MetricsPageTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/pages/OptionsPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/SoneTemplatePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/TrustPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/pages/UntrustPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/pages/WebPageTest.kt
src/test/resources/net/pterodactylus/sone/core/sone-parser-with-invalid-recipient.xml
src/test/resources/net/pterodactylus/sone/core/sone-parser-with-recipient.xml
src/test/resources/net/pterodactylus/sone/core/sone-parser-with-valid-post-reply-time.xml
src/test/resources/net/pterodactylus/sone/core/sone-parser-with-valid-post-time.xml

index 5edd26d..2c43d38 100644 (file)
@@ -9,7 +9,7 @@ tasks:
       ./gradlew clean
   - build: |
       cd sone
-      ./gradlew build
+      ./gradlew -x findbugsTest build
   - test: |
       cd sone
       ./gradlew test
index fce4db9..abaaab1 100644 (file)
@@ -3,3 +3,5 @@
 
 /.gradle/
 /build/
+
+sone.properties
index 0beb42a..3730ead 100644 (file)
@@ -1,18 +1,13 @@
-group = 'net.pterodactylus'
-version = '80'
 
-buildscript {
-    ext.kotlinVersion = '1.2.71'
-    repositories {
-        mavenCentral()
-    }
-    dependencies {
-        classpath group: 'info.solidsoft.gradle.pitest', name: 'gradle-pitest-plugin', version: '1.4.0'
-        classpath group: 'org.jetbrains.kotlin', name: 'kotlin-gradle-plugin', version: kotlinVersion
-        classpath group: 'org.jetbrains.kotlin', name: 'kotlin-noarg', version: kotlinVersion
-    }
+plugins {
+    id 'org.jetbrains.kotlin.jvm' version '1.3.61'
+    id 'org.jetbrains.kotlin.plugin.noarg' version '1.3.61'
+    id 'info.solidsoft.pitest' version '1.4.5'
 }
 
+group = 'net.pterodactylus'
+version = '81'
+
 repositories {
      mavenCentral()
      maven { url "https://maven.pterodactylus.net/" }
@@ -20,15 +15,13 @@ repositories {
 
 apply plugin: 'java'
 
-sourceCompatibility = 1.7
-targetCompatibility = 1.7
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
 
 tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
 }
 
-apply plugin: 'kotlin'
-
 configurations {
     provided {
         dependencies.all { dep ->
@@ -43,25 +36,44 @@ dependencies {
     provided group: 'org.freenetproject', name: 'freenet-ext', version: '29'
     provided group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.54'
 
-    compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib'
-    compile group: 'net.pterodactylus', name: 'utils', version: '0.12.4'
+    compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8'
+    compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.0-RC'
+
+    compile group: 'net.pterodactylus', name: 'utils', version: '0.13.1'
     compile group: 'com.google.inject', name: 'guice', version: '4.2.2'
-    compile group: 'com.google.guava', name: 'guava', version: '27.0.1-android'
+    compile group: 'com.google.guava', name: 'guava', version: '27.0.1-jre'
     compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.1'
     compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.9.1'
     compile group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2'
     compile group: 'org.jsoup', name: 'jsoup', version: '1.10.2'
+    compile group: 'io.dropwizard.metrics', name: 'metrics-core', version: '4.1.0'
+    compile group: 'javax.activation', name: 'javax.activation-api', version: '1.2.0'
 
     testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit'
     testCompile group: 'junit', name: 'junit', version: '4.11'
-    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.10.0'
+    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.28.2'
     testCompile group: 'org.hamcrest', name: 'hamcrest-all', version: '1.3'
 }
 
 apply from: 'version.gradle'
 
-test {
+task parallelTest(type: Test) {
     maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
+    useJUnit {
+        excludeCategories 'net.pterodactylus.sone.test.NotParallel'
+    }
+}
+
+task notParallelTest(type: Test) {
+    maxParallelForks = 1
+    useJUnit {
+        includeCategories 'net.pterodactylus.sone.test.NotParallel'
+    }
+}
+
+test {
+    exclude '**'
+    dependsOn parallelTest, notParallelTest
 }
 
 task fatJar(type: Jar) {
@@ -86,14 +98,13 @@ javadoc {
 apply plugin: 'jacoco'
 
 jacoco {
-    toolVersion = '0.7.9'
+    toolVersion = '0.8.4'
 }
 
 jacocoTestReport.dependsOn test
 
-apply plugin: 'info.solidsoft.pitest'
-
 pitest {
+    pitestVersion = '1.4.10'
     outputFormats = ['HTML', 'XML']
     timestampedReports = false
     timeoutFactor = 3.0
@@ -125,8 +136,6 @@ task countLines {
     dependsOn tasks.countLinesTest
 }
 
-apply plugin: 'kotlin-noarg'
-
 noArg {
     annotation('net.pterodactylus.sone.main.NoArg')
 }
index c19a936..1cdded7 100644 (file)
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip
index b0df7a9..18588a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Core.java - Copyright © 2010–2019 David Roden
+ * Sone - Core.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ import static com.google.common.primitives.Longs.tryParse;
 import static java.lang.String.format;
 import static java.util.logging.Level.WARNING;
 import static java.util.logging.Logger.getLogger;
+import static net.pterodactylus.sone.data.AlbumsKt.getAllImages;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -37,30 +38,20 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import com.codahale.metrics.*;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidImageFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
-import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
-import net.pterodactylus.sone.core.event.InsertionDelayChangedEvent;
-import net.pterodactylus.sone.core.event.MarkPostKnownEvent;
-import net.pterodactylus.sone.core.event.MarkPostReplyKnownEvent;
-import net.pterodactylus.sone.core.event.MarkSoneKnownEvent;
-import net.pterodactylus.sone.core.event.NewPostFoundEvent;
-import net.pterodactylus.sone.core.event.NewPostReplyFoundEvent;
-import net.pterodactylus.sone.core.event.NewSoneFoundEvent;
-import net.pterodactylus.sone.core.event.PostRemovedEvent;
-import net.pterodactylus.sone.core.event.PostReplyRemovedEvent;
-import net.pterodactylus.sone.core.event.SoneLockedEvent;
-import net.pterodactylus.sone.core.event.SoneRemovedEvent;
-import net.pterodactylus.sone.core.event.SoneUnlockedEvent;
+import net.pterodactylus.sone.core.event.*;
 import net.pterodactylus.sone.data.Album;
 import net.pterodactylus.sone.data.Client;
 import net.pterodactylus.sone.data.Image;
@@ -98,7 +89,7 @@ import net.pterodactylus.util.service.AbstractService;
 import net.pterodactylus.util.thread.NamedThreadFactory;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
+import com.google.common.base.Stopwatch;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
@@ -121,6 +112,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
        /** The start time. */
        private final long startupTime = System.currentTimeMillis();
 
+       private final AtomicBoolean debug = new AtomicBoolean(false);
+
        /** The preferences. */
        private final Preferences preferences;
 
@@ -184,6 +177,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
        /** The time the configuration was last touched. */
        private volatile long lastConfigurationUpdate;
 
+       private final MetricRegistry metricRegistry;
+       private final Histogram configurationSaveTimeHistogram;
+
        /**
         * Creates a new core.
         *
@@ -201,7 +197,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         *            The database
         */
        @Inject
-       public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, SoneDownloader soneDownloader, ImageInserter imageInserter, UpdateChecker updateChecker, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, Database database) {
+       public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, SoneDownloader soneDownloader, ImageInserter imageInserter, UpdateChecker updateChecker, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, Database database, MetricRegistry metricRegistry) {
                super("Sone Core");
                this.configuration = configuration;
                this.freenetInterface = freenetInterface;
@@ -212,7 +208,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                this.webOfTrustUpdater = webOfTrustUpdater;
                this.eventBus = eventBus;
                this.database = database;
+               this.metricRegistry = metricRegistry;
                preferences = new Preferences(eventBus);
+               this.configurationSaveTimeHistogram = metricRegistry.histogram("configuration.save.duration", () -> new Histogram(new ExponentiallyDecayingReservoir(3000, 0)));
        }
 
        //
@@ -228,6 +226,16 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                return startupTime;
        }
 
+       @Nonnull
+       public boolean getDebug() {
+               return debug.get();
+       }
+
+       public void setDebug() {
+               debug.set(true);
+               eventBus.post(new DebugActivatedEvent());
+       }
+
        /**
         * Returns the options used by the core.
         *
@@ -618,7 +626,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                sone.setLatestEdition(fromNullable(tryParse(property)).or(0L));
                sone.setClient(new Client("Sone", SonePlugin.getPluginVersion()));
                sone.setKnown(true);
-               SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, ownIdentity.getId());
+               SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, metricRegistry, ownIdentity.getId());
                soneInserter.insertionDelayChanged(new InsertionDelayChangedEvent(preferences.getInsertionDelay()));
                eventBus.register(soneInserter);
                synchronized (soneInserters) {
@@ -627,6 +635,11 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                loadSone(sone);
                database.storeSone(sone);
                sone.setStatus(SoneStatus.idle);
+               if (sone.getPosts().isEmpty() && sone.getReplies().isEmpty() && getAllImages(sone.getRootAlbum()).isEmpty()) {
+                       // dirty hack
+                       lockSone(sone);
+                       eventBus.post(new SoneLockedOnStartup(sone));
+               }
                soneInserter.start();
                return sone;
        }
@@ -738,75 +751,6 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
        }
 
        /**
-        * Sets the trust value of the given origin Sone for the target Sone.
-        *
-        * @param origin
-        *            The origin Sone
-        * @param target
-        *            The target Sone
-        * @param trustValue
-        *            The trust value (from {@code -100} to {@code 100})
-        */
-       public void setTrust(Sone origin, Sone target, int trustValue) {
-               checkNotNull(origin, "origin must not be null");
-               checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin must be a local Sone");
-               checkNotNull(target, "target must not be null");
-               checkArgument((trustValue >= -100) && (trustValue <= 100), "trustValue must be within [-100, 100]");
-               webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), trustValue, preferences.getTrustComment());
-       }
-
-       /**
-        * Removes any trust assignment for the given target Sone.
-        *
-        * @param origin
-        *            The trust origin
-        * @param target
-        *            The trust target
-        */
-       public void removeTrust(Sone origin, Sone target) {
-               checkNotNull(origin, "origin must not be null");
-               checkNotNull(target, "target must not be null");
-               checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin must be a local Sone");
-               webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), null, null);
-       }
-
-       /**
-        * Assigns the configured positive trust value for the given target.
-        *
-        * @param origin
-        *            The trust origin
-        * @param target
-        *            The trust target
-        */
-       public void trustSone(Sone origin, Sone target) {
-               setTrust(origin, target, preferences.getPositiveTrust());
-       }
-
-       /**
-        * Assigns the configured negative trust value for the given target.
-        *
-        * @param origin
-        *            The trust origin
-        * @param target
-        *            The trust target
-        */
-       public void distrustSone(Sone origin, Sone target) {
-               setTrust(origin, target, preferences.getNegativeTrust());
-       }
-
-       /**
-        * Removes the trust assignment for the given target.
-        *
-        * @param origin
-        *            The trust origin
-        * @param target
-        *            The trust target
-        */
-       public void untrustSone(Sone origin, Sone target) {
-               removeTrust(origin, target);
-       }
-
-       /**
         * Updates the stored Sone with the given Sone.
         *
         * @param sone
@@ -1063,7 +1007,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         *            The text of the post
         * @return The created post
         */
-       public Post createPost(Sone sone, Optional<Sone> recipient, String text) {
+       public Post createPost(Sone sone, @Nullable Sone recipient, String text) {
                checkNotNull(text, "text must not be null");
                checkArgument(text.trim().length() > 0, "text must not be empty");
                if (!sone.isLocal()) {
@@ -1072,8 +1016,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                }
                PostBuilder postBuilder = database.newPostBuilder();
                postBuilder.from(sone.getId()).randomId().currentTime().withText(text.trim());
-               if (recipient.isPresent()) {
-                       postBuilder.to(recipient.get().getId());
+               if (recipient != null) {
+                       postBuilder.to(recipient.getId());
                }
                final Post post = postBuilder.build();
                database.storePost(post);
@@ -1359,7 +1303,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                synchronized (soneInserters) {
                        for (Entry<Sone, SoneInserter> soneInserter : soneInserters.entrySet()) {
                                soneInserter.getValue().stop();
-                               saveSone(soneInserter.getKey());
+                               Sone latestSone = getLocalSone(soneInserter.getKey().getId());
+                               saveSone(latestSone);
                        }
                }
                synchronized (soneRescuers) {
@@ -1501,8 +1446,6 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        configuration.getStringValue(sonePrefix + "/Options/ShowCustomAvatars").setValue(sone.getOptions().getShowCustomAvatars().name());
                        configuration.getStringValue(sonePrefix + "/Options/LoadLinkedImages").setValue(sone.getOptions().getLoadLinkedImages().name());
 
-                       configuration.save();
-
                        webOfTrustUpdater.setProperty((OwnIdentity) sone.getIdentity(), "Sone.LatestEdition", String.valueOf(sone.getLatestEdition()));
 
                        logger.log(Level.INFO, String.format("Sone %s saved.", sone));
@@ -1540,7 +1483,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        database.save();
 
                        /* now save it. */
+                       Stopwatch stopwatch = Stopwatch.createStarted();
                        configuration.save();
+                       configurationSaveTimeHistogram.update(stopwatch.elapsed(TimeUnit.MICROSECONDS));
 
                } catch (ConfigurationException ce1) {
                        logger.log(Level.SEVERE, "Could not store configuration!", ce1);
@@ -1580,7 +1525,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void ownIdentityAdded(OwnIdentityAddedEvent ownIdentityAddedEvent) {
-               OwnIdentity ownIdentity = ownIdentityAddedEvent.ownIdentity();
+               OwnIdentity ownIdentity = ownIdentityAddedEvent.getOwnIdentity();
                logger.log(Level.FINEST, String.format("Adding OwnIdentity: %s", ownIdentity));
                if (ownIdentity.hasContext("Sone")) {
                        addLocalSone(ownIdentity);
@@ -1595,7 +1540,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void ownIdentityRemoved(OwnIdentityRemovedEvent ownIdentityRemovedEvent) {
-               OwnIdentity ownIdentity = ownIdentityRemovedEvent.ownIdentity();
+               OwnIdentity ownIdentity = ownIdentityRemovedEvent.getOwnIdentity();
                logger.log(Level.FINEST, String.format("Removing OwnIdentity: %s", ownIdentity));
                trustedIdentities.removeAll(ownIdentity);
        }
@@ -1608,9 +1553,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void identityAdded(IdentityAddedEvent identityAddedEvent) {
-               Identity identity = identityAddedEvent.identity();
+               Identity identity = identityAddedEvent.getIdentity();
                logger.log(Level.FINEST, String.format("Adding Identity: %s", identity));
-               trustedIdentities.put(identityAddedEvent.ownIdentity(), identity);
+               trustedIdentities.put(identityAddedEvent.getOwnIdentity(), identity);
                addRemoteSone(identity);
        }
 
@@ -1622,7 +1567,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void identityUpdated(IdentityUpdatedEvent identityUpdatedEvent) {
-               Identity identity = identityUpdatedEvent.identity();
+               Identity identity = identityUpdatedEvent.getIdentity();
                final Sone sone = getRemoteSone(identity.getId());
                if (sone.isLocal()) {
                        return;
@@ -1646,8 +1591,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void identityRemoved(IdentityRemovedEvent identityRemovedEvent) {
-               OwnIdentity ownIdentity = identityRemovedEvent.ownIdentity();
-               Identity identity = identityRemovedEvent.identity();
+               OwnIdentity ownIdentity = identityRemovedEvent.getOwnIdentity();
+               Identity identity = identityRemovedEvent.getIdentity();
                trustedIdentities.remove(ownIdentity, identity);
                for (Entry<OwnIdentity, Collection<Identity>> trustedIdentity : trustedIdentities.asMap().entrySet()) {
                        if (trustedIdentity.getKey().equals(ownIdentity)) {
@@ -1680,9 +1625,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void imageInsertFinished(ImageInsertFinishedEvent imageInsertFinishedEvent) {
-               logger.log(Level.WARNING, String.format("Image insert finished for %s: %s", imageInsertFinishedEvent.image(), imageInsertFinishedEvent.resultingUri()));
-               imageInsertFinishedEvent.image().modify().setKey(imageInsertFinishedEvent.resultingUri().toString()).update();
-               deleteTemporaryImage(imageInsertFinishedEvent.image().getId());
+               logger.log(Level.WARNING, String.format("Image insert finished for %s: %s", imageInsertFinishedEvent.getImage(), imageInsertFinishedEvent.getResultingUri()));
+               imageInsertFinishedEvent.getImage().modify().setKey(imageInsertFinishedEvent.getResultingUri().toString()).update();
+               deleteTemporaryImage(imageInsertFinishedEvent.getImage().getId());
                touchConfiguration();
        }
 
index 1ed2024..a01a2bb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - FreenetInterface.java - Copyright © 2010–2019 David Roden
+ * Sone - FreenetInterface.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,6 @@ import static freenet.keys.USK.create;
 import static java.lang.String.format;
 import static java.util.logging.Level.WARNING;
 import static java.util.logging.Logger.getLogger;
-import static net.pterodactylus.sone.freenet.Key.routingKey;
 
 import java.io.IOException;
 import java.net.MalformedURLException;
@@ -75,6 +74,7 @@ import freenet.support.api.Bucket;
 import freenet.support.api.RandomAccessBucket;
 import freenet.support.io.ArrayBucket;
 import freenet.support.io.ResumeFailedException;
+import net.pterodactylus.sone.freenet.*;
 
 /**
  * Contains all necessary functionality for interacting with the Freenet node.
@@ -255,7 +255,7 @@ public class FreenetInterface {
        public void registerActiveUsk(FreenetURI requestUri,
                        USKCallback uskCallback) {
                try {
-                       soneUskCallbacks.put(routingKey(requestUri), uskCallback);
+                       soneUskCallbacks.put(FreenetURIsKt.getRoutingKeyString(requestUri), uskCallback);
                        node.clientCore.uskManager.subscribe(create(requestUri),
                                        uskCallback, true, requestClient);
                } catch (MalformedURLException mue1) {
@@ -267,7 +267,7 @@ public class FreenetInterface {
        public void registerPassiveUsk(FreenetURI requestUri,
                        USKCallback uskCallback) {
                try {
-                       soneUskCallbacks.put(routingKey(requestUri), uskCallback);
+                       soneUskCallbacks.put(FreenetURIsKt.getRoutingKeyString(requestUri), uskCallback);
                        node.clientCore
                                        .uskManager
                                        .subscribe(create(requestUri), uskCallback, false, requestClient);
@@ -327,7 +327,7 @@ public class FreenetInterface {
                };
                try {
                        node.clientCore.uskManager.subscribe(USK.create(uri), uskCallback, true, requestClient);
-                       uriUskCallbacks.put(uri, uskCallback);
+                       uriUskCallbacks.put(USK.create(uri).clearCopy().getURI(), uskCallback);
                } catch (MalformedURLException mue1) {
                        logger.log(Level.WARNING, String.format("Could not subscribe to USK: %s", uri), mue1);
                }
@@ -340,12 +340,12 @@ public class FreenetInterface {
         *            The URI to unregister the USK watcher for
         */
        public void unregisterUsk(FreenetURI uri) {
-               USKCallback uskCallback = uriUskCallbacks.remove(uri);
-               if (uskCallback == null) {
-                       logger.log(Level.INFO, String.format("Could not unregister unknown USK: %s", uri));
-                       return;
-               }
                try {
+                       USKCallback uskCallback = uriUskCallbacks.remove(USK.create(uri).clearCopy().getURI());
+                       if (uskCallback == null) {
+                               logger.log(Level.INFO, String.format("Could not unregister unknown USK: %s", uri));
+                               return;
+                       }
                        node.clientCore.uskManager.unsubscribe(USK.create(uri), uskCallback);
                } catch (MalformedURLException mue1) {
                        logger.log(Level.INFO, String.format("Could not unregister invalid USK: %s", uri), mue1);
index fc76ca9..76519f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - ImageInserter.java - Copyright © 2011–2019 David Roden
+ * Sone - ImageInserter.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index af88dd8..88e33a0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Options.java - Copyright © 2010–2019 David Roden
+ * Sone - Options.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/main/java/net/pterodactylus/sone/core/PreferencesLoader.java b/src/main/java/net/pterodactylus/sone/core/PreferencesLoader.java
deleted file mode 100644 (file)
index a730983..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-package net.pterodactylus.sone.core;
-
-import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired;
-import net.pterodactylus.util.config.Configuration;
-import net.pterodactylus.util.config.ConfigurationException;
-
-/**
- * Loads preferences stored in a {@link Configuration} into a {@link
- * Preferences} object.
- */
-public class PreferencesLoader {
-
-       private final Preferences preferences;
-
-       public PreferencesLoader(Preferences preferences) {
-               this.preferences = preferences;
-       }
-
-       public void loadFrom(Configuration configuration) {
-               loadInsertionDelay(configuration);
-               loadPostsPerPage(configuration);
-               loadImagesPerPage(configuration);
-               loadCharactersPerPost(configuration);
-               loadPostCutOffLength(configuration);
-               loadRequireFullAccess(configuration);
-               loadPositiveTrust(configuration);
-               loadNegativeTrust(configuration);
-               loadTrustComment(configuration);
-               loadFcpInterfaceActive(configuration);
-               loadFcpFullAccessRequired(configuration);
-       }
-
-       private void loadInsertionDelay(Configuration configuration) {
-               preferences.setNewInsertionDelay(configuration.getIntValue(
-                               "Option/InsertionDelay").getValue(null));
-       }
-
-       private void loadPostsPerPage(Configuration configuration) {
-               preferences.setNewPostsPerPage(
-                               configuration.getIntValue("Option/PostsPerPage")
-                                               .getValue(null));
-       }
-
-       private void loadImagesPerPage(Configuration configuration) {
-               preferences.setNewImagesPerPage(
-                               configuration.getIntValue("Option/ImagesPerPage")
-                                               .getValue(null));
-       }
-
-       private void loadCharactersPerPost(Configuration configuration) {
-               preferences.setNewCharactersPerPost(
-                               configuration.getIntValue("Option/CharactersPerPost")
-                                               .getValue(null));
-       }
-
-       private void loadPostCutOffLength(Configuration configuration) {
-               try {
-                       preferences.setNewPostCutOffLength(
-                                       configuration.getIntValue("Option/PostCutOffLength")
-                                                       .getValue(null));
-               } catch (IllegalArgumentException iae1) {
-                       /* previous versions allowed -1, ignore and use default. */
-               }
-       }
-
-       private void loadRequireFullAccess(Configuration configuration) {
-               preferences.setNewRequireFullAccess(
-                               configuration.getBooleanValue("Option/RequireFullAccess")
-                                               .getValue(null));
-       }
-
-       private void loadPositiveTrust(Configuration configuration) {
-               preferences.setNewPositiveTrust(
-                               configuration.getIntValue("Option/PositiveTrust")
-                                               .getValue(null));
-       }
-
-       private void loadNegativeTrust(Configuration configuration) {
-               preferences.setNewNegativeTrust(
-                               configuration.getIntValue("Option/NegativeTrust")
-                                               .getValue(null));
-       }
-
-       private void loadTrustComment(Configuration configuration) {
-               preferences.setNewTrustComment(
-                               configuration.getStringValue("Option/TrustComment")
-                                               .getValue(null));
-       }
-
-       private void loadFcpInterfaceActive(Configuration configuration) {
-               preferences.setNewFcpInterfaceActive(configuration.getBooleanValue(
-                               "Option/ActivateFcpInterface").getValue(null));
-       }
-
-       private void loadFcpFullAccessRequired(Configuration configuration) {
-               Integer fullAccessRequiredInteger = configuration
-                               .getIntValue("Option/FcpFullAccessRequired").getValue(null);
-               preferences.setNewFcpFullAccessRequired(
-                               (fullAccessRequiredInteger == null) ? null :
-                                               FullAccessRequired.values()[fullAccessRequiredInteger]);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/PreferencesLoader.kt b/src/main/java/net/pterodactylus/sone/core/PreferencesLoader.kt
new file mode 100644 (file)
index 0000000..32c35cb
--- /dev/null
@@ -0,0 +1,58 @@
+package net.pterodactylus.sone.core
+
+import net.pterodactylus.sone.fcp.FcpInterface.*
+import net.pterodactylus.util.config.*
+
+/**
+ * Loads preferences stored in a [Configuration] into a [Preferences] object.
+ */
+class PreferencesLoader(private val preferences: Preferences) {
+
+       fun loadFrom(configuration: Configuration) {
+               loadInsertionDelay(configuration)
+               loadPostsPerPage(configuration)
+               loadImagesPerPage(configuration)
+               loadCharactersPerPost(configuration)
+               loadPostCutOffLength(configuration)
+               loadRequireFullAccess(configuration)
+               loadFcpInterfaceActive(configuration)
+               loadFcpFullAccessRequired(configuration)
+       }
+
+       private fun loadInsertionDelay(configuration: Configuration) {
+               preferences.newInsertionDelay = configuration.getIntValue("Option/InsertionDelay").getValue(null)
+       }
+
+       private fun loadPostsPerPage(configuration: Configuration) {
+               preferences.newPostsPerPage = configuration.getIntValue("Option/PostsPerPage").getValue(null)
+       }
+
+       private fun loadImagesPerPage(configuration: Configuration) {
+               preferences.newImagesPerPage = configuration.getIntValue("Option/ImagesPerPage").getValue(null)
+       }
+
+       private fun loadCharactersPerPost(configuration: Configuration) {
+               preferences.newCharactersPerPost = configuration.getIntValue("Option/CharactersPerPost").getValue(null)
+       }
+
+       private fun loadPostCutOffLength(configuration: Configuration) {
+               try {
+                       preferences.newPostCutOffLength = configuration.getIntValue("Option/PostCutOffLength").getValue(null)
+               } catch (iae1: IllegalArgumentException) { /* previous versions allowed -1, ignore and use default. */
+               }
+       }
+
+       private fun loadRequireFullAccess(configuration: Configuration) {
+               preferences.newRequireFullAccess = configuration.getBooleanValue("Option/RequireFullAccess").getValue(null)
+       }
+
+       private fun loadFcpInterfaceActive(configuration: Configuration) {
+               preferences.newFcpInterfaceActive = configuration.getBooleanValue("Option/ActivateFcpInterface").getValue(null)
+       }
+
+       private fun loadFcpFullAccessRequired(configuration: Configuration) {
+               val fullAccessRequiredInteger = configuration.getIntValue("Option/FcpFullAccessRequired").getValue(null)
+               preferences.newFcpFullAccessRequired = fullAccessRequiredInteger?.let { FullAccessRequired.values()[it] }
+       }
+
+}
index ba1c632..0538c8b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneDownloaderImpl.java - Copyright © 2010–2019 David Roden
+ * Sone - SoneDownloaderImpl.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -183,7 +183,7 @@ public class SoneDownloaderImpl extends AbstractService implements SoneDownloade
         * @return The parsed Sone, or {@code null} if the Sone could not be parsed
         */
        private Sone parseSone(Sone originalSone, FetchResult fetchResult, FreenetURI requestUri) {
-               logger.log(Level.FINEST, String.format("Parsing FetchResult (%d bytes, %s) for %s…", fetchResult.size(), fetchResult.getMimeType(), originalSone));
+               logger.finest(() -> format("Parsing FetchResult (%d bytes, %s) for %s…", fetchResult.size(), fetchResult.getMimeType(), originalSone));
                Bucket soneBucket = fetchResult.asBucket();
                InputStream soneInputStream = null;
                try {
@@ -191,12 +191,12 @@ public class SoneDownloaderImpl extends AbstractService implements SoneDownloade
                        Sone parsedSone = soneParser.parseSone(originalSone,
                                        soneInputStream);
                        if (parsedSone != null) {
-                               logger.log(Level.FINER, "Sone %s was successfully parsed.", parsedSone);
+                               logger.finer(() -> format("Sone %s was successfully parsed.", parsedSone));
                                parsedSone.setLatestEdition(requestUri.getEdition());
                        }
                        return parsedSone;
                } catch (Exception e1) {
-                       logger.log(Level.WARNING, String.format("Could not parse Sone from %s!", requestUri), e1);
+                       logger.log(Level.WARNING, e1, () -> format("Could not parse Sone from %s!", requestUri));
                } finally {
                        close(soneInputStream);
                        close(soneBucket);
index e460ee7..152f629 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneException.java - Copyright © 2010–2019 David Roden
+ * Sone - SoneException.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 8a0ff53..4aa71c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneInsertException.java - Copyright © 2011–2019 David Roden
+ * Sone - SoneInsertException.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 79a6259..7ccb374 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneInserter.java - Copyright © 2010–2019 David Roden
+ * Sone - SoneInserter.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@ package net.pterodactylus.sone.core;
 
 import static java.lang.String.format;
 import static java.lang.System.currentTimeMillis;
+import static java.util.concurrent.TimeUnit.*;
 import static java.util.logging.Logger.getLogger;
 import static net.pterodactylus.sone.data.Album.NOT_EMPTY;
 
@@ -31,10 +32,13 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.codahale.metrics.*;
+import com.google.common.base.*;
 import net.pterodactylus.sone.core.SoneModificationDetector.LockableFingerprintProvider;
 import net.pterodactylus.sone.core.event.InsertionDelayChangedEvent;
 import net.pterodactylus.sone.core.event.SoneInsertAbortedEvent;
@@ -58,7 +62,6 @@ import net.pterodactylus.util.template.TemplateParser;
 import net.pterodactylus.util.template.XmlFilter;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Ordering;
 import com.google.common.eventbus.EventBus;
@@ -105,6 +108,8 @@ public class SoneInserter extends AbstractService {
        private final SoneModificationDetector soneModificationDetector;
        private final long delay;
        private final String soneId;
+       private final Histogram soneInsertDurationHistogram;
+       private final Meter soneInsertErrorMeter;
 
        /**
         * Creates a new Sone inserter.
@@ -118,8 +123,8 @@ public class SoneInserter extends AbstractService {
         * @param soneId
         *            The ID of the Sone to insert
         */
-       public SoneInserter(final Core core, EventBus eventBus, FreenetInterface freenetInterface, final String soneId) {
-               this(core, eventBus, freenetInterface, soneId, new SoneModificationDetector(new LockableFingerprintProvider() {
+       public SoneInserter(final Core core, EventBus eventBus, FreenetInterface freenetInterface, MetricRegistry metricRegistry, final String soneId) {
+               this(core, eventBus, freenetInterface, metricRegistry, soneId, new SoneModificationDetector(new LockableFingerprintProvider() {
                        @Override
                        public boolean isLocked() {
                                Sone sone = core.getSone(soneId);
@@ -141,11 +146,13 @@ public class SoneInserter extends AbstractService {
        }
 
        @VisibleForTesting
-       SoneInserter(Core core, EventBus eventBus, FreenetInterface freenetInterface, String soneId, SoneModificationDetector soneModificationDetector, long delay) {
+       SoneInserter(Core core, EventBus eventBus, FreenetInterface freenetInterface, MetricRegistry metricRegistry, String soneId, SoneModificationDetector soneModificationDetector, long delay) {
                super("Sone Inserter for “" + soneId + "”", false);
                this.core = core;
                this.eventBus = eventBus;
                this.freenetInterface = freenetInterface;
+               this.soneInsertDurationHistogram = metricRegistry.histogram("sone.insert.duration", () -> new Histogram(new ExponentiallyDecayingReservoir(3000, 0)));
+               this.soneInsertErrorMeter = metricRegistry.meter("sone.insert.errors");
                this.soneId = soneId;
                this.soneModificationDetector = soneModificationDetector;
                this.delay = delay;
@@ -229,8 +236,11 @@ public class SoneInserter extends AbstractService {
                                                sone.setStatus(SoneStatus.inserting);
                                                long insertTime = currentTimeMillis();
                                                eventBus.post(new SoneInsertingEvent(sone));
+                                               Stopwatch stopwatch = Stopwatch.createStarted();
                                                FreenetURI finalUri = freenetInterface.insertDirectory(sone.getInsertUri(), insertInformation.generateManifestEntries(), "index.html");
-                                               eventBus.post(new SoneInsertedEvent(sone, currentTimeMillis() - insertTime, insertInformation.getFingerprint()));
+                                               stopwatch.stop();
+                                               soneInsertDurationHistogram.update(stopwatch.elapsed(MICROSECONDS));
+                                               eventBus.post(new SoneInsertedEvent(sone, stopwatch.elapsed(MILLISECONDS), insertInformation.getFingerprint()));
                                                /* at this point we might already be stopped. */
                                                if (shouldStop()) {
                                                        /* if so, bail out, don’t change anything. */
@@ -242,6 +252,7 @@ public class SoneInserter extends AbstractService {
                                                success = true;
                                                logger.log(Level.INFO, String.format("Inserted Sone “%s” at %s.", sone.getName(), finalUri));
                                        } catch (SoneException se1) {
+                                               soneInsertErrorMeter.mark();
                                                eventBus.post(new SoneInsertAbortedEvent(sone, se1));
                                                logger.log(Level.WARNING, String.format("Could not insert Sone “%s”!", sone.getName()), se1);
                                        } finally {
index 92fa3dc..e5e20d9 100644 (file)
@@ -24,7 +24,7 @@ class SoneModificationDetector {
        private final Ticker ticker;
        private final LockableFingerprintProvider lockableFingerprintProvider;
        private final AtomicInteger insertionDelay;
-       private Optional<Long> lastModificationTime;
+       private Long lastModificationTime;
        private String lastInsertFingerprint;
        private String lastCheckFingerprint;
 
@@ -42,18 +42,18 @@ class SoneModificationDetector {
 
        public boolean isEligibleForInsert() {
                if (lockableFingerprintProvider.isLocked()) {
-                       lastModificationTime = absent();
+                       lastModificationTime = null;
                        lastCheckFingerprint = "";
                        return false;
                }
                String fingerprint = lockableFingerprintProvider.getFingerprint();
                if (fingerprint.equals(lastInsertFingerprint)) {
-                       lastModificationTime = absent();
+                       lastModificationTime = null;
                        lastCheckFingerprint = fingerprint;
                        return false;
                }
                if (!Objects.equal(lastCheckFingerprint, fingerprint)) {
-                       lastModificationTime = of(ticker.read());
+                       lastModificationTime = ticker.read();
                        lastCheckFingerprint = fingerprint;
                        return false;
                }
@@ -67,11 +67,11 @@ class SoneModificationDetector {
        public void setFingerprint(String fingerprint) {
                lastInsertFingerprint = fingerprint;
                lastCheckFingerprint = lastInsertFingerprint;
-               lastModificationTime = absent();
+               lastModificationTime = null;
        }
 
        private boolean insertionDelayHasPassed() {
-               return NANOSECONDS.toSeconds(ticker.read() - lastModificationTime.get()) >= insertionDelay.get();
+               return NANOSECONDS.toSeconds(ticker.read() - lastModificationTime) >= insertionDelay.get();
        }
 
        public boolean isModified() {
index 1f30565..e1fd9ff 100644 (file)
@@ -1,38 +1,24 @@
 package net.pterodactylus.sone.core;
 
-import static java.util.logging.Logger.getLogger;
-import static net.pterodactylus.sone.utils.NumberParsers.parseInt;
-import static net.pterodactylus.sone.utils.NumberParsers.parseLong;
+import static java.util.concurrent.TimeUnit.*;
+import static java.util.logging.Logger.*;
+import static net.pterodactylus.sone.utils.NumberParsers.*;
 
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.io.*;
+import java.util.*;
+import java.util.logging.*;
 
-import javax.inject.Inject;
+import javax.annotation.*;
+import javax.inject.*;
 
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Client;
-import net.pterodactylus.sone.data.Image;
-import net.pterodactylus.sone.data.Post;
-import net.pterodactylus.sone.data.PostReply;
-import net.pterodactylus.sone.data.Profile;
-import net.pterodactylus.sone.data.Profile.DuplicateField;
-import net.pterodactylus.sone.data.Profile.EmptyFieldName;
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.database.Database;
-import net.pterodactylus.sone.database.PostBuilder;
-import net.pterodactylus.sone.database.PostReplyBuilder;
-import net.pterodactylus.sone.database.SoneBuilder;
-import net.pterodactylus.util.xml.SimpleXML;
-import net.pterodactylus.util.xml.XML;
+import net.pterodactylus.sone.data.*;
+import net.pterodactylus.sone.data.Profile.*;
+import net.pterodactylus.sone.database.*;
+import net.pterodactylus.util.xml.*;
 
-import org.w3c.dom.Document;
+import com.codahale.metrics.*;
+import com.google.common.base.*;
+import org.w3c.dom.*;
 
 /**
  * Parses a {@link Sone} from an XML {@link InputStream}.
@@ -42,15 +28,19 @@ public class SoneParser {
        private static final Logger logger = getLogger(SoneParser.class.getName());
        private static final int MAX_PROTOCOL_VERSION = 0;
        private final Database database;
+       private final Histogram soneParsingDurationHistogram;
 
        @Inject
-       public SoneParser(Database database) {
+       public SoneParser(Database database, MetricRegistry metricRegistry) {
                this.database = database;
+               this.soneParsingDurationHistogram = metricRegistry.histogram("sone.parse.duration", () -> new Histogram(new ExponentiallyDecayingReservoir(3000, 0)));
        }
 
+       @Nullable
        public Sone parseSone(Sone originalSone, InputStream soneInputStream) throws SoneException {
                /* TODO - impose a size limit? */
 
+               Stopwatch stopwatch = Stopwatch.createStarted();
                Document document;
                /* XML parsing is not thread-safe. */
                synchronized (this) {
@@ -257,6 +247,7 @@ public class SoneParser {
                SimpleXML albumsXml = soneXml.getNode("albums");
                Map<String, Image> allImages = new HashMap<>();
                List<Album> topLevelAlbums = new ArrayList<>();
+               Map<String, Album> allAlbums = new HashMap<>();
                if (albumsXml != null) {
                        for (SimpleXML albumXml : albumsXml.getNodes("album")) {
                                String id = albumXml.getValue("id", null);
@@ -269,7 +260,7 @@ public class SoneParser {
                                }
                                Album parent = null;
                                if (parentId != null) {
-                                       parent = database.getAlbum(parentId);
+                                       parent = allAlbums.get(parentId);
                                        if (parent == null) {
                                                logger.log(Level.WARNING, String.format("Downloaded Sone %s has album with invalid parent!", sone));
                                                return null;
@@ -288,6 +279,7 @@ public class SoneParser {
                                } else {
                                        topLevelAlbums.add(album);
                                }
+                               allAlbums.put(album.getId(), album);
                                SimpleXML imagesXml = albumXml.getNode("images");
                                if (imagesXml != null) {
                                        for (SimpleXML imageXml : imagesXml.getNodes("image")) {
@@ -334,6 +326,11 @@ public class SoneParser {
                        sone.getRootAlbum().addAlbum(album);
                }
 
+               // record the duration
+               stopwatch.stop();
+               soneParsingDurationHistogram.update(stopwatch.elapsed(MICROSECONDS));
+               logger.fine(() -> "Parsed " + originalSone.getIdentity().getId() + "@" + originalSone.getLatestEdition() + " in " + stopwatch.elapsed(MICROSECONDS) + "μs.");
+
                return sone;
 
        }
index 2246ac9..2a1d14d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneRescuer.java - Copyright © 2011–2019 David Roden
+ * Sone - SoneRescuer.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 373077f..a929950 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneUri.java - Copyright © 2013–2019 David Roden
+ * Sone - SoneUri.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/main/java/net/pterodactylus/sone/core/UpdateChecker.java b/src/main/java/net/pterodactylus/sone/core/UpdateChecker.java
deleted file mode 100644 (file)
index 9f6963f..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Sone - UpdateChecker.java - Copyright © 2011–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core;
-
-import static java.util.logging.Logger.getLogger;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.util.Date;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.inject.Singleton;
-
-import net.pterodactylus.sone.core.event.UpdateFoundEvent;
-import net.pterodactylus.sone.main.PluginHomepage;
-import net.pterodactylus.sone.main.SonePlugin;
-import net.pterodactylus.util.io.Closer;
-import net.pterodactylus.util.version.Version;
-
-import com.google.common.eventbus.EventBus;
-import com.google.inject.Inject;
-
-import freenet.keys.FreenetURI;
-import freenet.support.api.Bucket;
-
-/**
- * Watches the official Sone homepage for new releases.
- */
-@Singleton
-public class UpdateChecker {
-
-       /** The logger. */
-       private static final Logger logger = getLogger(UpdateChecker.class.getName());
-
-       /** The event bus. */
-       private final EventBus eventBus;
-
-       /** The Freenet interface. */
-       private final FreenetInterface freenetInterface;
-
-       /** The current URI of the homepage. */
-       private FreenetURI currentUri;
-
-       /** The latest known edition. */
-       private long latestEdition = SonePlugin.getLatestEdition();
-
-       /** The current latest known version. */
-       private Version currentLatestVersion;
-       private final Version currentRunningVersion;
-
-       /** The release date of the latest version. */
-       private long latestVersionDate;
-
-       private final PluginHomepage pluginHomepage;
-
-       /**
-        * Creates a new update checker.
-        *
-        * @param eventBus
-        *            The event bus
-        * @param freenetInterface
-        *            The freenet interface to use
-        */
-       @Inject
-       public UpdateChecker(EventBus eventBus, FreenetInterface freenetInterface, Version currentVersion, PluginHomepage pluginHomepage) {
-               this.eventBus = eventBus;
-               this.freenetInterface = freenetInterface;
-               this.currentRunningVersion = currentVersion;
-               this.currentLatestVersion = currentVersion;
-               this.pluginHomepage = pluginHomepage;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns whether a version that is later than the currently running
-        * version has been found.
-        *
-        * @return {@code true} if a new version was found
-        */
-       public boolean hasLatestVersion() {
-               return currentLatestVersion.compareTo(currentRunningVersion) > 0;
-       }
-
-       /**
-        * Returns the latest version. If no new latest version has been found, the
-        * current version is returned.
-        *
-        * @return The latest known version
-        */
-       public Version getLatestVersion() {
-               return currentLatestVersion;
-       }
-
-       /**
-        * Returns the release time of the latest version. If no new latest version
-        * has been found, the returned value is undefined.
-        *
-        * @return The release time of the latest version, if a new version was
-        *         found
-        */
-       public long getLatestVersionDate() {
-               return latestVersionDate;
-       }
-
-       /**
-        * Returns the latest known edition of the Sone homepage.
-        *
-        * @return The latest edition of the Sone homepage
-        */
-       public long getLatestEdition() {
-               return latestEdition;
-       }
-
-       //
-       // ACTIONS
-       //
-
-       /**
-        * Starts the update checker.
-        */
-       public void start() {
-               try {
-                       currentUri = new FreenetURI(pluginHomepage.getHomepage());
-               } catch (MalformedURLException mue1) {
-                       /* this can not really happen unless I screw up. */
-                       logger.log(Level.SEVERE, "Sone Homepage URI invalid!", mue1);
-               }
-               freenetInterface.registerUsk(currentUri, new FreenetInterface.Callback() {
-
-                       @Override
-                       @SuppressWarnings("synthetic-access")
-                       public void editionFound(FreenetURI uri, long edition, boolean newKnownGood, boolean newSlot) {
-                               logger.log(Level.FINEST, String.format("Found update for %s: %d, %s, %s", uri, edition, newKnownGood, newSlot));
-                               if (newKnownGood || newSlot) {
-                                       Fetched uriResult = freenetInterface.fetchUri(uri.setMetaString(new String[] { "sone.properties" }));
-                                       if (uriResult == null) {
-                                               logger.log(Level.WARNING, String.format("Could not fetch properties of latest homepage: %s", uri));
-                                               return;
-                                       }
-                                       Bucket resultBucket = uriResult.getFetchResult().asBucket();
-                                       try {
-                                               parseProperties(resultBucket.getInputStream(), edition);
-                                               latestEdition = edition;
-                                       } catch (IOException ioe1) {
-                                               logger.log(Level.WARNING, String.format("Could not parse sone.properties of %s!", uri), ioe1);
-                                       } finally {
-                                               resultBucket.free();
-                                       }
-                               }
-                       }
-               });
-       }
-
-       /**
-        * Stops the update checker.
-        */
-       public void stop() {
-               freenetInterface.unregisterUsk(currentUri);
-       }
-
-       //
-       // PRIVATE ACTIONS
-       //
-
-       /**
-        * Parses the properties of the latest version and fires events, if
-        * necessary.
-        *
-        * @see UpdateFoundEvent
-        * @param propertiesInputStream
-        *            The input stream to parse
-        * @param edition
-        *            The latest edition of the Sone homepage
-        * @throws IOException
-        *             if an I/O error occured
-        */
-       private void parseProperties(InputStream propertiesInputStream, long edition) throws IOException {
-               Properties properties = new Properties();
-               InputStreamReader inputStreamReader = null;
-               try {
-                       inputStreamReader = new InputStreamReader(propertiesInputStream, "UTF-8");
-                       properties.load(inputStreamReader);
-               } finally {
-                       Closer.close(inputStreamReader);
-               }
-               String versionString = properties.getProperty("CurrentVersion/Version");
-               String releaseTimeString = properties.getProperty("CurrentVersion/ReleaseTime");
-               if ((versionString == null) || (releaseTimeString == null)) {
-                       logger.log(Level.INFO, "Invalid data parsed from properties.");
-                       return;
-               }
-               Version version = Version.parse(versionString);
-               long releaseTime = 0;
-               try {
-                       releaseTime = Long.parseLong(releaseTimeString);
-               } catch (NumberFormatException nfe1) {
-                       /* ignore. */
-               }
-               if ((version == null) || (releaseTime == 0)) {
-                       logger.log(Level.INFO, "Could not parse data from properties.");
-                       return;
-               }
-               if (version.compareTo(currentLatestVersion) > 0) {
-                       currentLatestVersion = version;
-                       latestVersionDate = releaseTime;
-                       boolean disruptive = disruptiveVersionBetweenCurrentAndFound(properties);
-                       logger.log(Level.INFO, String.format("Found new version: %s (%tc%s)", version, new Date(releaseTime), disruptive ? ", disruptive" : ""));
-                       eventBus.post(new UpdateFoundEvent(version, releaseTime, edition, disruptive));
-               }
-       }
-
-       private boolean disruptiveVersionBetweenCurrentAndFound(Properties properties) {
-               for (String key : properties.stringPropertyNames()) {
-                       if (key.startsWith("DisruptiveVersion/")) {
-                               Version disruptiveVersion = Version.parse(key.substring("DisruptiveVersion/".length()));
-                               if (disruptiveVersion.compareTo(currentRunningVersion) > 0) {
-                                       return true;
-                               }
-                       }
-               }
-               return false;
-       }
-
-}
index 35c3203..95d066d 100644 (file)
@@ -1,6 +1,5 @@
 package net.pterodactylus.sone.core;
 
-import net.pterodactylus.sone.freenet.wot.Identity;
 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
 import net.pterodactylus.util.service.Service;
 
@@ -12,7 +11,6 @@ import com.google.inject.ImplementedBy;
 @ImplementedBy(WebOfTrustUpdaterImpl.class)
 public interface WebOfTrustUpdater extends Service {
 
-       void setTrust(OwnIdentity truster, Identity trustee, Integer score, String comment);
        boolean addContextWait(OwnIdentity ownIdentity, String context);
        void removeContext(OwnIdentity ownIdentity, String context);
        void setProperty(OwnIdentity ownIdentity, String propertyName, String propertyValue);
index 809ca20..da27152 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - WebOfTrustUpdaterImpl.java - Copyright © 2013–2019 David Roden
+ * Sone - WebOfTrustUpdaterImpl.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,11 +26,8 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import net.pterodactylus.sone.freenet.plugin.PluginException;
-import net.pterodactylus.sone.freenet.wot.Identity;
 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
-import net.pterodactylus.sone.freenet.wot.Trust;
 import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector;
-import net.pterodactylus.sone.freenet.wot.WebOfTrustException;
 import net.pterodactylus.util.service.AbstractService;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -74,34 +71,6 @@ public class WebOfTrustUpdaterImpl extends AbstractService implements WebOfTrust
        //
 
        /**
-        * Updates the trust relation between the truster and the trustee. This method
-        * will return immediately and perform a trust update in the background.
-        *
-        * @param truster
-        *              The identity giving the trust
-        * @param trustee
-        *              The identity receiving the trust
-        * @param score
-        *              The new level of trust (from -100 to 100, may be {@code null} to remove
-        *              the trust completely)
-        * @param comment
-        *              The comment of the trust relation
-        */
-       @Override
-       public void setTrust(OwnIdentity truster, Identity trustee, Integer score, String comment) {
-               SetTrustJob setTrustJob = new SetTrustJob(truster, trustee, score, comment);
-               if (updateJobs.contains(setTrustJob)) {
-                       updateJobs.remove(setTrustJob);
-               }
-               logger.log(Level.FINER, "Adding Trust Update Job: " + setTrustJob);
-               try {
-                       updateJobs.put(setTrustJob);
-               } catch (InterruptedException e) {
-                       /* the queue is unbounded so it should never block. */
-               }
-       }
-
-       /**
         * Adds the given context to the given own identity, waiting for completion of
         * the operation.
         *
@@ -297,91 +266,6 @@ public class WebOfTrustUpdaterImpl extends AbstractService implements WebOfTrust
        }
 
        /**
-        * Update job that sets the trust relation between two identities.
-        */
-       @VisibleForTesting
-       class SetTrustJob extends WebOfTrustUpdateJob {
-
-               /** The identity giving the trust. */
-               private final OwnIdentity truster;
-
-               /** The identity receiving the trust. */
-               private final Identity trustee;
-
-               /** The score of the relation. */
-               private final Integer score;
-
-               /** The comment of the relation. */
-               private final String comment;
-
-               /**
-                * Creates a new set trust job.
-                *
-                * @param truster
-                *              The identity giving the trust
-                * @param trustee
-                *              The identity receiving the trust
-                * @param score
-                *              The score of the trust (from -100 to 100, may be {@code null} to remote
-                *              the trust relation completely)
-                * @param comment
-                *              The comment of the trust relation
-                */
-               public SetTrustJob(OwnIdentity truster, Identity trustee, Integer score, String comment) {
-                       this.truster = checkNotNull(truster, "truster must not be null");
-                       this.trustee = checkNotNull(trustee, "trustee must not be null");
-                       this.score = score;
-                       this.comment = comment;
-               }
-
-               /** {@inheritDoc} */
-               @Override
-               @SuppressWarnings("synthetic-access")
-               public void run() {
-                       try {
-                               if (score != null) {
-                                       webOfTrustConnector.setTrust(truster, trustee, score, comment);
-                                       trustee.setTrust(truster, new Trust(score, null, 0));
-                               } else {
-                                       webOfTrustConnector.removeTrust(truster, trustee);
-                                       trustee.removeTrust(truster);
-                               }
-                               finish(true);
-                       } catch (WebOfTrustException wote1) {
-                               logger.log(Level.WARNING, "Could not set Trust value for " + truster + " -> " + trustee + " to " + score + " (" + comment + ")!", wote1);
-                               finish(false);
-                       }
-               }
-
-               //
-               // OBJECT METHODS
-               //
-
-               /** {@inheritDoc} */
-               @Override
-               public boolean equals(Object object) {
-                       if ((object == null) || !object.getClass().equals(getClass())) {
-                               return false;
-                       }
-                       SetTrustJob updateJob = (SetTrustJob) object;
-                       return updateJob.truster.equals(truster) && updateJob.trustee.equals(trustee);
-               }
-
-               /** {@inheritDoc} */
-               @Override
-               public int hashCode() {
-                       return getClass().hashCode() ^ truster.hashCode() ^ trustee.hashCode();
-               }
-
-               /** {@inheritDoc} */
-               @Override
-               public String toString() {
-                       return String.format("%s[truster=%s,trustee=%s]", getClass().getSimpleName(), truster.getId(), trustee.getId());
-               }
-
-       }
-
-       /**
         * Base class for context updates of an {@link OwnIdentity}.
         */
        @VisibleForTesting
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageEvent.java
deleted file mode 100644 (file)
index 6daef1a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Sone - ImageEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-
-/**
- * Base class for {@link Image} events.
- */
-public abstract class ImageEvent {
-
-       /** The image this event is about. */
-       private final Image image;
-
-       /**
-        * Creates a new image event.
-        *
-        * @param image
-        *            The image this event is about
-        */
-       protected ImageEvent(Image image) {
-               this.image = image;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the image this event is about.
-        *
-        * @return The image this event is about
-        */
-       public Image image() {
-               return image;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageInsertAbortedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageInsertAbortedEvent.java
deleted file mode 100644 (file)
index 2bfa3a2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - ImageInsertAbortedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-
-/**
- * Event that signals that an {@link Image} insert is aborted.
- */
-public class ImageInsertAbortedEvent extends ImageEvent {
-
-       /**
-        * Creates a new “image insert aborted” event.
-        *
-        * @param image
-        *            The image whose insert aborted
-        */
-       public ImageInsertAbortedEvent(Image image) {
-               super(image);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageInsertFailedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageInsertFailedEvent.java
deleted file mode 100644 (file)
index 430c64b..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Sone - ImageInsertFailedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-
-/**
- * Event that signals that an {@link Image} insert has failed.
- */
-public class ImageInsertFailedEvent extends ImageEvent {
-
-       /** The cause of the insert failure. */
-       private final Throwable cause;
-
-       /**
-        * Creates a new “image insert failed” event.
-        *
-        * @param image
-        *            The image whose insert failed
-        * @param cause
-        *            The cause of the insert failure
-        */
-       public ImageInsertFailedEvent(Image image, Throwable cause) {
-               super(image);
-               this.cause = cause;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the cause of the insert failure.
-        *
-        * @return The cause of the insert failure
-        */
-       public Throwable cause() {
-               return cause;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageInsertFinishedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageInsertFinishedEvent.java
deleted file mode 100644 (file)
index 4419311..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Sone - ImageInsertFinishedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-import freenet.keys.FreenetURI;
-
-/**
- * Event that signals that an {@link Image} insert is finished.
- */
-public class ImageInsertFinishedEvent extends ImageEvent {
-
-       /** The URI of the image. */
-       private final FreenetURI resultingUri;
-
-       /**
-        * Creates a new “image insert finished” event.
-        *
-        * @param image
-        *            The image whose insert finished
-        * @param resultingUri
-        *            The resulting URI of the image
-        */
-       public ImageInsertFinishedEvent(Image image, FreenetURI resultingUri) {
-               super(image);
-               this.resultingUri = resultingUri;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the URI of the image.
-        *
-        * @return The URI of the image
-        */
-       public FreenetURI resultingUri() {
-               return resultingUri;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageInsertStartedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageInsertStartedEvent.java
deleted file mode 100644 (file)
index ac9e3e3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - ImageInsertStartedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-
-/**
- * Event that signals that an {@link Image} is not being inserted.
- */
-public class ImageInsertStartedEvent extends ImageEvent {
-
-       /**
-        * Creates a new “image is inserted” event.
-        *
-        * @param image
-        *            The image that is being inserted
-        */
-       public ImageInsertStartedEvent(Image image) {
-               super(image);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/MarkPostKnownEvent.java b/src/main/java/net/pterodactylus/sone/core/event/MarkPostKnownEvent.java
deleted file mode 100644 (file)
index 7c8a6c3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - MarkPostKnownEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Post;
-
-/**
- * Event that signals that a {@link Post} has been marked as
- * {@link Post#isKnown() known}.
- */
-public class MarkPostKnownEvent extends PostEvent {
-
-       /**
-        * Creates a new “post marked known” event.
-        *
-        * @param post
-        *            The post that was marked as known
-        */
-       public MarkPostKnownEvent(Post post) {
-               super(post);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/MarkPostReplyKnownEvent.java b/src/main/java/net/pterodactylus/sone/core/event/MarkPostReplyKnownEvent.java
deleted file mode 100644 (file)
index 4c0e2fc..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - MarkPostReplyKnownEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.PostReply;
-
-/**
- * Event that signals that a {@link PostReply} has been marked as
- * {@link PostReply#isKnown() known}.
- */
-public class MarkPostReplyKnownEvent extends PostReplyEvent {
-
-       /**
-        * Creates a new “post reply marked known” event.
-        *
-        * @param postReply
-        *            The post reply that was marked as known
-        */
-       public MarkPostReplyKnownEvent(PostReply postReply) {
-               super(postReply);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/MarkSoneKnownEvent.java b/src/main/java/net/pterodactylus/sone/core/event/MarkSoneKnownEvent.java
deleted file mode 100644 (file)
index 5bbdf5e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - MarkSoneKnownEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} has been marked as
- * {@link Sone#isKnown() known}.
- */
-public class MarkSoneKnownEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone marked known” event.
-        *
-        * @param sone
-        *            The Sone that was marked as known
-        */
-       public MarkSoneKnownEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/NewSoneFoundEvent.java b/src/main/java/net/pterodactylus/sone/core/event/NewSoneFoundEvent.java
deleted file mode 100644 (file)
index 8fb17d2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - NewSoneFoundEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a new remote Sone was found.
- */
-public class NewSoneFoundEvent extends SoneEvent {
-
-       /**
-        * Creates a new “new Sone found” event.
-        *
-        * @param sone
-        *            The Sone that was found
-        */
-       public NewSoneFoundEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/PostEvent.java b/src/main/java/net/pterodactylus/sone/core/event/PostEvent.java
deleted file mode 100644 (file)
index 93a61c6..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Sone - PostEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Post;
-
-/**
- * Base class for post events.
- */
-public class PostEvent {
-
-       /** The post the event is about. */
-       private final Post post;
-
-       /**
-        * Creates a new post event.
-        *
-        * @param post
-        *            The post the event is about
-        */
-       protected PostEvent(Post post) {
-               this.post = post;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the post the event is about.
-        *
-        * @return The post the event is about
-        */
-       public Post post() {
-               return post;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/PostReplyEvent.java b/src/main/java/net/pterodactylus/sone/core/event/PostReplyEvent.java
deleted file mode 100644 (file)
index e31870b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Sone - PostReplyEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.PostReply;
-
-/**
- * Base class for {@link PostReply} events.
- */
-public class PostReplyEvent {
-
-       /** The post reply the event is about. */
-       private final PostReply postReply;
-
-       /**
-        * Creates a new post reply event.
-        *
-        * @param postReply
-        *            The post reply the event is about
-        */
-       protected PostReplyEvent(PostReply postReply) {
-               this.postReply = postReply;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the post reply the event is about.
-        *
-        * @return The post reply the event is about
-        */
-       public PostReply postReply() {
-               return postReply;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneEvent.java
deleted file mode 100644 (file)
index b7497ff..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Sone - SoneEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Base class for Sone events.
- */
-public abstract class SoneEvent {
-
-       /** The Sone this event is about. */
-       private final Sone sone;
-
-       /**
-        * Creates a new Sone event.
-        *
-        * @param sone
-        *            The Sone this event is about
-        */
-       protected SoneEvent(Sone sone) {
-               this.sone = sone;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the Sone this event is about.
-        *
-        * @return The Sone this event is about
-        */
-       public Sone sone() {
-               return sone;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneInsertAbortedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneInsertAbortedEvent.java
deleted file mode 100644 (file)
index a8c9bb6..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Sone - SoneInsertAbortedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} insert was aborted.
- */
-public class SoneInsertAbortedEvent extends SoneEvent {
-
-       /** The cause of the abortion. */
-       private final Throwable cause;
-
-       /**
-        * Creates a new “Sone was inserted” event.
-        *
-        * @param sone
-        *            The Sone that was inserted
-        * @param cause
-        *            The cause of the abortion
-        */
-       public SoneInsertAbortedEvent(Sone sone, Throwable cause) {
-               super(sone);
-               this.cause = cause;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the cause of the abortion.
-        *
-        * @return The cause of the abortion (may be {@code null})
-        */
-       public Throwable cause() {
-               return cause;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneInsertedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneInsertedEvent.java
deleted file mode 100644 (file)
index 53fa935..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Sone - SoneInsertedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} was inserted.
- */
-public class SoneInsertedEvent extends SoneEvent {
-
-       private final long insertDuration;
-       private final String insertFingerprint;
-
-       public SoneInsertedEvent(Sone sone, long insertDuration, String insertFingerprint) {
-               super(sone);
-               this.insertDuration = insertDuration;
-               this.insertFingerprint = insertFingerprint;
-       }
-
-       public long insertDuration() {
-               return insertDuration;
-       }
-
-       public String insertFingerprint() {
-               return insertFingerprint;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneInsertingEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneInsertingEvent.java
deleted file mode 100644 (file)
index a9ef6fb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - SoneInsertingEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} is now being inserted.
- */
-public class SoneInsertingEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone is being inserted” event.
-        *
-        * @param sone
-        *            The Sone that is being inserted
-        */
-       public SoneInsertingEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneLockedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneLockedEvent.java
deleted file mode 100644 (file)
index cdc9e3a..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - SoneLockedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} was locked. Only
- * {@link Sone#isLocal() local Sones} can be locked.
- */
-public class SoneLockedEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone locked” event.
-        *
-        * @param sone
-        *            The Sone that was locked
-        */
-       public SoneLockedEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneRemovedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneRemovedEvent.java
deleted file mode 100644 (file)
index e46272d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - SoneRemovedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} was removed.
- */
-public class SoneRemovedEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone removed” event.
-        *
-        * @param sone
-        *            The Sone that was removed
-        */
-       public SoneRemovedEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneUnlockedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneUnlockedEvent.java
deleted file mode 100644 (file)
index 106d32d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - SoneUnlockedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} was unlocked. Only
- * {@link Sone#isLocal() local Sones} can be locked.
- */
-public class SoneUnlockedEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone unlocked” event.
-        *
-        * @param sone
-        *            The Sone that was unlocked
-        */
-       public SoneUnlockedEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/UpdateFoundEvent.java b/src/main/java/net/pterodactylus/sone/core/event/UpdateFoundEvent.java
deleted file mode 100644 (file)
index 2884090..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Sone - UpdateFoundEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.util.version.Version;
-
-/**
- * Event that signals that an update for Sone was found.
- */
-public class UpdateFoundEvent {
-
-       private final Version version;
-       private final long releaseTime;
-       private final long latestEdition;
-       private final boolean disruptive;
-
-       public UpdateFoundEvent(Version version, long releaseTime, long latestEdition, boolean disruptive) {
-               this.version = version;
-               this.releaseTime = releaseTime;
-               this.latestEdition = latestEdition;
-               this.disruptive = disruptive;
-       }
-
-       public Version version() {
-               return version;
-       }
-
-       public long releaseTime() {
-               return releaseTime;
-       }
-
-       public long latestEdition() {
-               return latestEdition;
-       }
-
-       public boolean disruptive() {
-               return disruptive;
-       }
-
-}
index c4af294..576c73a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Album.java - Copyright © 2011–2019 David Roden
+ * Sone - Album.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index f23decf..7642957 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Client.java - Copyright © 2010–2019 David Roden
+ * Sone - Client.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -81,4 +81,9 @@ public class Client {
                return Objects.hashCode(name, version);
        }
 
+       @Override
+       public String toString() {
+               return name + " " + version;
+       }
+
 }
index 93d0702..8414f3a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Image.java - Copyright © 2011–2019 David Roden
+ * Sone - Image.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index b6648e2..a4a794e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Post.java - Copyright © 2010–2019 David Roden
+ * Sone - Post.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index dc4a903..f5ffea3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - PostReply.java - Copyright © 2010–2019 David Roden
+ * Sone - PostReply.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 8ea09f7..b87ef4f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Profile.java - Copyright © 2010–2019 David Roden
+ * Sone - Profile.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index c596605..120575e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Reply.java - Copyright © 2010–2019 David Roden
+ * Sone - Reply.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 273b73e..b43d025 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Sone.java - Copyright © 2010–2019 David Roden
+ * Sone - Sone.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 378a348..b76c3cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - TemporaryImage.java - Copyright © 2011–2019 David Roden
+ * Sone - TemporaryImage.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 460be4e..04b0eac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractAlbumBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractAlbumBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index f545ae9..56ceb6d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractImageBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractImageBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index cabe8d5..ca927b2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractPostBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractPostBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 0fe124e..8dffdcd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractPostReplyBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractPostReplyBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 052ca2d..7e95f38 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractReplyBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractReplyBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 601daa8..696d08d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AlbumBuilderImpl.java - Copyright © 2013–2019 David Roden
+ * Sone - AlbumBuilderImpl.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 3ec362f..04ab8e9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AlbumImpl.java - Copyright © 2011–2019 David Roden
+ * Sone - AlbumImpl.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.data.impl;
 
-import static com.google.common.base.Optional.absent;
-import static com.google.common.base.Optional.fromNullable;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Image;
-import net.pterodactylus.sone.data.Sone;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Collections2;
-import com.google.common.hash.Hasher;
+import java.util.*;
+import javax.annotation.*;
+
+import com.google.common.base.*;
+import com.google.common.collect.*;
 import com.google.common.hash.Hashing;
+import com.google.common.hash.*;
+import net.pterodactylus.sone.data.*;
+
+import static com.google.common.base.Preconditions.*;
+import static java.nio.charset.StandardCharsets.*;
 
 /**
  * Container for images that can also contain nested {@link AlbumImpl}s.
@@ -258,32 +247,33 @@ public class AlbumImpl implements Album {
        public Modifier modify() throws IllegalStateException {
                // TODO: reenable check for local Sones
                return new Modifier() {
-                       private Optional<String> title = absent();
-
-                       private Optional<String> description = absent();
+                       @Nullable
+                       private String title;
+                       @Nullable
+                       private String description;
 
                        @Override
                        public Modifier setTitle(String title) {
-                               this.title = fromNullable(title);
+                               this.title = title;
                                return this;
                        }
 
                        @Override
                        public Modifier setDescription(String description) {
-                               this.description = fromNullable(description);
+                               this.description = description;
                                return this;
                        }
 
                        @Override
                        public Album update() throws IllegalStateException {
-                               if (title.isPresent() && title.get().trim().isEmpty()) {
+                               if (title != null && title.trim().isEmpty()) {
                                        throw new AlbumTitleMustNotBeEmpty();
                                }
-                               if (title.isPresent()) {
-                                       AlbumImpl.this.title = title.get();
+                               if (title != null) {
+                                       AlbumImpl.this.title = title;
                                }
-                               if (description.isPresent()) {
-                                       AlbumImpl.this.description = description.get();
+                               if (description != null) {
+                                       AlbumImpl.this.description = description;
                                }
                                return AlbumImpl.this;
                        }
index b62cc40..e74b71a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - ImageBuilderImpl.java - Copyright © 2013–2019 David Roden
+ * Sone - ImageBuilderImpl.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index a54a8de..0dd84fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - ImageImpl.java - Copyright © 2011–2019 David Roden
+ * Sone - ImageImpl.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  */
 package net.pterodactylus.sone.data.impl;
 
-import static com.google.common.base.Optional.absent;
-import static com.google.common.base.Optional.fromNullable;
-import static com.google.common.base.Optional.of;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static java.nio.charset.StandardCharsets.UTF_8;
+import java.util.*;
+import javax.annotation.*;
 
-import java.util.UUID;
+import com.google.common.hash.*;
+import net.pterodactylus.sone.data.*;
 
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Image;
-import net.pterodactylus.sone.data.Sone;
-
-import com.google.common.base.Optional;
-import com.google.common.hash.Hasher;
-import com.google.common.hash.Hashing;
+import static com.google.common.base.Preconditions.*;
+import static java.nio.charset.StandardCharsets.*;
 
 /**
  * Container for image metadata.
@@ -146,93 +138,94 @@ public class ImageImpl implements Image {
        public Modifier modify() throws IllegalStateException {
                // TODO: reenable check for local images
                return new Modifier() {
-                       private Optional<Sone> sone = absent();
-
-                       private Optional<Long> creationTime = absent();
-
-                       private Optional<String> key = absent();
-
-                       private Optional<String> title = absent();
-
-                       private Optional<String> description = absent();
-
-                       private Optional<Integer> width = absent();
-
-                       private Optional<Integer> height = absent();
+                       @Nullable
+                       private Sone sone;
+                       @Nullable
+                       private Long creationTime;
+                       @Nullable
+                       private String key;
+                       @Nullable
+                       private String title;
+                       @Nullable
+                       private String description;
+                       @Nullable
+                       private Integer width;
+                       @Nullable
+                       private Integer height;
 
                        @Override
                        public Modifier setSone(Sone sone) {
-                               this.sone = fromNullable(sone);
+                               this.sone = sone;
                                return this;
                        }
 
                        @Override
                        public Modifier setCreationTime(long creationTime) {
-                               this.creationTime = of(creationTime);
+                               this.creationTime = creationTime;
                                return this;
                        }
 
                        @Override
                        public Modifier setKey(String key) {
-                               this.key = fromNullable(key);
+                               this.key = key;
                                return this;
                        }
 
                        @Override
                        public Modifier setTitle(String title) {
-                               this.title = fromNullable(title);
+                               this.title = title;
                                return this;
                        }
 
                        @Override
                        public Modifier setDescription(String description) {
-                               this.description = fromNullable(description);
+                               this.description = description;
                                return this;
                        }
 
                        @Override
                        public Modifier setWidth(int width) {
-                               this.width = of(width);
+                               this.width = width;
                                return this;
                        }
 
                        @Override
                        public Modifier setHeight(int height) {
-                               this.height = of(height);
+                               this.height = height;
                                return this;
                        }
 
                        @Override
                        public Image update() throws IllegalStateException {
-                               checkState(!sone.isPresent() || (ImageImpl.this.sone == null) || sone.get().equals(ImageImpl.this.sone), "can not change Sone once set");
-                               checkState(!creationTime.isPresent() || ((ImageImpl.this.creationTime == 0) || (ImageImpl.this.creationTime == creationTime.get())), "can not change creation time once set");
-                               checkState(!key.isPresent() || (ImageImpl.this.key == null) || key.get().equals(ImageImpl.this.key), "can not change key once set");
-                               if (title.isPresent() && title.get().trim().isEmpty()) {
+                               checkState(sone == null || (ImageImpl.this.sone == null) || sone.equals(ImageImpl.this.sone), "can not change Sone once set");
+                               checkState(creationTime == null || ((ImageImpl.this.creationTime == 0) || (ImageImpl.this.creationTime == creationTime)), "can not change creation time once set");
+                               checkState(key == null || (ImageImpl.this.key == null) || key.equals(ImageImpl.this.key), "can not change key once set");
+                               if (title != null && title.trim().isEmpty()) {
                                        throw new ImageTitleMustNotBeEmpty();
                                }
-                               checkState(!width.isPresent() || (ImageImpl.this.width == 0) || width.get().equals(ImageImpl.this.width), "can not change width once set");
-                               checkState(!height.isPresent() || (ImageImpl.this.height == 0) || height.get().equals(ImageImpl.this.height), "can not change height once set");
+                               checkState(width == null || (ImageImpl.this.width == 0) || width.equals(ImageImpl.this.width), "can not change width once set");
+                               checkState(height == null || (ImageImpl.this.height == 0) || height.equals(ImageImpl.this.height), "can not change height once set");
 
-                               if (sone.isPresent()) {
-                                       ImageImpl.this.sone = sone.get();
+                               if (sone != null) {
+                                       ImageImpl.this.sone = sone;
                                }
-                               if (creationTime.isPresent()) {
-                                       ImageImpl.this.creationTime = creationTime.get();
+                               if (creationTime != null) {
+                                       ImageImpl.this.creationTime = creationTime;
                                }
-                               if (key.isPresent()) {
-                                       ImageImpl.this.key = key.get();
+                               if (key != null) {
+                                       ImageImpl.this.key = key;
                                }
-                               if (title.isPresent()) {
-                                       ImageImpl.this.title = title.get();
+                               if (title != null) {
+                                       ImageImpl.this.title = title;
                                }
-                               if (description.isPresent()) {
-                                       ImageImpl.this.description = description.get();
+                               if (description != null) {
+                                       ImageImpl.this.description = description;
                                }
-                               if (width.isPresent()) {
-                                       ImageImpl.this.width = width.get();
+                               if (width != null) {
+                                       ImageImpl.this.width = width;
                                }
-                               if (height.isPresent()) {
-                                       ImageImpl.this.height = height.get();
+                               if (height != null) {
+                                       ImageImpl.this.height = height;
                                }
 
                                return ImageImpl.this;
index 3366448..1069550 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneImpl.java - Copyright © 2010–2019 David Roden
+ * Sone - SoneImpl.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 9763ad6..6a24756 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - DatabaseException.java - Copyright © 2013–2019 David Roden
+ * Sone - DatabaseException.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 6fce7e0..8722873 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryDatabase.kt - Copyright © 2013–2019 David Roden
+ * Sone - MemoryDatabase.kt - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@ import com.google.common.base.Preconditions.checkNotNull
 import com.google.common.collect.HashMultimap
 import com.google.common.collect.Multimap
 import com.google.common.collect.TreeMultimap
-import com.google.common.util.concurrent.AbstractService
+import com.google.common.util.concurrent.*
 import com.google.inject.Inject
 import com.google.inject.Singleton
 import net.pterodactylus.sone.data.Album
@@ -41,7 +41,7 @@ import net.pterodactylus.sone.database.ImageBuilder
 import net.pterodactylus.sone.database.PostBuilder
 import net.pterodactylus.sone.database.PostDatabase
 import net.pterodactylus.sone.database.PostReplyBuilder
-import net.pterodactylus.sone.utils.unit
+import net.pterodactylus.sone.utils.*
 import net.pterodactylus.util.config.Configuration
 import net.pterodactylus.util.config.ConfigurationException
 import java.util.concurrent.locks.ReentrantReadWriteLock
@@ -70,6 +70,9 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio
        private val soneImages: Multimap<String, Image> = HashMultimap.create<String, Image>()
        private val memoryBookmarkDatabase = MemoryBookmarkDatabase(this, configurationLoader)
        private val memoryFriendDatabase = MemoryFriendDatabase(configurationLoader)
+       private val saveRateLimiter: RateLimiter = RateLimiter.create(1.0)
+       private val saveKnownPostsRateLimiter: RateLimiter = RateLimiter.create(1.0)
+       private val saveKnownPostRepliesRateLimiter: RateLimiter = RateLimiter.create(1.0)
 
        override val soneLoader get() = this::getSone
 
@@ -82,8 +85,10 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio
        override val bookmarkedPosts get() = memoryBookmarkDatabase.bookmarkedPosts
 
        override fun save() {
-               saveKnownPosts()
-               saveKnownPostReplies()
+               if (saveRateLimiter.tryAcquire()) {
+                       saveKnownPosts()
+                       saveKnownPostReplies()
+               }
        }
 
        override fun doStart() {
@@ -311,15 +316,17 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio
                                        }
 
        private fun saveKnownPosts() =
-                       try {
-                               readLock.withLock {
-                                       knownPosts.forEachIndexed { index, knownPostId ->
-                                               configuration.getStringValue("KnownPosts/$index/ID").value = knownPostId
+                       saveKnownPostsRateLimiter.tryAcquire().ifTrue {
+                               try {
+                                       readLock.withLock {
+                                               knownPosts.forEachIndexed { index, knownPostId ->
+                                                       configuration.getStringValue("KnownPosts/$index/ID").value = knownPostId
+                                               }
+                                               configuration.getStringValue("KnownPosts/${knownPosts.size}/ID").value = null
                                        }
-                                       configuration.getStringValue("KnownPosts/${knownPosts.size}/ID").value = null
+                               } catch (ce1: ConfigurationException) {
+                                       throw DatabaseException("Could not save database.", ce1)
                                }
-                       } catch (ce1: ConfigurationException) {
-                               throw DatabaseException("Could not save database.", ce1)
                        }
 
        private fun loadKnownPostReplies(): Unit =
@@ -331,15 +338,17 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio
                        }
 
        private fun saveKnownPostReplies() =
-                       try {
-                               readLock.withLock {
-                                       knownPostReplies.forEachIndexed { index, knownPostReply ->
-                                               configuration.getStringValue("KnownReplies/$index/ID").value = knownPostReply
+                       saveKnownPostRepliesRateLimiter.tryAcquire().ifTrue {
+                               try {
+                                       readLock.withLock {
+                                               knownPostReplies.forEachIndexed { index, knownPostReply ->
+                                                       configuration.getStringValue("KnownReplies/$index/ID").value = knownPostReply
+                                               }
+                                               configuration.getStringValue("KnownReplies/${knownPostReplies.size}/ID").value = null
                                        }
-                                       configuration.getStringValue("KnownReplies/${knownPostReplies.size}/ID").value = null
+                               } catch (ce1: ConfigurationException) {
+                                       throw DatabaseException("Could not save database.", ce1)
                                }
-                       } catch (ce1: ConfigurationException) {
-                               throw DatabaseException("Could not save database.", ce1)
                        }
 
 }
index 30fc2b0..451b6b5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryPost.java - Copyright © 2010–2019 David Roden
+ * Sone - MemoryPost.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index dea3449..b9e66fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryPostBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - MemoryPostBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.database.memory;
 
-import java.util.UUID;
+import java.util.*;
+import javax.annotation.*;
 
-import net.pterodactylus.sone.data.Post;
-import net.pterodactylus.sone.data.impl.AbstractPostBuilder;
-import net.pterodactylus.sone.database.PostBuilder;
-import net.pterodactylus.sone.database.SoneProvider;
+import net.pterodactylus.sone.data.*;
+import net.pterodactylus.sone.data.impl.*;
+import net.pterodactylus.sone.database.*;
 
 /**
  * {@link PostBuilder} implementation that creates a {@link MemoryPost}.
  */
 class MemoryPostBuilder extends AbstractPostBuilder {
 
-       /** The database. */
        private final MemoryDatabase database;
 
-       /**
-        * Creates a new memory post builder.
-        *
-        * @param memoryDatabase
-        *            The database
-        * @param soneProvider
-        *            The Sone provider
-        */
        public MemoryPostBuilder(MemoryDatabase memoryDatabase, SoneProvider soneProvider) {
                super(soneProvider);
                database = memoryDatabase;
        }
 
-       /**
-        * {@inheritDocs}
-        */
+       @Nonnull
        @Override
        public Post build() throws IllegalStateException {
                validate();
-               Post post = new MemoryPost(database, soneProvider, randomId ? UUID.randomUUID().toString() : id, senderId, recipientId, currentTime ? System.currentTimeMillis() : time, text);
-               post.setKnown(database.isPostKnown(post));
-               return post;
+               return new MemoryPost(database, soneProvider, randomId ? UUID.randomUUID().toString() : id, senderId, recipientId, currentTime ? System.currentTimeMillis() : time, text);
        }
 
 }
index 40f0775..e4a8f30 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryPostReply.java - Copyright © 2013–2019 David Roden
+ * Sone - MemoryPostReply.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 3bcfe33..b6e2e24 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryPostReplyBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - MemoryPostReplyBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.database.memory;
 
-import java.util.UUID;
+import java.util.*;
+import javax.annotation.*;
 
-import net.pterodactylus.sone.data.PostReply;
-import net.pterodactylus.sone.data.impl.AbstractPostReplyBuilder;
-import net.pterodactylus.sone.database.PostReplyBuilder;
-import net.pterodactylus.sone.database.SoneProvider;
+import net.pterodactylus.sone.data.*;
+import net.pterodactylus.sone.data.impl.*;
+import net.pterodactylus.sone.database.*;
 
 /**
  * {@link PostReplyBuilder} implementation that creates {@link MemoryPostReply}
@@ -30,35 +30,20 @@ import net.pterodactylus.sone.database.SoneProvider;
  */
 class MemoryPostReplyBuilder extends AbstractPostReplyBuilder {
 
-       /** The database. */
        private final MemoryDatabase database;
-
-       /** The Sone provider. */
        private final SoneProvider soneProvider;
 
-       /**
-        * Creates a new {@link MemoryPostReply} builder.
-        *
-        * @param database
-        *            The database
-        * @param soneProvider
-        *            The Sone provider
-        */
        public MemoryPostReplyBuilder(MemoryDatabase database, SoneProvider soneProvider) {
                this.database = database;
                this.soneProvider = soneProvider;
        }
 
-       /**
-        * {@inheritDocs}
-        */
+       @Nonnull
        @Override
        public PostReply build() throws IllegalStateException {
                validate();
 
-               PostReply postReply = new MemoryPostReply(database, soneProvider, randomId ? UUID.randomUUID().toString() : id, senderId, currentTime ? System.currentTimeMillis() : time, text, postId);
-               postReply.setKnown(database.isPostReplyKnown(postReply));
-               return postReply;
+               return new MemoryPostReply(database, soneProvider, randomId ? UUID.randomUUID().toString() : id, senderId, currentTime ? System.currentTimeMillis() : time, text, postId);
        }
 
 }
index 2c8456d..39a6a1e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - CreatePostCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - CreatePostCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@ import freenet.support.SimpleFieldSet;
 /**
  * FCP command that creates a new {@link Post}.
  *
- * @see Core#createPost(Sone, Optional, String)
+ * @see Core#createPost(Sone, Sone, String)
  */
 public class CreatePostCommand extends AbstractSoneCommand {
 
@@ -57,7 +57,7 @@ public class CreatePostCommand extends AbstractSoneCommand {
                if (sone.equals(recipient)) {
                        return new ErrorResponse("Sone and Recipient must not be the same.");
                }
-               Post post = getCore().createPost(sone, Optional.fromNullable(recipient), text);
+               Post post = getCore().createPost(sone, recipient, text);
                return new Response("PostCreated", new SimpleFieldSetBuilder().put("Post", post.getId()).get());
        }
 
index 9f17940..de0f309 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - CreateReplyCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - CreateReplyCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index c93029f..5d599e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - DeletePostCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - DeletePostCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 4531f93..59f744a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - DeleteReplyCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - DeleteReplyCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 0b321f4..3bb8777 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - FcpInterface.java - Copyright © 2011–2019 David Roden
+ * Sone - FcpInterface.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 1427fe7..3ef919e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - GetLocalSonesCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - GetLocalSonesCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index d1dc643..8033bcb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - GetPostCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - GetPostCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index bf80dc2..821c198 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - GetPostFeedCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - GetPostFeedCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 9cc131b..2f250a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - GetPostsCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - GetPostsCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index a4b936b..64d24fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - GetSoneCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - GetSoneCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index ec43143..83167cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - GetSonesCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - GetSonesCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index edd5a43..058045a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - LikePostCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - LikePostCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 800e43c..acdfb98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - LikeReplyCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - LikeReplyCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 691bc4b..fbceb9a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - LockSoneCommand.java - Copyright © 2013–2019 David Roden
+ * Sone - LockSoneCommand.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index ca5a59e..d489603 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - UnlockSoneCommand.java - Copyright © 2013–2019 David Roden
+ * Sone - UnlockSoneCommand.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 7acea2d..a7d1cd7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - VersionCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - VersionCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/main/java/net/pterodactylus/sone/freenet/Key.java b/src/main/java/net/pterodactylus/sone/freenet/Key.java
deleted file mode 100644 (file)
index 6811642..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-package net.pterodactylus.sone.freenet;
-
-import static freenet.support.Base64.encode;
-import static java.lang.String.format;
-
-import freenet.keys.FreenetURI;
-
-import com.google.common.annotations.VisibleForTesting;
-
-/**
- * Encapsulates the parts of a {@link FreenetURI} that do not change while
- * being converted from SSK to USK and/or back.
- */
-public class Key {
-
-       private final byte[] routingKey;
-       private final byte[] cryptoKey;
-       private final byte[] extra;
-
-       private Key(byte[] routingKey, byte[] cryptoKey, byte[] extra) {
-               this.routingKey = routingKey;
-               this.cryptoKey = cryptoKey;
-               this.extra = extra;
-       }
-
-       @VisibleForTesting
-       public String getRoutingKey() {
-               return encode(routingKey);
-       }
-
-       @VisibleForTesting
-       public String getCryptoKey() {
-               return encode(cryptoKey);
-       }
-
-       @VisibleForTesting
-       public String getExtra() {
-               return encode(extra);
-       }
-
-       public FreenetURI toUsk(String docName, long edition, String... paths) {
-               return new FreenetURI("USK", docName, paths, routingKey, cryptoKey,
-                               extra, edition);
-       }
-
-       public FreenetURI toSsk(String docName, String... paths) {
-               return new FreenetURI("SSK", docName, paths, routingKey, cryptoKey,
-                               extra);
-       }
-
-       public FreenetURI toSsk(String docName, long edition, String... paths) {
-               return new FreenetURI("SSK", format("%s-%d", docName, edition), paths,
-                               routingKey, cryptoKey, extra, edition);
-       }
-
-       public static Key from(FreenetURI freenetURI) {
-               return new Key(freenetURI.getRoutingKey(), freenetURI.getCryptoKey(),
-                               freenetURI.getExtra());
-       }
-
-       public static String routingKey(FreenetURI freenetURI) {
-               return from(freenetURI).getRoutingKey();
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/L10nFilter.java b/src/main/java/net/pterodactylus/sone/freenet/L10nFilter.java
deleted file mode 100644 (file)
index d667811..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Sone - L10nFilter.java - Copyright © 2010–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.freenet;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
-import net.pterodactylus.util.template.Filter;
-import net.pterodactylus.util.template.TemplateContext;
-
-import freenet.l10n.BaseL10n;
-
-/**
- * {@link Filter} implementation replaces {@link String} values with their
- * translated equivalents.
- */
-public class L10nFilter implements Filter {
-
-       private final BaseL10n l10n;
-
-       public L10nFilter(BaseL10n l10n) {
-               this.l10n = l10n;
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public String format(TemplateContext templateContext, Object data, Map<String, Object> parameters) {
-               List<Object> parameterValues = getParameters(data, parameters);
-               String text = getText(data);
-               if (parameterValues.isEmpty()) {
-                       return l10n.getString(text);
-               }
-               return new MessageFormat(l10n.getString(text), new Locale(l10n.getSelectedLanguage().shortCode)).format(parameterValues.toArray());
-       }
-
-       @Nonnull
-       private String getText(Object data) {
-               return (data instanceof L10nText) ? ((L10nText) data).getText() : String.valueOf(data);
-       }
-
-       @Nonnull
-       private List<Object> getParameters(Object data, Map<String, Object> parameters) {
-               if (data instanceof L10nText) {
-                       return ((L10nText) data).getParameters();
-               }
-               List<Object> parameterValues = new ArrayList<>();
-               int parameterIndex = 0;
-               while (parameters.containsKey(String.valueOf(parameterIndex))) {
-                       Object value = parameters.get(String.valueOf(parameterIndex));
-                       parameterValues.add(value);
-                       ++parameterIndex;
-               }
-               return parameterValues;
-       }
-
-}
index cce544f..a8a2697 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - PluginStoreConfigurationBackend.java - Copyright © 2010–2019 David Roden
+ * Sone - PluginStoreConfigurationBackend.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 48eb4bf..a974a0c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SimpleFieldSetBuilder.java - Copyright © 2011–2019 David Roden
+ * Sone - SimpleFieldSetBuilder.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 3ea4804..890e3ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - AbstractCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 63fc8eb..f3f32cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Command.java - Copyright © 2011–2019 David Roden
+ * Sone - Command.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 0e156a1..db70018 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - FcpException.java - Copyright © 2011–2019 David Roden
+ * Sone - FcpException.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/main/java/net/pterodactylus/sone/freenet/plugin/PluginConnector.java b/src/main/java/net/pterodactylus/sone/freenet/plugin/PluginConnector.java
deleted file mode 100644 (file)
index fbaabb3..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Sone - PluginConnector.java - Copyright © 2010–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.freenet.plugin;
-
-import net.pterodactylus.sone.freenet.plugin.event.ReceivedReplyEvent;
-
-import com.google.common.eventbus.EventBus;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-
-import freenet.pluginmanager.FredPluginTalker;
-import freenet.pluginmanager.PluginNotFoundException;
-import freenet.pluginmanager.PluginRespirator;
-import freenet.pluginmanager.PluginTalker;
-import freenet.support.SimpleFieldSet;
-import freenet.support.api.Bucket;
-
-/**
- * Interface for talking to other plugins. Other plugins are identified by their
- * name and a unique connection identifier.
- */
-@Singleton
-public class PluginConnector implements FredPluginTalker {
-
-       /** The event bus. */
-       private final EventBus eventBus;
-
-       /** The plugin respirator. */
-       private final PluginRespirator pluginRespirator;
-
-       /**
-        * Creates a new plugin connector.
-        *
-        * @param eventBus
-        *            The event bus
-        * @param pluginRespirator
-        *            The plugin respirator
-        */
-       @Inject
-       public PluginConnector(EventBus eventBus, PluginRespirator pluginRespirator) {
-               this.eventBus = eventBus;
-               this.pluginRespirator = pluginRespirator;
-       }
-
-       //
-       // ACTIONS
-       //
-
-       /**
-        * Sends a request to the given plugin.
-        *
-        * @param pluginName
-        *            The name of the plugin
-        * @param identifier
-        *            The identifier of the connection
-        * @param fields
-        *            The fields of the message
-        * @throws PluginException
-        *             if the plugin can not be found
-        */
-       public void sendRequest(String pluginName, String identifier, SimpleFieldSet fields) throws PluginException {
-               sendRequest(pluginName, identifier, fields, null);
-       }
-
-       /**
-        * Sends a request to the given plugin.
-        *
-        * @param pluginName
-        *            The name of the plugin
-        * @param identifier
-        *            The identifier of the connection
-        * @param fields
-        *            The fields of the message
-        * @param data
-        *            The payload of the message (may be null)
-        * @throws PluginException
-        *             if the plugin can not be found
-        */
-       public void sendRequest(String pluginName, String identifier, SimpleFieldSet fields, Bucket data) throws PluginException {
-               getPluginTalker(pluginName, identifier).send(fields, data);
-       }
-
-       //
-       // PRIVATE METHODS
-       //
-
-       /**
-        * Returns the plugin talker for the given plugin connection.
-        *
-        * @param pluginName
-        *            The name of the plugin
-        * @param identifier
-        *            The identifier of the connection
-        * @return The plugin talker
-        * @throws PluginException
-        *             if the plugin can not be found
-        */
-       private PluginTalker getPluginTalker(String pluginName, String identifier) throws PluginException {
-               try {
-                       return pluginRespirator.getPluginTalker(this, pluginName, identifier);
-               } catch (PluginNotFoundException pnfe1) {
-                       throw new PluginException(pnfe1);
-               }
-       }
-
-       //
-       // INTERFACE FredPluginTalker
-       //
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public void onReply(String pluginName, String identifier, SimpleFieldSet params, Bucket data) {
-               eventBus.post(new ReceivedReplyEvent(this, pluginName, identifier, params, data));
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/plugin/PluginException.java b/src/main/java/net/pterodactylus/sone/freenet/plugin/PluginException.java
deleted file mode 100644 (file)
index e263a60..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Sone - PluginException.java - Copyright © 2010–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.freenet.plugin;
-
-import net.pterodactylus.sone.freenet.wot.WebOfTrustException;
-
-/**
- * Exception that signals an error when communicating with a plugin.
- */
-public class PluginException extends WebOfTrustException {
-
-       /**
-        * Creates a new plugin exception.
-        */
-       public PluginException() {
-               super();
-       }
-
-       /**
-        * Creates a new plugin exception.
-        *
-        * @param message
-        *            The message of the exception
-        */
-       public PluginException(String message) {
-               super(message);
-       }
-
-       /**
-        * Creates a new plugin exception.
-        *
-        * @param cause
-        *            The cause of the exception
-        */
-       public PluginException(Throwable cause) {
-               super(cause);
-       }
-
-       /**
-        * Creates a new plugin exception.
-        *
-        * @param message
-        *            The message of the exception
-        * @param cause
-        *            The cause of the exception
-        */
-       public PluginException(String message, Throwable cause) {
-               super(message, cause);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/freenet/plugin/event/ReceivedReplyEvent.java b/src/main/java/net/pterodactylus/sone/freenet/plugin/event/ReceivedReplyEvent.java
deleted file mode 100644 (file)
index ce2ba7f..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Sone - ReceivedReplyEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.freenet.plugin.event;
-
-import net.pterodactylus.sone.freenet.plugin.PluginConnector;
-import freenet.support.SimpleFieldSet;
-import freenet.support.api.Bucket;
-
-/**
- * Event that signals that a plugin reply was received.
- */
-public class ReceivedReplyEvent {
-
-       /** The connector that received the reply. */
-       private final PluginConnector pluginConnector;
-
-       /** The name of the plugin that sent the reply. */
-       private final String pluginName;
-
-       /** The identifier of the initial request. */
-       private final String identifier;
-
-       /** The fields containing the reply. */
-       private final SimpleFieldSet fieldSet;
-
-       /** The optional reply data. */
-       private final Bucket data;
-
-       /**
-        * Creates a new “reply received” event.
-        *
-        * @param pluginConnector
-        *            The connector that received the event
-        * @param pluginName
-        *            The name of the plugin that sent the reply
-        * @param identifier
-        *            The identifier of the initial request
-        * @param fieldSet
-        *            The fields containing the reply
-        * @param data
-        *            The optional data of the reply
-        */
-       public ReceivedReplyEvent(PluginConnector pluginConnector, String pluginName, String identifier, SimpleFieldSet fieldSet, Bucket data) {
-               this.pluginConnector = pluginConnector;
-               this.pluginName = pluginName;
-               this.identifier = identifier;
-               this.fieldSet = fieldSet;
-               this.data = data;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the plugin connector that received the reply.
-        *
-        * @return The plugin connector that received the reply
-        */
-       public PluginConnector pluginConnector() {
-               return pluginConnector;
-       }
-
-       /**
-        * Returns the name of the plugin that sent the reply.
-        *
-        * @return The name of the plugin that sent the reply
-        */
-       public String pluginName() {
-               return pluginName;
-       }
-
-       /**
-        * Returns the identifier of the initial request.
-        *
-        * @return The identifier of the initial request
-        */
-       public String identifier() {
-