From 4738428c2c205f42200386ae09b44b9ec07b9144 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sat, 27 Jul 2013 14:33:25 -0700 Subject: Move subsonic-android to root --- .../main/java/net/sourceforge/subsonic/Logger.java | 231 --- .../net/sourceforge/subsonic/ajax/ChatService.java | 163 -- .../sourceforge/subsonic/ajax/CoverArtInfo.java | 43 - .../sourceforge/subsonic/ajax/CoverArtService.java | 145 -- .../net/sourceforge/subsonic/ajax/LyricsInfo.java | 53 - .../sourceforge/subsonic/ajax/LyricsService.java | 105 -- .../sourceforge/subsonic/ajax/MultiService.java | 51 - .../sourceforge/subsonic/ajax/NetworkStatus.java | 55 - .../sourceforge/subsonic/ajax/NowPlayingInfo.java | 98 - .../subsonic/ajax/NowPlayingService.java | 172 -- .../sourceforge/subsonic/ajax/PlayQueueInfo.java | 174 -- .../subsonic/ajax/PlayQueueService.java | 455 ----- .../sourceforge/subsonic/ajax/PlaylistInfo.java | 90 - .../sourceforge/subsonic/ajax/PlaylistService.java | 187 -- .../net/sourceforge/subsonic/ajax/ScanInfo.java | 43 - .../net/sourceforge/subsonic/ajax/StarService.java | 64 - .../net/sourceforge/subsonic/ajax/TagService.java | 128 -- .../sourceforge/subsonic/ajax/TransferService.java | 49 - .../net/sourceforge/subsonic/ajax/UploadInfo.java | 52 - .../sourceforge/subsonic/cache/CacheFactory.java | 58 - .../subsonic/command/AdvancedSettingsCommand.java | 146 -- .../subsonic/command/DonateCommand.java | 88 - .../sourceforge/subsonic/command/EnumHolder.java | 42 - .../subsonic/command/GeneralSettingsCommand.java | 184 -- .../command/MusicFolderSettingsCommand.java | 187 -- .../subsonic/command/NetworkSettingsCommand.java | 92 - .../subsonic/command/PasswordSettingsCommand.java | 65 - .../subsonic/command/PersonalSettingsCommand.java | 215 --- .../subsonic/command/PlayerSettingsCommand.java | 250 --- .../subsonic/command/PodcastSettingsCommand.java | 66 - .../subsonic/command/SearchCommand.java | 135 -- .../subsonic/command/UserSettingsCommand.java | 278 --- .../controller/AbstractChartController.java | 60 - .../controller/AdvancedSettingsController.java | 91 - .../subsonic/controller/AllmusicController.java | 38 - .../subsonic/controller/AvatarController.java | 82 - .../controller/AvatarUploadController.java | 141 -- .../controller/ChangeCoverArtController.java | 72 - .../subsonic/controller/CoverArtController.java | 294 --- .../subsonic/controller/DBController.java | 66 - .../subsonic/controller/DonateController.java | 74 - .../subsonic/controller/DownloadController.java | 453 ----- .../subsonic/controller/EditTagsController.java | 194 -- .../controller/ExternalPlayerController.java | 179 -- .../controller/GeneralSettingsController.java | 114 -- .../subsonic/controller/HelpController.java | 80 - .../subsonic/controller/HomeController.java | 340 ---- .../controller/ImportPlaylistController.java | 93 - .../InternetRadioSettingsController.java | 116 -- .../subsonic/controller/LeftController.java | 270 --- .../subsonic/controller/LyricsController.java | 46 - .../subsonic/controller/M3UController.java | 128 -- .../subsonic/controller/MainController.java | 297 --- .../subsonic/controller/MoreController.java | 89 - .../subsonic/controller/MultiController.java | 244 --- .../controller/MusicFolderSettingsController.java | 130 -- .../controller/NetworkSettingsController.java | 89 - .../subsonic/controller/NowPlayingController.java | 79 - .../controller/PasswordSettingsController.java | 58 - .../controller/PersonalSettingsController.java | 164 -- .../subsonic/controller/PlayQueueController.java | 77 - .../controller/PlayerSettingsController.java | 150 -- .../subsonic/controller/PlaylistController.java | 82 - .../subsonic/controller/PodcastController.java | 152 -- .../controller/PodcastReceiverAdminController.java | 102 - .../controller/PodcastReceiverController.java | 85 - .../controller/PodcastSettingsController.java | 67 - .../subsonic/controller/ProxyController.java | 68 - .../subsonic/controller/RESTController.java | 1983 -------------------- .../controller/RandomPlayQueueController.java | 101 - .../subsonic/controller/ReloadFrame.java | 52 - .../subsonic/controller/RightController.java | 66 - .../subsonic/controller/SearchController.java | 106 -- .../controller/SetMusicFileInfoController.java | 58 - .../subsonic/controller/SetRatingController.java | 69 - .../subsonic/controller/SettingsController.java | 52 - .../controller/ShareManagementController.java | 123 -- .../controller/ShareSettingsController.java | 161 -- .../subsonic/controller/StarredController.java | 96 - .../subsonic/controller/StatusChartController.java | 149 -- .../subsonic/controller/StatusController.java | 141 -- .../subsonic/controller/StreamController.java | 419 ----- .../subsonic/controller/TopController.java | 84 - .../controller/TranscodingSettingsController.java | 139 -- .../subsonic/controller/UploadController.java | 260 --- .../subsonic/controller/UserChartController.java | 145 -- .../controller/UserSettingsController.java | 159 -- .../subsonic/controller/VideoPlayerController.java | 110 -- .../subsonic/controller/WapController.java | 247 --- .../net/sourceforge/subsonic/dao/AbstractDao.java | 127 -- .../net/sourceforge/subsonic/dao/AlbumDao.java | 243 --- .../net/sourceforge/subsonic/dao/ArtistDao.java | 161 -- .../net/sourceforge/subsonic/dao/AvatarDao.java | 94 - .../net/sourceforge/subsonic/dao/DaoHelper.java | 117 -- .../sourceforge/subsonic/dao/InternetRadioDao.java | 89 - .../net/sourceforge/subsonic/dao/MediaFileDao.java | 374 ---- .../sourceforge/subsonic/dao/MusicFolderDao.java | 91 - .../net/sourceforge/subsonic/dao/PlayerDao.java | 194 -- .../net/sourceforge/subsonic/dao/PlaylistDao.java | 142 -- .../net/sourceforge/subsonic/dao/PodcastDao.java | 165 -- .../net/sourceforge/subsonic/dao/RatingDao.java | 99 - .../net/sourceforge/subsonic/dao/ShareDao.java | 131 -- .../sourceforge/subsonic/dao/TranscodingDao.java | 123 -- .../java/net/sourceforge/subsonic/dao/UserDao.java | 352 ---- .../sourceforge/subsonic/dao/schema/Schema.java | 66 - .../sourceforge/subsonic/dao/schema/Schema25.java | 81 - .../sourceforge/subsonic/dao/schema/Schema26.java | 110 -- .../sourceforge/subsonic/dao/schema/Schema27.java | 54 - .../sourceforge/subsonic/dao/schema/Schema28.java | 110 -- .../sourceforge/subsonic/dao/schema/Schema29.java | 55 - .../sourceforge/subsonic/dao/schema/Schema30.java | 56 - .../sourceforge/subsonic/dao/schema/Schema31.java | 52 - .../sourceforge/subsonic/dao/schema/Schema32.java | 93 - .../sourceforge/subsonic/dao/schema/Schema33.java | 47 - .../sourceforge/subsonic/dao/schema/Schema34.java | 53 - .../sourceforge/subsonic/dao/schema/Schema35.java | 151 -- .../sourceforge/subsonic/dao/schema/Schema36.java | 48 - .../sourceforge/subsonic/dao/schema/Schema37.java | 77 - .../sourceforge/subsonic/dao/schema/Schema38.java | 54 - .../sourceforge/subsonic/dao/schema/Schema40.java | 46 - .../sourceforge/subsonic/dao/schema/Schema43.java | 65 - .../sourceforge/subsonic/dao/schema/Schema45.java | 76 - .../sourceforge/subsonic/dao/schema/Schema46.java | 87 - .../sourceforge/subsonic/dao/schema/Schema47.java | 234 --- .../net/sourceforge/subsonic/domain/Album.java | 166 -- .../net/sourceforge/subsonic/domain/Artist.java | 95 - .../net/sourceforge/subsonic/domain/Avatar.java | 75 - .../sourceforge/subsonic/domain/AvatarScheme.java | 52 - .../sourceforge/subsonic/domain/CacheElement.java | 65 - .../subsonic/domain/CoverArtScheme.java | 48 - .../sourceforge/subsonic/domain/InternetRadio.java | 168 -- .../net/sourceforge/subsonic/domain/MediaFile.java | 449 ----- .../subsonic/domain/MediaFileComparator.java | 99 - .../subsonic/domain/MediaLibraryStatistics.java | 62 - .../sourceforge/subsonic/domain/MusicFolder.java | 148 -- .../sourceforge/subsonic/domain/MusicIndex.java | 167 -- .../sourceforge/subsonic/domain/NATPMPRouter.java | 61 - .../net/sourceforge/subsonic/domain/PlayQueue.java | 417 ---- .../net/sourceforge/subsonic/domain/Player.java | 338 ---- .../subsonic/domain/PlayerTechnology.java | 49 - .../net/sourceforge/subsonic/domain/Playlist.java | 141 -- .../subsonic/domain/PodcastChannel.java | 96 - .../subsonic/domain/PodcastEpisode.java | 172 -- .../sourceforge/subsonic/domain/PodcastStatus.java | 29 - .../subsonic/domain/RandomSearchCriteria.java | 70 - .../net/sourceforge/subsonic/domain/Router.java | 43 - .../sourceforge/subsonic/domain/SBBIRouter.java | 63 - .../subsonic/domain/SearchCriteria.java | 59 - .../sourceforge/subsonic/domain/SearchResult.java | 69 - .../net/sourceforge/subsonic/domain/Share.java | 100 - .../net/sourceforge/subsonic/domain/Theme.java | 42 - .../subsonic/domain/TranscodeScheme.java | 104 - .../sourceforge/subsonic/domain/Transcoding.java | 221 --- .../subsonic/domain/TransferStatus.java | 303 --- .../java/net/sourceforge/subsonic/domain/User.java | 245 --- .../sourceforge/subsonic/domain/UserSettings.java | 328 ---- .../net/sourceforge/subsonic/domain/Version.java | 141 -- .../subsonic/domain/VideoTranscodingSettings.java | 50 - .../sourceforge/subsonic/domain/WeUPnPRouter.java | 56 - .../filter/BootstrapVerificationFilter.java | 107 -- .../subsonic/filter/ParameterDecodingFilter.java | 147 -- .../subsonic/filter/RequestEncodingFilter.java | 54 - .../subsonic/filter/ResponseHeaderFilter.java | 57 - .../subsonic/i18n/SubsonicLocaleResolver.java | 104 - .../subsonic/io/InputStreamReaderThread.java | 63 - .../subsonic/io/PlayQueueInputStream.java | 154 -- .../sourceforge/subsonic/io/RangeOutputStream.java | 150 -- .../subsonic/io/ShoutCastOutputStream.java | 205 -- .../subsonic/io/TranscodeInputStream.java | 124 -- .../ldap/SubsonicLdapBindAuthenticator.java | 131 -- ...serDetailsServiceBasedAuthoritiesPopulator.java | 50 - .../RESTRequestParameterProcessingFilter.java | 246 --- .../sourceforge/subsonic/service/AdService.java | 71 - .../subsonic/service/AudioScrobblerService.java | 331 ---- .../subsonic/service/JukeboxService.java | 206 -- .../subsonic/service/MediaFileService.java | 614 ------ .../subsonic/service/MediaScannerService.java | 354 ---- .../subsonic/service/MusicIndexService.java | 250 --- .../subsonic/service/NetworkService.java | 336 ---- .../subsonic/service/PlayerService.java | 317 ---- .../subsonic/service/PlaylistService.java | 426 ----- .../subsonic/service/PodcastService.java | 599 ------ .../subsonic/service/RatingService.java | 101 - .../subsonic/service/SearchService.java | 567 ------ .../subsonic/service/SecurityService.java | 303 --- .../subsonic/service/ServiceLocator.java | 46 - .../subsonic/service/SettingsService.java | 1225 ------------ .../sourceforge/subsonic/service/ShareService.java | 133 -- .../subsonic/service/StatusService.java | 134 -- .../subsonic/service/TranscodingService.java | 530 ------ .../subsonic/service/VersionService.java | 267 --- .../subsonic/service/jukebox/AudioPlayer.java | 207 -- .../subsonic/service/jukebox/PlayerTest.java | 75 - .../service/metadata/DefaultMetaDataParser.java | 74 - .../subsonic/service/metadata/FFmpegParser.java | 170 -- .../service/metadata/JaudiotaggerParser.java | 296 --- .../subsonic/service/metadata/MetaData.java | 135 -- .../subsonic/service/metadata/MetaDataParser.java | 162 -- .../service/metadata/MetaDataParserFactory.java | 51 - .../subsonic/taglib/EscapeJavaScriptTag.java | 77 - .../subsonic/taglib/FormatBytesTag.java | 76 - .../net/sourceforge/subsonic/taglib/ParamTag.java | 67 - .../net/sourceforge/subsonic/taglib/UrlTag.java | 207 -- .../net/sourceforge/subsonic/taglib/WikiTag.java | 72 - .../subsonic/theme/SubsonicThemeResolver.java | 117 -- .../subsonic/theme/SubsonicThemeSource.java | 49 - .../subsonic/upload/MonitoredDiskFileItem.java | 51 - .../upload/MonitoredDiskFileItemFactory.java | 47 - .../subsonic/upload/MonitoredOutputStream.java | 60 - .../subsonic/upload/UploadListener.java | 29 - .../net/sourceforge/subsonic/util/BoundedList.java | 71 - .../net/sourceforge/subsonic/util/FileUtil.java | 186 -- .../java/net/sourceforge/subsonic/util/Pair.java | 54 - .../net/sourceforge/subsonic/util/StringUtil.java | 537 ------ .../java/net/sourceforge/subsonic/util/Util.java | 127 -- .../net/sourceforge/subsonic/util/XMLBuilder.java | 328 ---- .../subsonic/validator/DonateValidator.java | 51 - .../validator/PasswordSettingsValidator.java | 45 - .../subsonic/validator/UserSettingsValidator.java | 91 - subsonic-main/src/main/java/org/json/CDL.java | 279 --- subsonic-main/src/main/java/org/json/Cookie.java | 169 -- .../src/main/java/org/json/CookieList.java | 90 - subsonic-main/src/main/java/org/json/HTTP.java | 163 -- .../src/main/java/org/json/HTTPTokener.java | 77 - .../src/main/java/org/json/JSONArray.java | 920 --------- .../src/main/java/org/json/JSONException.java | 28 - subsonic-main/src/main/java/org/json/JSONML.java | 465 ----- .../src/main/java/org/json/JSONObject.java | 1630 ---------------- .../src/main/java/org/json/JSONString.java | 18 - .../src/main/java/org/json/JSONStringer.java | 78 - .../src/main/java/org/json/JSONTokener.java | 446 ----- .../src/main/java/org/json/JSONWriter.java | 327 ---- subsonic-main/src/main/java/org/json/XML.java | 508 ----- .../src/main/java/org/json/XMLTokener.java | 365 ---- 234 files changed, 40133 deletions(-) delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/Logger.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/ChatService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/CoverArtInfo.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/CoverArtService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/LyricsInfo.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/LyricsService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/MultiService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NetworkStatus.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NowPlayingInfo.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NowPlayingService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlayQueueInfo.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlayQueueService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlaylistInfo.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlaylistService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/ScanInfo.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/StarService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/TagService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/TransferService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/UploadInfo.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/cache/CacheFactory.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/AdvancedSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/DonateCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/EnumHolder.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/GeneralSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/MusicFolderSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/NetworkSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/PasswordSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/PersonalSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/PlayerSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/PodcastSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/SearchCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/command/UserSettingsCommand.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AbstractChartController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AdvancedSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AllmusicController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AvatarController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AvatarUploadController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ChangeCoverArtController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DBController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DonateController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DownloadController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/EditTagsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ExternalPlayerController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/GeneralSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/HelpController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/HomeController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ImportPlaylistController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/InternetRadioSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/LeftController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/LyricsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/M3UController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MainController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MoreController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MultiController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MusicFolderSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/NetworkSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/NowPlayingController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PasswordSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PersonalSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlayQueueController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlayerSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlaylistController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastReceiverAdminController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastReceiverController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ProxyController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RESTController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RandomPlayQueueController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ReloadFrame.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RightController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SearchController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SetMusicFileInfoController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SetRatingController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ShareManagementController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ShareSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StarredController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StatusChartController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StatusController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/TopController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/TranscodingSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UploadController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UserChartController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UserSettingsController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/VideoPlayerController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/controller/WapController.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AbstractDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AlbumDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/ArtistDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AvatarDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/DaoHelper.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/InternetRadioDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/MediaFileDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/MusicFolderDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PlayerDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PlaylistDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PodcastDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/RatingDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/ShareDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/TranscodingDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/UserDao.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema25.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema26.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema27.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema28.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema29.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema30.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema31.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema32.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema33.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema34.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema35.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema36.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema37.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema38.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema40.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema43.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema45.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema46.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema47.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Album.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Artist.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Avatar.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/AvatarScheme.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/CacheElement.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/CoverArtScheme.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/InternetRadio.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFile.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaLibraryStatistics.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MusicFolder.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MusicIndex.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/NATPMPRouter.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PlayQueue.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Player.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PlayerTechnology.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Playlist.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastChannel.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastEpisode.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastStatus.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/RandomSearchCriteria.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Router.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SBBIRouter.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SearchCriteria.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SearchResult.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Share.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Theme.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/TranscodeScheme.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Transcoding.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/TransferStatus.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/User.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/UserSettings.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Version.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/VideoTranscodingSettings.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/domain/WeUPnPRouter.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/filter/BootstrapVerificationFilter.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ParameterDecodingFilter.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/filter/RequestEncodingFilter.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ResponseHeaderFilter.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/i18n/SubsonicLocaleResolver.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/io/InputStreamReaderThread.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/io/ShoutCastOutputStream.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/io/TranscodeInputStream.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ldap/SubsonicLdapBindAuthenticator.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/ldap/UserDetailsServiceBasedAuthoritiesPopulator.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/security/RESTRequestParameterProcessingFilter.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/AdService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/AudioScrobblerService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/JukeboxService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/MediaFileService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/MediaScannerService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/MusicIndexService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/NetworkService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/PlayerService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/PlaylistService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/PodcastService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/RatingService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/SearchService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/SecurityService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/ServiceLocator.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/SettingsService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/ShareService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/StatusService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/TranscodingService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/PlayerTest.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/DefaultMetaDataParser.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/FFmpegParser.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/JaudiotaggerParser.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaData.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaDataParser.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaDataParserFactory.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/EscapeJavaScriptTag.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/FormatBytesTag.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/ParamTag.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/UrlTag.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/WikiTag.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/theme/SubsonicThemeResolver.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/theme/SubsonicThemeSource.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredDiskFileItem.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredDiskFileItemFactory.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredOutputStream.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/upload/UploadListener.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/util/BoundedList.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/util/FileUtil.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/util/Pair.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/util/StringUtil.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/util/Util.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/util/XMLBuilder.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/validator/DonateValidator.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/validator/PasswordSettingsValidator.java delete mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/validator/UserSettingsValidator.java delete mode 100644 subsonic-main/src/main/java/org/json/CDL.java delete mode 100644 subsonic-main/src/main/java/org/json/Cookie.java delete mode 100644 subsonic-main/src/main/java/org/json/CookieList.java delete mode 100644 subsonic-main/src/main/java/org/json/HTTP.java delete mode 100644 subsonic-main/src/main/java/org/json/HTTPTokener.java delete mode 100644 subsonic-main/src/main/java/org/json/JSONArray.java delete mode 100644 subsonic-main/src/main/java/org/json/JSONException.java delete mode 100644 subsonic-main/src/main/java/org/json/JSONML.java delete mode 100644 subsonic-main/src/main/java/org/json/JSONObject.java delete mode 100644 subsonic-main/src/main/java/org/json/JSONString.java delete mode 100644 subsonic-main/src/main/java/org/json/JSONStringer.java delete mode 100644 subsonic-main/src/main/java/org/json/JSONTokener.java delete mode 100644 subsonic-main/src/main/java/org/json/JSONWriter.java delete mode 100644 subsonic-main/src/main/java/org/json/XML.java delete mode 100644 subsonic-main/src/main/java/org/json/XMLTokener.java (limited to 'subsonic-main/src/main/java') diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/Logger.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/Logger.java deleted file mode 100644 index 0e595458..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/Logger.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic; - -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.util.*; -import org.apache.commons.lang.exception.*; - -import java.io.*; -import java.text.*; -import java.util.*; - -/** - * Logger implementation which logs to SUBSONIC_HOME/subsonic.log. - *
- * Note: Third party logging libraries (such as log4j and Commons logging) are intentionally not - * used. These libraries causes a lot of headache when deploying to some application servers - * (for instance Jetty and JBoss). - * - * @author Sindre Mehus - * @version $Revision: 1.1 $ $Date: 2005/05/09 19:58:26 $ - */ -public class Logger { - - private String category; - - private static List entries = Collections.synchronizedList(new BoundedList(50)); - private static PrintWriter writer; - - /** - * Creates a logger for the given class. - * @param clazz The class. - * @return A logger for the class. - */ - public static Logger getLogger(Class clazz) { - return new Logger(clazz.getName()); - } - - /** - * Creates a logger for the given namee. - * @param name The name. - * @return A logger for the name. - */ - public static Logger getLogger(String name) { - return new Logger(name); - } - - /** - * Returns the last few log entries. - * @return The last few log entries. - */ - public static Entry[] getLatestLogEntries() { - return entries.toArray(new Entry[0]); - } - - private Logger(String name) { - int lastDot = name.lastIndexOf('.'); - if (lastDot == -1) { - category = name; - } else { - category = name.substring(lastDot + 1); - } - } - - /** - * Logs a debug message. - * @param message The log message. - */ - public void debug(Object message) { - debug(message, null); - } - - /** - * Logs a debug message. - * @param message The message. - * @param error The optional exception. - */ - public void debug(Object message, Throwable error) { - add(Level.DEBUG, message, error); - } - - /** - * Logs an info message. - * @param message The message. - */ - public void info(Object message) { - info(message, null); - } - - /** - * Logs an info message. - * @param message The message. - * @param error The optional exception. - */ - public void info(Object message, Throwable error) { - add(Level.INFO, message, error); - } - - /** - * Logs a warning message. - * @param message The message. - */ - public void warn(Object message) { - warn(message, null); - } - - /** - * Logs a warning message. - * @param message The message. - * @param error The optional exception. - */ - public void warn(Object message, Throwable error) { - add(Level.WARN, message, error); - } - - /** - * Logs an error message. - * @param message The message. - */ - public void error(Object message) { - error(message, null); - } - - /** - * Logs an error message. - * @param message The message. - * @param error The optional exception. - */ - public void error(Object message, Throwable error) { - add(Level.ERROR, message, error); - } - - private void add(Level level, Object message, Throwable error) { - Entry entry = new Entry(category, level, message, error); - try { - getPrintWriter().println(entry); - } catch (IOException x) { - System.err.println("Failed to write to subsonic.log."); - x.printStackTrace(); - } - entries.add(entry); - } - - private static synchronized PrintWriter getPrintWriter() throws IOException { - if (writer == null) { - writer = new PrintWriter(new FileWriter(getLogFile(), false), true); - } - return writer; - } - - public static File getLogFile() { - File subsonicHome = SettingsService.getSubsonicHome(); - return new File(subsonicHome, "subsonic.log"); - } - - /** - * Log level. - */ - public enum Level { - DEBUG, INFO, WARN, ERROR - } - - /** - * Log entry. - */ - public static class Entry { - private String category; - private Date date; - private Level level; - private Object message; - private Throwable error; - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); - - public Entry(String category, Level level, Object message, Throwable error) { - this.date = new Date(); - this.category = category; - this.level = level; - this.message = message; - this.error = error; - } - - public String getCategory() { - return category; - } - - public Date getDate() { - return date; - } - - public Level getLevel() { - return level; - } - - public Object getMessage() { - return message; - } - - public Throwable getError() { - return error; - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append('[').append(DATE_FORMAT.format(date)).append("] "); - buf.append(level).append(' '); - buf.append(category).append(" - "); - buf.append(message); - - if (error != null) { - buf.append('\n').append(ExceptionUtils.getFullStackTrace(error)); - } - return buf.toString(); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/ChatService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/ChatService.java deleted file mode 100644 index 8905c8a6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/ChatService.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.util.BoundedList; -import org.apache.commons.lang.StringUtils; -import org.directwebremoting.WebContext; -import org.directwebremoting.WebContextFactory; - -import javax.servlet.http.HttpServletRequest; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * Provides AJAX-enabled services for the chatting. - * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class ChatService { - - private static final Logger LOG = Logger.getLogger(ChatService.class); - private static final String CACHE_KEY = "1"; - private static final int MAX_MESSAGES = 10; - private static final long TTL_MILLIS = 3L * 24L * 60L * 60L * 1000L; // 3 days. - - private final LinkedList messages = new BoundedList(MAX_MESSAGES); - private SecurityService securityService; - - private long revision = System.identityHashCode(this); - - /** - * Invoked by Spring. - */ - public void init() { - // Delete old messages every hour. - ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); - Runnable runnable = new Runnable() { - public void run() { - removeOldMessages(); - } - }; - executor.scheduleWithFixedDelay(runnable, 0L, 3600L, TimeUnit.SECONDS); - } - - private synchronized void removeOldMessages() { - long now = System.currentTimeMillis(); - for (Iterator iterator = messages.iterator(); iterator.hasNext();) { - Message message = iterator.next(); - if (now - message.getDate().getTime() > TTL_MILLIS) { - iterator.remove(); - revision++; - } - } - } - - public synchronized void addMessage(String message) { - WebContext webContext = WebContextFactory.get(); - doAddMessage(message, webContext.getHttpServletRequest()); - } - - public synchronized void doAddMessage(String message, HttpServletRequest request) { - - String user = securityService.getCurrentUsername(request); - message = StringUtils.trimToNull(message); - if (message != null && user != null) { - messages.addFirst(new Message(message, user, new Date())); - revision++; - } - } - - public synchronized void clearMessages() { - messages.clear(); - revision++; - } - - /** - * Returns all messages, but only if the given revision is different from the - * current revision. - */ - public synchronized Messages getMessages(long revision) { - if (this.revision != revision) { - return new Messages(new ArrayList(messages), this.revision); - } - return null; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public static class Messages implements Serializable { - - private static final long serialVersionUID = -752602719879818165L; - private final List messages; - private final long revision; - - public Messages(List messages, long revision) { - this.messages = messages; - this.revision = revision; - } - - public List getMessages() { - return messages; - } - - public long getRevision() { - return revision; - } - } - - public static class Message implements Serializable { - - private static final long serialVersionUID = -1907101191518133712L; - private final String content; - private final String username; - private final Date date; - - public Message(String content, String username, Date date) { - this.content = content; - this.username = username; - this.date = date; - } - - public String getContent() { - return content; - } - - public String getUsername() { - return username; - } - - public Date getDate() { - return date; - } - - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/CoverArtInfo.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/CoverArtInfo.java deleted file mode 100644 index c9160f26..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/CoverArtInfo.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -/** - * Contains info about cover art images for an album. - * - * @author Sindre Mehus - */ -public class CoverArtInfo { - - private final String imagePreviewUrl; - private final String imageDownloadUrl; - - public CoverArtInfo(String imagePreviewUrl, String imageDownloadUrl) { - this.imagePreviewUrl = imagePreviewUrl; - this.imageDownloadUrl = imageDownloadUrl; - } - - public String getImagePreviewUrl() { - return imagePreviewUrl; - } - - public String getImageDownloadUrl() { - return imageDownloadUrl; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/CoverArtService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/CoverArtService.java deleted file mode 100644 index 1c3642b6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/CoverArtService.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; - -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.util.StringUtil; - -/** - * Provides AJAX-enabled services for changing cover art images. - *

- * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class CoverArtService { - - private static final Logger LOG = Logger.getLogger(CoverArtService.class); - - private SecurityService securityService; - private MediaFileService mediaFileService; - - /** - * Downloads and saves the cover art at the given URL. - * - * @param albumId ID of the album in question. - * @param url The image URL. - * @return The error string if something goes wrong, null otherwise. - */ - public String setCoverArtImage(int albumId, String url) { - try { - MediaFile mediaFile = mediaFileService.getMediaFile(albumId); - saveCoverArt(mediaFile.getPath(), url); - return null; - } catch (Exception x) { - LOG.warn("Failed to save cover art for album " + albumId, x); - return x.toString(); - } - } - - private void saveCoverArt(String path, String url) throws Exception { - InputStream input = null; - HttpClient client = new DefaultHttpClient(); - - try { - HttpConnectionParams.setConnectionTimeout(client.getParams(), 20 * 1000); // 20 seconds - HttpConnectionParams.setSoTimeout(client.getParams(), 20 * 1000); // 20 seconds - HttpGet method = new HttpGet(url); - - HttpResponse response = client.execute(method); - input = response.getEntity().getContent(); - - // Attempt to resolve proper suffix. - String suffix = "jpg"; - if (url.toLowerCase().endsWith(".gif")) { - suffix = "gif"; - } else if (url.toLowerCase().endsWith(".png")) { - suffix = "png"; - } - - // Check permissions. - File newCoverFile = new File(path, "cover." + suffix); - if (!securityService.isWriteAllowed(newCoverFile)) { - throw new Exception("Permission denied: " + StringUtil.toHtml(newCoverFile.getPath())); - } - - // If file exists, create a backup. - backup(newCoverFile, new File(path, "cover.backup." + suffix)); - - // Write file. - IOUtils.copy(input, new FileOutputStream(newCoverFile)); - - MediaFile mediaFile = mediaFileService.getMediaFile(path); - - // Rename existing cover file if new cover file is not the preferred. - try { - File coverFile = mediaFileService.getCoverArt(mediaFile); - if (coverFile != null) { - if (!newCoverFile.equals(coverFile)) { - coverFile.renameTo(new File(coverFile.getCanonicalPath() + ".old")); - LOG.info("Renamed old image file " + coverFile); - } - } - } catch (Exception x) { - LOG.warn("Failed to rename existing cover file.", x); - } - - mediaFileService.refreshMediaFile(mediaFile); - - } finally { - IOUtils.closeQuietly(input); - client.getConnectionManager().shutdown(); - } - } - - private void backup(File newCoverFile, File backup) { - if (newCoverFile.exists()) { - if (backup.exists()) { - backup.delete(); - } - if (newCoverFile.renameTo(backup)) { - LOG.info("Backed up old image file to " + backup); - } else { - LOG.warn("Failed to create image file backup " + backup); - } - } - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/LyricsInfo.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/LyricsInfo.java deleted file mode 100644 index b84ffe1f..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/LyricsInfo.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -/** - * Contains lyrics info for a song. - * - * @author Sindre Mehus - */ -public class LyricsInfo { - - private final String lyrics; - private final String artist; - private final String title; - - public LyricsInfo() { - this(null, null, null); - } - - public LyricsInfo(String lyrics, String artist, String title) { - this.lyrics = lyrics; - this.artist = artist; - this.title = title; - } - - public String getLyrics() { - return lyrics; - } - - public String getArtist() { - return artist; - } - - public String getTitle() { - return title; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/LyricsService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/LyricsService.java deleted file mode 100644 index 45c039f7..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/LyricsService.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.util.StringUtil; - -import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.params.HttpConnectionParams; -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.Namespace; -import org.jdom.input.SAXBuilder; - -import java.io.IOException; -import java.io.StringReader; - -/** - * Provides AJAX-enabled services for retrieving song lyrics from chartlyrics.com. - *

- * See http://www.chartlyrics.com/api.aspx for details. - *

- * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class LyricsService { - - private static final Logger LOG = Logger.getLogger(LyricsService.class); - - /** - * Returns lyrics for the given song and artist. - * - * @param artist The artist. - * @param song The song. - * @return The lyrics, never null . - */ - public LyricsInfo getLyrics(String artist, String song) { - LyricsInfo lyrics = new LyricsInfo(); - try { - - artist = StringUtil.urlEncode(artist); - song = StringUtil.urlEncode(song); - - String url = "http://api.chartlyrics.com/apiv1.asmx/SearchLyricDirect?artist=" + artist + "&song=" + song; - String xml = executeGetRequest(url); - - lyrics = parseSearchResult(xml); - - } catch (Exception x) { - LOG.warn("Failed to get lyrics for song '" + song + "'.", x); - } - return lyrics; - } - - - private LyricsInfo parseSearchResult(String xml) throws Exception { - SAXBuilder builder = new SAXBuilder(); - Document document = builder.build(new StringReader(xml)); - - Element root = document.getRootElement(); - Namespace ns = root.getNamespace(); - - String lyric = root.getChildText("Lyric", ns); - String song = root.getChildText("LyricSong", ns); - String artist = root.getChildText("LyricArtist", ns); - - return new LyricsInfo(lyric, artist, song); - } - - private String executeGetRequest(String url) throws IOException { - HttpClient client = new DefaultHttpClient(); - HttpConnectionParams.setConnectionTimeout(client.getParams(), 15000); - HttpConnectionParams.setSoTimeout(client.getParams(), 15000); - HttpGet method = new HttpGet(url); - try { - - ResponseHandler responseHandler = new BasicResponseHandler(); - return client.execute(method, responseHandler); - - } finally { - client.getConnectionManager().shutdown(); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/MultiService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/MultiService.java deleted file mode 100644 index 0c83e30f..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/MultiService.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.service.NetworkService; - -/** - * Provides miscellaneous AJAX-enabled services. - *

- * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class MultiService { - - private static final Logger LOG = Logger.getLogger(MultiService.class); - private NetworkService networkService; - - /** - * Returns status for port forwarding and URL redirection. - */ - public NetworkStatus getNetworkStatus() { - NetworkService.Status portForwardingStatus = networkService.getPortForwardingStatus(); - NetworkService.Status urlRedirectionStatus = networkService.getURLRedirecionStatus(); - return new NetworkStatus(portForwardingStatus.getText(), - portForwardingStatus.getDate(), - urlRedirectionStatus.getText(), - urlRedirectionStatus.getDate()); - } - - public void setNetworkService(NetworkService networkService) { - this.networkService = networkService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NetworkStatus.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NetworkStatus.java deleted file mode 100644 index 8634af26..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NetworkStatus.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import java.util.Date; - -/** - * @author Sindre Mehus - */ -public class NetworkStatus { - private final String portForwardingStatusText; - private final Date portForwardingStatusDate; - private final String urlRedirectionStatusText; - private final Date urlRedirectionStatusDate; - - public NetworkStatus(String portForwardingStatusText, Date portForwardingStatusDate, - String urlRedirectionStatusText, Date urlRedirectionStatusDate) { - this.portForwardingStatusText = portForwardingStatusText; - this.portForwardingStatusDate = portForwardingStatusDate; - this.urlRedirectionStatusText = urlRedirectionStatusText; - this.urlRedirectionStatusDate = urlRedirectionStatusDate; - } - - public String getPortForwardingStatusText() { - return portForwardingStatusText; - } - - public Date getPortForwardingStatusDate() { - return portForwardingStatusDate; - } - - public String getUrlRedirectionStatusText() { - return urlRedirectionStatusText; - } - - public Date getUrlRedirectionStatusDate() { - return urlRedirectionStatusDate; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NowPlayingInfo.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NowPlayingInfo.java deleted file mode 100644 index 520cfcab..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NowPlayingInfo.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -/** - * Details about what a user is currently listening to. - * - * @author Sindre Mehus - */ -public class NowPlayingInfo { - - private final String username; - private final String artist; - private final String title; - private final String tooltip; - private final String streamUrl; - private final String albumUrl; - private final String lyricsUrl; - private final String coverArtUrl; - private final String coverArtZoomUrl; - private final String avatarUrl; - private final int minutesAgo; - - public NowPlayingInfo(String user, String artist, String title, String tooltip, String streamUrl, String albumUrl, - String lyricsUrl, String coverArtUrl, String coverArtZoomUrl, String avatarUrl, int minutesAgo) { - this.username = user; - this.artist = artist; - this.title = title; - this.tooltip = tooltip; - this.streamUrl = streamUrl; - this.albumUrl = albumUrl; - this.lyricsUrl = lyricsUrl; - this.coverArtUrl = coverArtUrl; - this.coverArtZoomUrl = coverArtZoomUrl; - this.avatarUrl = avatarUrl; - this.minutesAgo = minutesAgo; - } - - public String getUsername() { - return username; - } - - public String getArtist() { - return artist; - } - - public String getTitle() { - return title; - } - - public String getTooltip() { - return tooltip; - } - - public String getStreamUrl() { - return streamUrl; - } - - public String getAlbumUrl() { - return albumUrl; - } - - public String getLyricsUrl() { - return lyricsUrl; - } - - public String getCoverArtUrl() { - return coverArtUrl; - } - - public String getCoverArtZoomUrl() { - return coverArtZoomUrl; - } - - public String getAvatarUrl() { - return avatarUrl; - } - - public int getMinutesAgo() { - return minutesAgo; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NowPlayingService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NowPlayingService.java deleted file mode 100644 index ef7922b4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/NowPlayingService.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import net.sourceforge.subsonic.domain.AvatarScheme; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.MediaScannerService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.StatusService; -import net.sourceforge.subsonic.util.StringUtil; -import org.apache.commons.lang.StringUtils; -import org.directwebremoting.WebContext; -import org.directwebremoting.WebContextFactory; - -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * Provides AJAX-enabled services for retrieving the currently playing file and directory. - * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class NowPlayingService { - - private PlayerService playerService; - private StatusService statusService; - private SettingsService settingsService; - private MediaScannerService mediaScannerService; - private MediaFileService mediaFileService; - - /** - * Returns details about what the current player is playing. - * - * @return Details about what the current player is playing, or null if not playing anything. - */ - public NowPlayingInfo getNowPlayingForCurrentPlayer() throws Exception { - WebContext webContext = WebContextFactory.get(); - Player player = playerService.getPlayer(webContext.getHttpServletRequest(), webContext.getHttpServletResponse()); - List statuses = statusService.getStreamStatusesForPlayer(player); - List result = convert(statuses); - - return result.isEmpty() ? null : result.get(0); - } - - /** - * Returns details about what all users are currently playing. - * - * @return Details about what all users are currently playing. - */ - public List getNowPlaying() throws Exception { - return convert(statusService.getAllStreamStatuses()); - } - - /** - * Returns media folder scanning status. - */ - public ScanInfo getScanningStatus() { - return new ScanInfo(mediaScannerService.isScanning(), mediaScannerService.getScanCount()); - } - - private List convert(List statuses) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - String url = request.getRequestURL().toString(); - List result = new ArrayList(); - for (TransferStatus status : statuses) { - - Player player = status.getPlayer(); - File file = status.getFile(); - - if (player != null && player.getUsername() != null && file != null) { - - String username = player.getUsername(); - UserSettings userSettings = settingsService.getUserSettings(username); - if (!userSettings.isNowPlayingAllowed()) { - continue; - } - - MediaFile mediaFile = mediaFileService.getMediaFile(file); - File coverArt = mediaFileService.getCoverArt(mediaFile); - - String artist = mediaFile.getArtist(); - String title = mediaFile.getTitle(); - String streamUrl = url.replaceFirst("/dwr/.*", "/stream?player=" + player.getId() + "&id=" + mediaFile.getId()); - String albumUrl = url.replaceFirst("/dwr/.*", "/main.view?id=" + mediaFile.getId()); - String lyricsUrl = url.replaceFirst("/dwr/.*", "/lyrics.view?artistUtf8Hex=" + StringUtil.utf8HexEncode(artist) + - "&songUtf8Hex=" + StringUtil.utf8HexEncode(title)); - String coverArtUrl = coverArt == null ? null : url.replaceFirst("/dwr/.*", "/coverArt.view?size=48&id=" + mediaFile.getId()); - String coverArtZoomUrl = coverArt == null ? null : url.replaceFirst("/dwr/.*", "/coverArt.view?id=" + mediaFile.getId()); - - String avatarUrl = null; - if (userSettings.getAvatarScheme() == AvatarScheme.SYSTEM) { - avatarUrl = url.replaceFirst("/dwr/.*", "/avatar.view?id=" + userSettings.getSystemAvatarId()); - } else if (userSettings.getAvatarScheme() == AvatarScheme.CUSTOM && settingsService.getCustomAvatar(username) != null) { - avatarUrl = url.replaceFirst("/dwr/.*", "/avatar.view?username=" + username); - } - - // Rewrite URLs in case we're behind a proxy. - if (settingsService.isRewriteUrlEnabled()) { - String referer = request.getHeader("referer"); - streamUrl = StringUtil.rewriteUrl(streamUrl, referer); - albumUrl = StringUtil.rewriteUrl(albumUrl, referer); - lyricsUrl = StringUtil.rewriteUrl(lyricsUrl, referer); - coverArtUrl = StringUtil.rewriteUrl(coverArtUrl, referer); - coverArtZoomUrl = StringUtil.rewriteUrl(coverArtZoomUrl, referer); - avatarUrl = StringUtil.rewriteUrl(avatarUrl, referer); - } - - String tooltip = StringUtil.toHtml(artist) + " – " + StringUtil.toHtml(title); - - if (StringUtils.isNotBlank(player.getName())) { - username += "@" + player.getName(); - } - artist = StringUtil.toHtml(StringUtils.abbreviate(artist, 25)); - title = StringUtil.toHtml(StringUtils.abbreviate(title, 25)); - username = StringUtil.toHtml(StringUtils.abbreviate(username, 25)); - - long minutesAgo = status.getMillisSinceLastUpdate() / 1000L / 60L; - if (minutesAgo < 60) { - result.add(new NowPlayingInfo(username, artist, title, tooltip, streamUrl, albumUrl, lyricsUrl, - coverArtUrl, coverArtZoomUrl, avatarUrl, (int) minutesAgo)); - } - } - } - - return result; - - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setMediaScannerService(MediaScannerService mediaScannerService) { - this.mediaScannerService = mediaScannerService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlayQueueInfo.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlayQueueInfo.java deleted file mode 100644 index e95ec1c8..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlayQueueInfo.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import java.util.List; - -/** - * The playlist of a player. - * - * @author Sindre Mehus - */ -public class PlayQueueInfo { - - private final List entries; - private final int index; - private final boolean stopEnabled; - private final boolean repeatEnabled; - private final boolean sendM3U; - private final float gain; - - public PlayQueueInfo(List entries, int index, boolean stopEnabled, boolean repeatEnabled, boolean sendM3U, float gain) { - this.entries = entries; - this.index = index; - this.stopEnabled = stopEnabled; - this.repeatEnabled = repeatEnabled; - this.sendM3U = sendM3U; - this.gain = gain; - } - - public List getEntries() { - return entries; - } - - public int getIndex() { - return index; - } - - public boolean isStopEnabled() { - return stopEnabled; - } - - public boolean isSendM3U() { - return sendM3U; - } - - public boolean isRepeatEnabled() { - return repeatEnabled; - } - - public float getGain() { - return gain; - } - - public static class Entry { - private final int id; - private final Integer trackNumber; - private final String title; - private final String artist; - private final String album; - private final String genre; - private final Integer year; - private final String bitRate; - private final Integer duration; - private final String durationAsString; - private final String format; - private final String contentType; - private final String fileSize; - private final boolean starred; - private final String albumUrl; - private final String streamUrl; - - public Entry(int id, Integer trackNumber, String title, String artist, String album, String genre, Integer year, - String bitRate, Integer duration, String durationAsString, String format, String contentType, String fileSize, - boolean starred, String albumUrl, String streamUrl) { - this.id = id; - this.trackNumber = trackNumber; - this.title = title; - this.artist = artist; - this.album = album; - this.genre = genre; - this.year = year; - this.bitRate = bitRate; - this.duration = duration; - this.durationAsString = durationAsString; - this.format = format; - this.contentType = contentType; - this.fileSize = fileSize; - this.starred = starred; - this.albumUrl = albumUrl; - this.streamUrl = streamUrl; - } - - public int getId() { - return id; - } - - public Integer getTrackNumber() { - return trackNumber; - } - - public String getTitle() { - return title; - } - - public String getArtist() { - return artist; - } - - public String getAlbum() { - return album; - } - - public String getGenre() { - return genre; - } - - public Integer getYear() { - return year; - } - - public String getBitRate() { - return bitRate; - } - - public String getDurationAsString() { - return durationAsString; - } - - public Integer getDuration() { - return duration; - } - - public String getFormat() { - return format; - } - - public String getContentType() { - return contentType; - } - - public String getFileSize() { - return fileSize; - } - - public boolean isStarred() { - return starred; - } - - public String getAlbumUrl() { - return albumUrl; - } - - public String getStreamUrl() { - return streamUrl; - } - } - -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlayQueueService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlayQueueService.java deleted file mode 100644 index 94f78aba..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlayQueueService.java +++ /dev/null @@ -1,455 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import java.io.IOException; -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.domain.Playlist; -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.service.PlaylistService; -import org.directwebremoting.WebContextFactory; -import org.springframework.web.servlet.support.RequestContextUtils; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.util.StringUtil; - -/** - * Provides AJAX-enabled services for manipulating the play queue of a player. - * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class PlayQueueService { - - private PlayerService playerService; - private JukeboxService jukeboxService; - private TranscodingService transcodingService; - private SettingsService settingsService; - private MediaFileService mediaFileService; - private SecurityService securityService; - private MediaFileDao mediaFileDao; - private net.sourceforge.subsonic.service.PlaylistService playlistService; - - /** - * Returns the play queue for the player of the current user. - * - * @return The play queue. - */ - public PlayQueueInfo getPlayQueue() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - return convert(request, player, false); - } - - public PlayQueueInfo start() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - return doStart(request, response); - } - - public PlayQueueInfo doStart(HttpServletRequest request, HttpServletResponse response) throws Exception { - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().setStatus(PlayQueue.Status.PLAYING); - return convert(request, player, true); - } - - public PlayQueueInfo stop() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - return doStop(request, response); - } - - public PlayQueueInfo doStop(HttpServletRequest request, HttpServletResponse response) throws Exception { - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().setStatus(PlayQueue.Status.STOPPED); - return convert(request, player, true); - } - - public PlayQueueInfo skip(int index) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - return doSkip(request, response, index, 0); - } - - public PlayQueueInfo doSkip(HttpServletRequest request, HttpServletResponse response, int index, int offset) throws Exception { - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().setIndex(index); - boolean serverSidePlaylist = !player.isExternalWithPlaylist(); - return convert(request, player, serverSidePlaylist, offset); - } - - public PlayQueueInfo play(int id) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - - Player player = getCurrentPlayer(request, response); - MediaFile file = mediaFileService.getMediaFile(id); - List files = mediaFileService.getDescendantsOf(file, true); - return doPlay(request, player, files); - } - - public PlayQueueInfo playPlaylist(int id) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - - List files = playlistService.getFilesInPlaylist(id); - Player player = getCurrentPlayer(request, response); - return doPlay(request, player, files); - } - - private PlayQueueInfo doPlay(HttpServletRequest request, Player player, List files) throws Exception { - if (player.isWeb()) { - removeVideoFiles(files); - } - player.getPlayQueue().addFiles(false, files); - player.getPlayQueue().setRandomSearchCriteria(null); - return convert(request, player, true); - } - - public PlayQueueInfo playRandom(int id, int count) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - - MediaFile file = mediaFileService.getMediaFile(id); - List randomFiles = getRandomChildren(file, count); - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().addFiles(false, randomFiles); - player.getPlayQueue().setRandomSearchCriteria(null); - return convert(request, player, true); - } - - public PlayQueueInfo add(int id) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - return doAdd(request, response, new int[]{id}); - } - - public PlayQueueInfo doAdd(HttpServletRequest request, HttpServletResponse response, int[] ids) throws Exception { - Player player = getCurrentPlayer(request, response); - List files = new ArrayList(ids.length); - for (int id : ids) { - MediaFile ancestor = mediaFileService.getMediaFile(id); - files.addAll(mediaFileService.getDescendantsOf(ancestor, true)); - } - if (player.isWeb()) { - removeVideoFiles(files); - } - player.getPlayQueue().addFiles(true, files); - player.getPlayQueue().setRandomSearchCriteria(null); - return convert(request, player, false); - } - - public PlayQueueInfo doSet(HttpServletRequest request, HttpServletResponse response, int[] ids) throws Exception { - Player player = getCurrentPlayer(request, response); - PlayQueue playQueue = player.getPlayQueue(); - MediaFile currentFile = playQueue.getCurrentFile(); - PlayQueue.Status status = playQueue.getStatus(); - - playQueue.clear(); - PlayQueueInfo result = doAdd(request, response, ids); - - int index = currentFile == null ? -1 : playQueue.getFiles().indexOf(currentFile); - playQueue.setIndex(index); - playQueue.setStatus(status); - return result; - } - - public PlayQueueInfo clear() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - return doClear(request, response); - } - - public PlayQueueInfo doClear(HttpServletRequest request, HttpServletResponse response) throws Exception { - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().clear(); - boolean serverSidePlaylist = !player.isExternalWithPlaylist(); - return convert(request, player, serverSidePlaylist); - } - - public PlayQueueInfo shuffle() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - return doShuffle(request, response); - } - - public PlayQueueInfo doShuffle(HttpServletRequest request, HttpServletResponse response) throws Exception { - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().shuffle(); - return convert(request, player, false); - } - - public PlayQueueInfo remove(int index) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - return doRemove(request, response, index); - } - - public PlayQueueInfo toggleStar(int index) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - - MediaFile file = player.getPlayQueue().getFile(index); - String username = securityService.getCurrentUsername(request); - boolean starred = mediaFileDao.getMediaFileStarredDate(file.getId(), username) != null; - if (starred) { - mediaFileDao.unstarMediaFile(file.getId(), username); - } else { - mediaFileDao.starMediaFile(file.getId(), username); - } - return convert(request, player, false); - } - - public PlayQueueInfo doRemove(HttpServletRequest request, HttpServletResponse response, int index) throws Exception { - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().removeFileAt(index); - return convert(request, player, false); - } - - public PlayQueueInfo removeMany(int[] indexes) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - for (int i = indexes.length - 1; i >= 0; i--) { - player.getPlayQueue().removeFileAt(indexes[i]); - } - return convert(request, player, false); - } - - public PlayQueueInfo up(int index) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().moveUp(index); - return convert(request, player, false); - } - - public PlayQueueInfo down(int index) throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().moveDown(index); - return convert(request, player, false); - } - - public PlayQueueInfo toggleRepeat() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().setRepeatEnabled(!player.getPlayQueue().isRepeatEnabled()); - return convert(request, player, false); - } - - public PlayQueueInfo undo() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().undo(); - boolean serverSidePlaylist = !player.isExternalWithPlaylist(); - return convert(request, player, serverSidePlaylist); - } - - public PlayQueueInfo sortByTrack() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().sort(PlayQueue.SortOrder.TRACK); - return convert(request, player, false); - } - - public PlayQueueInfo sortByArtist() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().sort(PlayQueue.SortOrder.ARTIST); - return convert(request, player, false); - } - - public PlayQueueInfo sortByAlbum() throws Exception { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - player.getPlayQueue().sort(PlayQueue.SortOrder.ALBUM); - return convert(request, player, false); - } - - public void setGain(float gain) { - jukeboxService.setGain(gain); - } - - - public String savePlaylist() { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - HttpServletResponse response = WebContextFactory.get().getHttpServletResponse(); - Player player = getCurrentPlayer(request, response); - Locale locale = settingsService.getLocale(); - DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, locale); - - Date now = new Date(); - Playlist playlist = new Playlist(); - playlist.setUsername(securityService.getCurrentUsername(request)); - playlist.setCreated(now); - playlist.setChanged(now); - playlist.setPublic(false); - playlist.setName(dateFormat.format(now)); - - playlistService.createPlaylist(playlist); - playlistService.setFilesInPlaylist(playlist.getId(), player.getPlayQueue().getFiles()); - return playlist.getName(); - } - - private List getRandomChildren(MediaFile file, int count) throws IOException { - List children = mediaFileService.getDescendantsOf(file, false); - removeVideoFiles(children); - - if (children.isEmpty()) { - return children; - } - Collections.shuffle(children); - return children.subList(0, Math.min(count, children.size())); - } - - private void removeVideoFiles(List files) { - Iterator iterator = files.iterator(); - while (iterator.hasNext()) { - MediaFile file = iterator.next(); - if (file.isVideo()) { - iterator.remove(); - } - } - } - - private PlayQueueInfo convert(HttpServletRequest request, Player player, boolean sendM3U) throws Exception { - return convert(request, player, sendM3U, 0); - } - - private PlayQueueInfo convert(HttpServletRequest request, Player player, boolean sendM3U, int offset) throws Exception { - String url = request.getRequestURL().toString(); - - if (sendM3U && player.isJukebox()) { - jukeboxService.updateJukebox(player, offset); - } - boolean isCurrentPlayer = player.getIpAddress() != null && player.getIpAddress().equals(request.getRemoteAddr()); - - boolean m3uSupported = player.isExternal() || player.isExternalWithPlaylist(); - sendM3U = player.isAutoControlEnabled() && m3uSupported && isCurrentPlayer && sendM3U; - Locale locale = RequestContextUtils.getLocale(request); - - List entries = new ArrayList(); - PlayQueue playQueue = player.getPlayQueue(); - for (MediaFile file : playQueue.getFiles()) { - String albumUrl = url.replaceFirst("/dwr/.*", "/main.view?id=" + file.getId()); - String streamUrl = url.replaceFirst("/dwr/.*", "/stream?player=" + player.getId() + "&id=" + file.getId()); - - // Rewrite URLs in case we're behind a proxy. - if (settingsService.isRewriteUrlEnabled()) { - String referer = request.getHeader("referer"); - albumUrl = StringUtil.rewriteUrl(albumUrl, referer); - streamUrl = StringUtil.rewriteUrl(streamUrl, referer); - } - - String format = formatFormat(player, file); - String username = securityService.getCurrentUsername(request); - boolean starred = mediaFileService.getMediaFileStarredDate(file.getId(), username) != null; - entries.add(new PlayQueueInfo.Entry(file.getId(), file.getTrackNumber(), file.getTitle(), file.getArtist(), - file.getAlbumName(), file.getGenre(), file.getYear(), formatBitRate(file), - file.getDurationSeconds(), file.getDurationString(), format, formatContentType(format), - formatFileSize(file.getFileSize(), locale), starred, albumUrl, streamUrl)); - } - boolean isStopEnabled = playQueue.getStatus() == PlayQueue.Status.PLAYING && !player.isExternalWithPlaylist(); - float gain = jukeboxService.getGain(); - return new PlayQueueInfo(entries, playQueue.getIndex(), isStopEnabled, playQueue.isRepeatEnabled(), sendM3U, gain); - } - - private String formatFileSize(Long fileSize, Locale locale) { - if (fileSize == null) { - return null; - } - return StringUtil.formatBytes(fileSize, locale); - } - - private String formatFormat(Player player, MediaFile file) { - return transcodingService.getSuffix(player, file, null); - } - - private String formatContentType(String format) { - return StringUtil.getMimeType(format); - } - - private String formatBitRate(MediaFile mediaFile) { - if (mediaFile.getBitRate() == null) { - return null; - } - if (mediaFile.isVariableBitRate()) { - return mediaFile.getBitRate() + " Kbps vbr"; - } - return mediaFile.getBitRate() + " Kbps"; - } - - private Player getCurrentPlayer(HttpServletRequest request, HttpServletResponse response) { - return playerService.getPlayer(request, response); - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setJukeboxService(JukeboxService jukeboxService) { - this.jukeboxService = jukeboxService; - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlaylistInfo.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlaylistInfo.java deleted file mode 100644 index 3fcbfb14..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlaylistInfo.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import java.util.List; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Playlist; - -/** - * The playlist of a player. - * - * @author Sindre Mehus - */ -public class PlaylistInfo { - - private final Playlist playlist; - private final List entries; - - public PlaylistInfo(Playlist playlist, List entries) { - this.playlist = playlist; - this.entries = entries; - } - - public Playlist getPlaylist() { - return playlist; - } - - public List getEntries() { - return entries; - } - - public static class Entry { - private final int id; - private final String title; - private final String artist; - private final String album; - private final String durationAsString; - private final boolean starred; - - public Entry(int id, String title, String artist, String album, String durationAsString, boolean starred) { - this.id = id; - this.title = title; - this.artist = artist; - this.album = album; - this.durationAsString = durationAsString; - this.starred = starred; - } - - public int getId() { - return id; - } - - public String getTitle() { - return title; - } - - public String getArtist() { - return artist; - } - - public String getAlbum() { - return album; - } - - public String getDurationAsString() { - return durationAsString; - } - - public boolean isStarred() { - return starred; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlaylistService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlaylistService.java deleted file mode 100644 index d3bf854f..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/PlaylistService.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import javax.servlet.http.HttpServletRequest; - -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.service.SettingsService; -import org.directwebremoting.WebContextFactory; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Playlist; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.SecurityService; - -/** - * Provides AJAX-enabled services for manipulating playlists. - * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class PlaylistService { - - private MediaFileService mediaFileService; - private SecurityService securityService; - private net.sourceforge.subsonic.service.PlaylistService playlistService; - private MediaFileDao mediaFileDao; - private SettingsService settingsService; - - public List getReadablePlaylists() { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - String username = securityService.getCurrentUsername(request); - return playlistService.getReadablePlaylistsForUser(username); - } - - public List getWritablePlaylists() { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - String username = securityService.getCurrentUsername(request); - return playlistService.getWritablePlaylistsForUser(username); - } - - public PlaylistInfo getPlaylist(int id) { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - - Playlist playlist = playlistService.getPlaylist(id); - List files = playlistService.getFilesInPlaylist(id); - - String username = securityService.getCurrentUsername(request); - mediaFileService.populateStarredDate(files, username); - return new PlaylistInfo(playlist, createEntries(files)); - } - - public List createEmptyPlaylist() { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - Locale locale = settingsService.getLocale(); - DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, locale); - - Date now = new Date(); - Playlist playlist = new Playlist(); - playlist.setUsername(securityService.getCurrentUsername(request)); - playlist.setCreated(now); - playlist.setChanged(now); - playlist.setPublic(false); - playlist.setName(dateFormat.format(now)); - - playlistService.createPlaylist(playlist); - return getReadablePlaylists(); - } - - public void appendToPlaylist(int playlistId, List mediaFileIds) { - List files = playlistService.getFilesInPlaylist(playlistId); - for (Integer mediaFileId : mediaFileIds) { - MediaFile file = mediaFileService.getMediaFile(mediaFileId); - if (file != null) { - files.add(file); - } - } - playlistService.setFilesInPlaylist(playlistId, files); - } - - private List createEntries(List files) { - List result = new ArrayList(); - for (MediaFile file : files) { - result.add(new PlaylistInfo.Entry(file.getId(), file.getTitle(), file.getArtist(), file.getAlbumName(), - file.getDurationString(), file.getStarredDate() != null)); - } - - return result; - } - - public PlaylistInfo toggleStar(int id, int index) { - HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); - String username = securityService.getCurrentUsername(request); - List files = playlistService.getFilesInPlaylist(id); - MediaFile file = files.get(index); - - boolean starred = mediaFileDao.getMediaFileStarredDate(file.getId(), username) != null; - if (starred) { - mediaFileDao.unstarMediaFile(file.getId(), username); - } else { - mediaFileDao.starMediaFile(file.getId(), username); - } - return getPlaylist(id); - } - - public PlaylistInfo remove(int id, int index) { - List files = playlistService.getFilesInPlaylist(id); - files.remove(index); - playlistService.setFilesInPlaylist(id, files); - return getPlaylist(id); - } - - public PlaylistInfo up(int id, int index) { - List files = playlistService.getFilesInPlaylist(id); - if (index > 0) { - MediaFile file = files.remove(index); - files.add(index - 1, file); - playlistService.setFilesInPlaylist(id, files); - } - return getPlaylist(id); - } - - public PlaylistInfo down(int id, int index) { - List files = playlistService.getFilesInPlaylist(id); - if (index < files.size() - 1) { - MediaFile file = files.remove(index); - files.add(index + 1, file); - playlistService.setFilesInPlaylist(id, files); - } - return getPlaylist(id); - } - - public void deletePlaylist(int id) { - playlistService.deletePlaylist(id); - } - - public PlaylistInfo updatePlaylist(int id, String name, String comment, boolean isPublic) { - Playlist playlist = playlistService.getPlaylist(id); - playlist.setName(name); - playlist.setComment(comment); - playlist.setPublic(isPublic); - playlistService.updatePlaylist(playlist); - return getPlaylist(id); - } - - public void setPlaylistService(net.sourceforge.subsonic.service.PlaylistService playlistService) { - this.playlistService = playlistService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/ScanInfo.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/ScanInfo.java deleted file mode 100644 index d984069e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/ScanInfo.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -/** - * Media folder scanning status. - * - * @author Sindre Mehus - */ -public class ScanInfo { - - private final boolean scanning; - private final int count; - - public ScanInfo(boolean scanning, int count) { - this.scanning = scanning; - this.count = count; - } - - public boolean isScanning() { - return scanning; - } - - public int getCount() { - return count; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/StarService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/StarService.java deleted file mode 100644 index 15ba359b..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/StarService.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.service.SecurityService; -import org.directwebremoting.WebContext; -import org.directwebremoting.WebContextFactory; - -/** - * Provides AJAX-enabled services for starring. - *

- * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class StarService { - - private static final Logger LOG = Logger.getLogger(StarService.class); - - private SecurityService securityService; - private MediaFileDao mediaFileDao; - - public void star(int id) { - mediaFileDao.starMediaFile(id, getUser()); - } - - public void unstar(int id) { - mediaFileDao.unstarMediaFile(id, getUser()); - } - - private String getUser() { - WebContext webContext = WebContextFactory.get(); - User user = securityService.getCurrentUser(webContext.getHttpServletRequest()); - return user.getUsername(); - } - - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/TagService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/TagService.java deleted file mode 100644 index f7373b4e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/TagService.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.metadata.MetaData; -import net.sourceforge.subsonic.service.metadata.MetaDataParser; -import net.sourceforge.subsonic.service.metadata.MetaDataParserFactory; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; - -/** - * Provides AJAX-enabled services for editing tags in music files. - * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class TagService { - - private static final Logger LOG = Logger.getLogger(TagService.class); - - private MetaDataParserFactory metaDataParserFactory; - private MediaFileService mediaFileService; - - /** - * Updated tags for a given music file. - * - * @param id The ID of the music file. - * @param track The track number. - * @param artist The artist name. - * @param album The album name. - * @param title The song title. - * @param year The release year. - * @param genre The musical genre. - * @return "UPDATED" if the new tags were updated, "SKIPPED" if no update was necessary. - * Otherwise the error message is returned. - */ - public String setTags(int id, String track, String artist, String album, String title, String year, String genre) { - - track = StringUtils.trimToNull(track); - artist = StringUtils.trimToNull(artist); - album = StringUtils.trimToNull(album); - title = StringUtils.trimToNull(title); - year = StringUtils.trimToNull(year); - genre = StringUtils.trimToNull(genre); - - Integer trackNumber = null; - if (track != null) { - try { - trackNumber = new Integer(track); - } catch (NumberFormatException x) { - LOG.warn("Illegal track number: " + track, x); - } - } - - Integer yearNumber = null; - if (year != null) { - try { - yearNumber = new Integer(year); - } catch (NumberFormatException x) { - LOG.warn("Illegal year: " + year, x); - } - } - - try { - - MediaFile file = mediaFileService.getMediaFile(id); - MetaDataParser parser = metaDataParserFactory.getParser(file.getFile()); - - if (!parser.isEditingSupported()) { - return "Tag editing of " + FilenameUtils.getExtension(file.getPath()) + " files is not supported."; - } - - MetaData existingMetaData = parser.getRawMetaData(file.getFile()); - - if (StringUtils.equals(artist, existingMetaData.getArtist()) && - StringUtils.equals(album, existingMetaData.getAlbumName()) && - StringUtils.equals(title, existingMetaData.getTitle()) && - ObjectUtils.equals(yearNumber, existingMetaData.getYear()) && - StringUtils.equals(genre, existingMetaData.getGenre()) && - ObjectUtils.equals(trackNumber, existingMetaData.getTrackNumber())) { - return "SKIPPED"; - } - - MetaData newMetaData = new MetaData(); - newMetaData.setArtist(artist); - newMetaData.setAlbumName(album); - newMetaData.setTitle(title); - newMetaData.setYear(yearNumber); - newMetaData.setGenre(genre); - newMetaData.setTrackNumber(trackNumber); - parser.setMetaData(file, newMetaData); - mediaFileService.refreshMediaFile(file); - return "UPDATED"; - - } catch (Exception x) { - LOG.warn("Failed to update tags for " + id, x); - return x.getMessage(); - } - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setMetaDataParserFactory(MetaDataParserFactory metaDataParserFactory) { - this.metaDataParserFactory = metaDataParserFactory; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/TransferService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/TransferService.java deleted file mode 100644 index 19309348..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/TransferService.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.controller.*; -import org.directwebremoting.*; - -import javax.servlet.http.*; - -/** - * Provides AJAX-enabled services for retrieving the status of ongoing transfers. - * This class is used by the DWR framework (http://getahead.ltd.uk/dwr/). - * - * @author Sindre Mehus - */ -public class TransferService { - - /** - * Returns info about any ongoing upload within the current session. - * @return Info about ongoing upload. - */ - public UploadInfo getUploadInfo() { - - HttpSession session = WebContextFactory.get().getSession(); - TransferStatus status = (TransferStatus) session.getAttribute(UploadController.UPLOAD_STATUS); - - if (status != null) { - return new UploadInfo(status.getBytesTransfered(), status.getBytesTotal()); - } - return new UploadInfo(0L, 0L); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/UploadInfo.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/UploadInfo.java deleted file mode 100644 index 47f9de99..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ajax/UploadInfo.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ajax; - -/** - * Contains status for a file upload. - * - * @author Sindre Mehus - */ -public class UploadInfo { - - private long bytesUploaded; - private long bytesTotal; - - public UploadInfo(long bytesUploaded, long bytesTotal) { - this.bytesUploaded = bytesUploaded; - this.bytesTotal = bytesTotal; - } - - /** - * Returns the number of bytes uploaded. - * @return The number of bytes uploaded. - */ - public long getBytesUploaded() { - return bytesUploaded; - } - - /** - * Returns the total number of bytes. - * @return The total number of bytes. - */ - public long getBytesTotal() { - return bytesTotal; - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/cache/CacheFactory.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/cache/CacheFactory.java deleted file mode 100644 index 00f656b1..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/cache/CacheFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.cache; - - -import java.io.File; - -import org.springframework.beans.factory.InitializingBean; - -import net.sf.ehcache.Cache; -import net.sf.ehcache.CacheManager; -import net.sf.ehcache.Ehcache; -import net.sf.ehcache.config.Configuration; -import net.sf.ehcache.config.ConfigurationFactory; -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.service.SettingsService; - -/** - * Initializes Ehcache and creates caches. - * - * @author Sindre Mehus - * @version $Id$ - */ -public class CacheFactory implements InitializingBean { - - private static final Logger LOG = Logger.getLogger(CacheFactory.class); - private CacheManager cacheManager; - - public void afterPropertiesSet() throws Exception { - Configuration configuration = ConfigurationFactory.parseConfiguration(); - - // Override configuration to make sure cache is stored in Subsonic home dir. - File cacheDir = new File(SettingsService.getSubsonicHome(), "cache"); - configuration.getDiskStoreConfiguration().setPath(cacheDir.getPath()); - - cacheManager = CacheManager.create(configuration); - } - - public Ehcache getCache(String name) { - return cacheManager.getCache(name); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/AdvancedSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/AdvancedSettingsCommand.java deleted file mode 100644 index 6c87df51..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/AdvancedSettingsCommand.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import net.sourceforge.subsonic.controller.AdvancedSettingsController; - -/** - * Command used in {@link AdvancedSettingsController}. - * - * @author Sindre Mehus - */ -public class AdvancedSettingsCommand { - private String downsampleCommand; - private String coverArtLimit; - private String downloadLimit; - private String uploadLimit; - private String streamPort; - private boolean ldapEnabled; - private String ldapUrl; - private String ldapSearchFilter; - private String ldapManagerDn; - private String ldapManagerPassword; - private boolean ldapAutoShadowing; - private String brand; - private boolean isReloadNeeded; - - public String getDownsampleCommand() { - return downsampleCommand; - } - - public void setDownsampleCommand(String downsampleCommand) { - this.downsampleCommand = downsampleCommand; - } - - public String getCoverArtLimit() { - return coverArtLimit; - } - - public void setCoverArtLimit(String coverArtLimit) { - this.coverArtLimit = coverArtLimit; - } - - public String getDownloadLimit() { - return downloadLimit; - } - - public void setDownloadLimit(String downloadLimit) { - this.downloadLimit = downloadLimit; - } - - public String getUploadLimit() { - return uploadLimit; - } - - public String getStreamPort() { - return streamPort; - } - - public void setStreamPort(String streamPort) { - this.streamPort = streamPort; - } - - public void setUploadLimit(String uploadLimit) { - this.uploadLimit = uploadLimit; - } - - public boolean isLdapEnabled() { - return ldapEnabled; - } - - public void setLdapEnabled(boolean ldapEnabled) { - this.ldapEnabled = ldapEnabled; - } - - public String getLdapUrl() { - return ldapUrl; - } - - public void setLdapUrl(String ldapUrl) { - this.ldapUrl = ldapUrl; - } - - public String getLdapSearchFilter() { - return ldapSearchFilter; - } - - public void setLdapSearchFilter(String ldapSearchFilter) { - this.ldapSearchFilter = ldapSearchFilter; - } - - public String getLdapManagerDn() { - return ldapManagerDn; - } - - public void setLdapManagerDn(String ldapManagerDn) { - this.ldapManagerDn = ldapManagerDn; - } - - public String getLdapManagerPassword() { - return ldapManagerPassword; - } - - public void setLdapManagerPassword(String ldapManagerPassword) { - this.ldapManagerPassword = ldapManagerPassword; - } - - public boolean isLdapAutoShadowing() { - return ldapAutoShadowing; - } - - public void setLdapAutoShadowing(boolean ldapAutoShadowing) { - this.ldapAutoShadowing = ldapAutoShadowing; - } - - public void setBrand(String brand) { - this.brand = brand; - } - - public String getBrand() { - return brand; - } - - public void setReloadNeeded(boolean reloadNeeded) { - isReloadNeeded = reloadNeeded; - } - - public boolean isReloadNeeded() { - return isReloadNeeded; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/DonateCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/DonateCommand.java deleted file mode 100644 index 04af0ff6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/DonateCommand.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import net.sourceforge.subsonic.controller.DonateController; - -import java.util.Date; - -import org.apache.commons.lang.StringUtils; - -/** - * Command used in {@link DonateController}. - * - * @author Sindre Mehus - */ -public class DonateCommand { - - private String path; - private String emailAddress; - private String license; - private Date licenseDate; - private boolean licenseValid; - private String brand; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getEmailAddress() { - return emailAddress; - } - - public void setEmailAddress(String emailAddress) { - this.emailAddress = StringUtils.trim(emailAddress); - } - - public String getLicense() { - return license; - } - - public void setLicense(String license) { - this.license = StringUtils.trim(license); - } - - public Date getLicenseDate() { - return licenseDate; - } - - public void setLicenseDate(Date licenseDate) { - this.licenseDate = licenseDate; - } - - public boolean isLicenseValid() { - return licenseValid; - } - - public void setLicenseValid(boolean licenseValid) { - this.licenseValid = licenseValid; - } - - public String getBrand() { - return brand; - } - - public void setBrand(String brand) { - this.brand = brand; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/EnumHolder.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/EnumHolder.java deleted file mode 100644 index bb1fc5ff..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/EnumHolder.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -/** - * Holds the name and description of an enum value. - * - * @author Sindre Mehus - */ -public class EnumHolder { - private String name; - private String description; - - public EnumHolder(String name, String description) { - this.name = name; - this.description = description; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/GeneralSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/GeneralSettingsCommand.java deleted file mode 100644 index 2322a3bd..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/GeneralSettingsCommand.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import net.sourceforge.subsonic.controller.GeneralSettingsController; -import net.sourceforge.subsonic.domain.Theme; - -/** - * Command used in {@link GeneralSettingsController}. - * - * @author Sindre Mehus - */ -public class GeneralSettingsCommand { - - private String musicFileTypes; - private String videoFileTypes; - private String coverArtFileTypes; - private String index; - private String ignoredArticles; - private String shortcuts; - private boolean sortAlbumsByYear; - private boolean gettingStartedEnabled; - private String welcomeTitle; - private String welcomeSubtitle; - private String welcomeMessage; - private String loginMessage; - private String localeIndex; - private String[] locales; - private String themeIndex; - private Theme[] themes; - private boolean isReloadNeeded; - - public String getMusicFileTypes() { - return musicFileTypes; - } - - public void setMusicFileTypes(String musicFileTypes) { - this.musicFileTypes = musicFileTypes; - } - - public String getVideoFileTypes() { - return videoFileTypes; - } - - public void setVideoFileTypes(String videoFileTypes) { - this.videoFileTypes = videoFileTypes; - } - - public String getCoverArtFileTypes() { - return coverArtFileTypes; - } - - public void setCoverArtFileTypes(String coverArtFileTypes) { - this.coverArtFileTypes = coverArtFileTypes; - } - - public String getIndex() { - return index; - } - - public void setIndex(String index) { - this.index = index; - } - - public String getIgnoredArticles() { - return ignoredArticles; - } - - public void setIgnoredArticles(String ignoredArticles) { - this.ignoredArticles = ignoredArticles; - } - - public String getShortcuts() { - return shortcuts; - } - - public void setShortcuts(String shortcuts) { - this.shortcuts = shortcuts; - } - - public String getWelcomeTitle() { - return welcomeTitle; - } - - public void setWelcomeTitle(String welcomeTitle) { - this.welcomeTitle = welcomeTitle; - } - - public String getWelcomeSubtitle() { - return welcomeSubtitle; - } - - public void setWelcomeSubtitle(String welcomeSubtitle) { - this.welcomeSubtitle = welcomeSubtitle; - } - - public String getWelcomeMessage() { - return welcomeMessage; - } - - public void setWelcomeMessage(String welcomeMessage) { - this.welcomeMessage = welcomeMessage; - } - - public String getLoginMessage() { - return loginMessage; - } - - public void setLoginMessage(String loginMessage) { - this.loginMessage = loginMessage; - } - - public String getLocaleIndex() { - return localeIndex; - } - - public void setLocaleIndex(String localeIndex) { - this.localeIndex = localeIndex; - } - - public String[] getLocales() { - return locales; - } - - public void setLocales(String[] locales) { - this.locales = locales; - } - - public String getThemeIndex() { - return themeIndex; - } - - public void setThemeIndex(String themeIndex) { - this.themeIndex = themeIndex; - } - - public Theme[] getThemes() { - return themes; - } - - public void setThemes(Theme[] themes) { - this.themes = themes; - } - - public boolean isReloadNeeded() { - return isReloadNeeded; - } - - public void setReloadNeeded(boolean reloadNeeded) { - isReloadNeeded = reloadNeeded; - } - - public boolean isSortAlbumsByYear() { - return sortAlbumsByYear; - } - - public void setSortAlbumsByYear(boolean sortAlbumsByYear) { - this.sortAlbumsByYear = sortAlbumsByYear; - } - - public boolean isGettingStartedEnabled() { - return gettingStartedEnabled; - } - - public void setGettingStartedEnabled(boolean gettingStartedEnabled) { - this.gettingStartedEnabled = gettingStartedEnabled; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/MusicFolderSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/MusicFolderSettingsCommand.java deleted file mode 100644 index 8fcfa72c..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/MusicFolderSettingsCommand.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import java.io.File; -import java.util.Date; -import java.util.List; - -import net.sourceforge.subsonic.controller.MusicFolderSettingsController; -import net.sourceforge.subsonic.domain.MusicFolder; -import org.apache.commons.lang.StringUtils; - -/** - * Command used in {@link MusicFolderSettingsController}. - * - * @author Sindre Mehus - */ -public class MusicFolderSettingsCommand { - - private String interval; - private String hour; - private boolean scanning; - private boolean fastCache; - private boolean organizeByFolderStructure; - private List musicFolders; - private MusicFolderInfo newMusicFolder; - private boolean reload; - - public String getInterval() { - return interval; - } - - public void setInterval(String interval) { - this.interval = interval; - } - - public String getHour() { - return hour; - } - - public void setHour(String hour) { - this.hour = hour; - } - - public boolean isScanning() { - return scanning; - } - - public void setScanning(boolean scanning) { - this.scanning = scanning; - } - - public boolean isFastCache() { - return fastCache; - } - - public List getMusicFolders() { - return musicFolders; - } - - public void setMusicFolders(List musicFolders) { - this.musicFolders = musicFolders; - } - - public void setFastCache(boolean fastCache) { - this.fastCache = fastCache; - } - - public MusicFolderInfo getNewMusicFolder() { - return newMusicFolder; - } - - public void setNewMusicFolder(MusicFolderInfo newMusicFolder) { - this.newMusicFolder = newMusicFolder; - } - - public void setReload(boolean reload) { - this.reload = reload; - } - - public boolean isReload() { - return reload; - } - - public boolean isOrganizeByFolderStructure() { - return organizeByFolderStructure; - } - - public void setOrganizeByFolderStructure(boolean organizeByFolderStructure) { - this.organizeByFolderStructure = organizeByFolderStructure; - } - - public static class MusicFolderInfo { - - private Integer id; - private String path; - private String name; - private boolean enabled; - private boolean delete; - private boolean existing; - - public MusicFolderInfo(MusicFolder musicFolder) { - id = musicFolder.getId(); - path = musicFolder.getPath().getPath(); - name = musicFolder.getName(); - enabled = musicFolder.isEnabled(); - existing = musicFolder.getPath().exists() && musicFolder.getPath().isDirectory(); - } - - public MusicFolderInfo() { - enabled = true; - } - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public boolean isDelete() { - return delete; - } - - public void setDelete(boolean delete) { - this.delete = delete; - } - - public MusicFolder toMusicFolder() { - String path = StringUtils.trimToNull(this.path); - if (path == null) { - return null; - } - File file = new File(path); - String name = StringUtils.trimToNull(this.name); - if (name == null) { - name = file.getName(); - } - return new MusicFolder(id, new File(path), name, enabled, new Date()); - } - - public boolean isExisting() { - return existing; - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/NetworkSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/NetworkSettingsCommand.java deleted file mode 100644 index d0ae2b07..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/NetworkSettingsCommand.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import java.util.Date; - -/** - * @author Sindre Mehus - * @version $Id$ - */ -public class NetworkSettingsCommand { - - private boolean portForwardingEnabled; - private boolean urlRedirectionEnabled; - private String urlRedirectFrom; - private int port; - private boolean trial; - private Date trialExpires; - private boolean trialExpired; - - public void setPortForwardingEnabled(boolean portForwardingEnabled) { - this.portForwardingEnabled = portForwardingEnabled; - } - - public boolean isPortForwardingEnabled() { - return portForwardingEnabled; - } - - public boolean isUrlRedirectionEnabled() { - return urlRedirectionEnabled; - } - - public void setUrlRedirectionEnabled(boolean urlRedirectionEnabled) { - this.urlRedirectionEnabled = urlRedirectionEnabled; - } - - public String getUrlRedirectFrom() { - return urlRedirectFrom; - } - - public void setUrlRedirectFrom(String urlRedirectFrom) { - this.urlRedirectFrom = urlRedirectFrom; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public void setTrial(boolean trial) { - this.trial = trial; - } - - public boolean isTrial() { - return trial; - } - - public void setTrialExpires(Date trialExpires) { - this.trialExpires = trialExpires; - } - - public Date getTrialExpires() { - return trialExpires; - } - - public void setTrialExpired(boolean trialExpired) { - this.trialExpired = trialExpired; - } - - public boolean isTrialExpired() { - return trialExpired; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PasswordSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PasswordSettingsCommand.java deleted file mode 100644 index b9e5383c..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PasswordSettingsCommand.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import net.sourceforge.subsonic.controller.*; - -/** - * Command used in {@link PasswordSettingsController}. - * - * @author Sindre Mehus - */ -public class PasswordSettingsCommand { - private String username; - private String password; - private String confirmPassword; - private boolean ldapAuthenticated; - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getConfirmPassword() { - return confirmPassword; - } - - public void setConfirmPassword(String confirmPassword) { - this.confirmPassword = confirmPassword; - } - - public boolean isLdapAuthenticated() { - return ldapAuthenticated; - } - - public void setLdapAuthenticated(boolean ldapAuthenticated) { - this.ldapAuthenticated = ldapAuthenticated; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PersonalSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PersonalSettingsCommand.java deleted file mode 100644 index 680d06e9..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PersonalSettingsCommand.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import net.sourceforge.subsonic.controller.PersonalSettingsController; -import net.sourceforge.subsonic.domain.Avatar; -import net.sourceforge.subsonic.domain.Theme; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; - -import java.util.List; - -/** - * Command used in {@link PersonalSettingsController}. - * - * @author Sindre Mehus - */ -public class PersonalSettingsCommand { - private User user; - private String localeIndex; - private String[] locales; - private String themeIndex; - private Theme[] themes; - private int avatarId; - private List avatars; - private Avatar customAvatar; - private UserSettings.Visibility mainVisibility; - private UserSettings.Visibility playlistVisibility; - private boolean partyModeEnabled; - private boolean showNowPlayingEnabled; - private boolean showChatEnabled; - private boolean nowPlayingAllowed; - private boolean finalVersionNotificationEnabled; - private boolean betaVersionNotificationEnabled; - private boolean lastFmEnabled; - private String lastFmUsername; - private String lastFmPassword; - private boolean isReloadNeeded; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public String getLocaleIndex() { - return localeIndex; - } - - public void setLocaleIndex(String localeIndex) { - this.localeIndex = localeIndex; - } - - public String[] getLocales() { - return locales; - } - - public void setLocales(String[] locales) { - this.locales = locales; - } - - public String getThemeIndex() { - return themeIndex; - } - - public void setThemeIndex(String themeIndex) { - this.themeIndex = themeIndex; - } - - public Theme[] getThemes() { - return themes; - } - - public void setThemes(Theme[] themes) { - this.themes = themes; - } - - public int getAvatarId() { - return avatarId; - } - - public void setAvatarId(int avatarId) { - this.avatarId = avatarId; - } - - public List getAvatars() { - return avatars; - } - - public void setAvatars(List avatars) { - this.avatars = avatars; - } - - public Avatar getCustomAvatar() { - return customAvatar; - } - - public void setCustomAvatar(Avatar customAvatar) { - this.customAvatar = customAvatar; - } - - public UserSettings.Visibility getMainVisibility() { - return mainVisibility; - } - - public void setMainVisibility(UserSettings.Visibility mainVisibility) { - this.mainVisibility = mainVisibility; - } - - public UserSettings.Visibility getPlaylistVisibility() { - return playlistVisibility; - } - - public void setPlaylistVisibility(UserSettings.Visibility playlistVisibility) { - this.playlistVisibility = playlistVisibility; - } - - public boolean isPartyModeEnabled() { - return partyModeEnabled; - } - - public void setPartyModeEnabled(boolean partyModeEnabled) { - this.partyModeEnabled = partyModeEnabled; - } - - public boolean isShowNowPlayingEnabled() { - return showNowPlayingEnabled; - } - - public void setShowNowPlayingEnabled(boolean showNowPlayingEnabled) { - this.showNowPlayingEnabled = showNowPlayingEnabled; - } - - public boolean isShowChatEnabled() { - return showChatEnabled; - } - - public void setShowChatEnabled(boolean showChatEnabled) { - this.showChatEnabled = showChatEnabled; - } - - public boolean isNowPlayingAllowed() { - return nowPlayingAllowed; - } - - public void setNowPlayingAllowed(boolean nowPlayingAllowed) { - this.nowPlayingAllowed = nowPlayingAllowed; - } - - public boolean isFinalVersionNotificationEnabled() { - return finalVersionNotificationEnabled; - } - - public void setFinalVersionNotificationEnabled(boolean finalVersionNotificationEnabled) { - this.finalVersionNotificationEnabled = finalVersionNotificationEnabled; - } - - public boolean isBetaVersionNotificationEnabled() { - return betaVersionNotificationEnabled; - } - - public void setBetaVersionNotificationEnabled(boolean betaVersionNotificationEnabled) { - this.betaVersionNotificationEnabled = betaVersionNotificationEnabled; - } - - public boolean isLastFmEnabled() { - return lastFmEnabled; - } - - public void setLastFmEnabled(boolean lastFmEnabled) { - this.lastFmEnabled = lastFmEnabled; - } - - public String getLastFmUsername() { - return lastFmUsername; - } - - public void setLastFmUsername(String lastFmUsername) { - this.lastFmUsername = lastFmUsername; - } - - public String getLastFmPassword() { - return lastFmPassword; - } - - public void setLastFmPassword(String lastFmPassword) { - this.lastFmPassword = lastFmPassword; - } - - public boolean isReloadNeeded() { - return isReloadNeeded; - } - - public void setReloadNeeded(boolean reloadNeeded) { - isReloadNeeded = reloadNeeded; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PlayerSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PlayerSettingsCommand.java deleted file mode 100644 index 8331260d..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PlayerSettingsCommand.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import java.util.Date; -import java.util.List; - -import net.sourceforge.subsonic.controller.PlayerSettingsController; -import net.sourceforge.subsonic.domain.CoverArtScheme; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayerTechnology; -import net.sourceforge.subsonic.domain.TranscodeScheme; -import net.sourceforge.subsonic.domain.Transcoding; - -/** - * Command used in {@link PlayerSettingsController}. - * - * @author Sindre Mehus - */ -public class PlayerSettingsCommand { - private String playerId; - private String name; - private String description; - private String type; - private Date lastSeen; - private boolean isDynamicIp; - private boolean isAutoControlEnabled; - private String coverArtSchemeName; - private String technologyName; - private String transcodeSchemeName; - private boolean transcodingSupported; - private String transcodeDirectory; - private List allTranscodings; - private int[] activeTranscodingIds; - private EnumHolder[] technologyHolders; - private EnumHolder[] transcodeSchemeHolders; - private EnumHolder[] coverArtSchemeHolders; - private Player[] players; - private boolean isAdmin; - private boolean isReloadNeeded; - - public String getPlayerId() { - return playerId; - } - - public void setPlayerId(String playerId) { - this.playerId = playerId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Date getLastSeen() { - return lastSeen; - } - - public void setLastSeen(Date lastSeen) { - this.lastSeen = lastSeen; - } - - public boolean isDynamicIp() { - return isDynamicIp; - } - - public void setDynamicIp(boolean dynamicIp) { - isDynamicIp = dynamicIp; - } - - public boolean isAutoControlEnabled() { - return isAutoControlEnabled; - } - - public void setAutoControlEnabled(boolean autoControlEnabled) { - isAutoControlEnabled = autoControlEnabled; - } - - public String getCoverArtSchemeName() { - return coverArtSchemeName; - } - - public void setCoverArtSchemeName(String coverArtSchemeName) { - this.coverArtSchemeName = coverArtSchemeName; - } - - public String getTranscodeSchemeName() { - return transcodeSchemeName; - } - - public void setTranscodeSchemeName(String transcodeSchemeName) { - this.transcodeSchemeName = transcodeSchemeName; - } - - public boolean isTranscodingSupported() { - return transcodingSupported; - } - - public void setTranscodingSupported(boolean transcodingSupported) { - this.transcodingSupported = transcodingSupported; - } - - public String getTranscodeDirectory() { - return transcodeDirectory; - } - - public void setTranscodeDirectory(String transcodeDirectory) { - this.transcodeDirectory = transcodeDirectory; - } - - public List getAllTranscodings() { - return allTranscodings; - } - - public void setAllTranscodings(List allTranscodings) { - this.allTranscodings = allTranscodings; - } - - public int[] getActiveTranscodingIds() { - return activeTranscodingIds; - } - - public void setActiveTranscodingIds(int[] activeTranscodingIds) { - this.activeTranscodingIds = activeTranscodingIds; - } - - public EnumHolder[] getTechnologyHolders() { - return technologyHolders; - } - - public void setTechnologies(PlayerTechnology[] technologies) { - technologyHolders = new EnumHolder[technologies.length]; - for (int i = 0; i < technologies.length; i++) { - PlayerTechnology technology = technologies[i]; - technologyHolders[i] = new EnumHolder(technology.name(), technology.toString()); - } - } - - public EnumHolder[] getTranscodeSchemeHolders() { - return transcodeSchemeHolders; - } - - public void setTranscodeSchemes(TranscodeScheme[] transcodeSchemes) { - transcodeSchemeHolders = new EnumHolder[transcodeSchemes.length]; - for (int i = 0; i < transcodeSchemes.length; i++) { - TranscodeScheme scheme = transcodeSchemes[i]; - transcodeSchemeHolders[i] = new EnumHolder(scheme.name(), scheme.toString()); - } - } - - public EnumHolder[] getCoverArtSchemeHolders() { - return coverArtSchemeHolders; - } - - public void setCoverArtSchemes(CoverArtScheme[] coverArtSchemes) { - coverArtSchemeHolders = new EnumHolder[coverArtSchemes.length]; - for (int i = 0; i < coverArtSchemes.length; i++) { - CoverArtScheme scheme = coverArtSchemes[i]; - coverArtSchemeHolders[i] = new EnumHolder(scheme.name(), scheme.toString()); - } - } - - public String getTechnologyName() { - return technologyName; - } - - public void setTechnologyName(String technologyName) { - this.technologyName = technologyName; - } - - public Player[] getPlayers() { - return players; - } - - public void setPlayers(Player[] players) { - this.players = players; - } - - public boolean isAdmin() { - return isAdmin; - } - - public void setAdmin(boolean admin) { - isAdmin = admin; - } - - public boolean isReloadNeeded() { - return isReloadNeeded; - } - - public void setReloadNeeded(boolean reloadNeeded) { - isReloadNeeded = reloadNeeded; - } - - /** - * Holds the transcoding and whether it is active for the given player. - */ - public static class TranscodingHolder { - private Transcoding transcoding; - private boolean isActive; - - public TranscodingHolder(Transcoding transcoding, boolean isActive) { - this.transcoding = transcoding; - this.isActive = isActive; - } - - public Transcoding getTranscoding() { - return transcoding; - } - - public boolean isActive() { - return isActive; - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PodcastSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PodcastSettingsCommand.java deleted file mode 100644 index e6917ff4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/PodcastSettingsCommand.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import net.sourceforge.subsonic.controller.PodcastSettingsController; - -/** - * Command used in {@link PodcastSettingsController}. - * - * @author Sindre Mehus - */ -public class PodcastSettingsCommand { - - private String interval; - private String folder; - private String episodeRetentionCount; - private String episodeDownloadCount; - - public String getInterval() { - return interval; - } - - public void setInterval(String interval) { - this.interval = interval; - } - - public String getFolder() { - return folder; - } - - public void setFolder(String folder) { - this.folder = folder; - } - - public String getEpisodeRetentionCount() { - return episodeRetentionCount; - } - - public void setEpisodeRetentionCount(String episodeRetentionCount) { - this.episodeRetentionCount = episodeRetentionCount; - } - - public String getEpisodeDownloadCount() { - return episodeDownloadCount; - } - - public void setEpisodeDownloadCount(String episodeDownloadCount) { - this.episodeDownloadCount = episodeDownloadCount; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/SearchCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/SearchCommand.java deleted file mode 100644 index 0dacfbd4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/SearchCommand.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.controller.*; - -import java.util.*; - -/** - * Command used in {@link SearchController}. - * - * @author Sindre Mehus - */ -public class SearchCommand { - - private String query; - private List artists; - private List albums; - private List songs; - private boolean isIndexBeingCreated; - private User user; - private boolean partyModeEnabled; - private Player player; - - public String getQuery() { - return query; - } - - public void setQuery(String query) { - this.query = query; - } - - public boolean isIndexBeingCreated() { - return isIndexBeingCreated; - } - - public void setIndexBeingCreated(boolean indexBeingCreated) { - isIndexBeingCreated = indexBeingCreated; - } - - public List getArtists() { - return artists; - } - - public void setArtists(List artists) { - this.artists = artists; - } - - public List getAlbums() { - return albums; - } - - public void setAlbums(List albums) { - this.albums = albums; - } - - public List getSongs() { - return songs; - } - - public void setSongs(List songs) { - this.songs = songs; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public boolean isPartyModeEnabled() { - return partyModeEnabled; - } - - public void setPartyModeEnabled(boolean partyModeEnabled) { - this.partyModeEnabled = partyModeEnabled; - } - - public Player getPlayer() { - return player; - } - - public void setPlayer(Player player) { - this.player = player; - } - - public static class Match { - private MediaFile mediaFile; - private String title; - private String album; - private String artist; - - public Match(MediaFile mediaFile, String title, String album, String artist) { - this.mediaFile = mediaFile; - this.title = title; - this.album = album; - this.artist = artist; - } - - public MediaFile getMediaFile() { - return mediaFile; - } - - public String getTitle() { - return title; - } - - public String getAlbum() { - return album; - } - - public String getArtist() { - return artist; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/UserSettingsCommand.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/command/UserSettingsCommand.java deleted file mode 100644 index ce185f7b..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/command/UserSettingsCommand.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.command; - -import java.util.List; - -import net.sourceforge.subsonic.controller.*; -import net.sourceforge.subsonic.domain.*; - -/** - * Command used in {@link UserSettingsController}. - * - * @author Sindre Mehus - */ -public class UserSettingsCommand { - private String username; - private boolean isAdminRole; - private boolean isDownloadRole; - private boolean isUploadRole; - private boolean isCoverArtRole; - private boolean isCommentRole; - private boolean isPodcastRole; - private boolean isStreamRole; - private boolean isJukeboxRole; - private boolean isSettingsRole; - private boolean isShareRole; - - private List users; - private boolean isAdmin; - private boolean isPasswordChange; - private boolean isNew; - private boolean isDelete; - private String password; - private String confirmPassword; - private String email; - private boolean isLdapAuthenticated; - private boolean isLdapEnabled; - - private String transcodeSchemeName; - private EnumHolder[] transcodeSchemeHolders; - private boolean transcodingSupported; - private String transcodeDirectory; - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public boolean isAdminRole() { - return isAdminRole; - } - - public void setAdminRole(boolean adminRole) { - isAdminRole = adminRole; - } - - public boolean isDownloadRole() { - return isDownloadRole; - } - - public void setDownloadRole(boolean downloadRole) { - isDownloadRole = downloadRole; - } - - public boolean isUploadRole() { - return isUploadRole; - } - - public void setUploadRole(boolean uploadRole) { - isUploadRole = uploadRole; - } - - public boolean isCoverArtRole() { - return isCoverArtRole; - } - - public void setCoverArtRole(boolean coverArtRole) { - isCoverArtRole = coverArtRole; - } - - public boolean isCommentRole() { - return isCommentRole; - } - - public void setCommentRole(boolean commentRole) { - isCommentRole = commentRole; - } - - public boolean isPodcastRole() { - return isPodcastRole; - } - - public void setPodcastRole(boolean podcastRole) { - isPodcastRole = podcastRole; - } - - public boolean isStreamRole() { - return isStreamRole; - } - - public void setStreamRole(boolean streamRole) { - isStreamRole = streamRole; - } - - public boolean isJukeboxRole() { - return isJukeboxRole; - } - - public void setJukeboxRole(boolean jukeboxRole) { - isJukeboxRole = jukeboxRole; - } - - public boolean isSettingsRole() { - return isSettingsRole; - } - - public void setSettingsRole(boolean settingsRole) { - isSettingsRole = settingsRole; - } - - public boolean isShareRole() { - return isShareRole; - } - - public void setShareRole(boolean shareRole) { - isShareRole = shareRole; - } - - public List getUsers() { - return users; - } - - public void setUsers(List users) { - this.users = users; - } - - public boolean isAdmin() { - return isAdmin; - } - - public void setAdmin(boolean admin) { - isAdmin = admin; - } - - public boolean isPasswordChange() { - return isPasswordChange; - } - - public void setPasswordChange(boolean passwordChange) { - isPasswordChange = passwordChange; - } - - public boolean isNew() { - return isNew; - } - - public void setNew(boolean isNew) { - this.isNew = isNew; - } - - public boolean isDelete() { - return isDelete; - } - - public void setDelete(boolean delete) { - isDelete = delete; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getConfirmPassword() { - return confirmPassword; - } - - public void setConfirmPassword(String confirmPassword) { - this.confirmPassword = confirmPassword; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public boolean isLdapAuthenticated() { - return isLdapAuthenticated; - } - - public void setLdapAuthenticated(boolean ldapAuthenticated) { - isLdapAuthenticated = ldapAuthenticated; - } - - public boolean isLdapEnabled() { - return isLdapEnabled; - } - - public void setLdapEnabled(boolean ldapEnabled) { - isLdapEnabled = ldapEnabled; - } - - public String getTranscodeSchemeName() { - return transcodeSchemeName; - } - - public void setTranscodeSchemeName(String transcodeSchemeName) { - this.transcodeSchemeName = transcodeSchemeName; - } - - public EnumHolder[] getTranscodeSchemeHolders() { - return transcodeSchemeHolders; - } - - public void setTranscodeSchemes(TranscodeScheme[] transcodeSchemes) { - transcodeSchemeHolders = new EnumHolder[transcodeSchemes.length]; - for (int i = 0; i < transcodeSchemes.length; i++) { - TranscodeScheme scheme = transcodeSchemes[i]; - transcodeSchemeHolders[i] = new EnumHolder(scheme.name(), scheme.toString()); - } - } - - public boolean isTranscodingSupported() { - return transcodingSupported; - } - - public void setTranscodingSupported(boolean transcodingSupported) { - this.transcodingSupported = transcodingSupported; - } - - public String getTranscodeDirectory() { - return transcodeDirectory; - } - - public void setTranscodeDirectory(String transcodeDirectory) { - this.transcodeDirectory = transcodeDirectory; - } - - public void setUser(User user) { - username = user == null ? null : user.getUsername(); - isAdminRole = user != null && user.isAdminRole(); - isDownloadRole = user != null && user.isDownloadRole(); - isUploadRole = user != null && user.isUploadRole(); - isCoverArtRole = user != null && user.isCoverArtRole(); - isCommentRole = user != null && user.isCommentRole(); - isPodcastRole = user != null && user.isPodcastRole(); - isStreamRole = user != null && user.isStreamRole(); - isJukeboxRole = user != null && user.isJukeboxRole(); - isSettingsRole = user != null && user.isSettingsRole(); - isShareRole = user != null && user.isShareRole(); - isLdapAuthenticated = user != null && user.isLdapAuthenticated(); - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AbstractChartController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AbstractChartController.java deleted file mode 100644 index f163f82d..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AbstractChartController.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import org.springframework.web.servlet.support.*; -import org.springframework.web.servlet.mvc.*; -import org.springframework.ui.context.*; - -import javax.servlet.http.*; -import java.awt.*; -import java.util.*; - -/** - * Abstract super class for controllers which generate charts. - * - * @author Sindre Mehus - */ -public abstract class AbstractChartController implements Controller { - - /** - * Returns the chart background color for the current theme. - * @param request The servlet request. - * @return The chart background color. - */ - protected Color getBackground(HttpServletRequest request) { - return getColor("backgroundColor", request); - } - - /** - * Returns the chart foreground color for the current theme. - * @param request The servlet request. - * @return The chart foreground color. - */ - protected Color getForeground(HttpServletRequest request) { - return getColor("textColor", request); - } - - private Color getColor(String code, HttpServletRequest request) { - Theme theme = RequestContextUtils.getTheme(request); - Locale locale = RequestContextUtils.getLocale(request); - String colorHex = theme.getMessageSource().getMessage(code, new Object[0], locale); - return new Color(Integer.parseInt(colorHex, 16)); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AdvancedSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AdvancedSettingsController.java deleted file mode 100644 index 0b43f4eb..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AdvancedSettingsController.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.command.AdvancedSettingsCommand; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.web.servlet.mvc.SimpleFormController; -import org.apache.commons.lang.StringUtils; - -import javax.servlet.http.HttpServletRequest; - -/** - * Controller for the page used to administrate advanced settings. - * - * @author Sindre Mehus - */ -public class AdvancedSettingsController extends SimpleFormController { - - private SettingsService settingsService; - - @Override - protected Object formBackingObject(HttpServletRequest request) throws Exception { - AdvancedSettingsCommand command = new AdvancedSettingsCommand(); - command.setCoverArtLimit(String.valueOf(settingsService.getCoverArtLimit())); - command.setDownsampleCommand(settingsService.getDownsamplingCommand()); - command.setDownloadLimit(String.valueOf(settingsService.getDownloadBitrateLimit())); - command.setUploadLimit(String.valueOf(settingsService.getUploadBitrateLimit())); - command.setStreamPort(String.valueOf(settingsService.getStreamPort())); - command.setLdapEnabled(settingsService.isLdapEnabled()); - command.setLdapUrl(settingsService.getLdapUrl()); - command.setLdapSearchFilter(settingsService.getLdapSearchFilter()); - command.setLdapManagerDn(settingsService.getLdapManagerDn()); - command.setLdapAutoShadowing(settingsService.isLdapAutoShadowing()); - command.setBrand(settingsService.getBrand()); - - return command; - } - - @Override - protected void doSubmitAction(Object comm) throws Exception { - AdvancedSettingsCommand command = (AdvancedSettingsCommand) comm; - - command.setReloadNeeded(false); - settingsService.setDownsamplingCommand(command.getDownsampleCommand()); - - try { - settingsService.setCoverArtLimit(Integer.parseInt(command.getCoverArtLimit())); - } catch (NumberFormatException x) { /* Intentionally ignored. */ } - try { - settingsService.setDownloadBitrateLimit(Long.parseLong(command.getDownloadLimit())); - } catch (NumberFormatException x) { /* Intentionally ignored. */ } - try { - settingsService.setUploadBitrateLimit(Long.parseLong(command.getUploadLimit())); - } catch (NumberFormatException x) { /* Intentionally ignored. */ } - try { - settingsService.setStreamPort(Integer.parseInt(command.getStreamPort())); - } catch (NumberFormatException x) { /* Intentionally ignored. */ } - - settingsService.setLdapEnabled(command.isLdapEnabled()); - settingsService.setLdapUrl(command.getLdapUrl()); - settingsService.setLdapSearchFilter(command.getLdapSearchFilter()); - settingsService.setLdapManagerDn(command.getLdapManagerDn()); - settingsService.setLdapAutoShadowing(command.isLdapAutoShadowing()); - - if (StringUtils.isNotEmpty(command.getLdapManagerPassword())) { - settingsService.setLdapManagerPassword(command.getLdapManagerPassword()); - } - - settingsService.save(); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AllmusicController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AllmusicController.java deleted file mode 100644 index 8b34f383..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AllmusicController.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import org.springframework.web.servlet.*; -import org.springframework.web.servlet.mvc.*; - -import javax.servlet.http.*; - -/** - * Controller for the page which forwards to allmusic.com. - * - * @author Sindre Mehus - */ -public class AllmusicController extends ParameterizableViewController { - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("album", request.getParameter("album")); - return result; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AvatarController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AvatarController.java deleted file mode 100644 index 100fcedb..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AvatarController.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.Avatar; -import net.sourceforge.subsonic.domain.AvatarScheme; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; -import org.springframework.web.servlet.mvc.LastModified; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * Controller which produces avatar images. - * - * @author Sindre Mehus - */ -public class AvatarController implements Controller, LastModified { - - private SettingsService settingsService; - - public long getLastModified(HttpServletRequest request) { - Avatar avatar = getAvatar(request); - return avatar == null ? -1L : avatar.getCreatedDate().getTime(); - } - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - Avatar avatar = getAvatar(request); - - if (avatar == null) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return null; - } - - // TODO: specify caching filter. - - response.setContentType(avatar.getMimeType()); - response.getOutputStream().write(avatar.getData()); - return null; - } - - private Avatar getAvatar(HttpServletRequest request) { - String id = request.getParameter("id"); - if (id != null) { - return settingsService.getSystemAvatar(Integer.parseInt(id)); - } - - String username = request.getParameter("username"); - if (username == null) { - return null; - } - - UserSettings userSettings = settingsService.getUserSettings(username); - if (userSettings.getAvatarScheme() == AvatarScheme.SYSTEM) { - return settingsService.getSystemAvatar(userSettings.getSystemAvatarId()); - } - return settingsService.getCustomAvatar(username); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AvatarUploadController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AvatarUploadController.java deleted file mode 100644 index a22cd9a9..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/AvatarUploadController.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.Avatar; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.util.StringUtil; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.imageio.ImageIO; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Controller which receives uploaded avatar images. - * - * @author Sindre Mehus - */ -public class AvatarUploadController extends ParameterizableViewController { - - private static final Logger LOG = Logger.getLogger(AvatarUploadController.class); - private static final int MAX_AVATAR_SIZE = 64; - - private SettingsService settingsService; - private SecurityService securityService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - String username = securityService.getCurrentUsername(request); - - // Check that we have a file upload request. - if (!ServletFileUpload.isMultipartContent(request)) { - throw new Exception("Illegal request."); - } - - Map map = new HashMap(); - FileItemFactory factory = new DiskFileItemFactory(); - ServletFileUpload upload = new ServletFileUpload(factory); - List items = upload.parseRequest(request); - - // Look for file items. - for (Object o : items) { - FileItem item = (FileItem) o; - - if (!item.isFormField()) { - String fileName = item.getName(); - byte[] data = item.get(); - - if (StringUtils.isNotBlank(fileName) && data.length > 0) { - createAvatar(fileName, data, username, map); - } else { - map.put("error", new Exception("Missing file.")); - LOG.warn("Failed to upload personal image. No file specified."); - } - break; - } - } - - map.put("username", username); - map.put("avatar", settingsService.getCustomAvatar(username)); - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - private void createAvatar(String fileName, byte[] data, String username, Map map) throws IOException { - - BufferedImage image; - try { - image = ImageIO.read(new ByteArrayInputStream(data)); - if (image == null) { - throw new Exception("Failed to decode incoming image: " + fileName + " (" + data.length + " bytes)."); - } - int width = image.getWidth(); - int height = image.getHeight(); - String mimeType = StringUtil.getMimeType(FilenameUtils.getExtension(fileName)); - - // Scale down image if necessary. - if (width > MAX_AVATAR_SIZE || height > MAX_AVATAR_SIZE) { - double scaleFactor = (double) MAX_AVATAR_SIZE / (double) Math.max(width, height); - height = (int) (height * scaleFactor); - width = (int) (width * scaleFactor); - image = CoverArtController.scale(image, width, height); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ImageIO.write(image, "jpeg", out); - data = out.toByteArray(); - mimeType = StringUtil.getMimeType("jpeg"); - map.put("resized", true); - } - Avatar avatar = new Avatar(0, fileName, new Date(), mimeType, width, height, data); - settingsService.setCustomAvatar(avatar, username); - LOG.info("Created avatar '" + fileName + "' (" + data.length + " bytes) for user " + username); - - } catch (Exception x) { - LOG.warn("Failed to upload personal image: " + x, x); - map.put("error", x); - } - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ChangeCoverArtController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ChangeCoverArtController.java deleted file mode 100644 index 94c88656..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ChangeCoverArtController.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.service.MediaFileService; - -/** - * Controller for changing cover art. - * - * @author Sindre Mehus - */ -public class ChangeCoverArtController extends ParameterizableViewController { - - private MediaFileService mediaFileService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - String artist = request.getParameter("artist"); - String album = request.getParameter("album"); - MediaFile dir = mediaFileService.getMediaFile(id); - - if (artist == null) { - artist = dir.getArtist(); - } - if (album == null) { - album = dir.getAlbumName(); - } - - Map map = new HashMap(); - map.put("id", id); - map.put("artist", artist); - map.put("album", album); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - - return result; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java deleted file mode 100644 index a5093024..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.AlbumDao; -import net.sourceforge.subsonic.dao.ArtistDao; -import net.sourceforge.subsonic.domain.Album; -import net.sourceforge.subsonic.domain.Artist; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.metadata.JaudiotaggerParser; -import net.sourceforge.subsonic.util.FileUtil; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; -import org.springframework.web.servlet.mvc.LastModified; - -import javax.imageio.ImageIO; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Controller which produces cover art images. - * - * @author Sindre Mehus - */ -public class CoverArtController implements Controller, LastModified { - - public static final String ALBUM_COVERART_PREFIX = "al-"; - public static final String ARTIST_COVERART_PREFIX = "ar-"; - - private static final Logger LOG = Logger.getLogger(CoverArtController.class); - - private SecurityService securityService; - private MediaFileService mediaFileService; - private ArtistDao artistDao; - private AlbumDao albumDao; - - public long getLastModified(HttpServletRequest request) { - try { - File file = getImageFile(request); - if (file == null) { - return 0; // Request for the default image. - } - if (!FileUtil.exists(file)) { - return -1; - } - - return FileUtil.lastModified(file); - } catch (Exception e) { - return -1; - } - } - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - File file = getImageFile(request); - - if (file != null && !FileUtil.exists(file)) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return null; - } - - // Check access. - if (file != null && !securityService.isReadAllowed(file)) { - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return null; - } - - // Send default image if no path is given. (No need to cache it, since it will be cached in browser.) - Integer size = ServletRequestUtils.getIntParameter(request, "size"); - if (file == null) { - sendDefault(size, response); - return null; - } - - // Optimize if no scaling is required. - if (size == null) { - sendUnscaled(file, response); - return null; - } - - // Send cached image, creating it if necessary. - try { - File cachedImage = getCachedImage(file, size); - sendImage(cachedImage, response); - } catch (IOException e) { - sendDefault(size, response); - } - - return null; - } - - private File getImageFile(HttpServletRequest request) { - String id = request.getParameter("id"); - if (id != null) { - if (id.startsWith(ALBUM_COVERART_PREFIX)) { - return getAlbumImage(Integer.valueOf(id.replace(ALBUM_COVERART_PREFIX, ""))); - } - if (id.startsWith(ARTIST_COVERART_PREFIX)) { - return getArtistImage(Integer.valueOf(id.replace(ARTIST_COVERART_PREFIX, ""))); - } - return getMediaFileImage(Integer.valueOf(id)); - } - - String path = StringUtils.trimToNull(request.getParameter("path")); - return path != null ? new File(path) : null; - } - - private File getArtistImage(int id) { - Artist artist = artistDao.getArtist(id); - return artist == null || artist.getCoverArtPath() == null ? null : new File(artist.getCoverArtPath()); - } - - private File getAlbumImage(int id) { - Album album = albumDao.getAlbum(id); - return album == null || album.getCoverArtPath() == null ? null : new File(album.getCoverArtPath()); - } - - private File getMediaFileImage(int id) { - MediaFile mediaFile = mediaFileService.getMediaFile(id); - return mediaFile == null ? null : mediaFileService.getCoverArt(mediaFile); - } - - private void sendImage(File file, HttpServletResponse response) throws IOException { - InputStream in = new FileInputStream(file); - try { - IOUtils.copy(in, response.getOutputStream()); - } finally { - IOUtils.closeQuietly(in); - } - } - - private void sendDefault(Integer size, HttpServletResponse response) throws IOException { - InputStream in = null; - try { - in = getClass().getResourceAsStream("default_cover.jpg"); - BufferedImage image = ImageIO.read(in); - if (size != null) { - image = scale(image, size, size); - } - ImageIO.write(image, "jpeg", response.getOutputStream()); - } finally { - IOUtils.closeQuietly(in); - } - } - - private void sendUnscaled(File file, HttpServletResponse response) throws IOException { - InputStream in = null; - try { - in = getImageInputStream(file); - IOUtils.copy(in, response.getOutputStream()); - } finally { - IOUtils.closeQuietly(in); - } - } - - private File getCachedImage(File file, int size) throws IOException { - String md5 = DigestUtils.md5Hex(file.getPath()); - File cachedImage = new File(getImageCacheDirectory(size), md5 + ".jpeg"); - - // Is cache missing or obsolete? - if (!cachedImage.exists() || FileUtil.lastModified(file) > cachedImage.lastModified()) { - InputStream in = null; - OutputStream out = null; - try { - in = getImageInputStream(file); - out = new FileOutputStream(cachedImage); - BufferedImage image = ImageIO.read(in); - if (image == null) { - throw new Exception("Unable to decode image."); - } - - image = scale(image, size, size); - ImageIO.write(image, "jpeg", out); - - } catch (Throwable x) { - // Delete corrupt (probably empty) thumbnail cache. - LOG.warn("Failed to create thumbnail for " + file, x); - IOUtils.closeQuietly(out); - cachedImage.delete(); - throw new IOException("Failed to create thumbnail for " + file + ". " + x.getMessage()); - - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - } - } - return cachedImage; - } - - /** - * Returns an input stream to the image in the given file. If the file is an audio file, - * the embedded album art is returned. - */ - private InputStream getImageInputStream(File file) throws IOException { - JaudiotaggerParser parser = new JaudiotaggerParser(); - if (parser.isApplicable(file)) { - MediaFile mediaFile = mediaFileService.getMediaFile(file); - return new ByteArrayInputStream(parser.getImageData(mediaFile)); - } else { - return new FileInputStream(file); - } - } - - private synchronized File getImageCacheDirectory(int size) { - File dir = new File(SettingsService.getSubsonicHome(), "thumbs"); - dir = new File(dir, String.valueOf(size)); - if (!dir.exists()) { - if (dir.mkdirs()) { - LOG.info("Created thumbnail cache " + dir); - } else { - LOG.error("Failed to create thumbnail cache " + dir); - } - } - - return dir; - } - - public static BufferedImage scale(BufferedImage image, int width, int height) { - int w = image.getWidth(); - int h = image.getHeight(); - BufferedImage thumb = image; - - // For optimal results, use step by step bilinear resampling - halfing the size at each step. - do { - w /= 2; - h /= 2; - if (w < width) { - w = width; - } - if (h < height) { - h = height; - } - - BufferedImage temp = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); - Graphics2D g2 = temp.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null); - g2.dispose(); - - thumb = temp; - } while (w != width); - - return thumb; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setArtistDao(ArtistDao artistDao) { - this.artistDao = artistDao; - } - - public void setAlbumDao(AlbumDao albumDao) { - this.albumDao = albumDao; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DBController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DBController.java deleted file mode 100644 index 17d06497..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DBController.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.dao.DaoHelper; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.ColumnMapRowMapper; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Controller for the DB admin page. - * - * @author Sindre Mehus - */ -public class DBController extends ParameterizableViewController { - - private DaoHelper daoHelper; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - String query = request.getParameter("query"); - if (query != null) { - map.put("query", query); - - try { - List result = daoHelper.getJdbcTemplate().query(query, new ColumnMapRowMapper()); - map.put("result", result); - } catch (DataAccessException x) { - map.put("error", ExceptionUtils.getRootCause(x).getMessage()); - } - } - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setDaoHelper(DaoHelper daoHelper) { - this.daoHelper = daoHelper; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DonateController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DonateController.java deleted file mode 100644 index 144d3327..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DonateController.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.command.DonateCommand; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.validation.BindException; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.SimpleFormController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.Date; - -/** - * Controller for the donation page. - * - * @author Sindre Mehus - */ -public class DonateController extends SimpleFormController { - - private SettingsService settingsService; - - protected Object formBackingObject(HttpServletRequest request) throws Exception { - DonateCommand command = new DonateCommand(); - command.setPath(request.getParameter("path")); - - command.setEmailAddress(settingsService.getLicenseEmail()); - command.setLicenseDate(settingsService.getLicenseDate()); - command.setLicenseValid(settingsService.isLicenseValid()); - command.setLicense(settingsService.getLicenseCode()); - command.setBrand(settingsService.getBrand()); - - return command; - } - - protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object com, BindException errors) - throws Exception { - DonateCommand command = (DonateCommand) com; - Date now = new Date(); - - settingsService.setLicenseCode(command.getLicense()); - settingsService.setLicenseEmail(command.getEmailAddress()); - settingsService.setLicenseDate(now); - settingsService.save(); - settingsService.validateLicenseAsync(); - - // Reflect changes in view. The validator has already validated the license. - command.setLicenseValid(true); - command.setLicenseDate(now); - - return new ModelAndView(getSuccessView(), errors.getModel()); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DownloadController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DownloadController.java deleted file mode 100644 index 0125d3bb..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/DownloadController.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.io.RangeOutputStream; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.PlaylistService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.StatusService; -import net.sourceforge.subsonic.util.FileUtil; -import net.sourceforge.subsonic.util.StringUtil; -import net.sourceforge.subsonic.util.Util; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.math.LongRange; -import org.apache.tools.zip.ZipEntry; -import org.apache.tools.zip.ZipOutputStream; -import org.springframework.web.bind.ServletRequestBindingException; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; -import org.springframework.web.servlet.mvc.LastModified; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.zip.CRC32; - -/** - * A controller used for downloading files to a remote client. If the requested path refers to a file, the - * given file is downloaded. If the requested path refers to a directory, the entire directory (including - * sub-directories) are downloaded as an uncompressed zip-file. - * - * @author Sindre Mehus - */ -public class DownloadController implements Controller, LastModified { - - private static final Logger LOG = Logger.getLogger(DownloadController.class); - - private PlayerService playerService; - private StatusService statusService; - private SecurityService securityService; - private PlaylistService playlistService; - private SettingsService settingsService; - private MediaFileService mediaFileService; - - public long getLastModified(HttpServletRequest request) { - try { - MediaFile mediaFile = getSingleFile(request); - if (mediaFile == null || mediaFile.isDirectory() || mediaFile.getChanged() == null) { - return -1; - } - return mediaFile.getChanged().getTime(); - } catch (ServletRequestBindingException e) { - return -1; - } - } - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - - TransferStatus status = null; - try { - - status = statusService.createDownloadStatus(playerService.getPlayer(request, response, false, false)); - - MediaFile mediaFile = getSingleFile(request); - String dir = request.getParameter("dir"); - Integer playlistId = ServletRequestUtils.getIntParameter(request, "playlist"); - String playerId = request.getParameter("player"); - int[] indexes = ServletRequestUtils.getIntParameters(request, "i"); - - if (mediaFile != null) { - response.setIntHeader("ETag", mediaFile.getId()); - response.setHeader("Accept-Ranges", "bytes"); - } - - LongRange range = StringUtil.parseRange(request.getHeader("Range")); - if (range != null) { - response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); - LOG.info("Got range: " + range); - } - - if (mediaFile != null) { - File file = mediaFile.getFile(); - if (!securityService.isReadAllowed(file)) { - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return null; - } - - if (file.isFile()) { - downloadFile(response, status, file, range); - } else { - downloadDirectory(response, status, file, range); - } - } else if (dir != null) { - File file = new File(dir); - if (!securityService.isReadAllowed(file)) { - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return null; - } - downloadFiles(response, status, file, indexes); - - } else if (playlistId != null) { - List songs = playlistService.getFilesInPlaylist(playlistId); - downloadFiles(response, status, songs, null, range); - - } else if (playerId != null) { - Player player = playerService.getPlayerById(playerId); - PlayQueue playQueue = player.getPlayQueue(); - playQueue.setName("Playlist"); - downloadFiles(response, status, playQueue.getFiles(), indexes.length == 0 ? null : indexes, range); - } - - - } finally { - if (status != null) { - statusService.removeDownloadStatus(status); - User user = securityService.getCurrentUser(request); - securityService.updateUserByteCounts(user, 0L, status.getBytesTransfered(), 0L); - } - } - - return null; - } - - private MediaFile getSingleFile(HttpServletRequest request) throws ServletRequestBindingException { - String path = request.getParameter("path"); - if (path != null) { - return mediaFileService.getMediaFile(path); - } - Integer id = ServletRequestUtils.getIntParameter(request, "id"); - if (id != null) { - return mediaFileService.getMediaFile(id); - } - return null; - } - - /** - * Downloads a single file. - * - * @param response The HTTP response. - * @param status The download status. - * @param file The file to download. - * @param range The byte range, may be null. - * @throws IOException If an I/O error occurs. - */ - private void downloadFile(HttpServletResponse response, TransferStatus status, File file, LongRange range) throws IOException { - LOG.info("Starting to download '" + FileUtil.getShortPath(file) + "' to " + status.getPlayer()); - status.setFile(file); - - response.setContentType("application/x-download"); - response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + '\"'); - if (range == null) { - Util.setContentLength(response, file.length()); - } - - copyFileToStream(file, RangeOutputStream.wrap(response.getOutputStream(), range), status, range); - LOG.info("Downloaded '" + FileUtil.getShortPath(file) + "' to " + status.getPlayer()); - } - - /** - * Downloads a collection of files within a directory. - * - * @param response The HTTP response. - * @param status The download status. - * @param dir The directory. - * @param indexes Only download files with these indexes within the directory. - * @throws IOException If an I/O error occurs. - */ - private void downloadFiles(HttpServletResponse response, TransferStatus status, File dir, int[] indexes) throws IOException { - String zipFileName = dir.getName() + ".zip"; - LOG.info("Starting to download '" + zipFileName + "' to " + status.getPlayer()); - status.setFile(dir); - - response.setContentType("application/x-download"); - response.setHeader("Content-Disposition", "attachment; filename=\"" + zipFileName + "\""); - - ZipOutputStream out = new ZipOutputStream(response.getOutputStream()); - out.setMethod(ZipOutputStream.STORED); // No compression. - - List allChildren = mediaFileService.getChildrenOf(dir, true, true, true); - List mediaFiles = new ArrayList(); - for (int index : indexes) { - mediaFiles.add(allChildren.get(index)); - } - - for (MediaFile mediaFile : mediaFiles) { - zip(out, mediaFile.getParentFile(), mediaFile.getFile(), status, null); - } - - out.close(); - LOG.info("Downloaded '" + zipFileName + "' to " + status.getPlayer()); - } - - /** - * Downloads all files in a directory (including sub-directories). The files are packed together in an - * uncompressed zip-file. - * - * @param response The HTTP response. - * @param status The download status. - * @param file The file to download. - * @param range The byte range, may be null. - * @throws IOException If an I/O error occurs. - */ - private void downloadDirectory(HttpServletResponse response, TransferStatus status, File file, LongRange range) throws IOException { - String zipFileName = file.getName() + ".zip"; - LOG.info("Starting to download '" + zipFileName + "' to " + status.getPlayer()); - response.setContentType("application/x-download"); - response.setHeader("Content-Disposition", "attachment; filename=\"" + zipFileName + '"'); - - ZipOutputStream out = new ZipOutputStream(RangeOutputStream.wrap(response.getOutputStream(), range)); - out.setMethod(ZipOutputStream.STORED); // No compression. - - zip(out, file.getParentFile(), file, status, range); - out.close(); - LOG.info("Downloaded '" + zipFileName + "' to " + status.getPlayer()); - } - - /** - * Downloads the given files. The files are packed together in an - * uncompressed zip-file. - * - * @param response The HTTP response. - * @param status The download status. - * @param files The files to download. - * @param indexes Only download songs at these indexes. May be null. - * @param range The byte range, may be null. - * @throws IOException If an I/O error occurs. - */ - private void downloadFiles(HttpServletResponse response, TransferStatus status, List files, int[] indexes, LongRange range) throws IOException { - if (indexes != null && indexes.length == 1) { - downloadFile(response, status, files.get(indexes[0]).getFile(), range); - return; - } - - String zipFileName = "download.zip"; - LOG.info("Starting to download '" + zipFileName + "' to " + status.getPlayer()); - response.setContentType("application/x-download"); - response.setHeader("Content-Disposition", "attachment; filename=\"" + zipFileName + '"'); - - ZipOutputStream out = new ZipOutputStream(RangeOutputStream.wrap(response.getOutputStream(), range)); - out.setMethod(ZipOutputStream.STORED); // No compression. - - List filesToDownload = new ArrayList(); - if (indexes == null) { - filesToDownload.addAll(files); - } else { - for (int index : indexes) { - try { - filesToDownload.add(files.get(index)); - } catch (IndexOutOfBoundsException x) { /* Ignored */} - } - } - - for (MediaFile mediaFile : filesToDownload) { - zip(out, mediaFile.getParentFile(), mediaFile.getFile(), status, range); - } - - out.close(); - LOG.info("Downloaded '" + zipFileName + "' to " + status.getPlayer()); - } - - /** - * Utility method for writing the content of a given file to a given output stream. - * - * @param file The file to copy. - * @param out The output stream to write to. - * @param status The download status. - * @param range The byte range, may be null. - * @throws IOException If an I/O error occurs. - */ - private void copyFileToStream(File file, OutputStream out, TransferStatus status, LongRange range) throws IOException { - LOG.info("Downloading '" + FileUtil.getShortPath(file) + "' to " + status.getPlayer()); - - final int bufferSize = 16 * 1024; // 16 Kbit - InputStream in = new BufferedInputStream(new FileInputStream(file), bufferSize); - - try { - byte[] buf = new byte[bufferSize]; - long bitrateLimit = 0; - long lastLimitCheck = 0; - - while (true) { - long before = System.currentTimeMillis(); - int n = in.read(buf); - if (n == -1) { - break; - } - out.write(buf, 0, n); - - // Don't sleep if outside range. - if (range != null && !range.containsLong(status.getBytesSkipped() + status.getBytesTransfered())) { - status.addBytesSkipped(n); - continue; - } - - status.addBytesTransfered(n); - long after = System.currentTimeMillis(); - - // Calculate bitrate limit every 5 seconds. - if (after - lastLimitCheck > 5000) { - bitrateLimit = 1024L * settingsService.getDownloadBitrateLimit() / - Math.max(1, statusService.getAllDownloadStatuses().size()); - lastLimitCheck = after; - } - - // Sleep for a while to throttle bitrate. - if (bitrateLimit != 0) { - long sleepTime = 8L * 1000 * bufferSize / bitrateLimit - (after - before); - if (sleepTime > 0L) { - try { - Thread.sleep(sleepTime); - } catch (Exception x) { - LOG.warn("Failed to sleep.", x); - } - } - } - } - } finally { - out.flush(); - IOUtils.closeQuietly(in); - } - } - - /** - * Writes a file or a directory structure to a zip output stream. File entries in the zip file are relative - * to the given root. - * - * @param out The zip output stream. - * @param root The root of the directory structure. Used to create path information in the zip file. - * @param file The file or directory to zip. - * @param status The download status. - * @param range The byte range, may be null. - * @throws IOException If an I/O error occurs. - */ - private void zip(ZipOutputStream out, File root, File file, TransferStatus status, LongRange range) throws IOException { - - // Exclude all hidden files starting with a "." - if (file.getName().startsWith(".")) { - return; - } - - String zipName = file.getCanonicalPath().substring(root.getCanonicalPath().length() + 1); - - if (file.isFile()) { - status.setFile(file); - - ZipEntry zipEntry = new ZipEntry(zipName); - zipEntry.setSize(file.length()); - zipEntry.setCompressedSize(file.length()); - zipEntry.setCrc(computeCrc(file)); - - out.putNextEntry(zipEntry); - copyFileToStream(file, out, status, range); - out.closeEntry(); - - } else { - ZipEntry zipEntry = new ZipEntry(zipName + '/'); - zipEntry.setSize(0); - zipEntry.setCompressedSize(0); - zipEntry.setCrc(0); - - out.putNextEntry(zipEntry); - out.closeEntry(); - - File[] children = FileUtil.listFiles(file); - for (File child : children) { - zip(out, root, child, status, range); - } - } - } - - /** - * Computes the CRC checksum for the given file. - * - * @param file The file to compute checksum for. - * @return A CRC32 checksum. - * @throws IOException If an I/O error occurs. - */ - private long computeCrc(File file) throws IOException { - CRC32 crc = new CRC32(); - InputStream in = new FileInputStream(file); - - try { - - byte[] buf = new byte[8192]; - int n = in.read(buf); - while (n != -1) { - crc.update(buf, 0, n); - n = in.read(buf); - } - - } finally { - in.close(); - } - - return crc.getValue(); - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/EditTagsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/EditTagsController.java deleted file mode 100644 index 91492222..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/EditTagsController.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.service.metadata.MetaData; -import net.sourceforge.subsonic.service.metadata.MetaDataParser; -import net.sourceforge.subsonic.service.metadata.MetaDataParserFactory; -import net.sourceforge.subsonic.service.metadata.JaudiotaggerParser; - -import org.apache.commons.io.FilenameUtils; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.*; -import org.springframework.web.servlet.mvc.*; - -import javax.servlet.http.*; -import java.util.*; - -/** - * Controller for the page used to edit MP3 tags. - * - * @author Sindre Mehus - */ -public class EditTagsController extends ParameterizableViewController { - - private MetaDataParserFactory metaDataParserFactory; - private MediaFileService mediaFileService; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - MediaFile dir = mediaFileService.getMediaFile(id); - List files = mediaFileService.getChildrenOf(dir, true, false, true); - - Map map = new HashMap(); - if (!files.isEmpty()) { - map.put("defaultArtist", files.get(0).getArtist()); - map.put("defaultAlbum", files.get(0).getAlbumName()); - map.put("defaultYear", files.get(0).getYear()); - map.put("defaultGenre", files.get(0).getGenre()); - } - map.put("allGenres", JaudiotaggerParser.getID3V1Genres()); - - List songs = new ArrayList(); - for (int i = 0; i < files.size(); i++) { - songs.add(createSong(files.get(i), i)); - } - map.put("id", id); - map.put("songs", songs); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - private Song createSong(MediaFile file, int index) { - MetaDataParser parser = metaDataParserFactory.getParser(file.getFile()); - MetaData metaData = parser.getRawMetaData(file.getFile()); - - Song song = new Song(); - song.setId(file.getId()); - song.setFileName(FilenameUtils.getBaseName(file.getPath())); - song.setTrack(metaData.getTrackNumber()); - song.setSuggestedTrack(index + 1); - song.setTitle(metaData.getTitle()); - song.setSuggestedTitle(parser.guessTitle(file.getFile())); - song.setArtist(metaData.getArtist()); - song.setAlbum(metaData.getAlbumName()); - song.setYear(metaData.getYear()); - song.setGenre(metaData.getGenre()); - return song; - } - - public void setMetaDataParserFactory(MetaDataParserFactory metaDataParserFactory) { - this.metaDataParserFactory = metaDataParserFactory; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - /** - * Contains information about a single song. - */ - public static class Song { - private int id; - private String fileName; - private Integer suggestedTrack; - private Integer track; - private String suggestedTitle; - private String title; - private String artist; - private String album; - private Integer year; - private String genre; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getFileName() { - return fileName; - } - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public Integer getSuggestedTrack() { - return suggestedTrack; - } - - public void setSuggestedTrack(Integer suggestedTrack) { - this.suggestedTrack = suggestedTrack; - } - - public Integer getTrack() { - return track; - } - - public void setTrack(Integer track) { - this.track = track; - } - - public String getSuggestedTitle() { - return suggestedTitle; - } - - public void setSuggestedTitle(String suggestedTitle) { - this.suggestedTitle = suggestedTitle; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getArtist() { - return artist; - } - - public void setArtist(String artist) { - this.artist = artist; - } - - public String getAlbum() { - return album; - } - - public void setAlbum(String album) { - this.album = album; - } - - public Integer getYear() { - return year; - } - - public void setYear(Integer year) { - this.year = year; - } - - public String getGenre() { - return genre; - } - - public void setGenre(String genre) { - this.genre = genre; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ExternalPlayerController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ExternalPlayerController.java deleted file mode 100644 index d8d28f93..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ExternalPlayerController.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.ShareDao; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.Share; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import org.apache.commons.lang.RandomStringUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Controller for the page used to play shared music (Twitter, Facebook etc). - * - * @author Sindre Mehus - */ -public class ExternalPlayerController extends ParameterizableViewController { - - private static final Logger LOG = Logger.getLogger(ExternalPlayerController.class); - private static final String GUEST_USERNAME = "guest"; - - private SettingsService settingsService; - private SecurityService securityService; - private PlayerService playerService; - private ShareDao shareDao; - private MediaFileService mediaFileService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - - String pathInfo = request.getPathInfo(); - - if (pathInfo == null || !pathInfo.startsWith("/")) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return null; - } - - Share share = shareDao.getShareByName(pathInfo.substring(1)); - if (share == null) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return null; - } - - if (share.getExpires() != null && share.getExpires().before(new Date())) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return null; - } - - share.setLastVisited(new Date()); - share.setVisitCount(share.getVisitCount() + 1); - shareDao.updateShare(share); - - List songs = getSongs(share); - List coverArts = getCoverArts(songs); - - map.put("share", share); - map.put("songs", songs); - map.put("coverArts", coverArts); - - if (!coverArts.isEmpty()) { - map.put("coverArt", coverArts.get(0)); - } - map.put("redirectFrom", settingsService.getUrlRedirectFrom()); - map.put("player", getPlayer(request).getId()); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - private List getSongs(Share share) throws IOException { - List result = new ArrayList(); - - for (String path : shareDao.getSharedFiles(share.getId())) { - try { - MediaFile file = mediaFileService.getMediaFile(path); - if (file.getFile().exists()) { - if (file.isDirectory()) { - result.addAll(mediaFileService.getChildrenOf(file, true, false, true)); - } else { - result.add(file); - } - } - } catch (Exception x) { - LOG.warn("Couldn't read file " + path); - } - } - return result; - } - - private List getCoverArts(List songs) throws IOException { - List result = new ArrayList(); - for (MediaFile song : songs) { - result.add(mediaFileService.getCoverArt(song)); - } - return result; - } - - - private Player getPlayer(HttpServletRequest request) { - - // Create guest user if necessary. - User user = securityService.getUserByName(GUEST_USERNAME); - if (user == null) { - user = new User(GUEST_USERNAME, RandomStringUtils.randomAlphanumeric(30), null); - user.setStreamRole(true); - securityService.createUser(user); - } - - // Look for existing player. - List players = playerService.getPlayersForUserAndClientId(GUEST_USERNAME, null); - if (!players.isEmpty()) { - return players.get(0); - } - - // Create player if necessary. - Player player = new Player(); - player.setIpAddress(request.getRemoteAddr()); - player.setUsername(GUEST_USERNAME); - playerService.createPlayer(player); - - return player; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setShareDao(ShareDao shareDao) { - this.shareDao = shareDao; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/GeneralSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/GeneralSettingsController.java deleted file mode 100644 index e7b19b04..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/GeneralSettingsController.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.command.GeneralSettingsCommand; -import net.sourceforge.subsonic.domain.Theme; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.web.servlet.mvc.SimpleFormController; - -import javax.servlet.http.HttpServletRequest; -import java.util.Locale; - -/** - * Controller for the page used to administrate general settings. - * - * @author Sindre Mehus - */ -public class GeneralSettingsController extends SimpleFormController { - - private SettingsService settingsService; - - protected Object formBackingObject(HttpServletRequest request) throws Exception { - GeneralSettingsCommand command = new GeneralSettingsCommand(); - command.setCoverArtFileTypes(settingsService.getCoverArtFileTypes()); - command.setIgnoredArticles(settingsService.getIgnoredArticles()); - command.setShortcuts(settingsService.getShortcuts()); - command.setIndex(settingsService.getIndexString()); - command.setMusicFileTypes(settingsService.getMusicFileTypes()); - command.setVideoFileTypes(settingsService.getVideoFileTypes()); - command.setSortAlbumsByYear(settingsService.isSortAlbumsByYear()); - command.setGettingStartedEnabled(settingsService.isGettingStartedEnabled()); - command.setWelcomeTitle(settingsService.getWelcomeTitle()); - command.setWelcomeSubtitle(settingsService.getWelcomeSubtitle()); - command.setWelcomeMessage(settingsService.getWelcomeMessage()); - command.setLoginMessage(settingsService.getLoginMessage()); - - Theme[] themes = settingsService.getAvailableThemes(); - command.setThemes(themes); - String currentThemeId = settingsService.getThemeId(); - for (int i = 0; i < themes.length; i++) { - if (currentThemeId.equals(themes[i].getId())) { - command.setThemeIndex(String.valueOf(i)); - break; - } - } - - Locale currentLocale = settingsService.getLocale(); - Locale[] locales = settingsService.getAvailableLocales(); - String[] localeStrings = new String[locales.length]; - for (int i = 0; i < locales.length; i++) { - localeStrings[i] = locales[i].getDisplayName(locales[i]); - - if (currentLocale.equals(locales[i])) { - command.setLocaleIndex(String.valueOf(i)); - } - } - command.setLocales(localeStrings); - - return command; - - } - - protected void doSubmitAction(Object comm) throws Exception { - GeneralSettingsCommand command = (GeneralSettingsCommand) comm; - - int themeIndex = Integer.parseInt(command.getThemeIndex()); - Theme theme = settingsService.getAvailableThemes()[themeIndex]; - - int localeIndex = Integer.parseInt(command.getLocaleIndex()); - Locale locale = settingsService.getAvailableLocales()[localeIndex]; - - command.setReloadNeeded(!settingsService.getIndexString().equals(command.getIndex()) || - !settingsService.getIgnoredArticles().equals(command.getIgnoredArticles()) || - !settingsService.getShortcuts().equals(command.getShortcuts()) || - !settingsService.getThemeId().equals(theme.getId()) || - !settingsService.getLocale().equals(locale)); - - settingsService.setIndexString(command.getIndex()); - settingsService.setIgnoredArticles(command.getIgnoredArticles()); - settingsService.setShortcuts(command.getShortcuts()); - settingsService.setMusicFileTypes(command.getMusicFileTypes()); - settingsService.setVideoFileTypes(command.getVideoFileTypes()); - settingsService.setCoverArtFileTypes(command.getCoverArtFileTypes()); - settingsService.setSortAlbumsByYear(command.isSortAlbumsByYear()); - settingsService.setGettingStartedEnabled(command.isGettingStartedEnabled()); - settingsService.setWelcomeTitle(command.getWelcomeTitle()); - settingsService.setWelcomeSubtitle(command.getWelcomeSubtitle()); - settingsService.setWelcomeMessage(command.getWelcomeMessage()); - settingsService.setLoginMessage(command.getLoginMessage()); - settingsService.setThemeId(theme.getId()); - settingsService.setLocale(locale); - settingsService.save(); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/HelpController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/HelpController.java deleted file mode 100644 index 4e0b0945..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/HelpController.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.*; -import net.sourceforge.subsonic.service.*; -import org.springframework.web.servlet.*; -import org.springframework.web.servlet.mvc.*; - -import javax.servlet.http.*; -import java.util.*; - -/** - * Controller for the help page. - * - * @author Sindre Mehus - */ -public class HelpController extends ParameterizableViewController { - - private VersionService versionService; - private SettingsService settingsService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - if (versionService.isNewFinalVersionAvailable()) { - map.put("newVersionAvailable", true); - map.put("latestVersion", versionService.getLatestFinalVersion()); - } else if (versionService.isNewBetaVersionAvailable()) { - map.put("newVersionAvailable", true); - map.put("latestVersion", versionService.getLatestBetaVersion()); - } - - long totalMemory = Runtime.getRuntime().totalMemory(); - long freeMemory = Runtime.getRuntime().freeMemory(); - - String serverInfo = request.getSession().getServletContext().getServerInfo() + - ", java " + System.getProperty("java.version") + - ", " + System.getProperty("os.name"); - - map.put("brand", settingsService.getBrand()); - map.put("localVersion", versionService.getLocalVersion()); - map.put("buildDate", versionService.getLocalBuildDate()); - map.put("buildNumber", versionService.getLocalBuildNumber()); - map.put("serverInfo", serverInfo); - map.put("usedMemory", totalMemory - freeMemory); - map.put("totalMemory", totalMemory); - map.put("logEntries", Logger.getLatestLogEntries()); - map.put("logFile", Logger.getLogFile()); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setVersionService(VersionService versionService) { - this.versionService = versionService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/HomeController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/HomeController.java deleted file mode 100644 index 49c95926..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/HomeController.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.MediaScannerService; -import net.sourceforge.subsonic.service.RatingService; -import net.sourceforge.subsonic.service.SearchService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; -import org.springframework.web.servlet.view.RedirectView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Controller for the home page. - * - * @author Sindre Mehus - */ -public class HomeController extends ParameterizableViewController { - - private static final Logger LOG = Logger.getLogger(HomeController.class); - - private static final int DEFAULT_LIST_SIZE = 10; - private static final int MAX_LIST_SIZE = 500; - private static final int DEFAULT_LIST_OFFSET = 0; - private static final int MAX_LIST_OFFSET = 5000; - - private SettingsService settingsService; - private MediaScannerService mediaScannerService; - private RatingService ratingService; - private SecurityService securityService; - private MediaFileService mediaFileService; - private SearchService searchService; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - User user = securityService.getCurrentUser(request); - if (user.isAdminRole() && settingsService.isGettingStartedEnabled()) { - return new ModelAndView(new RedirectView("gettingStarted.view")); - } - - int listSize = DEFAULT_LIST_SIZE; - int listOffset = DEFAULT_LIST_OFFSET; - if (request.getParameter("listSize") != null) { - listSize = Math.max(0, Math.min(Integer.parseInt(request.getParameter("listSize")), MAX_LIST_SIZE)); - } - if (request.getParameter("listOffset") != null) { - listOffset = Math.max(0, Math.min(Integer.parseInt(request.getParameter("listOffset")), MAX_LIST_OFFSET)); - } - - String listType = request.getParameter("listType"); - if (listType == null) { - listType = "random"; - } - - List albums; - if ("highest".equals(listType)) { - albums = getHighestRated(listOffset, listSize); - } else if ("frequent".equals(listType)) { - albums = getMostFrequent(listOffset, listSize); - } else if ("recent".equals(listType)) { - albums = getMostRecent(listOffset, listSize); - } else if ("newest".equals(listType)) { - albums = getNewest(listOffset, listSize); - } else if ("starred".equals(listType)) { - albums = getStarred(listOffset, listSize, user.getUsername()); - } else if ("random".equals(listType)) { - albums = getRandom(listSize); - } else if ("alphabetical".equals(listType)) { - albums = getAlphabetical(listOffset, listSize, true); - } else { - albums = Collections.emptyList(); - } - - Map map = new HashMap(); - map.put("albums", albums); - map.put("welcomeTitle", settingsService.getWelcomeTitle()); - map.put("welcomeSubtitle", settingsService.getWelcomeSubtitle()); - map.put("welcomeMessage", settingsService.getWelcomeMessage()); - map.put("isIndexBeingCreated", mediaScannerService.isScanning()); - map.put("listType", listType); - map.put("listSize", listSize); - map.put("listOffset", listOffset); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - List getHighestRated(int offset, int count) { - List result = new ArrayList(); - for (MediaFile mediaFile : ratingService.getHighestRated(offset, count)) { - Album album = createAlbum(mediaFile); - if (album != null) { - album.setRating((int) Math.round(ratingService.getAverageRating(mediaFile) * 10.0D)); - result.add(album); - } - } - return result; - } - - List getMostFrequent(int offset, int count) { - List result = new ArrayList(); - for (MediaFile mediaFile : mediaFileService.getMostFrequentlyPlayedAlbums(offset, count)) { - Album album = createAlbum(mediaFile); - if (album != null) { - album.setPlayCount(mediaFile.getPlayCount()); - result.add(album); - } - } - return result; - } - - List getMostRecent(int offset, int count) { - List result = new ArrayList(); - for (MediaFile mediaFile : mediaFileService.getMostRecentlyPlayedAlbums(offset, count)) { - Album album = createAlbum(mediaFile); - if (album != null) { - album.setLastPlayed(mediaFile.getLastPlayed()); - result.add(album); - } - } - return result; - } - - List getNewest(int offset, int count) throws IOException { - List result = new ArrayList(); - for (MediaFile file : mediaFileService.getNewestAlbums(offset, count)) { - Album album = createAlbum(file); - if (album != null) { - Date created = file.getCreated(); - if (created == null) { - created = file.getChanged(); - } - album.setCreated(created); - result.add(album); - } - } - return result; - } - - List getStarred(int offset, int count, String username) throws IOException { - List result = new ArrayList(); - for (MediaFile file : mediaFileService.getStarredAlbums(offset, count, username)) { - Album album = createAlbum(file); - if (album != null) { - result.add(album); - } - } - return result; - } - - List getRandom(int count) throws IOException { - List result = new ArrayList(); - for (MediaFile file : searchService.getRandomAlbums(count)) { - Album album = createAlbum(file); - if (album != null) { - result.add(album); - } - } - return result; - } - - List getAlphabetical(int offset, int count, boolean byArtist) throws IOException { - List result = new ArrayList(); - for (MediaFile file : mediaFileService.getAlphabetialAlbums(offset, count, byArtist)) { - Album album = createAlbum(file); - if (album != null) { - result.add(album); - } - } - return result; - } - - private Album createAlbum(MediaFile file) { - Album album = new Album(); - album.setId(file.getId()); - album.setPath(file.getPath()); - try { - resolveArtistAndAlbumTitle(album, file); - resolveCoverArt(album, file); - } catch (Exception x) { - LOG.warn("Failed to create albumTitle list entry for " + file.getPath(), x); - return null; - } - return album; - } - - private void resolveArtistAndAlbumTitle(Album album, MediaFile file) throws IOException { - album.setArtist(file.getArtist()); - album.setAlbumTitle(file.getAlbumName()); - } - - private void resolveCoverArt(Album album, MediaFile file) { - album.setCoverArtPath(file.getCoverArtPath()); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setMediaScannerService(MediaScannerService mediaScannerService) { - this.mediaScannerService = mediaScannerService; - } - - public void setRatingService(RatingService ratingService) { - this.ratingService = ratingService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setSearchService(SearchService searchService) { - this.searchService = searchService; - } - - /** - * Contains info for a single album. - */ - @Deprecated - public static class Album { - private String path; - private String coverArtPath; - private String artist; - private String albumTitle; - private Date created; - private Date lastPlayed; - private Integer playCount; - private Integer rating; - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getCoverArtPath() { - return coverArtPath; - } - - public void setCoverArtPath(String coverArtPath) { - this.coverArtPath = coverArtPath; - } - - public String getArtist() { - return artist; - } - - public void setArtist(String artist) { - this.artist = artist; - } - - public String getAlbumTitle() { - return albumTitle; - } - - public void setAlbumTitle(String albumTitle) { - this.albumTitle = albumTitle; - } - - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - public Date getLastPlayed() { - return lastPlayed; - } - - public void setLastPlayed(Date lastPlayed) { - this.lastPlayed = lastPlayed; - } - - public Integer getPlayCount() { - return playCount; - } - - public void setPlayCount(Integer playCount) { - this.playCount = playCount; - } - - public Integer getRating() { - return rating; - } - - public void setRating(Integer rating) { - this.rating = rating; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ImportPlaylistController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ImportPlaylistController.java deleted file mode 100644 index 55e9b200..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ImportPlaylistController.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import net.sourceforge.subsonic.domain.Playlist; -import net.sourceforge.subsonic.service.PlaylistService; -import net.sourceforge.subsonic.service.SecurityService; - -/** - * @author Sindre Mehus - */ -public class ImportPlaylistController extends ParameterizableViewController { - - private static final long MAX_PLAYLIST_SIZE_MB = 5L; - - private SecurityService securityService; - private PlaylistService playlistService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - try { - if (ServletFileUpload.isMultipartContent(request)) { - - FileItemFactory factory = new DiskFileItemFactory(); - ServletFileUpload upload = new ServletFileUpload(factory); - List items = upload.parseRequest(request); - for (Object o : items) { - FileItem item = (FileItem) o; - - if ("file".equals(item.getFieldName()) && !StringUtils.isBlank(item.getName())) { - if (item.getSize() > MAX_PLAYLIST_SIZE_MB * 1024L * 1024L) { - throw new Exception("The playlist file is too large. Max file size is " + MAX_PLAYLIST_SIZE_MB + " MB."); - } - String playlistName = FilenameUtils.getBaseName(item.getName()); - String fileName = FilenameUtils.getName(item.getName()); - String format = StringUtils.lowerCase(FilenameUtils.getExtension(item.getName())); - String username = securityService.getCurrentUsername(request); - Playlist playlist = playlistService.importPlaylist(username, playlistName, fileName, format, item.getInputStream()); - map.put("playlist", playlist); - } - } - } - } catch (Exception e) { - map.put("error", e.getMessage()); - } - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/InternetRadioSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/InternetRadioSettingsController.java deleted file mode 100644 index 5ee7b799..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/InternetRadioSettingsController.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.InternetRadio; -import net.sourceforge.subsonic.service.SettingsService; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Date; - -/** - * Controller for the page used to administrate the set of internet radio/tv stations. - * - * @author Sindre Mehus - */ -public class InternetRadioSettingsController extends ParameterizableViewController { - - private SettingsService settingsService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - - if (isFormSubmission(request)) { - String error = handleParameters(request); - map.put("error", error); - if (error == null) { - map.put("reload", true); - } - } - - ModelAndView result = super.handleRequestInternal(request, response); - map.put("internetRadios", settingsService.getAllInternetRadios(true)); - - result.addObject("model", map); - return result; - } - - /** - * Determine if the given request represents a form submission. - * - * @param request current HTTP request - * @return if the request represents a form submission - */ - private boolean isFormSubmission(HttpServletRequest request) { - return "POST".equals(request.getMethod()); - } - - private String handleParameters(HttpServletRequest request) { - List radios = settingsService.getAllInternetRadios(true); - for (InternetRadio radio : radios) { - Integer id = radio.getId(); - String streamUrl = getParameter(request, "streamUrl", id); - String homepageUrl = getParameter(request, "homepageUrl", id); - String name = getParameter(request, "name", id); - boolean enabled = getParameter(request, "enabled", id) != null; - boolean delete = getParameter(request, "delete", id) != null; - - if (delete) { - settingsService.deleteInternetRadio(id); - } else { - if (name == null) { - return "internetradiosettings.noname"; - } - if (streamUrl == null) { - return "internetradiosettings.nourl"; - } - settingsService.updateInternetRadio(new InternetRadio(id, name, streamUrl, homepageUrl, enabled, new Date())); - } - } - - String name = StringUtils.trimToNull(request.getParameter("name")); - String streamUrl = StringUtils.trimToNull(request.getParameter("streamUrl")); - String homepageUrl = StringUtils.trimToNull(request.getParameter("homepageUrl")); - boolean enabled = StringUtils.trimToNull(request.getParameter("enabled")) != null; - - if (name != null && streamUrl != null) { - settingsService.createInternetRadio(new InternetRadio(name, streamUrl, homepageUrl, enabled, new Date())); - } - - return null; - } - - private String getParameter(HttpServletRequest request, String name, Integer id) { - return StringUtils.trimToNull(request.getParameter(name + "[" + id + "]")); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/LeftController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/LeftController.java deleted file mode 100644 index d273f0b9..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/LeftController.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.SortedMap; -import java.util.SortedSet; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import net.sourceforge.subsonic.service.PlaylistService; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.LastModified; -import org.springframework.web.servlet.mvc.ParameterizableViewController; -import org.springframework.web.servlet.support.RequestContextUtils; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.InternetRadio; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MediaLibraryStatistics; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.MusicIndex; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.MediaScannerService; -import net.sourceforge.subsonic.service.MusicIndexService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.util.FileUtil; -import net.sourceforge.subsonic.util.StringUtil; - -/** - * Controller for the left index frame. - * - * @author Sindre Mehus - */ -public class LeftController extends ParameterizableViewController implements LastModified { - - private static final Logger LOG = Logger.getLogger(LeftController.class); - - // Update this time if you want to force a refresh in clients. - private static final Calendar LAST_COMPATIBILITY_TIME = Calendar.getInstance(); - static { - LAST_COMPATIBILITY_TIME.set(2012, Calendar.MARCH, 6, 0, 0, 0); - LAST_COMPATIBILITY_TIME.set(Calendar.MILLISECOND, 0); - } - - private MediaScannerService mediaScannerService; - private SettingsService settingsService; - private SecurityService securityService; - private MediaFileService mediaFileService; - private MusicIndexService musicIndexService; - private PlayerService playerService; - private PlaylistService playlistService; - - public long getLastModified(HttpServletRequest request) { - saveSelectedMusicFolder(request); - - if (mediaScannerService.isScanning()) { - return -1L; - } - - long lastModified = LAST_COMPATIBILITY_TIME.getTimeInMillis(); - String username = securityService.getCurrentUsername(request); - - // When was settings last changed? - lastModified = Math.max(lastModified, settingsService.getSettingsChanged()); - - // When was music folder(s) on disk last changed? - List allMusicFolders = settingsService.getAllMusicFolders(); - MusicFolder selectedMusicFolder = getSelectedMusicFolder(request); - if (selectedMusicFolder != null) { - File file = selectedMusicFolder.getPath(); - lastModified = Math.max(lastModified, FileUtil.lastModified(file)); - } else { - for (MusicFolder musicFolder : allMusicFolders) { - File file = musicFolder.getPath(); - lastModified = Math.max(lastModified, FileUtil.lastModified(file)); - } - } - - // When was music folder table last changed? - for (MusicFolder musicFolder : allMusicFolders) { - lastModified = Math.max(lastModified, musicFolder.getChanged().getTime()); - } - - // When was internet radio table last changed? - for (InternetRadio internetRadio : settingsService.getAllInternetRadios()) { - lastModified = Math.max(lastModified, internetRadio.getChanged().getTime()); - } - - // When was user settings last changed? - UserSettings userSettings = settingsService.getUserSettings(username); - lastModified = Math.max(lastModified, userSettings.getChanged().getTime()); - - return lastModified; - } - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - saveSelectedMusicFolder(request); - Map map = new HashMap(); - - MediaLibraryStatistics statistics = mediaScannerService.getStatistics(); - Locale locale = RequestContextUtils.getLocale(request); - - String username = securityService.getCurrentUsername(request); - List allMusicFolders = settingsService.getAllMusicFolders(); - MusicFolder selectedMusicFolder = getSelectedMusicFolder(request); - List musicFoldersToUse = selectedMusicFolder == null ? allMusicFolders : Arrays.asList(selectedMusicFolder); - String[] shortcuts = settingsService.getShortcutsAsArray(); - UserSettings userSettings = settingsService.getUserSettings(username); - - MusicFolderContent musicFolderContent = getMusicFolderContent(musicFoldersToUse); - - map.put("player", playerService.getPlayer(request, response)); - map.put("scanning", mediaScannerService.isScanning()); - map.put("musicFolders", allMusicFolders); - map.put("selectedMusicFolder", selectedMusicFolder); - map.put("radios", settingsService.getAllInternetRadios()); - map.put("shortcuts", getShortcuts(musicFoldersToUse, shortcuts)); - map.put("captionCutoff", userSettings.getMainVisibility().getCaptionCutoff()); - map.put("partyMode", userSettings.isPartyModeEnabled()); - map.put("organizeByFolderStructure", settingsService.isOrganizeByFolderStructure()); - - if (statistics != null) { - map.put("statistics", statistics); - long bytes = statistics.getTotalLengthInBytes(); - long hours = statistics.getTotalDurationInSeconds() / 3600L; - map.put("hours", hours); - map.put("bytes", StringUtil.formatBytes(bytes, locale)); - } - - map.put("indexedArtists", musicFolderContent.getIndexedArtists()); - map.put("singleSongs", musicFolderContent.getSingleSongs()); - map.put("indexes", musicFolderContent.getIndexedArtists().keySet()); - map.put("user", securityService.getCurrentUser(request)); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - private void saveSelectedMusicFolder(HttpServletRequest request) { - if (request.getParameter("musicFolderId") == null) { - return; - } - int musicFolderId = Integer.parseInt(request.getParameter("musicFolderId")); - - // Note: UserSettings.setChanged() is intentionally not called. This would break browser caching - // of the left frame. - UserSettings settings = settingsService.getUserSettings(securityService.getCurrentUsername(request)); - settings.setSelectedMusicFolderId(musicFolderId); - settingsService.updateUserSettings(settings); - } - - /** - * Returns the selected music folder, or null if all music folders should be displayed. - */ - private MusicFolder getSelectedMusicFolder(HttpServletRequest request) { - UserSettings settings = settingsService.getUserSettings(securityService.getCurrentUsername(request)); - int musicFolderId = settings.getSelectedMusicFolderId(); - - return settingsService.getMusicFolderById(musicFolderId); - } - - protected List getSingleSongs(List folders) throws IOException { - List result = new ArrayList(); - for (MusicFolder folder : folders) { - MediaFile parent = mediaFileService.getMediaFile(folder.getPath(), true); - result.addAll(mediaFileService.getChildrenOf(parent, true, false, true, true)); - } - return result; - } - - public List getShortcuts(List musicFoldersToUse, String[] shortcuts) { - List result = new ArrayList(); - - for (String shortcut : shortcuts) { - for (MusicFolder musicFolder : musicFoldersToUse) { - File file = new File(musicFolder.getPath(), shortcut); - if (FileUtil.exists(file)) { - result.add(mediaFileService.getMediaFile(file, true)); - } - } - } - - return result; - } - - public MusicFolderContent getMusicFolderContent(List musicFoldersToUse) throws Exception { - SortedMap> indexedArtists = musicIndexService.getIndexedArtists(musicFoldersToUse); - List singleSongs = getSingleSongs(musicFoldersToUse); - return new MusicFolderContent(indexedArtists, singleSongs); - } - - public void setMediaScannerService(MediaScannerService mediaScannerService) { - this.mediaScannerService = mediaScannerService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setMusicIndexService(MusicIndexService musicIndexService) { - this.musicIndexService = musicIndexService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } - - public static class MusicFolderContent { - - private final SortedMap> indexedArtists; - private final List singleSongs; - - public MusicFolderContent(SortedMap> indexedArtists, List singleSongs) { - this.indexedArtists = indexedArtists; - this.singleSongs = singleSongs; - } - - public SortedMap> getIndexedArtists() { - return indexedArtists; - } - - public List getSingleSongs() { - return singleSongs; - } - - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/LyricsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/LyricsController.java deleted file mode 100644 index d47ad233..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/LyricsController.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import org.springframework.web.servlet.mvc.ParameterizableViewController; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.Map; -import java.util.HashMap; - -/** - * Controller for the lyrics popup. - * - * @author Sindre Mehus - */ -public class LyricsController extends ParameterizableViewController { - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - map.put("artist", request.getParameter("artist")); - map.put("song", request.getParameter("song")); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/M3UController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/M3UController.java deleted file mode 100644 index bbd7a478..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/M3UController.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.TranscodingService; -import net.sourceforge.subsonic.util.StringUtil; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.List; - -/** - * Controller which produces the M3U playlist. - * - * @author Sindre Mehus - */ -public class M3UController implements Controller { - - private PlayerService playerService; - private SettingsService settingsService; - private TranscodingService transcodingService; - - private static final Logger LOG = Logger.getLogger(M3UController.class); - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - response.setContentType("audio/x-mpegurl"); - response.setCharacterEncoding(StringUtil.ENCODING_UTF8); - - Player player = playerService.getPlayer(request, response); - - String url = request.getRequestURL().toString(); - url = url.replaceFirst("play.m3u.*", "stream?"); - - // Rewrite URLs in case we're behind a proxy. - if (settingsService.isRewriteUrlEnabled()) { - String referer = request.getHeader("referer"); - url = StringUtil.rewriteUrl(url, referer); - } - - // Change protocol and port, if specified. (To make it work with players that don't support SSL.) - int streamPort = settingsService.getStreamPort(); - if (streamPort != 0) { - url = StringUtil.toHttpUrl(url, streamPort); - LOG.info("Using non-SSL port " + streamPort + " in m3u playlist."); - } - - if (player.isExternalWithPlaylist()) { - createClientSidePlaylist(response.getWriter(), player, url); - } else { - createServerSidePlaylist(response.getWriter(), player, url); - } - return null; - } - - private void createClientSidePlaylist(PrintWriter out, Player player, String url) throws Exception { - out.println("#EXTM3U"); - List result; - synchronized (player.getPlayQueue()) { - result = player.getPlayQueue().getFiles(); - } - for (MediaFile mediaFile : result) { - Integer duration = mediaFile.getDurationSeconds(); - if (duration == null) { - duration = -1; - } - out.println("#EXTINF:" + duration + "," + mediaFile.getArtist() + " - " + mediaFile.getTitle()); - out.println(url + "player=" + player.getId() + "&id=" +mediaFile.getId() + "&suffix=." + transcodingService.getSuffix(player, mediaFile, null)); - } - } - - private void createServerSidePlaylist(PrintWriter out, Player player, String url) throws IOException { - - url += "player=" + player.getId(); - - // Get suffix of current file, e.g., ".mp3". - String suffix = getSuffix(player); - if (suffix != null) { - url += "&suffix=." + suffix; - } - - out.println("#EXTM3U"); - out.println("#EXTINF:-1,Subsonic"); - out.println(url); - } - - private String getSuffix(Player player) { - PlayQueue playQueue = player.getPlayQueue(); - return playQueue.isEmpty() ? null : transcodingService.getSuffix(player, playQueue.getFile(0), null); - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MainController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MainController.java deleted file mode 100644 index 1d9e0a61..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MainController.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.CoverArtScheme; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.AdService; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.RatingService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; -import org.springframework.web.servlet.view.RedirectView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Controller for the main page. - * - * @author Sindre Mehus - */ -public class MainController extends ParameterizableViewController { - - private SecurityService securityService; - private PlayerService playerService; - private SettingsService settingsService; - private RatingService ratingService; - private MediaFileService mediaFileService; - private AdService adService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - Player player = playerService.getPlayer(request, response); - List mediaFiles = getMediaFiles(request); - - if (mediaFiles.isEmpty()) { - return new ModelAndView(new RedirectView("notFound.view")); - } - - MediaFile dir = mediaFiles.get(0); - if (dir.isFile()) { - dir = mediaFileService.getParentOf(dir); - } - - // Redirect if root directory. - if (mediaFileService.isRoot(dir)) { - return new ModelAndView(new RedirectView("home.view?")); - } - - List children = mediaFiles.size() == 1 ? mediaFileService.getChildrenOf(dir, true, true, true) : getMultiFolderChildren(mediaFiles); - String username = securityService.getCurrentUsername(request); - UserSettings userSettings = settingsService.getUserSettings(username); - - mediaFileService.populateStarredDate(dir, username); - mediaFileService.populateStarredDate(children, username); - - map.put("dir", dir); - map.put("ancestors", getAncestors(dir)); - map.put("children", children); - map.put("artist", guessArtist(children)); - map.put("album", guessAlbum(children)); - map.put("player", player); - map.put("user", securityService.getCurrentUser(request)); - map.put("multipleArtists", isMultipleArtists(children)); - map.put("visibility", userSettings.getMainVisibility()); - map.put("showAlbumYear", settingsService.isSortAlbumsByYear()); - map.put("updateNowPlaying", request.getParameter("updateNowPlaying") != null); - map.put("partyMode", userSettings.isPartyModeEnabled()); - map.put("brand", settingsService.getBrand()); - if (!settingsService.isLicenseValid()) { - map.put("ad", adService.getAd()); - } - - try { - MediaFile parent = mediaFileService.getParentOf(dir); - map.put("parent", parent); - map.put("navigateUpAllowed", !mediaFileService.isRoot(parent)); - } catch (SecurityException x) { - // Happens if Podcast directory is outside music folder. - } - - Integer userRating = ratingService.getRatingForUser(username, dir); - Double averageRating = ratingService.getAverageRating(dir); - - if (userRating == null) { - userRating = 0; - } - - if (averageRating == null) { - averageRating = 0.0D; - } - - map.put("userRating", 10 * userRating); - map.put("averageRating", Math.round(10.0D * averageRating)); - map.put("starred", mediaFileService.getMediaFileStarredDate(dir.getId(), username) != null); - - CoverArtScheme scheme = player.getCoverArtScheme(); - if (scheme != CoverArtScheme.OFF) { - List coverArts = getCoverArts(dir, children); - int size = coverArts.size() > 1 ? scheme.getSize() : scheme.getSize() * 2; - map.put("coverArts", coverArts); - map.put("coverArtSize", size); - if (coverArts.isEmpty() && dir.isAlbum()) { - map.put("showGenericCoverArt", true); - } - } - - setPreviousAndNextAlbums(dir, map); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - private List getMediaFiles(HttpServletRequest request) { - List mediaFiles = new ArrayList(); - for (String path : ServletRequestUtils.getStringParameters(request, "path")) { - MediaFile mediaFile = mediaFileService.getMediaFile(path); - if (mediaFile != null) { - mediaFiles.add(mediaFile); - } - } - for (int id : ServletRequestUtils.getIntParameters(request, "id")) { - MediaFile mediaFile = mediaFileService.getMediaFile(id); - if (mediaFile != null) { - mediaFiles.add(mediaFile); - } - } - return mediaFiles; - } - - private String guessArtist(List children) { - for (MediaFile child : children) { - if (child.isFile() && child.getArtist() != null) { - return child.getArtist(); - } - } - return null; - } - - private String guessAlbum(List children) { - for (MediaFile child : children) { - if (child.isFile() && child.getArtist() != null) { - return child.getAlbumName(); - } - } - return null; - } - - private List getCoverArts(MediaFile dir, List children) throws IOException { - int limit = settingsService.getCoverArtLimit(); - if (limit == 0) { - limit = Integer.MAX_VALUE; - } - - List coverArts = new ArrayList(); - if (dir.isAlbum() && dir.getCoverArtPath() != null) { - coverArts.add(dir); - } else { - for (MediaFile child : children) { - if (child.isAlbum()) { - if (child.getCoverArtPath() != null) { - coverArts.add(child); - } - if (coverArts.size() > limit) { - break; - } - } - } - } - return coverArts; - } - - private List getMultiFolderChildren(List mediaFiles) throws IOException { - List result = new ArrayList(); - for (MediaFile mediaFile : mediaFiles) { - if (mediaFile.isFile()) { - mediaFile = mediaFileService.getParentOf(mediaFile); - } - result.addAll(mediaFileService.getChildrenOf(mediaFile, true, true, true)); - } - return result; - } - - private List getAncestors(MediaFile dir) throws IOException { - LinkedList result = new LinkedList(); - - try { - MediaFile parent = mediaFileService.getParentOf(dir); - while (parent != null && !mediaFileService.isRoot(parent)) { - result.addFirst(parent); - parent = mediaFileService.getParentOf(parent); - } - } catch (SecurityException x) { - // Happens if Podcast directory is outside music folder. - } - return result; - } - - private void setPreviousAndNextAlbums(MediaFile dir, Map map) throws IOException { - MediaFile parent = mediaFileService.getParentOf(dir); - - if (dir.isAlbum() && !mediaFileService.isRoot(parent)) { - List sieblings = mediaFileService.getChildrenOf(parent, false, true, true); - - int index = sieblings.indexOf(dir); - if (index > 0) { - map.put("previousAlbum", sieblings.get(index - 1)); - } - if (index < sieblings.size() - 1) { - map.put("nextAlbum", sieblings.get(index + 1)); - } - } - } - - private boolean isMultipleArtists(List children) { - // Collect unique artist names. - Set artists = new HashSet(); - for (MediaFile child : children) { - if (child.getArtist() != null) { - artists.add(child.getArtist().toLowerCase()); - } - } - - // If zero or one artist, it is definitely not multiple artists. - if (artists.size() < 2) { - return false; - } - - // Fuzzily compare artist names, allowing for some differences in spelling, whitespace etc. - List artistList = new ArrayList(artists); - for (String artist : artistList) { - if (StringUtils.getLevenshteinDistance(artist, artistList.get(0)) > 3) { - return true; - } - } - return false; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setRatingService(RatingService ratingService) { - this.ratingService = ratingService; - } - - public void setAdService(AdService adService) { - this.adService = adService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MoreController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MoreController.java deleted file mode 100644 index f29cb346..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MoreController.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.io.File; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Calendar; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; - -/** - * Controller for the "more" page. - * - * @author Sindre Mehus - */ -public class MoreController extends ParameterizableViewController { - - private SettingsService settingsService; - private SecurityService securityService; - private PlayerService playerService; - private MediaFileService mediaFileService; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - String uploadDirectory = null; - List musicFolders = settingsService.getAllMusicFolders(); - if (musicFolders.size() > 0) { - uploadDirectory = new File(musicFolders.get(0).getPath(), "Incoming").getPath(); - } - - Player player = playerService.getPlayer(request, response); - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - map.put("user", securityService.getCurrentUser(request)); - map.put("uploadDirectory", uploadDirectory); - map.put("genres", mediaFileService.getGenres()); - map.put("currentYear", Calendar.getInstance().get(Calendar.YEAR)); - map.put("musicFolders", settingsService.getAllMusicFolders()); - map.put("clientSidePlaylist", player.isExternalWithPlaylist() || player.isWeb()); - map.put("brand", settingsService.getBrand()); - return result; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MultiController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MultiController.java deleted file mode 100644 index 1d781565..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MultiController.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.Playlist; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.PlaylistService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.util.StringUtil; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.params.HttpConnectionParams; -import org.springframework.web.bind.ServletRequestBindingException; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.multiaction.MultiActionController; -import org.springframework.web.servlet.view.RedirectView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Multi-controller used for simple pages. - * - * @author Sindre Mehus - */ -public class MultiController extends MultiActionController { - - private static final Logger LOG = Logger.getLogger(MultiController.class); - - private SecurityService securityService; - private SettingsService settingsService; - private PlaylistService playlistService; - - public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception { - - // Auto-login if "user" and "password" parameters are given. - String username = request.getParameter("user"); - String password = request.getParameter("password"); - if (username != null && password != null) { - username = StringUtil.urlEncode(username); - password = StringUtil.urlEncode(password); - return new ModelAndView(new RedirectView("j_acegi_security_check?j_username=" + username + - "&j_password=" + password + "&_acegi_security_remember_me=checked")); - } - - Map map = new HashMap(); - map.put("logout", request.getParameter("logout") != null); - map.put("error", request.getParameter("error") != null); - map.put("brand", settingsService.getBrand()); - map.put("loginMessage", settingsService.getLoginMessage()); - - User admin = securityService.getUserByName(User.USERNAME_ADMIN); - if (User.USERNAME_ADMIN.equals(admin.getPassword())) { - map.put("insecure", true); - } - - return new ModelAndView("login", "model", map); - } - - public ModelAndView recover(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - String usernameOrEmail = StringUtils.trimToNull(request.getParameter("usernameOrEmail")); - - if (usernameOrEmail != null) { - User user = getUserByUsernameOrEmail(usernameOrEmail); - if (user == null) { - map.put("error", "recover.error.usernotfound"); - } else if (user.getEmail() == null) { - map.put("error", "recover.error.noemail"); - } else { - String password = RandomStringUtils.randomAlphanumeric(8); - if (emailPassword(password, user.getUsername(), user.getEmail())) { - map.put("sentTo", user.getEmail()); - user.setLdapAuthenticated(false); - user.setPassword(password); - securityService.updateUser(user); - } else { - map.put("error", "recover.error.sendfailed"); - } - } - } - - return new ModelAndView("recover", "model", map); - } - - private boolean emailPassword(String password, String username, String email) { - HttpClient client = new DefaultHttpClient(); - try { - HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000); - HttpConnectionParams.setSoTimeout(client.getParams(), 10000); - HttpPost method = new HttpPost("http://subsonic.org/backend/sendMail.view"); - - List params = new ArrayList(); - params.add(new BasicNameValuePair("from", "noreply@subsonic.org")); - params.add(new BasicNameValuePair("to", email)); - params.add(new BasicNameValuePair("subject", "Subsonic Password")); - params.add(new BasicNameValuePair("text", - "Hi there!\n\n" + - "You have requested to reset your Subsonic password. Please find your new login details below.\n\n" + - "Username: " + username + "\n" + - "Password: " + password + "\n\n" + - "--\n" + - "The Subsonic Team\n" + - "subsonic.org")); - method.setEntity(new UrlEncodedFormEntity(params, StringUtil.ENCODING_UTF8)); - client.execute(method); - return true; - } catch (Exception x) { - LOG.warn("Failed to send email.", x); - return false; - } finally { - client.getConnectionManager().shutdown(); - } - } - - private User getUserByUsernameOrEmail(String usernameOrEmail) { - if (usernameOrEmail != null) { - User user = securityService.getUserByName(usernameOrEmail); - if (user != null) { - return user; - } - return securityService.getUserByEmail(usernameOrEmail); - } - return null; - } - - public ModelAndView accessDenied(HttpServletRequest request, HttpServletResponse response) { - return new ModelAndView("accessDenied"); - } - - public ModelAndView notFound(HttpServletRequest request, HttpServletResponse response) { - return new ModelAndView("notFound"); - } - - public ModelAndView gettingStarted(HttpServletRequest request, HttpServletResponse response) { - updatePortAndContextPath(request); - - if (request.getParameter("hide") != null) { - settingsService.setGettingStartedEnabled(false); - settingsService.save(); - return new ModelAndView(new RedirectView("home.view")); - } - - Map map = new HashMap(); - map.put("runningAsRoot", "root".equals(System.getProperty("user.name"))); - return new ModelAndView("gettingStarted", "model", map); - } - - public ModelAndView index(HttpServletRequest request, HttpServletResponse response) { - updatePortAndContextPath(request); - UserSettings userSettings = settingsService.getUserSettings(securityService.getCurrentUsername(request)); - - Map map = new HashMap(); - map.put("showRight", userSettings.isShowNowPlayingEnabled() || userSettings.isShowChatEnabled()); - map.put("brand", settingsService.getBrand()); - return new ModelAndView("index", "model", map); - } - - public ModelAndView exportPlaylist(HttpServletRequest request, HttpServletResponse response) throws Exception { - - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - Playlist playlist = playlistService.getPlaylist(id); - if (!playlistService.isReadAllowed(playlist, securityService.getCurrentUsername(request))) { - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return null; - - } - response.setContentType("application/x-download"); - response.setHeader("Content-Disposition", "attachment; filename=\"" + StringUtil.fileSystemSafe(playlist.getName()) + ".m3u8\""); - - playlistService.exportPlaylist(id, response.getOutputStream()); - return null; - } - - private void updatePortAndContextPath(HttpServletRequest request) { - - int port = Integer.parseInt(System.getProperty("subsonic.port", String.valueOf(request.getLocalPort()))); - int httpsPort = Integer.parseInt(System.getProperty("subsonic.httpsPort", "0")); - - String contextPath = request.getContextPath().replace("/", ""); - - if (settingsService.getPort() != port) { - settingsService.setPort(port); - settingsService.save(); - } - if (settingsService.getHttpsPort() != httpsPort) { - settingsService.setHttpsPort(httpsPort); - settingsService.save(); - } - if (!ObjectUtils.equals(settingsService.getUrlRedirectContextPath(), contextPath)) { - settingsService.setUrlRedirectContextPath(contextPath); - settingsService.save(); - } - } - - public ModelAndView test(HttpServletRequest request, HttpServletResponse response) { - return new ModelAndView("test"); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MusicFolderSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MusicFolderSettingsController.java deleted file mode 100644 index 8c002342..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/MusicFolderSettingsController.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.command.MusicFolderSettingsCommand; -import net.sourceforge.subsonic.dao.AlbumDao; -import net.sourceforge.subsonic.dao.ArtistDao; -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.service.MediaScannerService; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.SimpleFormController; -import org.springframework.web.servlet.view.RedirectView; - -import javax.servlet.http.HttpServletRequest; -import java.util.ArrayList; -import java.util.List; - -/** - * Controller for the page used to administrate the set of music folders. - * - * @author Sindre Mehus - */ -public class MusicFolderSettingsController extends SimpleFormController { - - private SettingsService settingsService; - private MediaScannerService mediaScannerService; - private ArtistDao artistDao; - private AlbumDao albumDao; - private MediaFileDao mediaFolderDao; - - protected Object formBackingObject(HttpServletRequest request) throws Exception { - MusicFolderSettingsCommand command = new MusicFolderSettingsCommand(); - - if (request.getParameter("scanNow") != null) { - mediaScannerService.scanLibrary(); - } - if (request.getParameter("expunge") != null) { - expunge(); - } - - command.setInterval(String.valueOf(settingsService.getIndexCreationInterval())); - command.setHour(String.valueOf(settingsService.getIndexCreationHour())); - command.setFastCache(settingsService.isFastCacheEnabled()); - command.setOrganizeByFolderStructure(settingsService.isOrganizeByFolderStructure()); - command.setScanning(mediaScannerService.isScanning()); - command.setMusicFolders(wrap(settingsService.getAllMusicFolders(true, true))); - command.setNewMusicFolder(new MusicFolderSettingsCommand.MusicFolderInfo()); - command.setReload(request.getParameter("reload") != null || request.getParameter("scanNow") != null); - return command; - } - - private void expunge() { - artistDao.expunge(); - albumDao.expunge(); - mediaFolderDao.expunge(); - } - - private List wrap(List musicFolders) { - ArrayList result = new ArrayList(); - for (MusicFolder musicFolder : musicFolders) { - result.add(new MusicFolderSettingsCommand.MusicFolderInfo(musicFolder)); - } - return result; - } - - @Override - protected ModelAndView onSubmit(Object comm) throws Exception { - MusicFolderSettingsCommand command = (MusicFolderSettingsCommand) comm; - - for (MusicFolderSettingsCommand.MusicFolderInfo musicFolderInfo : command.getMusicFolders()) { - if (musicFolderInfo.isDelete()) { - settingsService.deleteMusicFolder(musicFolderInfo.getId()); - } else { - settingsService.updateMusicFolder(musicFolderInfo.toMusicFolder()); - } - } - - MusicFolder newMusicFolder = command.getNewMusicFolder().toMusicFolder(); - if (newMusicFolder != null) { - settingsService.createMusicFolder(newMusicFolder); - } - - settingsService.setIndexCreationInterval(Integer.parseInt(command.getInterval())); - settingsService.setIndexCreationHour(Integer.parseInt(command.getHour())); - settingsService.setFastCacheEnabled(command.isFastCache()); - settingsService.setOrganizeByFolderStructure(command.isOrganizeByFolderStructure()); - settingsService.save(); - - mediaScannerService.schedule(); - return new ModelAndView(new RedirectView(getSuccessView() + ".view?reload")); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setMediaScannerService(MediaScannerService mediaScannerService) { - this.mediaScannerService = mediaScannerService; - } - - public void setArtistDao(ArtistDao artistDao) { - this.artistDao = artistDao; - } - - public void setAlbumDao(AlbumDao albumDao) { - this.albumDao = albumDao; - } - - public void setMediaFolderDao(MediaFileDao mediaFolderDao) { - this.mediaFolderDao = mediaFolderDao; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/NetworkSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/NetworkSettingsController.java deleted file mode 100644 index 3807eb71..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/NetworkSettingsController.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.util.Date; -import java.util.Random; - -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.lang.StringUtils; -import org.springframework.web.servlet.mvc.SimpleFormController; - -import net.sourceforge.subsonic.command.NetworkSettingsCommand; -import net.sourceforge.subsonic.service.NetworkService; -import net.sourceforge.subsonic.service.SettingsService; - -/** - * Controller for the page used to change the network settings. - * - * @author Sindre Mehus - */ -public class NetworkSettingsController extends SimpleFormController { - - private static final long TRIAL_DAYS = 30L; - - private SettingsService settingsService; - private NetworkService networkService; - - protected Object formBackingObject(HttpServletRequest request) throws Exception { - NetworkSettingsCommand command = new NetworkSettingsCommand(); - command.setPortForwardingEnabled(settingsService.isPortForwardingEnabled()); - command.setUrlRedirectionEnabled(settingsService.isUrlRedirectionEnabled()); - command.setUrlRedirectFrom(settingsService.getUrlRedirectFrom()); - command.setPort(settingsService.getPort()); - - Date trialExpires = settingsService.getUrlRedirectTrialExpires(); - command.setTrialExpires(trialExpires); - command.setTrialExpired(trialExpires != null && trialExpires.before(new Date())); - command.setTrial(trialExpires != null && !settingsService.isLicenseValid()); - - return command; - } - - protected void doSubmitAction(Object cmd) throws Exception { - NetworkSettingsCommand command = (NetworkSettingsCommand) cmd; - - settingsService.setPortForwardingEnabled(command.isPortForwardingEnabled()); - settingsService.setUrlRedirectionEnabled(command.isUrlRedirectionEnabled()); - settingsService.setUrlRedirectFrom(StringUtils.lowerCase(command.getUrlRedirectFrom())); - - if (!settingsService.isLicenseValid() && settingsService.getUrlRedirectTrialExpires() == null) { - Date expiryDate = new Date(System.currentTimeMillis() + TRIAL_DAYS * 24L * 3600L * 1000L); - settingsService.setUrlRedirectTrialExpires(expiryDate); - } - - if (settingsService.getServerId() == null) { - Random rand = new Random(System.currentTimeMillis()); - settingsService.setServerId(String.valueOf(Math.abs(rand.nextLong()))); - } - - settingsService.save(); - networkService.initPortForwarding(); - networkService.initUrlRedirection(true); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setNetworkService(NetworkService networkService) { - this.networkService = networkService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/NowPlayingController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/NowPlayingController.java deleted file mode 100644 index 79fe7c77..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/NowPlayingController.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.filter.ParameterDecodingFilter; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.StatusService; -import net.sourceforge.subsonic.util.StringUtil; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.AbstractController; -import org.springframework.web.servlet.view.RedirectView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * Controller for showing what's currently playing. - * - * @author Sindre Mehus - */ -public class NowPlayingController extends AbstractController { - - private PlayerService playerService; - private StatusService statusService; - private MediaFileService mediaFileService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Player player = playerService.getPlayer(request, response); - List statuses = statusService.getStreamStatusesForPlayer(player); - - MediaFile current = statuses.isEmpty() ? null : mediaFileService.getMediaFile(statuses.get(0).getFile()); - MediaFile dir = current == null ? null : mediaFileService.getParentOf(current); - - String url; - if (dir != null && !mediaFileService.isRoot(dir)) { - url = "main.view?path" + ParameterDecodingFilter.PARAM_SUFFIX + "=" + - StringUtil.utf8HexEncode(dir.getPath()) + "&updateNowPlaying=true"; - } else { - url = "home.view"; - } - - return new ModelAndView(new RedirectView(url)); - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PasswordSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PasswordSettingsController.java deleted file mode 100644 index 8dd8d875..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PasswordSettingsController.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import org.springframework.web.servlet.mvc.*; -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.command.*; -import net.sourceforge.subsonic.domain.*; - -import javax.servlet.http.*; - -/** - * Controller for the page used to change password. - * - * @author Sindre Mehus - */ -public class PasswordSettingsController extends SimpleFormController { - - private SecurityService securityService; - - protected Object formBackingObject(HttpServletRequest request) throws Exception { - PasswordSettingsCommand command = new PasswordSettingsCommand(); - User user = securityService.getCurrentUser(request); - command.setUsername(user.getUsername()); - command.setLdapAuthenticated(user.isLdapAuthenticated()); - return command; - } - - protected void doSubmitAction(Object comm) throws Exception { - PasswordSettingsCommand command = (PasswordSettingsCommand) comm; - User user = securityService.getUserByName(command.getUsername()); - user.setPassword(command.getPassword()); - securityService.updateUser(user); - - command.setPassword(null); - command.setConfirmPassword(null); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PersonalSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PersonalSettingsController.java deleted file mode 100644 index 3bc3f7a5..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PersonalSettingsController.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import org.springframework.web.servlet.mvc.*; -import org.apache.commons.lang.StringUtils; -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.command.*; -import net.sourceforge.subsonic.domain.*; - -import javax.servlet.http.*; -import java.util.*; - -/** - * Controller for the page used to administrate per-user settings. - * - * @author Sindre Mehus - */ -public class PersonalSettingsController extends SimpleFormController { - - private SettingsService settingsService; - private SecurityService securityService; - - @Override - protected Object formBackingObject(HttpServletRequest request) throws Exception { - PersonalSettingsCommand command = new PersonalSettingsCommand(); - - User user = securityService.getCurrentUser(request); - UserSettings userSettings = settingsService.getUserSettings(user.getUsername()); - - command.setUser(user); - command.setLocaleIndex("-1"); - command.setThemeIndex("-1"); - command.setAvatars(settingsService.getAllSystemAvatars()); - command.setCustomAvatar(settingsService.getCustomAvatar(user.getUsername())); - command.setAvatarId(getAvatarId(userSettings)); - command.setPartyModeEnabled(userSettings.isPartyModeEnabled()); - command.setShowNowPlayingEnabled(userSettings.isShowNowPlayingEnabled()); - command.setShowChatEnabled(userSettings.isShowChatEnabled()); - command.setNowPlayingAllowed(userSettings.isNowPlayingAllowed()); - command.setMainVisibility(userSettings.getMainVisibility()); - command.setPlaylistVisibility(userSettings.getPlaylistVisibility()); - command.setFinalVersionNotificationEnabled(userSettings.isFinalVersionNotificationEnabled()); - command.setBetaVersionNotificationEnabled(userSettings.isBetaVersionNotificationEnabled()); - command.setLastFmEnabled(userSettings.isLastFmEnabled()); - command.setLastFmUsername(userSettings.getLastFmUsername()); - command.setLastFmPassword(userSettings.getLastFmPassword()); - - Locale currentLocale = userSettings.getLocale(); - Locale[] locales = settingsService.getAvailableLocales(); - String[] localeStrings = new String[locales.length]; - for (int i = 0; i < locales.length; i++) { - localeStrings[i] = locales[i].getDisplayName(locales[i]); - if (locales[i].equals(currentLocale)) { - command.setLocaleIndex(String.valueOf(i)); - } - } - command.setLocales(localeStrings); - - String currentThemeId = userSettings.getThemeId(); - Theme[] themes = settingsService.getAvailableThemes(); - command.setThemes(themes); - for (int i = 0; i < themes.length; i++) { - if (themes[i].getId().equals(currentThemeId)) { - command.setThemeIndex(String.valueOf(i)); - break; - } - } - - return command; - } - - @Override - protected void doSubmitAction(Object comm) throws Exception { - PersonalSettingsCommand command = (PersonalSettingsCommand) comm; - - int localeIndex = Integer.parseInt(command.getLocaleIndex()); - Locale locale = null; - if (localeIndex != -1) { - locale = settingsService.getAvailableLocales()[localeIndex]; - } - - int themeIndex = Integer.parseInt(command.getThemeIndex()); - String themeId = null; - if (themeIndex != -1) { - themeId = settingsService.getAvailableThemes()[themeIndex].getId(); - } - - String username = command.getUser().getUsername(); - UserSettings settings = settingsService.getUserSettings(username); - - settings.setLocale(locale); - settings.setThemeId(themeId); - settings.setPartyModeEnabled(command.isPartyModeEnabled()); - settings.setShowNowPlayingEnabled(command.isShowNowPlayingEnabled()); - settings.setShowChatEnabled(command.isShowChatEnabled()); - settings.setNowPlayingAllowed(command.isNowPlayingAllowed()); - settings.setMainVisibility(command.getMainVisibility()); - settings.setPlaylistVisibility(command.getPlaylistVisibility()); - settings.setFinalVersionNotificationEnabled(command.isFinalVersionNotificationEnabled()); - settings.setBetaVersionNotificationEnabled(command.isBetaVersionNotificationEnabled()); - settings.setLastFmEnabled(command.isLastFmEnabled()); - settings.setLastFmUsername(command.getLastFmUsername()); - settings.setSystemAvatarId(getSystemAvatarId(command)); - settings.setAvatarScheme(getAvatarScheme(command)); - - if (StringUtils.isNotBlank(command.getLastFmPassword())) { - settings.setLastFmPassword(command.getLastFmPassword()); - } - - settings.setChanged(new Date()); - settingsService.updateUserSettings(settings); - - command.setReloadNeeded(true); - } - - private int getAvatarId(UserSettings userSettings) { - AvatarScheme avatarScheme = userSettings.getAvatarScheme(); - return avatarScheme == AvatarScheme.SYSTEM ? userSettings.getSystemAvatarId() : avatarScheme.getCode(); - } - - private AvatarScheme getAvatarScheme(PersonalSettingsCommand command) { - if (command.getAvatarId() == AvatarScheme.NONE.getCode()) { - return AvatarScheme.NONE; - } - if (command.getAvatarId() == AvatarScheme.CUSTOM.getCode()) { - return AvatarScheme.CUSTOM; - } - return AvatarScheme.SYSTEM; - } - - private Integer getSystemAvatarId(PersonalSettingsCommand command) { - int avatarId = command.getAvatarId(); - if (avatarId == AvatarScheme.NONE.getCode() || - avatarId == AvatarScheme.CUSTOM.getCode()) { - return null; - } - return avatarId; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlayQueueController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlayQueueController.java deleted file mode 100644 index 0074dda1..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlayQueueController.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; - -/** - * Controller for the playlist frame. - * - * @author Sindre Mehus - */ -public class PlayQueueController extends ParameterizableViewController { - - private PlayerService playerService; - private SecurityService securityService; - private SettingsService settingsService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - User user = securityService.getCurrentUser(request); - UserSettings userSettings = settingsService.getUserSettings(user.getUsername()); - Player player = playerService.getPlayer(request, response); - - Map map = new HashMap(); - map.put("user", user); - map.put("player", player); - map.put("players", playerService.getPlayersForUserAndClientId(user.getUsername(), null)); - map.put("visibility", userSettings.getPlaylistVisibility()); - map.put("partyMode", userSettings.isPartyModeEnabled()); - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlayerSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlayerSettingsController.java deleted file mode 100644 index 813d94a5..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlayerSettingsController.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.lang.StringUtils; -import org.springframework.web.servlet.mvc.SimpleFormController; - -import net.sourceforge.subsonic.command.PlayerSettingsCommand; -import net.sourceforge.subsonic.domain.CoverArtScheme; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayerTechnology; -import net.sourceforge.subsonic.domain.TranscodeScheme; -import net.sourceforge.subsonic.domain.Transcoding; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.TranscodingService; - -/** - * Controller for the player settings page. - * - * @author Sindre Mehus - */ -public class PlayerSettingsController extends SimpleFormController { - - private PlayerService playerService; - private SecurityService securityService; - private TranscodingService transcodingService; - - @Override - protected Object formBackingObject(HttpServletRequest request) throws Exception { - - handleRequestParameters(request); - List players = getPlayers(request); - - User user = securityService.getCurrentUser(request); - PlayerSettingsCommand command = new PlayerSettingsCommand(); - Player player = null; - String playerId = request.getParameter("id"); - if (playerId != null) { - player = playerService.getPlayerById(playerId); - } else if (!players.isEmpty()) { - player = players.get(0); - } - - if (player != null) { - command.setPlayerId(player.getId()); - command.setName(player.getName()); - command.setDescription(player.toString()); - command.setType(player.getType()); - command.setLastSeen(player.getLastSeen()); - command.setDynamicIp(player.isDynamicIp()); - command.setAutoControlEnabled(player.isAutoControlEnabled()); - command.setCoverArtSchemeName(player.getCoverArtScheme().name()); - command.setTranscodeSchemeName(player.getTranscodeScheme().name()); - command.setTechnologyName(player.getTechnology().name()); - command.setAllTranscodings(transcodingService.getAllTranscodings()); - List activeTranscodings = transcodingService.getTranscodingsForPlayer(player); - int[] activeTranscodingIds = new int[activeTranscodings.size()]; - for (int i = 0; i < activeTranscodings.size(); i++) { - activeTranscodingIds[i] = activeTranscodings.get(i).getId(); - } - command.setActiveTranscodingIds(activeTranscodingIds); - } - - command.setTranscodingSupported(transcodingService.isDownsamplingSupported(null)); - command.setTranscodeDirectory(transcodingService.getTranscodeDirectory().getPath()); - command.setCoverArtSchemes(CoverArtScheme.values()); - command.setTranscodeSchemes(TranscodeScheme.values()); - command.setTechnologies(PlayerTechnology.values()); - command.setPlayers(players.toArray(new Player[players.size()])); - command.setAdmin(user.isAdminRole()); - - return command; - } - - @Override - protected void doSubmitAction(Object comm) throws Exception { - PlayerSettingsCommand command = (PlayerSettingsCommand) comm; - Player player = playerService.getPlayerById(command.getPlayerId()); - - player.setAutoControlEnabled(command.isAutoControlEnabled()); - player.setCoverArtScheme(CoverArtScheme.valueOf(command.getCoverArtSchemeName())); - player.setDynamicIp(command.isDynamicIp()); - player.setName(StringUtils.trimToNull(command.getName())); - player.setTranscodeScheme(TranscodeScheme.valueOf(command.getTranscodeSchemeName())); - player.setTechnology(PlayerTechnology.valueOf(command.getTechnologyName())); - - playerService.updatePlayer(player); - transcodingService.setTranscodingsForPlayer(player, command.getActiveTranscodingIds()); - - command.setReloadNeeded(true); - } - - private List getPlayers(HttpServletRequest request) { - User user = securityService.getCurrentUser(request); - String username = user.getUsername(); - List players = playerService.getAllPlayers(); - List authorizedPlayers = new ArrayList(); - - for (Player player : players) { - // Only display authorized players. - if (user.isAdminRole() || username.equals(player.getUsername())) { - authorizedPlayers.add(player); - } - } - return authorizedPlayers; - } - - private void handleRequestParameters(HttpServletRequest request) { - if (request.getParameter("delete") != null) { - playerService.removePlayerById(request.getParameter("delete")); - } else if (request.getParameter("clone") != null) { - playerService.clonePlayer(request.getParameter("clone")); - } - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlaylistController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlaylistController.java deleted file mode 100644 index 6b24a3c5..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PlaylistController.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.Playlist; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.PlaylistService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; -import org.springframework.web.servlet.view.RedirectView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.Map; - -/** - * Controller for the main page. - * - * @author Sindre Mehus - */ -public class PlaylistController extends ParameterizableViewController { - - private SecurityService securityService; - private PlaylistService playlistService; - private SettingsService settingsService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - User user = securityService.getCurrentUser(request); - String username = user.getUsername(); - UserSettings userSettings = settingsService.getUserSettings(username); - Playlist playlist = playlistService.getPlaylist(id); - if (playlist == null) { - return new ModelAndView(new RedirectView("notFound.view")); - } - - map.put("playlist", playlist); - map.put("user", user); - map.put("editAllowed", username.equals(playlist.getUsername()) || securityService.isAdmin(username)); - map.put("partyMode", userSettings.isPartyModeEnabled()); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastController.java deleted file mode 100644 index dbc6854b..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastController.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Playlist; -import net.sourceforge.subsonic.service.PlaylistService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.util.StringUtil; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -/** - * Controller for the page used to generate the Podcast XML file. - * - * @author Sindre Mehus - */ -public class PodcastController extends ParameterizableViewController { - - private static final DateFormat RSS_DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); - private PlaylistService playlistService; - private SettingsService settingsService; - private SecurityService securityService; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - String url = request.getRequestURL().toString(); - String username = securityService.getCurrentUsername(request); - List playlists = playlistService.getReadablePlaylistsForUser(username); - List podcasts = new ArrayList(); - - for (Playlist playlist : playlists) { - - List songs = playlistService.getFilesInPlaylist(playlist.getId()); - if (songs.isEmpty()) { - continue; - } - long length = 0L; - for (MediaFile song : songs) { - length += song.getFileSize(); - } - String publishDate = RSS_DATE_FORMAT.format(playlist.getCreated()); - - // Resolve content type. - String suffix = songs.get(0).getFormat(); - String type = StringUtil.getMimeType(suffix); - - String enclosureUrl = url.replaceFirst("/podcast.*", "/stream?playlist=" + playlist.getId() + "&suffix=." + suffix); - - // Rewrite URLs in case we're behind a proxy. - if (settingsService.isRewriteUrlEnabled()) { - String referer = request.getHeader("referer"); - url = StringUtil.rewriteUrl(url, referer); - } - - // Change protocol and port, if specified. (To make it work with players that don't support SSL.) - int streamPort = settingsService.getStreamPort(); - if (streamPort != 0) { - enclosureUrl = StringUtil.toHttpUrl(enclosureUrl, streamPort); - } - - podcasts.add(new Podcast(playlist.getName(), publishDate, enclosureUrl, length, type)); - } - - Map map = new HashMap(); - - ModelAndView result = super.handleRequestInternal(request, response); - map.put("url", url); - map.put("podcasts", podcasts); - - result.addObject("model", map); - return result; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - /** - * Contains information about a single Podcast. - */ - public static class Podcast { - private String name; - private String publishDate; - private String enclosureUrl; - private long length; - private String type; - - public Podcast(String name, String publishDate, String enclosureUrl, long length, String type) { - this.name = name; - this.publishDate = publishDate; - this.enclosureUrl = enclosureUrl; - this.length = length; - this.type = type; - } - - public String getName() { - return name; - } - - public String getPublishDate() { - return publishDate; - } - - public String getEnclosureUrl() { - return enclosureUrl; - } - - public long getLength() { - return length; - } - - public String getType() { - return type; - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastReceiverAdminController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastReceiverAdminController.java deleted file mode 100644 index c955e884..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastReceiverAdminController.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.PodcastEpisode; -import net.sourceforge.subsonic.domain.PodcastStatus; -import net.sourceforge.subsonic.service.PodcastService; -import net.sourceforge.subsonic.util.StringUtil; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.AbstractController; -import org.springframework.web.servlet.view.RedirectView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.List; - -/** - * Controller for the "Podcast receiver" page. - * - * @author Sindre Mehus - */ -public class PodcastReceiverAdminController extends AbstractController { - - private PodcastService podcastService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - handleParameters(request); - return new ModelAndView(new RedirectView("podcastReceiver.view?expandedChannels=" + request.getParameter("expandedChannels"))); - } - - private void handleParameters(HttpServletRequest request) { - if (request.getParameter("add") != null) { - String url = request.getParameter("add"); - podcastService.createChannel(url); - } - if (request.getParameter("downloadChannel") != null || - request.getParameter("downloadEpisode") != null) { - download(StringUtil.parseInts(request.getParameter("downloadChannel")), - StringUtil.parseInts(request.getParameter("downloadEpisode"))); - } - if (request.getParameter("deleteChannel") != null) { - for (int channelId : StringUtil.parseInts(request.getParameter("deleteChannel"))) { - podcastService.deleteChannel(channelId); - } - } - if (request.getParameter("deleteEpisode") != null) { - for (int episodeId : StringUtil.parseInts(request.getParameter("deleteEpisode"))) { - podcastService.deleteEpisode(episodeId, true); - } - } - if (request.getParameter("refresh") != null) { - podcastService.refreshAllChannels(true); - } - } - - private void download(int[] channelIds, int[] episodeIds) { - SortedSet uniqueEpisodeIds = new TreeSet(); - for (int episodeId : episodeIds) { - uniqueEpisodeIds.add(episodeId); - } - for (int channelId : channelIds) { - List episodes = podcastService.getEpisodes(channelId, false); - for (PodcastEpisode episode : episodes) { - uniqueEpisodeIds.add(episode.getId()); - } - } - - for (Integer episodeId : uniqueEpisodeIds) { - PodcastEpisode episode = podcastService.getEpisode(episodeId, false); - if (episode != null && episode.getUrl() != null && - (episode.getStatus() == PodcastStatus.NEW || - episode.getStatus() == PodcastStatus.ERROR || - episode.getStatus() == PodcastStatus.SKIPPED)) { - - podcastService.downloadEpisode(episode); - } - } - } - - public void setPodcastService(PodcastService podcastService) { - this.podcastService = podcastService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastReceiverController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastReceiverController.java deleted file mode 100644 index 93640c22..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastReceiverController.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import net.sourceforge.subsonic.domain.PodcastChannel; -import net.sourceforge.subsonic.domain.PodcastEpisode; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.PodcastService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.util.StringUtil; - -/** - * Controller for the "Podcast receiver" page. - * - * @author Sindre Mehus - */ -public class PodcastReceiverController extends ParameterizableViewController { - - private PodcastService podcastService; - private SecurityService securityService; - private SettingsService settingsService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - - Map> channels = new LinkedHashMap>(); - for (PodcastChannel channel : podcastService.getAllChannels()) { - channels.put(channel, podcastService.getEpisodes(channel.getId(), false)); - } - - User user = securityService.getCurrentUser(request); - UserSettings userSettings = settingsService.getUserSettings(user.getUsername()); - - map.put("user", user); - map.put("partyMode", userSettings.isPartyModeEnabled()); - map.put("channels", channels); - map.put("expandedChannels", StringUtil.parseInts(request.getParameter("expandedChannels"))); - return result; - } - - public void setPodcastService(PodcastService podcastService) { - this.podcastService = podcastService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastSettingsController.java deleted file mode 100644 index b6389616..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/PodcastSettingsController.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import org.springframework.web.servlet.mvc.SimpleFormController; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.PodcastService; -import net.sourceforge.subsonic.command.PodcastSettingsCommand; - -import javax.servlet.http.HttpServletRequest; - -/** - * Controller for the page used to administrate the Podcast receiver. - * - * @author Sindre Mehus - */ -public class PodcastSettingsController extends SimpleFormController { - - private SettingsService settingsService; - private PodcastService podcastService; - - protected Object formBackingObject(HttpServletRequest request) throws Exception { - PodcastSettingsCommand command = new PodcastSettingsCommand(); - - command.setInterval(String.valueOf(settingsService.getPodcastUpdateInterval())); - command.setEpisodeRetentionCount(String.valueOf(settingsService.getPodcastEpisodeRetentionCount())); - command.setEpisodeDownloadCount(String.valueOf(settingsService.getPodcastEpisodeDownloadCount())); - command.setFolder(settingsService.getPodcastFolder()); - return command; - } - - protected void doSubmitAction(Object comm) throws Exception { - PodcastSettingsCommand command = (PodcastSettingsCommand) comm; - - settingsService.setPodcastUpdateInterval(Integer.parseInt(command.getInterval())); - settingsService.setPodcastEpisodeRetentionCount(Integer.parseInt(command.getEpisodeRetentionCount())); - settingsService.setPodcastEpisodeDownloadCount(Integer.parseInt(command.getEpisodeDownloadCount())); - settingsService.setPodcastFolder(command.getFolder()); - settingsService.save(); - - podcastService.schedule(); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setPodcastService(PodcastService podcastService) { - this.podcastService = podcastService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ProxyController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ProxyController.java deleted file mode 100644 index 9535e059..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ProxyController.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.io.InputStream; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; - -/** - * A proxy for external HTTP requests. - * - * @author Sindre Mehus - */ -public class ProxyController implements Controller { - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - String url = ServletRequestUtils.getRequiredStringParameter(request, "url"); - - HttpClient client = new DefaultHttpClient(); - HttpConnectionParams.setConnectionTimeout(client.getParams(), 15000); - HttpConnectionParams.setSoTimeout(client.getParams(), 15000); - HttpGet method = new HttpGet(url); - - InputStream in = null; - try { - HttpResponse resp = client.execute(method); - int statusCode = resp.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - response.sendError(statusCode); - } else { - in = resp.getEntity().getContent(); - IOUtils.copy(in, response.getOutputStream()); - } - } finally { - IOUtils.closeQuietly(in); - client.getConnectionManager().shutdown(); - } - return null; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RESTController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RESTController.java deleted file mode 100644 index 2d4fa73c..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RESTController.java +++ /dev/null @@ -1,1983 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.TreeSet; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletResponse; - -import net.sourceforge.subsonic.ajax.PlayQueueService; -import net.sourceforge.subsonic.domain.Playlist; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.bind.ServletRequestBindingException; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.multiaction.MultiActionController; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.ajax.ChatService; -import net.sourceforge.subsonic.ajax.LyricsInfo; -import net.sourceforge.subsonic.ajax.LyricsService; -import net.sourceforge.subsonic.command.UserSettingsCommand; -import net.sourceforge.subsonic.dao.AlbumDao; -import net.sourceforge.subsonic.dao.ArtistDao; -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.domain.Album; -import net.sourceforge.subsonic.domain.Artist; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.MusicIndex; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayerTechnology; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.PodcastChannel; -import net.sourceforge.subsonic.domain.PodcastEpisode; -import net.sourceforge.subsonic.domain.RandomSearchCriteria; -import net.sourceforge.subsonic.domain.SearchCriteria; -import net.sourceforge.subsonic.domain.SearchResult; -import net.sourceforge.subsonic.domain.Share; -import net.sourceforge.subsonic.domain.TranscodeScheme; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.AudioScrobblerService; -import net.sourceforge.subsonic.service.JukeboxService; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.PlaylistService; -import net.sourceforge.subsonic.service.PodcastService; -import net.sourceforge.subsonic.service.RatingService; -import net.sourceforge.subsonic.service.SearchService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.ShareService; -import net.sourceforge.subsonic.service.StatusService; -import net.sourceforge.subsonic.service.TranscodingService; -import net.sourceforge.subsonic.util.StringUtil; -import net.sourceforge.subsonic.util.XMLBuilder; - -import static net.sourceforge.subsonic.security.RESTRequestParameterProcessingFilter.decrypt; -import static net.sourceforge.subsonic.util.XMLBuilder.Attribute; -import static net.sourceforge.subsonic.util.XMLBuilder.AttributeSet; - -/** - * Multi-controller used for the REST API. - *

- * For documentation, please refer to api.jsp. - * - * @author Sindre Mehus - */ -public class RESTController extends MultiActionController { - - private static final Logger LOG = Logger.getLogger(RESTController.class); - - private SettingsService settingsService; - private SecurityService securityService; - private PlayerService playerService; - private MediaFileService mediaFileService; - private TranscodingService transcodingService; - private DownloadController downloadController; - private CoverArtController coverArtController; - private AvatarController avatarController; - private UserSettingsController userSettingsController; - private LeftController leftController; - private HomeController homeController; - private StatusService statusService; - private StreamController streamController; - private ShareService shareService; - private PlaylistService playlistService; - private ChatService chatService; - private LyricsService lyricsService; - private PlayQueueService playQueueService; - private JukeboxService jukeboxService; - private AudioScrobblerService audioScrobblerService; - private PodcastService podcastService; - private RatingService ratingService; - private SearchService searchService; - private MediaFileDao mediaFileDao; - private ArtistDao artistDao; - private AlbumDao albumDao; - - public void ping(HttpServletRequest request, HttpServletResponse response) throws Exception { - XMLBuilder builder = createXMLBuilder(request, response, true).endAll(); - response.getWriter().print(builder); - } - - public void getLicense(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - String email = settingsService.getLicenseEmail(); - String key = settingsService.getLicenseCode(); - Date date = settingsService.getLicenseDate(); - boolean valid = settingsService.isLicenseValid(); - - AttributeSet attributes = new AttributeSet(); - attributes.add("valid", valid); - if (valid) { - attributes.add("email", email); - attributes.add("key", key); - attributes.add("date", StringUtil.toISO8601(date)); - } - - builder.add("license", attributes, true); - builder.endAll(); - response.getWriter().print(builder); - } - - public void getMusicFolders(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("musicFolders", false); - - for (MusicFolder musicFolder : settingsService.getAllMusicFolders()) { - AttributeSet attributes = new AttributeSet(); - attributes.add("id", musicFolder.getId()); - attributes.add("name", musicFolder.getName()); - builder.add("musicFolder", attributes, true); - } - builder.endAll(); - response.getWriter().print(builder); - } - - public void getIndexes(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - long ifModifiedSince = ServletRequestUtils.getLongParameter(request, "ifModifiedSince", 0L); - long lastModified = leftController.getLastModified(request); - - if (lastModified <= ifModifiedSince) { - builder.endAll(); - response.getWriter().print(builder); - return; - } - - builder.add("indexes", "lastModified", lastModified, false); - - List musicFolders = settingsService.getAllMusicFolders(); - Integer musicFolderId = ServletRequestUtils.getIntParameter(request, "musicFolderId"); - if (musicFolderId != null) { - for (MusicFolder musicFolder : musicFolders) { - if (musicFolderId.equals(musicFolder.getId())) { - musicFolders = Arrays.asList(musicFolder); - break; - } - } - } - - List shortcuts = leftController.getShortcuts(musicFolders, settingsService.getShortcutsAsArray()); - for (MediaFile shortcut : shortcuts) { - builder.add("shortcut", true, - new Attribute("name", shortcut.getName()), - new Attribute("id", shortcut.getId())); - } - - SortedMap> indexedArtists = leftController.getMusicFolderContent(musicFolders).getIndexedArtists(); - - for (Map.Entry> entry : indexedArtists.entrySet()) { - builder.add("index", "name", entry.getKey().getIndex(), false); - - for (MusicIndex.Artist artist : entry.getValue()) { - for (MediaFile mediaFile : artist.getMediaFiles()) { - if (mediaFile.isDirectory()) { - builder.add("artist", true, - new Attribute("name", artist.getName()), - new Attribute("id", mediaFile.getId())); - } - } - } - builder.end(); - } - - // Add children - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - List singleSongs = leftController.getSingleSongs(musicFolders); - - for (MediaFile singleSong : singleSongs) { - builder.add("child", createAttributesForMediaFile(player, singleSong, username), true); - } - - builder.endAll(); - response.getWriter().print(builder); - } - - public void getArtists(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - String username = securityService.getCurrentUsername(request); - - builder.add("artists", false); - - List artists = artistDao.getAlphabetialArtists(0, Integer.MAX_VALUE); - for (Artist artist : artists) { - AttributeSet attributes = createAttributesForArtist(artist, username); - builder.add("artist", attributes, true); - } - - builder.endAll(); - response.getWriter().print(builder); - } - - private AttributeSet createAttributesForArtist(Artist artist, String username) { - AttributeSet attributes = new AttributeSet(); - attributes.add("id", artist.getId()); - attributes.add("name", artist.getName()); - if (artist.getCoverArtPath() != null) { - attributes.add("coverArt", CoverArtController.ARTIST_COVERART_PREFIX + artist.getId()); - } - attributes.add("albumCount", artist.getAlbumCount()); - attributes.add("starred", StringUtil.toISO8601(artistDao.getArtistStarredDate(artist.getId(), username))); - return attributes; - } - - public void getArtist(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - String username = securityService.getCurrentUsername(request); - Artist artist; - try { - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - artist = artistDao.getArtist(id); - if (artist == null) { - throw new Exception(); - } - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.NOT_FOUND, "Artist not found."); - return; - } - - builder.add("artist", createAttributesForArtist(artist, username), false); - for (Album album : albumDao.getAlbumsForArtist(artist.getName())) { - builder.add("album", createAttributesForAlbum(album, username), true); - } - - builder.endAll(); - response.getWriter().print(builder); - } - - private AttributeSet createAttributesForAlbum(Album album, String username) { - AttributeSet attributes; - attributes = new AttributeSet(); - attributes.add("id", album.getId()); - attributes.add("name", album.getName()); - attributes.add("artist", album.getArtist()); - if (album.getArtist() != null) { - Artist artist = artistDao.getArtist(album.getArtist()); - if (artist != null) { - attributes.add("artistId", artist.getId()); - } - } - if (album.getCoverArtPath() != null) { - attributes.add("coverArt", CoverArtController.ALBUM_COVERART_PREFIX + album.getId()); - } - attributes.add("songCount", album.getSongCount()); - attributes.add("duration", album.getDurationSeconds()); - attributes.add("created", StringUtil.toISO8601(album.getCreated())); - attributes.add("starred", StringUtil.toISO8601(albumDao.getAlbumStarredDate(album.getId(), username))); - - return attributes; - } - - private AttributeSet createAttributesForPlaylist(Playlist playlist) { - AttributeSet attributes; - attributes = new AttributeSet(); - attributes.add("id", playlist.getId()); - attributes.add("name", playlist.getName()); - attributes.add("comment", playlist.getComment()); - attributes.add("owner", playlist.getUsername()); - attributes.add("public", playlist.isPublic()); - attributes.add("songCount", playlist.getFileCount()); - attributes.add("duration", playlist.getDurationSeconds()); - attributes.add("created", StringUtil.toISO8601(playlist.getCreated())); - return attributes; - } - - public void getAlbum(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - Album album; - try { - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - album = albumDao.getAlbum(id); - if (album == null) { - throw new Exception(); - } - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.NOT_FOUND, "Album not found."); - return; - } - - builder.add("album", createAttributesForAlbum(album, username), false); - for (MediaFile mediaFile : mediaFileDao.getSongsForAlbum(album.getArtist(), album.getName())) { - builder.add("song", createAttributesForMediaFile(player, mediaFile, username) , true); - } - - builder.endAll(); - response.getWriter().print(builder); - } - - public void getSong(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - MediaFile song; - try { - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - song = mediaFileDao.getMediaFile(id); - if (song == null || song.isDirectory()) { - throw new Exception(); - } - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.NOT_FOUND, "Song not found."); - return; - } - - builder.add("song", createAttributesForMediaFile(player, song, username), true); - - builder.endAll(); - response.getWriter().print(builder); - } - - public void getMusicDirectory(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - MediaFile dir; - try { - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - dir = mediaFileService.getMediaFile(id); - if (dir == null) { - throw new Exception(); - } - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.NOT_FOUND, "Directory not found"); - return; - } - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("directory", false, - new Attribute("id", dir.getId()), - new Attribute("name", dir.getName())); - - for (MediaFile child : mediaFileService.getChildrenOf(dir, true, true, true)) { - AttributeSet attributes = createAttributesForMediaFile(player, child, username); - builder.add("child", attributes, true); - } - builder.endAll(); - response.getWriter().print(builder); - } - - @Deprecated - public void search(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - String any = request.getParameter("any"); - String artist = request.getParameter("artist"); - String album = request.getParameter("album"); - String title = request.getParameter("title"); - - StringBuilder query = new StringBuilder(); - if (any != null) { - query.append(any).append(" "); - } - if (artist != null) { - query.append(artist).append(" "); - } - if (album != null) { - query.append(album).append(" "); - } - if (title != null) { - query.append(title); - } - - SearchCriteria criteria = new SearchCriteria(); - criteria.setQuery(query.toString().trim()); - criteria.setCount(ServletRequestUtils.getIntParameter(request, "count", 20)); - criteria.setOffset(ServletRequestUtils.getIntParameter(request, "offset", 0)); - - SearchResult result = searchService.search(criteria, SearchService.IndexType.SONG); - builder.add("searchResult", false, - new Attribute("offset", result.getOffset()), - new Attribute("totalHits", result.getTotalHits())); - - for (MediaFile mediaFile : result.getMediaFiles()) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("match", attributes, true); - } - builder.endAll(); - response.getWriter().print(builder); - } - - public void search2(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - builder.add("searchResult2", false); - - String query = request.getParameter("query"); - SearchCriteria criteria = new SearchCriteria(); - criteria.setQuery(StringUtils.trimToEmpty(query)); - criteria.setCount(ServletRequestUtils.getIntParameter(request, "artistCount", 20)); - criteria.setOffset(ServletRequestUtils.getIntParameter(request, "artistOffset", 0)); - SearchResult artists = searchService.search(criteria, SearchService.IndexType.ARTIST); - for (MediaFile mediaFile : artists.getMediaFiles()) { - builder.add("artist", true, - new Attribute("name", mediaFile.getName()), - new Attribute("id", mediaFile.getId())); - } - - criteria.setCount(ServletRequestUtils.getIntParameter(request, "albumCount", 20)); - criteria.setOffset(ServletRequestUtils.getIntParameter(request, "albumOffset", 0)); - SearchResult albums = searchService.search(criteria, SearchService.IndexType.ALBUM); - for (MediaFile mediaFile : albums.getMediaFiles()) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("album", attributes, true); - } - - criteria.setCount(ServletRequestUtils.getIntParameter(request, "songCount", 20)); - criteria.setOffset(ServletRequestUtils.getIntParameter(request, "songOffset", 0)); - SearchResult songs = searchService.search(criteria, SearchService.IndexType.SONG); - for (MediaFile mediaFile : songs.getMediaFiles()) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("song", attributes, true); - } - - builder.endAll(); - response.getWriter().print(builder); - } - - public void search3(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - builder.add("searchResult3", false); - - String query = request.getParameter("query"); - SearchCriteria criteria = new SearchCriteria(); - criteria.setQuery(StringUtils.trimToEmpty(query)); - criteria.setCount(ServletRequestUtils.getIntParameter(request, "artistCount", 20)); - criteria.setOffset(ServletRequestUtils.getIntParameter(request, "artistOffset", 0)); - SearchResult searchResult = searchService.search(criteria, SearchService.IndexType.ARTIST_ID3); - for (Artist artist : searchResult.getArtists()) { - builder.add("artist", createAttributesForArtist(artist, username), true); - } - - criteria.setCount(ServletRequestUtils.getIntParameter(request, "albumCount", 20)); - criteria.setOffset(ServletRequestUtils.getIntParameter(request, "albumOffset", 0)); - searchResult = searchService.search(criteria, SearchService.IndexType.ALBUM_ID3); - for (Album album : searchResult.getAlbums()) { - builder.add("album", createAttributesForAlbum(album, username), true); - } - - criteria.setCount(ServletRequestUtils.getIntParameter(request, "songCount", 20)); - criteria.setOffset(ServletRequestUtils.getIntParameter(request, "songOffset", 0)); - searchResult = searchService.search(criteria, SearchService.IndexType.SONG); - for (MediaFile song : searchResult.getMediaFiles()) { - builder.add("song", createAttributesForMediaFile(player, song, username), true); - } - - builder.endAll(); - response.getWriter().print(builder); - } - - public void getPlaylists(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - User user = securityService.getCurrentUser(request); - String authenticatedUsername = user.getUsername(); - String requestedUsername = request.getParameter("username"); - - if (requestedUsername == null) { - requestedUsername = authenticatedUsername; - } else if (!user.isAdminRole()) { - error(request, response, ErrorCode.NOT_AUTHORIZED, authenticatedUsername + " is not authorized to get playlists for " + requestedUsername); - return; - } - - builder.add("playlists", false); - - for (Playlist playlist : playlistService.getReadablePlaylistsForUser(requestedUsername)) { - List sharedUsers = playlistService.getPlaylistUsers(playlist.getId()); - builder.add("playlist", createAttributesForPlaylist(playlist), sharedUsers.isEmpty()); - if (!sharedUsers.isEmpty()) { - for (String username : sharedUsers) { - builder.add("allowedUser", (Iterable) null, username, true); - } - builder.end(); - } - } - - builder.endAll(); - response.getWriter().print(builder); - } - - public void getPlaylist(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - XMLBuilder builder = createXMLBuilder(request, response, true); - - try { - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - - Playlist playlist = playlistService.getPlaylist(id); - if (playlist == null) { - error(request, response, ErrorCode.NOT_FOUND, "Playlist not found: " + id); - return; - } - if (!playlistService.isReadAllowed(playlist, username)) { - error(request, response, ErrorCode.NOT_AUTHORIZED, "Permission denied for playlist " + id); - return; - } - builder.add("playlist", createAttributesForPlaylist(playlist), false); - for (String allowedUser : playlistService.getPlaylistUsers(playlist.getId())) { - builder.add("allowedUser", (Iterable) null, allowedUser, true); - } - for (MediaFile mediaFile : playlistService.getFilesInPlaylist(id)) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("entry", attributes, true); - } - - builder.endAll(); - response.getWriter().print(builder); - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void jukeboxControl(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request, true); - - User user = securityService.getCurrentUser(request); - if (!user.isJukeboxRole()) { - error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to use jukebox."); - return; - } - - try { - boolean returnPlaylist = false; - String action = ServletRequestUtils.getRequiredStringParameter(request, "action"); - if ("start".equals(action)) { - playQueueService.doStart(request, response); - } else if ("stop".equals(action)) { - playQueueService.doStop(request, response); - } else if ("skip".equals(action)) { - int index = ServletRequestUtils.getRequiredIntParameter(request, "index"); - int offset = ServletRequestUtils.getIntParameter(request, "offset", 0); - playQueueService.doSkip(request, response, index, offset); - } else if ("add".equals(action)) { - int[] ids = ServletRequestUtils.getIntParameters(request, "id"); - playQueueService.doAdd(request, response, ids); - } else if ("set".equals(action)) { - int[] ids = ServletRequestUtils.getIntParameters(request, "id"); - playQueueService.doSet(request, response, ids); - } else if ("clear".equals(action)) { - playQueueService.doClear(request, response); - } else if ("remove".equals(action)) { - int index = ServletRequestUtils.getRequiredIntParameter(request, "index"); - playQueueService.doRemove(request, response, index); - } else if ("shuffle".equals(action)) { - playQueueService.doShuffle(request, response); - } else if ("setGain".equals(action)) { - float gain = ServletRequestUtils.getRequiredFloatParameter(request, "gain"); - jukeboxService.setGain(gain); - } else if ("get".equals(action)) { - returnPlaylist = true; - } else if ("status".equals(action)) { - // No action necessary. - } else { - throw new Exception("Unknown jukebox action: '" + action + "'."); - } - - XMLBuilder builder = createXMLBuilder(request, response, true); - - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - Player jukeboxPlayer = jukeboxService.getPlayer(); - boolean controlsJukebox = jukeboxPlayer != null && jukeboxPlayer.getId().equals(player.getId()); - PlayQueue playQueue = player.getPlayQueue(); - - List attrs = new ArrayList(Arrays.asList( - new Attribute("currentIndex", controlsJukebox && !playQueue.isEmpty() ? playQueue.getIndex() : -1), - new Attribute("playing", controlsJukebox && !playQueue.isEmpty() && playQueue.getStatus() == PlayQueue.Status.PLAYING), - new Attribute("gain", jukeboxService.getGain()), - new Attribute("position", controlsJukebox && !playQueue.isEmpty() ? jukeboxService.getPosition() : 0))); - - if (returnPlaylist) { - builder.add("jukeboxPlaylist", attrs, false); - List result; - synchronized (playQueue) { - result = playQueue.getFiles(); - } - for (MediaFile mediaFile : result) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("entry", attributes, true); - } - } else { - builder.add("jukeboxStatus", attrs, false); - } - - builder.endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void createPlaylist(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request, true); - String username = securityService.getCurrentUsername(request); - - try { - - Integer playlistId = ServletRequestUtils.getIntParameter(request, "playlistId"); - String name = request.getParameter("name"); - if (playlistId == null && name == null) { - error(request, response, ErrorCode.MISSING_PARAMETER, "Playlist ID or name must be specified."); - return; - } - - Playlist playlist; - if (playlistId != null) { - playlist = playlistService.getPlaylist(playlistId); - if (playlist == null) { - error(request, response, ErrorCode.NOT_FOUND, "Playlist not found: " + playlistId); - return; - } - if (!playlistService.isWriteAllowed(playlist, username)) { - error(request, response, ErrorCode.NOT_AUTHORIZED, "Permission denied for playlist " + playlistId); - return; - } - } else { - playlist = new Playlist(); - playlist.setName(name); - playlist.setCreated(new Date()); - playlist.setChanged(new Date()); - playlist.setPublic(false); - playlist.setUsername(username); - playlistService.createPlaylist(playlist); - } - - List songs = new ArrayList(); - for (int id : ServletRequestUtils.getIntParameters(request, "songId")) { - MediaFile song = mediaFileService.getMediaFile(id); - if (song != null) { - songs.add(song); - } - } - playlistService.setFilesInPlaylist(playlist.getId(), songs); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void updatePlaylist(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request, true); - String username = securityService.getCurrentUsername(request); - - try { - int id = ServletRequestUtils.getRequiredIntParameter(request, "playlistId"); - Playlist playlist = playlistService.getPlaylist(id); - if (playlist == null) { - error(request, response, ErrorCode.NOT_FOUND, "Playlist not found: " + id); - return; - } - if (!playlistService.isWriteAllowed(playlist, username)) { - error(request, response, ErrorCode.NOT_AUTHORIZED, "Permission denied for playlist " + id); - return; - } - - String name = request.getParameter("name"); - if (name != null) { - playlist.setName(name); - } - String comment = request.getParameter("comment"); - if (comment != null) { - playlist.setComment(comment); - } - Boolean isPublic = ServletRequestUtils.getBooleanParameter(request, "public"); - if (isPublic != null) { - playlist.setPublic(isPublic); - } - playlistService.updatePlaylist(playlist); - - // TODO: Add later -// for (String usernameToAdd : ServletRequestUtils.getStringParameters(request, "usernameToAdd")) { -// if (securityService.getUserByName(usernameToAdd) != null) { -// playlistService.addPlaylistUser(id, usernameToAdd); -// } -// } -// for (String usernameToRemove : ServletRequestUtils.getStringParameters(request, "usernameToRemove")) { -// if (securityService.getUserByName(usernameToRemove) != null) { -// playlistService.deletePlaylistUser(id, usernameToRemove); -// } -// } - List songs = playlistService.getFilesInPlaylist(id); - boolean songsChanged = false; - - SortedSet tmp = new TreeSet(); - for (int songIndexToRemove : ServletRequestUtils.getIntParameters(request, "songIndexToRemove")) { - tmp.add(songIndexToRemove); - } - List songIndexesToRemove = new ArrayList(tmp); - Collections.reverse(songIndexesToRemove); - for (Integer songIndexToRemove : songIndexesToRemove) { - songs.remove(songIndexToRemove.intValue()); - songsChanged = true; - } - for (int songToAdd : ServletRequestUtils.getIntParameters(request, "songIdToAdd")) { - MediaFile song = mediaFileService.getMediaFile(songToAdd); - if (song != null) { - songs.add(song); - songsChanged = true; - } - } - if (songsChanged) { - playlistService.setFilesInPlaylist(id, songs); - } - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void deletePlaylist(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request, true); - String username = securityService.getCurrentUsername(request); - - try { - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - Playlist playlist = playlistService.getPlaylist(id); - if (playlist == null) { - error(request, response, ErrorCode.NOT_FOUND, "Playlist not found: " + id); - return; - } - if (!playlistService.isWriteAllowed(playlist, username)) { - error(request, response, ErrorCode.NOT_AUTHORIZED, "Permission denied for playlist " + id); - return; - } - playlistService.deletePlaylist(id); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void getAlbumList(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("albumList", false); - - try { - int size = ServletRequestUtils.getIntParameter(request, "size", 10); - int offset = ServletRequestUtils.getIntParameter(request, "offset", 0); - size = Math.max(0, Math.min(size, 500)); - String type = ServletRequestUtils.getRequiredStringParameter(request, "type"); - - List albums; - if ("highest".equals(type)) { - albums = homeController.getHighestRated(offset, size); - } else if ("frequent".equals(type)) { - albums = homeController.getMostFrequent(offset, size); - } else if ("recent".equals(type)) { - albums = homeController.getMostRecent(offset, size); - } else if ("newest".equals(type)) { - albums = homeController.getNewest(offset, size); - } else if ("starred".equals(type)) { - albums = homeController.getStarred(offset, size, username); - } else if ("alphabeticalByArtist".equals(type)) { - albums = homeController.getAlphabetical(offset, size, true); - } else if ("alphabeticalByName".equals(type)) { - albums = homeController.getAlphabetical(offset, size, false); - } else if ("random".equals(type)) { - albums = homeController.getRandom(size); - } else { - throw new Exception("Invalid list type: " + type); - } - - for (HomeController.Album album : albums) { - MediaFile mediaFile = mediaFileService.getMediaFile(album.getPath()); - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("album", attributes, true); - } - builder.endAll(); - response.getWriter().print(builder); - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void getAlbumList2(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("albumList2", false); - - try { - int size = ServletRequestUtils.getIntParameter(request, "size", 10); - int offset = ServletRequestUtils.getIntParameter(request, "offset", 0); - size = Math.max(0, Math.min(size, 500)); - String type = ServletRequestUtils.getRequiredStringParameter(request, "type"); - String username = securityService.getCurrentUsername(request); - - List albums; - if ("frequent".equals(type)) { - albums = albumDao.getMostFrequentlyPlayedAlbums(offset, size); - } else if ("recent".equals(type)) { - albums = albumDao.getMostRecentlyPlayedAlbums(offset, size); - } else if ("newest".equals(type)) { - albums = albumDao.getNewestAlbums(offset, size); - } else if ("alphabeticalByArtist".equals(type)) { - albums = albumDao.getAlphabetialAlbums(offset, size, true); - } else if ("alphabeticalByName".equals(type)) { - albums = albumDao.getAlphabetialAlbums(offset, size, false); - } else if ("starred".equals(type)) { - albums = albumDao.getStarredAlbums(offset, size, securityService.getCurrentUser(request).getUsername()); - } else if ("random".equals(type)) { - albums = searchService.getRandomAlbumsId3(size); - } else { - throw new Exception("Invalid list type: " + type); - } - for (Album album : albums) { - builder.add("album", createAttributesForAlbum(album, username), true); - } - builder.endAll(); - response.getWriter().print(builder); - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void getRandomSongs(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("randomSongs", false); - - try { - int size = ServletRequestUtils.getIntParameter(request, "size", 10); - size = Math.max(0, Math.min(size, 500)); - String genre = ServletRequestUtils.getStringParameter(request, "genre"); - Integer fromYear = ServletRequestUtils.getIntParameter(request, "fromYear"); - Integer toYear = ServletRequestUtils.getIntParameter(request, "toYear"); - Integer musicFolderId = ServletRequestUtils.getIntParameter(request, "musicFolderId"); - RandomSearchCriteria criteria = new RandomSearchCriteria(size, genre, fromYear, toYear, musicFolderId); - - for (MediaFile mediaFile : searchService.getRandomSongs(criteria)) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("song", attributes, true); - } - builder.endAll(); - response.getWriter().print(builder); - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void getVideos(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("videos", false); - try { - int size = ServletRequestUtils.getIntParameter(request, "size", Integer.MAX_VALUE); - int offset = ServletRequestUtils.getIntParameter(request, "offset", 0); - - for (MediaFile mediaFile : mediaFileDao.getVideos(size, offset)) { - builder.add("video", createAttributesForMediaFile(player, mediaFile, username), true); - } - builder.endAll(); - response.getWriter().print(builder); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void getNowPlaying(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("nowPlaying", false); - - for (TransferStatus status : statusService.getAllStreamStatuses()) { - - Player player = status.getPlayer(); - File file = status.getFile(); - if (player != null && player.getUsername() != null && file != null) { - - String username = player.getUsername(); - UserSettings userSettings = settingsService.getUserSettings(username); - if (!userSettings.isNowPlayingAllowed()) { - continue; - } - - MediaFile mediaFile = mediaFileService.getMediaFile(file); - - long minutesAgo = status.getMillisSinceLastUpdate() / 1000L / 60L; - if (minutesAgo < 60) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - attributes.add("username", username); - attributes.add("playerId", player.getId()); - attributes.add("playerName", player.getName()); - attributes.add("minutesAgo", minutesAgo); - builder.add("entry", attributes, true); - } - } - } - - builder.endAll(); - response.getWriter().print(builder); - } - - private AttributeSet createAttributesForMediaFile(Player player, MediaFile mediaFile, String username) { - MediaFile parent = mediaFileService.getParentOf(mediaFile); - AttributeSet attributes = new AttributeSet(); - attributes.add("id", mediaFile.getId()); - try { - if (!mediaFileService.isRoot(parent)) { - attributes.add("parent", parent.getId()); - } - } catch (SecurityException x) { - // Ignored. - } - attributes.add("title", mediaFile.getName()); - attributes.add("album", mediaFile.getAlbumName()); - attributes.add("artist", mediaFile.getArtist()); - attributes.add("isDir", mediaFile.isDirectory()); - attributes.add("coverArt", findCoverArt(mediaFile, parent)); - attributes.add("created", StringUtil.toISO8601(mediaFile.getCreated())); - attributes.add("starred", StringUtil.toISO8601(mediaFileDao.getMediaFileStarredDate(mediaFile.getId(), username))); - attributes.add("userRating", ratingService.getRatingForUser(username, mediaFile)); - attributes.add("averageRating", ratingService.getAverageRating(mediaFile)); - - if (mediaFile.isFile()) { - attributes.add("duration", mediaFile.getDurationSeconds()); - attributes.add("bitRate", mediaFile.getBitRate()); - attributes.add("track", mediaFile.getTrackNumber()); - attributes.add("discNumber", mediaFile.getDiscNumber()); - attributes.add("year", mediaFile.getYear()); - attributes.add("genre", mediaFile.getGenre()); - attributes.add("size", mediaFile.getFileSize()); - String suffix = mediaFile.getFormat(); - attributes.add("suffix", suffix); - attributes.add("contentType", StringUtil.getMimeType(suffix)); - attributes.add("isVideo", mediaFile.isVideo()); - attributes.add("path", getRelativePath(mediaFile)); - - if (mediaFile.getArtist() != null && mediaFile.getAlbumName() != null) { - Album album = albumDao.getAlbum(mediaFile.getAlbumArtist(), mediaFile.getAlbumName()); - if (album != null) { - attributes.add("albumId", album.getId()); - } - } - if (mediaFile.getArtist() != null) { - Artist artist = artistDao.getArtist(mediaFile.getArtist()); - if (artist != null) { - attributes.add("artistId", artist.getId()); - } - } - switch (mediaFile.getMediaType()) { - case MUSIC: - attributes.add("type", "music"); - break; - case PODCAST: - attributes.add("type", "podcast"); - break; - case AUDIOBOOK: - attributes.add("type", "audiobook"); - break; - default: - break; - } - - if (transcodingService.isTranscodingRequired(mediaFile, player)) { - String transcodedSuffix = transcodingService.getSuffix(player, mediaFile, null); - attributes.add("transcodedSuffix", transcodedSuffix); - attributes.add("transcodedContentType", StringUtil.getMimeType(transcodedSuffix)); - } - } - return attributes; - } - - private Integer findCoverArt(MediaFile mediaFile, MediaFile parent) { - MediaFile dir = mediaFile.isDirectory() ? mediaFile : parent; - if (dir != null && dir.getCoverArtPath() != null) { - return dir.getId(); - } - return null; - } - - private String getRelativePath(MediaFile musicFile) { - - String filePath = musicFile.getPath(); - - // Convert slashes. - filePath = filePath.replace('\\', '/'); - - String filePathLower = filePath.toLowerCase(); - - List musicFolders = settingsService.getAllMusicFolders(false, true); - for (MusicFolder musicFolder : musicFolders) { - String folderPath = musicFolder.getPath().getPath(); - folderPath = folderPath.replace('\\', '/'); - String folderPathLower = folderPath.toLowerCase(); - - if (filePathLower.startsWith(folderPathLower)) { - String relativePath = filePath.substring(folderPath.length()); - return relativePath.startsWith("/") ? relativePath.substring(1) : relativePath; - } - } - - return null; - } - - public ModelAndView download(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - User user = securityService.getCurrentUser(request); - if (!user.isDownloadRole()) { - error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to download files."); - return null; - } - - long ifModifiedSince = request.getDateHeader("If-Modified-Since"); - long lastModified = downloadController.getLastModified(request); - - if (ifModifiedSince != -1 && lastModified != -1 && lastModified <= ifModifiedSince) { - response.sendError(HttpServletResponse.SC_NOT_MODIFIED); - return null; - } - - if (lastModified != -1) { - response.setDateHeader("Last-Modified", lastModified); - } - - return downloadController.handleRequest(request, response); - } - - public ModelAndView stream(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - User user = securityService.getCurrentUser(request); - if (!user.isStreamRole()) { - error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to play files."); - return null; - } - - streamController.handleRequest(request, response); - return null; - } - - public void scrobble(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - Player player = playerService.getPlayer(request, response); - - if (!settingsService.getUserSettings(player.getUsername()).isLastFmEnabled()) { - error(request, response, ErrorCode.GENERIC, "Scrobbling is not enabled for " + player.getUsername() + "."); - return; - } - - try { - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - MediaFile file = mediaFileService.getMediaFile(id); - if (file == null) { - error(request, response, ErrorCode.NOT_FOUND, "File not found: " + id); - return; - } - boolean submission = ServletRequestUtils.getBooleanParameter(request, "submission", true); - audioScrobblerService.register(file, player.getUsername(), submission); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - return; - } - - builder.endAll(); - response.getWriter().print(builder); - } - - public void star(HttpServletRequest request, HttpServletResponse response) throws Exception { - starOrUnstar(request, response, true); - } - - public void unstar(HttpServletRequest request, HttpServletResponse response) throws Exception { - starOrUnstar(request, response, false); - } - - private void starOrUnstar(HttpServletRequest request, HttpServletResponse response, boolean star) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - try { - String username = securityService.getCurrentUser(request).getUsername(); - for (int id : ServletRequestUtils.getIntParameters(request, "id")) { - MediaFile mediaFile = mediaFileDao.getMediaFile(id); - if (mediaFile == null) { - error(request, response, ErrorCode.NOT_FOUND, "Media file not found: " + id); - return; - } - if (star) { - mediaFileDao.starMediaFile(id, username); - } else { - mediaFileDao.unstarMediaFile(id, username); - } - } - for (int albumId : ServletRequestUtils.getIntParameters(request, "albumId")) { - Album album = albumDao.getAlbum(albumId); - if (album == null) { - error(request, response, ErrorCode.NOT_FOUND, "Album not found: " + albumId); - return; - } - if (star) { - albumDao.starAlbum(albumId, username); - } else { - albumDao.unstarAlbum(albumId, username); - } - } - for (int artistId : ServletRequestUtils.getIntParameters(request, "artistId")) { - Artist artist = artistDao.getArtist(artistId); - if (artist == null) { - error(request, response, ErrorCode.NOT_FOUND, "Artist not found: " + artistId); - return; - } - if (star) { - artistDao.starArtist(artistId, username); - } else { - artistDao.unstarArtist(artistId, username); - } - } - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - return; - } - - builder.endAll(); - response.getWriter().print(builder); - } - - public void getStarred(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("starred", false); - for (MediaFile artist : mediaFileDao.getStarredDirectories(0, Integer.MAX_VALUE, username)) { - builder.add("artist", true, - new Attribute("name", artist.getName()), - new Attribute("id", artist.getId())); - } - for (MediaFile album : mediaFileDao.getStarredAlbums(0, Integer.MAX_VALUE, username)) { - builder.add("album", createAttributesForMediaFile(player, album, username), true); - } - for (MediaFile song : mediaFileDao.getStarredFiles(0, Integer.MAX_VALUE, username)) { - builder.add("song", createAttributesForMediaFile(player, song, username), true); - } - builder.endAll(); - response.getWriter().print(builder); - } - - public void getStarred2(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("starred2", false); - for (Artist artist : artistDao.getStarredArtists(0, Integer.MAX_VALUE, username)) { - builder.add("artist", createAttributesForArtist(artist, username), true); - } - for (Album album : albumDao.getStarredAlbums(0, Integer.MAX_VALUE, username)) { - builder.add("album", createAttributesForAlbum(album, username), true); - } - for (MediaFile song : mediaFileDao.getStarredFiles(0, Integer.MAX_VALUE, username)) { - builder.add("song", createAttributesForMediaFile(player, song, username), true); - } - builder.endAll(); - response.getWriter().print(builder); - } - - public void getPodcasts(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - XMLBuilder builder = createXMLBuilder(request, response, true); - builder.add("podcasts", false); - - for (PodcastChannel channel : podcastService.getAllChannels()) { - AttributeSet channelAttrs = new AttributeSet(); - channelAttrs.add("id", channel.getId()); - channelAttrs.add("url", channel.getUrl()); - channelAttrs.add("status", channel.getStatus().toString().toLowerCase()); - channelAttrs.add("title", channel.getTitle()); - channelAttrs.add("description", channel.getDescription()); - channelAttrs.add("errorMessage", channel.getErrorMessage()); - builder.add("channel", channelAttrs, false); - - List episodes = podcastService.getEpisodes(channel.getId(), false); - for (PodcastEpisode episode : episodes) { - AttributeSet episodeAttrs = new AttributeSet(); - - String path = episode.getPath(); - if (path != null) { - MediaFile mediaFile = mediaFileService.getMediaFile(path); - episodeAttrs.addAll(createAttributesForMediaFile(player, mediaFile, username)); - episodeAttrs.add("streamId", mediaFile.getId()); - } - - episodeAttrs.add("id", episode.getId()); // Overwrites the previous "id" attribute. - episodeAttrs.add("status", episode.getStatus().toString().toLowerCase()); - episodeAttrs.add("title", episode.getTitle()); - episodeAttrs.add("description", episode.getDescription()); - episodeAttrs.add("publishDate", episode.getPublishDate()); - - builder.add("episode", episodeAttrs, true); - } - - builder.end(); // - } - builder.endAll(); - response.getWriter().print(builder); - } - - public void getShares(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - User user = securityService.getCurrentUser(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - builder.add("shares", false); - for (Share share : shareService.getSharesForUser(user)) { - builder.add("share", createAttributesForShare(share), false); - - for (MediaFile mediaFile : shareService.getSharedFiles(share.getId())) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("entry", attributes, true); - } - - builder.end(); - } - builder.endAll(); - response.getWriter().print(builder); - } - - public void createShare(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - Player player = playerService.getPlayer(request, response); - String username = securityService.getCurrentUsername(request); - - User user = securityService.getCurrentUser(request); - if (!user.isShareRole()) { - error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to share media."); - return; - } - - if (!settingsService.isUrlRedirectionEnabled()) { - error(request, response, ErrorCode.GENERIC, "Sharing is only supported for *.subsonic.org domain names."); - return; - } - - XMLBuilder builder = createXMLBuilder(request, response, true); - - try { - - List files = new ArrayList(); - for (int id : ServletRequestUtils.getRequiredIntParameters(request, "id")) { - files.add(mediaFileService.getMediaFile(id)); - } - - // TODO: Update api.jsp - - Share share = shareService.createShare(request, files); - share.setDescription(request.getParameter("description")); - long expires = ServletRequestUtils.getLongParameter(request, "expires", 0L); - if (expires != 0) { - share.setExpires(new Date(expires)); - } - shareService.updateShare(share); - - builder.add("shares", false); - builder.add("share", createAttributesForShare(share), false); - - for (MediaFile mediaFile : shareService.getSharedFiles(share.getId())) { - AttributeSet attributes = createAttributesForMediaFile(player, mediaFile, username); - builder.add("entry", attributes, true); - } - - builder.endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void deleteShare(HttpServletRequest request, HttpServletResponse response) throws Exception { - try { - request = wrapRequest(request); - User user = securityService.getCurrentUser(request); - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - - Share share = shareService.getShareById(id); - if (share == null) { - error(request, response, ErrorCode.NOT_FOUND, "Shared media not found."); - return; - } - if (!user.isAdminRole() && !share.getUsername().equals(user.getUsername())) { - error(request, response, ErrorCode.NOT_AUTHORIZED, "Not authorized to delete shared media."); - return; - } - - shareService.deleteShare(id); - XMLBuilder builder = createXMLBuilder(request, response, true).endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void updateShare(HttpServletRequest request, HttpServletResponse response) throws Exception { - try { - request = wrapRequest(request); - User user = securityService.getCurrentUser(request); - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - - Share share = shareService.getShareById(id); - if (share == null) { - error(request, response, ErrorCode.NOT_FOUND, "Shared media not found."); - return; - } - if (!user.isAdminRole() && !share.getUsername().equals(user.getUsername())) { - error(request, response, ErrorCode.NOT_AUTHORIZED, "Not authorized to modify shared media."); - return; - } - - share.setDescription(request.getParameter("description")); - String expiresString = request.getParameter("expires"); - if (expiresString != null) { - long expires = Long.parseLong(expiresString); - share.setExpires(expires == 0L ? null : new Date(expires)); - } - shareService.updateShare(share); - XMLBuilder builder = createXMLBuilder(request, response, true).endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - private List createAttributesForShare(Share share) { - List attributes = new ArrayList(); - - attributes.add(new Attribute("id", share.getId())); - attributes.add(new Attribute("url", shareService.getShareUrl(share))); - attributes.add(new Attribute("username", share.getUsername())); - attributes.add(new Attribute("created", StringUtil.toISO8601(share.getCreated()))); - attributes.add(new Attribute("visitCount", share.getVisitCount())); - attributes.add(new Attribute("description", share.getDescription())); - attributes.add(new Attribute("expires", StringUtil.toISO8601(share.getExpires()))); - attributes.add(new Attribute("lastVisited", StringUtil.toISO8601(share.getLastVisited()))); - - return attributes; - } - - public ModelAndView videoPlayer(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - - Map map = new HashMap(); - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - MediaFile file = mediaFileService.getMediaFile(id); - - int timeOffset = ServletRequestUtils.getIntParameter(request, "timeOffset", 0); - timeOffset = Math.max(0, timeOffset); - Integer duration = file.getDurationSeconds(); - if (duration != null) { - map.put("skipOffsets", VideoPlayerController.createSkipOffsets(duration)); - timeOffset = Math.min(duration, timeOffset); - duration -= timeOffset; - } - - map.put("id", request.getParameter("id")); - map.put("u", request.getParameter("u")); - map.put("p", request.getParameter("p")); - map.put("c", request.getParameter("c")); - map.put("v", request.getParameter("v")); - map.put("video", file); - map.put("maxBitRate", ServletRequestUtils.getIntParameter(request, "maxBitRate", VideoPlayerController.DEFAULT_BIT_RATE)); - map.put("duration", duration); - map.put("timeOffset", timeOffset); - map.put("bitRates", VideoPlayerController.BIT_RATES); - map.put("autoplay", ServletRequestUtils.getBooleanParameter(request, "autoplay", true)); - - ModelAndView result = new ModelAndView("rest/videoPlayer"); - result.addObject("model", map); - return result; - } - - public ModelAndView getCoverArt(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - return coverArtController.handleRequest(request, response); - } - - public ModelAndView getAvatar(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - return avatarController.handleRequest(request, response); - } - - public void changePassword(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - try { - - String username = ServletRequestUtils.getRequiredStringParameter(request, "username"); - String password = decrypt(ServletRequestUtils.getRequiredStringParameter(request, "password")); - - User authUser = securityService.getCurrentUser(request); - if (!authUser.isAdminRole() && !username.equals(authUser.getUsername())) { - error(request, response, ErrorCode.NOT_AUTHORIZED, authUser.getUsername() + " is not authorized to change password for " + username); - return; - } - - User user = securityService.getUserByName(username); - user.setPassword(password); - securityService.updateUser(user); - - XMLBuilder builder = createXMLBuilder(request, response, true).endAll(); - response.getWriter().print(builder); - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void getUser(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - - String username; - try { - username = ServletRequestUtils.getRequiredStringParameter(request, "username"); - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - return; - } - - User currentUser = securityService.getCurrentUser(request); - if (!username.equals(currentUser.getUsername()) && !currentUser.isAdminRole()) { - error(request, response, ErrorCode.NOT_AUTHORIZED, currentUser.getUsername() + " is not authorized to get details for other users."); - return; - } - - User requestedUser = securityService.getUserByName(username); - if (requestedUser == null) { - error(request, response, ErrorCode.NOT_FOUND, "No such user: " + username); - return; - } - - UserSettings userSettings = settingsService.getUserSettings(username); - - XMLBuilder builder = createXMLBuilder(request, response, true); - List attributes = Arrays.asList( - new Attribute("username", requestedUser.getUsername()), - new Attribute("email", requestedUser.getEmail()), - new Attribute("scrobblingEnabled", userSettings.isLastFmEnabled()), - new Attribute("adminRole", requestedUser.isAdminRole()), - new Attribute("settingsRole", requestedUser.isSettingsRole()), - new Attribute("downloadRole", requestedUser.isDownloadRole()), - new Attribute("uploadRole", requestedUser.isUploadRole()), - new Attribute("playlistRole", true), // Since 1.8.0 - new Attribute("coverArtRole", requestedUser.isCoverArtRole()), - new Attribute("commentRole", requestedUser.isCommentRole()), - new Attribute("podcastRole", requestedUser.isPodcastRole()), - new Attribute("streamRole", requestedUser.isStreamRole()), - new Attribute("jukeboxRole", requestedUser.isJukeboxRole()), - new Attribute("shareRole", requestedUser.isShareRole()) - ); - - builder.add("user", attributes, true); - builder.endAll(); - response.getWriter().print(builder); - } - - public void createUser(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - User user = securityService.getCurrentUser(request); - if (!user.isAdminRole()) { - error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to create new users."); - return; - } - - try { - UserSettingsCommand command = new UserSettingsCommand(); - command.setUsername(ServletRequestUtils.getRequiredStringParameter(request, "username")); - command.setPassword(decrypt(ServletRequestUtils.getRequiredStringParameter(request, "password"))); - command.setEmail(ServletRequestUtils.getRequiredStringParameter(request, "email")); - command.setLdapAuthenticated(ServletRequestUtils.getBooleanParameter(request, "ldapAuthenticated", false)); - command.setAdminRole(ServletRequestUtils.getBooleanParameter(request, "adminRole", false)); - command.setCommentRole(ServletRequestUtils.getBooleanParameter(request, "commentRole", false)); - command.setCoverArtRole(ServletRequestUtils.getBooleanParameter(request, "coverArtRole", false)); - command.setDownloadRole(ServletRequestUtils.getBooleanParameter(request, "downloadRole", false)); - command.setStreamRole(ServletRequestUtils.getBooleanParameter(request, "streamRole", true)); - command.setUploadRole(ServletRequestUtils.getBooleanParameter(request, "uploadRole", false)); - command.setJukeboxRole(ServletRequestUtils.getBooleanParameter(request, "jukeboxRole", false)); - command.setPodcastRole(ServletRequestUtils.getBooleanParameter(request, "podcastRole", false)); - command.setSettingsRole(ServletRequestUtils.getBooleanParameter(request, "settingsRole", true)); - command.setTranscodeSchemeName(ServletRequestUtils.getStringParameter(request, "transcodeScheme", TranscodeScheme.OFF.name())); - command.setShareRole(ServletRequestUtils.getBooleanParameter(request, "shareRole", false)); - - userSettingsController.createUser(command); - XMLBuilder builder = createXMLBuilder(request, response, true).endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void deleteUser(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - User user = securityService.getCurrentUser(request); - if (!user.isAdminRole()) { - error(request, response, ErrorCode.NOT_AUTHORIZED, user.getUsername() + " is not authorized to delete users."); - return; - } - - try { - String username = ServletRequestUtils.getRequiredStringParameter(request, "username"); - securityService.deleteUser(username); - - XMLBuilder builder = createXMLBuilder(request, response, true).endAll(); - response.getWriter().print(builder); - - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } catch (Exception x) { - LOG.warn("Error in REST API.", x); - error(request, response, ErrorCode.GENERIC, getErrorMessage(x)); - } - } - - public void getChatMessages(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - XMLBuilder builder = createXMLBuilder(request, response, true); - - long since = ServletRequestUtils.getLongParameter(request, "since", 0L); - - builder.add("chatMessages", false); - - for (ChatService.Message message : chatService.getMessages(0L).getMessages()) { - long time = message.getDate().getTime(); - if (time > since) { - builder.add("chatMessage", true, new Attribute("username", message.getUsername()), - new Attribute("time", time), new Attribute("message", message.getContent())); - } - } - builder.endAll(); - response.getWriter().print(builder); - } - - public void addChatMessage(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - try { - chatService.doAddMessage(ServletRequestUtils.getRequiredStringParameter(request, "message"), request); - XMLBuilder builder = createXMLBuilder(request, response, true).endAll(); - response.getWriter().print(builder); - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } - } - - public void getLyrics(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - String artist = request.getParameter("artist"); - String title = request.getParameter("title"); - LyricsInfo lyrics = lyricsService.getLyrics(artist, title); - - XMLBuilder builder = createXMLBuilder(request, response, true); - AttributeSet attributes = new AttributeSet(); - attributes.add("artist", lyrics.getArtist()); - attributes.add("title", lyrics.getTitle()); - builder.add("lyrics", attributes, lyrics.getLyrics(), true); - - builder.endAll(); - response.getWriter().print(builder); - } - - public void setRating(HttpServletRequest request, HttpServletResponse response) throws Exception { - request = wrapRequest(request); - try { - Integer rating = ServletRequestUtils.getRequiredIntParameter(request, "rating"); - if (rating == 0) { - rating = null; - } - - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - MediaFile mediaFile = mediaFileService.getMediaFile(id); - if (mediaFile == null) { - error(request, response, ErrorCode.NOT_FOUND, "File not found: " + id); - return; - } - - String username = securityService.getCurrentUsername(request); - ratingService.setRatingForUser(username, mediaFile, rating); - - XMLBuilder builder = createXMLBuilder(request, response, true).endAll(); - response.getWriter().print(builder); - } catch (ServletRequestBindingException x) { - error(request, response, ErrorCode.MISSING_PARAMETER, getErrorMessage(x)); - } - } - - private HttpServletRequest wrapRequest(HttpServletRequest request) { - return wrapRequest(request, false); - } - - private HttpServletRequest wrapRequest(final HttpServletRequest request, boolean jukebox) { - final String playerId = createPlayerIfNecessary(request, jukebox); - return new HttpServletRequestWrapper(request) { - @Override - public String getParameter(String name) { - // Returns the correct player to be used in PlayerService.getPlayer() - if ("player".equals(name)) { - return playerId; - } - - // Support old style ID parameters. - if ("id".equals(name)) { - return mapId(request.getParameter("id")); - } - - return super.getParameter(name); - } - }; - } - - private String mapId(String id) { - if (id == null || id.startsWith(CoverArtController.ALBUM_COVERART_PREFIX) || - id.startsWith(CoverArtController.ARTIST_COVERART_PREFIX) || StringUtils.isNumeric(id)) { - return id; - } - - try { - String path = StringUtil.utf8HexDecode(id); - MediaFile mediaFile = mediaFileService.getMediaFile(path); - return String.valueOf(mediaFile.getId()); - } catch (Exception x) { - return id; - } - } - - private String getErrorMessage(Exception x) { - if (x.getMessage() != null) { - return x.getMessage(); - } - return x.getClass().getSimpleName(); - } - - private void error(HttpServletRequest request, HttpServletResponse response, ErrorCode code, String message) throws IOException { - XMLBuilder builder = createXMLBuilder(request, response, false); - builder.add("error", true, - new XMLBuilder.Attribute("code", code.getCode()), - new XMLBuilder.Attribute("message", message)); - builder.end(); - response.getWriter().print(builder); - } - - private XMLBuilder createXMLBuilder(HttpServletRequest request, HttpServletResponse response, boolean ok) throws IOException { - String format = ServletRequestUtils.getStringParameter(request, "f", "xml"); - boolean json = "json".equals(format); - boolean jsonp = "jsonp".equals(format); - XMLBuilder builder; - - response.setCharacterEncoding(StringUtil.ENCODING_UTF8); - - if (json) { - builder = XMLBuilder.createJSONBuilder(); - response.setContentType("application/json"); - } else if (jsonp) { - builder = XMLBuilder.createJSONPBuilder(request.getParameter("callback")); - response.setContentType("text/javascript"); - } else { - builder = XMLBuilder.createXMLBuilder(); - response.setContentType("text/xml"); - } - - builder.preamble(StringUtil.ENCODING_UTF8); - builder.add("subsonic-response", false, - new Attribute("xmlns", "http://subsonic.org/restapi"), - new Attribute("status", ok ? "ok" : "failed"), - new Attribute("version", StringUtil.getRESTProtocolVersion())); - return builder; - } - - private String createPlayerIfNecessary(HttpServletRequest request, boolean jukebox) { - String username = request.getRemoteUser(); - String clientId = request.getParameter("c"); - if (jukebox) { - clientId += "-jukebox"; - } - - List players = playerService.getPlayersForUserAndClientId(username, clientId); - - // If not found, create it. - if (players.isEmpty()) { - Player player = new Player(); - player.setIpAddress(request.getRemoteAddr()); - player.setUsername(username); - player.setClientId(clientId); - player.setName(clientId); - player.setTechnology(jukebox ? PlayerTechnology.JUKEBOX : PlayerTechnology.EXTERNAL_WITH_PLAYLIST); - playerService.createPlayer(player); - players = playerService.getPlayersForUserAndClientId(username, clientId); - } - - // Return the player ID. - return !players.isEmpty() ? players.get(0).getId() : null; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } - - public void setDownloadController(DownloadController downloadController) { - this.downloadController = downloadController; - } - - public void setCoverArtController(CoverArtController coverArtController) { - this.coverArtController = coverArtController; - } - - public void setUserSettingsController(UserSettingsController userSettingsController) { - this.userSettingsController = userSettingsController; - } - - public void setLeftController(LeftController leftController) { - this.leftController = leftController; - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } - - public void setStreamController(StreamController streamController) { - this.streamController = streamController; - } - - public void setChatService(ChatService chatService) { - this.chatService = chatService; - } - - public void setHomeController(HomeController homeController) { - this.homeController = homeController; - } - - public void setLyricsService(LyricsService lyricsService) { - this.lyricsService = lyricsService; - } - - public void setPlayQueueService(PlayQueueService playQueueService) { - this.playQueueService = playQueueService; - } - - public void setJukeboxService(JukeboxService jukeboxService) { - this.jukeboxService = jukeboxService; - } - - public void setAudioScrobblerService(AudioScrobblerService audioScrobblerService) { - this.audioScrobblerService = audioScrobblerService; - } - - public void setPodcastService(PodcastService podcastService) { - this.podcastService = podcastService; - } - - public void setRatingService(RatingService ratingService) { - this.ratingService = ratingService; - } - - public void setSearchService(SearchService searchService) { - this.searchService = searchService; - } - - public void setShareService(ShareService shareService) { - this.shareService = shareService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setAvatarController(AvatarController avatarController) { - this.avatarController = avatarController; - } - - public void setArtistDao(ArtistDao artistDao) { - this.artistDao = artistDao; - } - - public void setAlbumDao(AlbumDao albumDao) { - this.albumDao = albumDao; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } - - public static enum ErrorCode { - - GENERIC(0, "A generic error."), - MISSING_PARAMETER(10, "Required parameter is missing."), - PROTOCOL_MISMATCH_CLIENT_TOO_OLD(20, "Incompatible Subsonic REST protocol version. Client must upgrade."), - PROTOCOL_MISMATCH_SERVER_TOO_OLD(30, "Incompatible Subsonic REST protocol version. Server must upgrade."), - NOT_AUTHENTICATED(40, "Wrong username or password."), - NOT_AUTHORIZED(50, "User is not authorized for the given operation."), - NOT_LICENSED(60, "The trial period for the Subsonic server is over. Please donate to get a license key. Visit subsonic.org for details."), - NOT_FOUND(70, "Requested data was not found."); - - private final int code; - private final String message; - - ErrorCode(int code, String message) { - this.code = code; - this.message = message; - } - - public int getCode() { - return code; - } - - public String getMessage() { - return message; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RandomPlayQueueController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RandomPlayQueueController.java deleted file mode 100644 index a3738684..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RandomPlayQueueController.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.RandomSearchCriteria; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SearchService; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Controller for the creating a random play queue. - * - * @author Sindre Mehus - */ -public class RandomPlayQueueController extends ParameterizableViewController { - - private PlayerService playerService; - private List reloadFrames; - private SearchService searchService; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - int size = ServletRequestUtils.getRequiredIntParameter(request, "size"); - String genre = request.getParameter("genre"); - if (StringUtils.equalsIgnoreCase("any", genre)) { - genre = null; - } - - Integer fromYear = null; - Integer toYear = null; - - String year = request.getParameter("year"); - if (!StringUtils.equalsIgnoreCase("any", year)) { - String[] tmp = StringUtils.split(year); - fromYear = Integer.parseInt(tmp[0]); - toYear = Integer.parseInt(tmp[1]); - } - - Integer musicFolderId = ServletRequestUtils.getRequiredIntParameter(request, "musicFolderId"); - if (musicFolderId == -1) { - musicFolderId = null; - } - - Player player = playerService.getPlayer(request, response); - PlayQueue playQueue = player.getPlayQueue(); - - RandomSearchCriteria criteria = new RandomSearchCriteria(size, genre, fromYear, toYear, musicFolderId); - playQueue.addFiles(false, searchService.getRandomSongs(criteria)); - - if (request.getParameter("autoRandom") != null) { - playQueue.setRandomSearchCriteria(criteria); - } - - Map map = new HashMap(); - map.put("reloadFrames", reloadFrames); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setReloadFrames(List reloadFrames) { - this.reloadFrames = reloadFrames; - } - - public void setSearchService(SearchService searchService) { - this.searchService = searchService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ReloadFrame.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ReloadFrame.java deleted file mode 100644 index 093b7fa1..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ReloadFrame.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -/** - * Used in subsonic-servlet.xml to specify frame reloading. - * - * @author Sindre Mehus - */ -public class ReloadFrame { - private String frame; - private String view; - - public ReloadFrame() {} - - public ReloadFrame(String frame, String view) { - this.frame = frame; - this.view = view; - } - - public String getFrame() { - return frame; - } - - public void setFrame(String frame) { - this.frame = frame; - } - - public String getView() { - return view; - } - - public void setView(String view) { - this.view = view; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RightController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RightController.java deleted file mode 100644 index 405c2dc7..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/RightController.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.dao.UserDao; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.SecurityService; - -/** - * Controller for the right frame. - * - * @author Sindre Mehus - */ -public class RightController extends ParameterizableViewController { - - private SettingsService settingsService; - private SecurityService securityService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - ModelAndView result = super.handleRequestInternal(request, response); - - UserSettings userSettings = settingsService.getUserSettings(securityService.getCurrentUsername(request)); - map.put("showNowPlaying", userSettings.isShowNowPlayingEnabled()); - map.put("showChat", userSettings.isShowChatEnabled()); - map.put("user", securityService.getCurrentUser(request)); - - result.addObject("model", map); - return result; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SearchController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SearchController.java deleted file mode 100644 index 387ec7db..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SearchController.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang.StringUtils; -import org.springframework.validation.BindException; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.SimpleFormController; - -import net.sourceforge.subsonic.command.SearchCommand; -import net.sourceforge.subsonic.domain.SearchCriteria; -import net.sourceforge.subsonic.domain.SearchResult; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.SearchService; - -/** - * Controller for the search page. - * - * @author Sindre Mehus - */ -public class SearchController extends SimpleFormController { - - private static final int MATCH_COUNT = 25; - - private SecurityService securityService; - private SettingsService settingsService; - private PlayerService playerService; - private SearchService searchService; - - @Override - protected Object formBackingObject(HttpServletRequest request) throws Exception { - return new SearchCommand(); - } - - @Override - protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object com, BindException errors) - throws Exception { - SearchCommand command = (SearchCommand) com; - - User user = securityService.getCurrentUser(request); - UserSettings userSettings = settingsService.getUserSettings(user.getUsername()); - command.setUser(user); - command.setPartyModeEnabled(userSettings.isPartyModeEnabled()); - - String any = StringUtils.trimToNull(command.getQuery()); - - if (any != null) { - - SearchCriteria criteria = new SearchCriteria(); - criteria.setCount(MATCH_COUNT); - criteria.setQuery(any); - - SearchResult artists = searchService.search(criteria, SearchService.IndexType.ARTIST); - command.setArtists(artists.getMediaFiles()); - - SearchResult albums = searchService.search(criteria, SearchService.IndexType.ALBUM); - command.setAlbums(albums.getMediaFiles()); - - SearchResult songs = searchService.search(criteria, SearchService.IndexType.SONG); - command.setSongs(songs.getMediaFiles()); - - command.setPlayer(playerService.getPlayer(request, response)); - } - - return new ModelAndView(getSuccessView(), errors.getModel()); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setSearchService(SearchService searchService) { - this.searchService = searchService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SetMusicFileInfoController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SetMusicFileInfoController.java deleted file mode 100644 index 8b3ebca7..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SetMusicFileInfoController.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.util.*; -import net.sourceforge.subsonic.filter.ParameterDecodingFilter; -import org.springframework.web.servlet.*; -import org.springframework.web.servlet.view.*; -import org.springframework.web.servlet.mvc.*; - -import javax.servlet.http.*; - -/** - * Controller for updating music file metadata. - * - * @author Sindre Mehus - */ -public class SetMusicFileInfoController extends AbstractController { - - private MediaFileService mediaFileService; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - String path = request.getParameter("path"); - String action = request.getParameter("action"); - - MediaFile mediaFile = mediaFileService.getMediaFile(path); - - if ("comment".equals(action)) { - mediaFile.setComment(StringUtil.toHtml(request.getParameter("comment"))); - mediaFileService.updateMediaFile(mediaFile); - } - - String url = "main.view?path" + ParameterDecodingFilter.PARAM_SUFFIX + "=" + StringUtil.utf8HexEncode(path); - return new ModelAndView(new RedirectView(url)); - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SetRatingController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SetRatingController.java deleted file mode 100644 index aaeaa4a4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SetRatingController.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.util.*; -import net.sourceforge.subsonic.filter.ParameterDecodingFilter; -import org.springframework.web.bind.*; -import org.springframework.web.servlet.*; -import org.springframework.web.servlet.mvc.*; -import org.springframework.web.servlet.view.*; - -import javax.servlet.http.*; - -/** - * Controller for updating music file ratings. - * - * @author Sindre Mehus - */ -public class SetRatingController extends AbstractController { - - private RatingService ratingService; - private SecurityService securityService; - private MediaFileService mediaFileService; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - String path = request.getParameter("path"); - Integer rating = ServletRequestUtils.getIntParameter(request, "rating"); - if (rating == 0) { - rating = null; - } - - MediaFile mediaFile = mediaFileService.getMediaFile(path); - String username = securityService.getCurrentUsername(request); - ratingService.setRatingForUser(username, mediaFile, rating); - - String url = "main.view?path" + ParameterDecodingFilter.PARAM_SUFFIX + "=" + StringUtil.utf8HexEncode(path); - return new ModelAndView(new RedirectView(url)); - } - - public void setRatingService(RatingService ratingService) { - this.ratingService = ratingService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SettingsController.java deleted file mode 100644 index ed0c21c5..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/SettingsController.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.service.*; -import org.springframework.web.servlet.*; -import org.springframework.web.servlet.view.*; -import org.springframework.web.servlet.mvc.*; - -import javax.servlet.http.*; - -/** - * Controller for the main settings page. - * - * @author Sindre Mehus - */ -public class SettingsController extends AbstractController { - - private SecurityService securityService; - - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - User user = securityService.getCurrentUser(request); - - // Redirect to music folder settings if admin. - String view = user.isAdminRole() ? "musicFolderSettings.view" : "personalSettings.view"; - - return new ModelAndView(new RedirectView(view)); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ShareManagementController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ShareManagementController.java deleted file mode 100644 index de2ea764..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ShareManagementController.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.service.*; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.multiaction.MultiActionController; - -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.Share; - -/** - * Controller for sharing music on Twitter, Facebook etc. - * - * @author Sindre Mehus - */ -public class ShareManagementController extends MultiActionController { - - private MediaFileService mediaFileService; - private SettingsService settingsService; - private ShareService shareService; - private PlayerService playerService; - private SecurityService securityService; - - public ModelAndView createShare(HttpServletRequest request, HttpServletResponse response) throws Exception { - - List files = getMediaFiles(request); - MediaFile dir = null; - if (!files.isEmpty()) { - dir = files.get(0); - if (!dir.isAlbum()) { - dir = mediaFileService.getParentOf(dir); - } - } - - Map map = new HashMap(); - map.put("urlRedirectionEnabled", settingsService.isUrlRedirectionEnabled()); - map.put("dir", dir); - map.put("user", securityService.getCurrentUser(request)); - Share share = shareService.createShare(request, files); - map.put("playUrl", shareService.getShareUrl(share)); - - return new ModelAndView("createShare", "model", map); - } - - private List getMediaFiles(HttpServletRequest request) throws IOException { - String dir = request.getParameter("dir"); - String playerId = request.getParameter("player"); - - List result = new ArrayList(); - - if (dir != null) { - MediaFile album = mediaFileService.getMediaFile(dir); - int[] indexes = ServletRequestUtils.getIntParameters(request, "i"); - if (indexes.length == 0) { - return Arrays.asList(album); - } - List children = mediaFileService.getChildrenOf(album, true, true, true); - for (int index : indexes) { - result.add(children.get(index)); - } - } else if (playerId != null) { - Player player = playerService.getPlayerById(playerId); - PlayQueue playQueue = player.getPlayQueue(); - List result1; - synchronized (playQueue) { - result1 = playQueue.getFiles(); - } - result = result1; - } - - return result; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setShareService(ShareService shareService) { - this.shareService = shareService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ShareSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ShareSettingsController.java deleted file mode 100644 index 2b8a958a..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/ShareSettingsController.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Share; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.ShareService; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Controller for the page used to administrate the set of shared media. - * - * @author Sindre Mehus - */ -public class ShareSettingsController extends ParameterizableViewController { - - private ShareService shareService; - private SecurityService securityService; - private MediaFileService mediaFileService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - - if (isFormSubmission(request)) { - String error = handleParameters(request); - map.put("error", error); - } - - ModelAndView result = super.handleRequestInternal(request, response); - map.put("shareBaseUrl", shareService.getShareBaseUrl()); - map.put("shareInfos", getShareInfos(request)); - map.put("user", securityService.getCurrentUser(request)); - - result.addObject("model", map); - return result; - } - - /** - * Determine if the given request represents a form submission. - * - * @param request current HTTP request - * @return if the request represents a form submission - */ - private boolean isFormSubmission(HttpServletRequest request) { - return "POST".equals(request.getMethod()); - } - - private String handleParameters(HttpServletRequest request) { - User user = securityService.getCurrentUser(request); - for (Share share : shareService.getSharesForUser(user)) { - int id = share.getId(); - - String description = getParameter(request, "description", id); - boolean delete = getParameter(request, "delete", id) != null; - String expireIn = getParameter(request, "expireIn", id); - - if (delete) { - shareService.deleteShare(id); - } else { - if (expireIn != null) { - share.setExpires(parseExpireIn(expireIn)); - } - share.setDescription(description); - shareService.updateShare(share); - } - } - - return null; - } - - private List getShareInfos(HttpServletRequest request) { - List result = new ArrayList(); - User user = securityService.getCurrentUser(request); - for (Share share : shareService.getSharesForUser(user)) { - List files = shareService.getSharedFiles(share.getId()); - if (!files.isEmpty()) { - MediaFile file = files.get(0); - result.add(new ShareInfo(share, file.isDirectory() ? file : mediaFileService.getParentOf(file))); - } - } - return result; - } - - - private String getParameter(HttpServletRequest request, String name, int id) { - return StringUtils.trimToNull(request.getParameter(name + "[" + id + "]")); - } - - private Date parseExpireIn(String expireIn) { - int days = Integer.parseInt(expireIn); - if (days == 0) { - return null; - } - - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.DAY_OF_YEAR, days); - return calendar.getTime(); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setShareService(ShareService shareService) { - this.shareService = shareService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public static class ShareInfo { - private final Share share; - private final MediaFile dir; - - public ShareInfo(Share share, MediaFile dir) { - this.share = share; - this.dir = dir; - } - - public Share getShare() { - return share; - } - - public MediaFile getDir() { - return dir; - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StarredController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StarredController.java deleted file mode 100644 index 2da8b5ad..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StarredController.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Controller for showing a user's starred items. - * - * @author Sindre Mehus - */ -public class StarredController extends ParameterizableViewController { - - private PlayerService playerService; - private MediaFileDao mediaFileDao; - private SecurityService securityService; - private SettingsService settingsService; - private MediaFileService mediaFileService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - User user = securityService.getCurrentUser(request); - String username = user.getUsername(); - UserSettings userSettings = settingsService.getUserSettings(username); - - List artists = mediaFileDao.getStarredDirectories(0, Integer.MAX_VALUE, username); - List albums = mediaFileDao.getStarredAlbums(0, Integer.MAX_VALUE, username); - List songs = mediaFileDao.getStarredFiles(0, Integer.MAX_VALUE, username); - mediaFileService.populateStarredDate(artists, username); - mediaFileService.populateStarredDate(albums, username); - mediaFileService.populateStarredDate(songs, username); - - map.put("user", user); - map.put("partyModeEnabled", userSettings.isPartyModeEnabled()); - map.put("player", playerService.getPlayer(request, response)); - map.put("artists", artists); - map.put("albums", albums); - map.put("songs", songs); - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StatusChartController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StatusChartController.java deleted file mode 100644 index 878b8ae8..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StatusChartController.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.service.*; -import org.jfree.chart.*; -import org.jfree.chart.axis.*; -import org.jfree.chart.plot.*; -import org.jfree.chart.renderer.xy.*; -import org.jfree.data.*; -import org.jfree.data.time.*; -import org.springframework.web.servlet.*; - -import javax.servlet.http.*; -import java.awt.*; -import java.util.*; -import java.util.List; - -/** - * Controller for generating a chart showing bitrate vs time. - * - * @author Sindre Mehus - */ -public class StatusChartController extends AbstractChartController { - - private StatusService statusService; - - public static final int IMAGE_WIDTH = 350; - public static final int IMAGE_HEIGHT = 150; - - public synchronized ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - String type = request.getParameter("type"); - int index = Integer.parseInt(request.getParameter("index")); - - List statuses = Collections.emptyList(); - if ("stream".equals(type)) { - statuses = statusService.getAllStreamStatuses(); - } else if ("download".equals(type)) { - statuses = statusService.getAllDownloadStatuses(); - } else if ("upload".equals(type)) { - statuses = statusService.getAllUploadStatuses(); - } - - if (index < 0 || index >= statuses.size()) { - return null; - } - TransferStatus status = statuses.get(index); - - TimeSeries series = new TimeSeries("Kbps", Millisecond.class); - TransferStatus.SampleHistory history = status.getHistory(); - long to = System.currentTimeMillis(); - long from = to - status.getHistoryLengthMillis(); - Range range = new DateRange(from, to); - - if (!history.isEmpty()) { - - TransferStatus.Sample previous = history.get(0); - - for (int i = 1; i < history.size(); i++) { - TransferStatus.Sample sample = history.get(i); - - long elapsedTimeMilis = sample.getTimestamp() - previous.getTimestamp(); - long bytesStreamed = Math.max(0L, sample.getBytesTransfered() - previous.getBytesTransfered()); - - double kbps = (8.0 * bytesStreamed / 1024.0) / (elapsedTimeMilis / 1000.0); - series.addOrUpdate(new Millisecond(new Date(sample.getTimestamp())), kbps); - - previous = sample; - } - } - - // Compute moving average. - series = MovingAverage.createMovingAverage(series, "Kbps", 20000, 5000); - - // Find min and max values. - double min = 100; - double max = 250; - for (Object obj : series.getItems()) { - TimeSeriesDataItem item = (TimeSeriesDataItem) obj; - double value = item.getValue().doubleValue(); - if (item.getPeriod().getFirstMillisecond() > from) { - min = Math.min(min, value); - max = Math.max(max, value); - } - } - - // Add 10% to max value. - max *= 1.1D; - - // Subtract 10% from min value. - min *= 0.9D; - - TimeSeriesCollection dataset = new TimeSeriesCollection(); - dataset.addSeries(series); - JFreeChart chart = ChartFactory.createTimeSeriesChart(null, null, null, dataset, false, false, false); - XYPlot plot = (XYPlot) chart.getPlot(); - - plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT); - Paint background = new GradientPaint(0, 0, Color.lightGray, 0, IMAGE_HEIGHT, Color.white); - plot.setBackgroundPaint(background); - - XYItemRenderer renderer = plot.getRendererForDataset(dataset); - renderer.setSeriesPaint(0, Color.blue.darker()); - renderer.setSeriesStroke(0, new BasicStroke(2f)); - - // Set theme-specific colors. - Color bgColor = getBackground(request); - Color fgColor = getForeground(request); - - chart.setBackgroundPaint(bgColor); - - ValueAxis domainAxis = plot.getDomainAxis(); - domainAxis.setRange(range); - domainAxis.setTickLabelPaint(fgColor); - domainAxis.setTickMarkPaint(fgColor); - domainAxis.setAxisLinePaint(fgColor); - - ValueAxis rangeAxis = plot.getRangeAxis(); - rangeAxis.setRange(new Range(min, max)); - rangeAxis.setTickLabelPaint(fgColor); - rangeAxis.setTickMarkPaint(fgColor); - rangeAxis.setAxisLinePaint(fgColor); - - ChartUtilities.writeChartAsPNG(response.getOutputStream(), chart, IMAGE_WIDTH, IMAGE_HEIGHT); - - return null; - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StatusController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StatusController.java deleted file mode 100644 index 964e7810..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StatusController.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.service.StatusService; -import net.sourceforge.subsonic.util.FileUtil; -import net.sourceforge.subsonic.util.StringUtil; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; -import org.springframework.web.servlet.support.RequestContextUtils; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -/** - * Controller for the status page. - * - * @author Sindre Mehus - */ -public class StatusController extends ParameterizableViewController { - - private StatusService statusService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - List streamStatuses = statusService.getAllStreamStatuses(); - List downloadStatuses = statusService.getAllDownloadStatuses(); - List uploadStatuses = statusService.getAllUploadStatuses(); - - Locale locale = RequestContextUtils.getLocale(request); - List transferStatuses = new ArrayList(); - - for (int i = 0; i < streamStatuses.size(); i++) { - long minutesAgo = streamStatuses.get(i).getMillisSinceLastUpdate() / 1000L / 60L; - if (minutesAgo < 60L) { - transferStatuses.add(new TransferStatusHolder(streamStatuses.get(i), true, false, false, i, locale)); - } - } - for (int i = 0; i < downloadStatuses.size(); i++) { - transferStatuses.add(new TransferStatusHolder(downloadStatuses.get(i), false, true, false, i, locale)); - } - for (int i = 0; i < uploadStatuses.size(); i++) { - transferStatuses.add(new TransferStatusHolder(uploadStatuses.get(i), false, false, true, i, locale)); - } - - map.put("transferStatuses", transferStatuses); - map.put("chartWidth", StatusChartController.IMAGE_WIDTH); - map.put("chartHeight", StatusChartController.IMAGE_HEIGHT); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public static class TransferStatusHolder { - private TransferStatus transferStatus; - private boolean isStream; - private boolean isDownload; - private boolean isUpload; - private int index; - private Locale locale; - - public TransferStatusHolder(TransferStatus transferStatus, boolean isStream, boolean isDownload, boolean isUpload, - int index, Locale locale) { - this.transferStatus = transferStatus; - this.isStream = isStream; - this.isDownload = isDownload; - this.isUpload = isUpload; - this.index = index; - this.locale = locale; - } - - public boolean isStream() { - return isStream; - } - - public boolean isDownload() { - return isDownload; - } - - public boolean isUpload() { - return isUpload; - } - - public int getIndex() { - return index; - } - - public Player getPlayer() { - return transferStatus.getPlayer(); - } - - public String getPlayerType() { - Player player = transferStatus.getPlayer(); - return player == null ? null : player.getType(); - } - - public String getUsername() { - Player player = transferStatus.getPlayer(); - return player == null ? null : player.getUsername(); - } - - public String getPath() { - return FileUtil.getShortPath(transferStatus.getFile()); - } - - public String getBytes() { - return StringUtil.formatBytes(transferStatus.getBytesTransfered(), locale); - } - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java deleted file mode 100644 index a40f5da4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.awt.Dimension; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.SearchService; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.math.LongRange; -import org.springframework.web.bind.ServletRequestBindingException; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.VideoTranscodingSettings; -import net.sourceforge.subsonic.io.PlayQueueInputStream; -import net.sourceforge.subsonic.io.RangeOutputStream; -import net.sourceforge.subsonic.io.ShoutCastOutputStream; -import net.sourceforge.subsonic.service.AudioScrobblerService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.PlaylistService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.StatusService; -import net.sourceforge.subsonic.service.TranscodingService; -import net.sourceforge.subsonic.util.StringUtil; -import net.sourceforge.subsonic.util.Util; - -/** - * A controller which streams the content of a {@link net.sourceforge.subsonic.domain.PlayQueue} to a remote - * {@link Player}. - * - * @author Sindre Mehus - */ -public class StreamController implements Controller { - - private static final Logger LOG = Logger.getLogger(StreamController.class); - - private StatusService statusService; - private PlayerService playerService; - private PlaylistService playlistService; - private SecurityService securityService; - private SettingsService settingsService; - private TranscodingService transcodingService; - private AudioScrobblerService audioScrobblerService; - private MediaFileService mediaFileService; - private SearchService searchService; - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - - TransferStatus status = null; - PlayQueueInputStream in = null; - Player player = playerService.getPlayer(request, response, false, true); - User user = securityService.getUserByName(player.getUsername()); - - try { - - if (!user.isStreamRole()) { - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Streaming is forbidden for user " + user.getUsername()); - return null; - } - - // If "playlist" request parameter is set, this is a Podcast request. In that case, create a separate - // play queue (in order to support multiple parallel Podcast streams). - Integer playlistId = ServletRequestUtils.getIntParameter(request, "playlist"); - boolean isPodcast = playlistId != null; - if (isPodcast) { - PlayQueue playQueue = new PlayQueue(); - playQueue.addFiles(false, playlistService.getFilesInPlaylist(playlistId)); - player.setPlayQueue(playQueue); - Util.setContentLength(response, playQueue.length()); - LOG.info("Incoming Podcast request for playlist " + playlistId); - } - - String contentType = StringUtil.getMimeType(request.getParameter("suffix")); - response.setContentType(contentType); - - String preferredTargetFormat = request.getParameter("format"); - Integer maxBitRate = ServletRequestUtils.getIntParameter(request, "maxBitRate"); - if (Integer.valueOf(0).equals(maxBitRate)) { - maxBitRate = null; - } - - VideoTranscodingSettings videoTranscodingSettings = null; - - // Is this a request for a single file (typically from the embedded Flash player)? - // In that case, create a separate playlist (in order to support multiple parallel streams). - // Also, enable partial download (HTTP byte range). - MediaFile file = getSingleFile(request); - boolean isSingleFile = file != null; - LongRange range = null; - - if (isSingleFile) { - PlayQueue playQueue = new PlayQueue(); - playQueue.addFiles(true, file); - player.setPlayQueue(playQueue); - - if (!file.isVideo()) { - response.setIntHeader("ETag", file.getId()); - response.setHeader("Accept-Ranges", "bytes"); - } - - TranscodingService.Parameters parameters = transcodingService.getParameters(file, player, maxBitRate, preferredTargetFormat, videoTranscodingSettings); - long fileLength = getFileLength(parameters); - boolean isConversion = parameters.isDownsample() || parameters.isTranscode(); - boolean estimateContentLength = ServletRequestUtils.getBooleanParameter(request, "estimateContentLength", false); - - range = getRange(request, file); - if (range != null) { - LOG.info("Got range: " + range); - response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); - Util.setContentLength(response, fileLength - range.getMinimumLong()); - long firstBytePos = range.getMinimumLong(); - long lastBytePos = fileLength - 1; - response.setHeader("Content-Range", "bytes " + firstBytePos + "-" + lastBytePos + "/" + fileLength); - } else if (!isConversion || estimateContentLength) { - Util.setContentLength(response, fileLength); - } - - String transcodedSuffix = transcodingService.getSuffix(player, file, preferredTargetFormat); - response.setContentType(StringUtil.getMimeType(transcodedSuffix)); - - if (file.isVideo()) { - videoTranscodingSettings = createVideoTranscodingSettings(file, request); - } - } - - if (request.getMethod().equals("HEAD")) { - return null; - } - - // Terminate any other streams to this player. - if (!isPodcast && !isSingleFile) { - for (TransferStatus streamStatus : statusService.getStreamStatusesForPlayer(player)) { - if (streamStatus.isActive()) { - streamStatus.terminate(); - } - } - } - - status = statusService.createStreamStatus(player); - - in = new PlayQueueInputStream(player, status, maxBitRate, preferredTargetFormat, videoTranscodingSettings, transcodingService, - audioScrobblerService, mediaFileService, searchService); - OutputStream out = RangeOutputStream.wrap(response.getOutputStream(), range); - - // Enabled SHOUTcast, if requested. - boolean isShoutCastRequested = "1".equals(request.getHeader("icy-metadata")); - if (isShoutCastRequested && !isSingleFile) { - response.setHeader("icy-metaint", "" + ShoutCastOutputStream.META_DATA_INTERVAL); - response.setHeader("icy-notice1", "This stream is served using Subsonic"); - response.setHeader("icy-notice2", "Subsonic - Free media streamer - subsonic.org"); - response.setHeader("icy-name", "Subsonic"); - response.setHeader("icy-genre", "Mixed"); - response.setHeader("icy-url", "http://subsonic.org/"); - out = new ShoutCastOutputStream(out, player.getPlayQueue(), settingsService); - } - - final int BUFFER_SIZE = 2048; - byte[] buf = new byte[BUFFER_SIZE]; - - while (true) { - - // Check if stream has been terminated. - if (status.terminated()) { - return null; - } - - if (player.getPlayQueue().getStatus() == PlayQueue.Status.STOPPED) { - if (isPodcast || isSingleFile) { - break; - } else { - sendDummy(buf, out); - } - } else { - - int n = in.read(buf); - if (n == -1) { - if (isPodcast || isSingleFile) { - break; - } else { - sendDummy(buf, out); - } - } else { - out.write(buf, 0, n); - } - } - } - - } finally { - if (status != null) { - securityService.updateUserByteCounts(user, status.getBytesTransfered(), 0L, 0L); - statusService.removeStreamStatus(status); - } - IOUtils.closeQuietly(in); - } - return null; - } - - private MediaFile getSingleFile(HttpServletRequest request) throws ServletRequestBindingException { - String path = request.getParameter("path"); - if (path != null) { - return mediaFileService.getMediaFile(path); - } - Integer id = ServletRequestUtils.getIntParameter(request, "id"); - if (id != null) { - return mediaFileService.getMediaFile(id); - } - return null; - } - - private long getFileLength(TranscodingService.Parameters parameters) { - MediaFile file = parameters.getMediaFile(); - - if (!parameters.isDownsample() && !parameters.isTranscode()) { - return file.getFileSize(); - } - Integer duration = file.getDurationSeconds(); - Integer maxBitRate = parameters.getMaxBitRate(); - - if (duration == null) { - LOG.warn("Unknown duration for " + file + ". Unable to estimate transcoded size."); - return file.getFileSize(); - } - - if (maxBitRate == null) { - LOG.error("Unknown bit rate for " + file + ". Unable to estimate transcoded size."); - return file.getFileSize(); - } - - return duration * maxBitRate * 1000L / 8L; - } - - private LongRange getRange(HttpServletRequest request, MediaFile file) { - - // First, look for "Range" HTTP header. - LongRange range = StringUtil.parseRange(request.getHeader("Range")); - if (range != null) { - return range; - } - - // Second, look for "offsetSeconds" request parameter. - String offsetSeconds = request.getParameter("offsetSeconds"); - range = parseAndConvertOffsetSeconds(offsetSeconds, file); - if (range != null) { - return range; - } - - return null; - } - - private LongRange parseAndConvertOffsetSeconds(String offsetSeconds, MediaFile file) { - if (offsetSeconds == null) { - return null; - } - - try { - Integer duration = file.getDurationSeconds(); - Long fileSize = file.getFileSize(); - if (duration == null || fileSize == null) { - return null; - } - float offset = Float.parseFloat(offsetSeconds); - - // Convert from time offset to byte offset. - long byteOffset = (long) (fileSize * (offset / duration)); - return new LongRange(byteOffset, Long.MAX_VALUE); - - } catch (Exception x) { - LOG.error("Failed to parse and convert time offset: " + offsetSeconds, x); - return null; - } - } - - private VideoTranscodingSettings createVideoTranscodingSettings(MediaFile file, HttpServletRequest request) throws ServletRequestBindingException { - Integer existingWidth = file.getWidth(); - Integer existingHeight = file.getHeight(); - Integer maxBitRate = ServletRequestUtils.getIntParameter(request, "maxBitRate"); - int timeOffset = ServletRequestUtils.getIntParameter(request, "timeOffset", 0); - - Dimension dim = getRequestedVideoSize(request.getParameter("size")); - if (dim == null) { - dim = getSuitableVideoSize(existingWidth, existingHeight, maxBitRate); - } - - return new VideoTranscodingSettings(dim.width, dim.height, timeOffset); - } - - protected Dimension getRequestedVideoSize(String sizeSpec) { - if (sizeSpec == null) { - return null; - } - - Pattern pattern = Pattern.compile("^(\\d+)x(\\d+)$"); - Matcher matcher = pattern.matcher(sizeSpec); - if (matcher.find()) { - int w = Integer.parseInt(matcher.group(1)); - int h = Integer.parseInt(matcher.group(2)); - if (w >= 0 && h >= 0 && w <= 2000 && h <= 2000) { - return new Dimension(w, h); - } - } - return null; - } - - protected Dimension getSuitableVideoSize(Integer existingWidth, Integer existingHeight, Integer maxBitRate) { - if (maxBitRate == null) { - return new Dimension(320, 240); - } - - int w, h; - if (maxBitRate <= 600) { - w = 320; h = 240; - } else if (maxBitRate <= 1000) { - w = 480; h = 360; - } else { - w = 640; h = 480; - } - - if (existingWidth == null || existingHeight == null) { - return new Dimension(w, h); - } - - if (existingWidth < w || existingHeight < h) { - return new Dimension(even(existingWidth), even(existingHeight)); - } - - double aspectRate = existingWidth.doubleValue() / existingHeight.doubleValue(); - w = (int) Math.round(h * aspectRate); - - return new Dimension(even(w), even(h)); - } - - // Make sure width and height are multiples of two, as some versions of ffmpeg require it. - private int even(int size) { - return size + (size % 2); - } - - /** - * Feed the other end with some dummy data to keep it from reconnecting. - */ - private void sendDummy(byte[] buf, OutputStream out) throws IOException { - try { - Thread.sleep(2000); - } catch (InterruptedException x) { - LOG.warn("Interrupted in sleep.", x); - } - Arrays.fill(buf, (byte) 0xFF); - out.write(buf); - out.flush(); - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } - - public void setAudioScrobblerService(AudioScrobblerService audioScrobblerService) { - this.audioScrobblerService = audioScrobblerService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setSearchService(SearchService searchService) { - this.searchService = searchService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/TopController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/TopController.java deleted file mode 100644 index 800aef0e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/TopController.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.VersionService; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Controller for the top frame. - * - * @author Sindre Mehus - */ -public class TopController extends ParameterizableViewController { - - private SettingsService settingsService; - private VersionService versionService; - private SecurityService securityService; - - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - - List allMusicFolders = settingsService.getAllMusicFolders(); - User user = securityService.getCurrentUser(request); - - map.put("user", user); - map.put("musicFoldersExist", !allMusicFolders.isEmpty()); - map.put("brand", settingsService.getBrand()); - map.put("licensed", settingsService.isLicenseValid()); - - UserSettings userSettings = settingsService.getUserSettings(user.getUsername()); - if (userSettings.isFinalVersionNotificationEnabled() && versionService.isNewFinalVersionAvailable()) { - map.put("newVersionAvailable", true); - map.put("latestVersion", versionService.getLatestFinalVersion()); - - } else if (userSettings.isBetaVersionNotificationEnabled() && versionService.isNewBetaVersionAvailable()) { - map.put("newVersionAvailable", true); - map.put("latestVersion", versionService.getLatestBetaVersion()); - } - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setVersionService(VersionService versionService) { - this.versionService = versionService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/TranscodingSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/TranscodingSettingsController.java deleted file mode 100644 index 8bd87408..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/TranscodingSettingsController.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.Transcoding; -import net.sourceforge.subsonic.service.TranscodingService; -import net.sourceforge.subsonic.service.SettingsService; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.Map; - -/** - * Controller for the page used to administrate the set of transcoding configurations. - * - * @author Sindre Mehus - */ -public class TranscodingSettingsController extends ParameterizableViewController { - - private TranscodingService transcodingService; - private SettingsService settingsService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - - if (isFormSubmission(request)) { - handleParameters(request, map); - } - - ModelAndView result = super.handleRequestInternal(request, response); - map.put("transcodings", transcodingService.getAllTranscodings()); - map.put("transcodeDirectory", transcodingService.getTranscodeDirectory()); - map.put("brand", settingsService.getBrand()); - - result.addObject("model", map); - return result; - } - - /** - * Determine if the given request represents a form submission. - * - * @param request current HTTP request - * @return if the request represents a form submission - */ - private boolean isFormSubmission(HttpServletRequest request) { - return "POST".equals(request.getMethod()); - } - - private void handleParameters(HttpServletRequest request, Map map) { - - for (Transcoding transcoding : transcodingService.getAllTranscodings()) { - Integer id = transcoding.getId(); - String name = getParameter(request, "name", id); - String sourceFormats = getParameter(request, "sourceFormats", id); - String targetFormat = getParameter(request, "targetFormat", id); - String step1 = getParameter(request, "step1", id); - String step2 = getParameter(request, "step2", id); - boolean delete = getParameter(request, "delete", id) != null; - - if (delete) { - transcodingService.deleteTranscoding(id); - } else if (name == null) { - map.put("error", "transcodingsettings.noname"); - } else if (sourceFormats == null) { - map.put("error", "transcodingsettings.nosourceformat"); - } else if (targetFormat == null) { - map.put("error", "transcodingsettings.notargetformat"); - } else if (step1 == null) { - map.put("error", "transcodingsettings.nostep1"); - } else { - transcoding.setName(name); - transcoding.setSourceFormats(sourceFormats); - transcoding.setTargetFormat(targetFormat); - transcoding.setStep1(step1); - transcoding.setStep2(step2); - transcodingService.updateTranscoding(transcoding); - } - } - - String name = StringUtils.trimToNull(request.getParameter("name")); - String sourceFormats = StringUtils.trimToNull(request.getParameter("sourceFormats")); - String targetFormat = StringUtils.trimToNull(request.getParameter("targetFormat")); - String step1 = StringUtils.trimToNull(request.getParameter("step1")); - String step2 = StringUtils.trimToNull(request.getParameter("step2")); - boolean defaultActive = request.getParameter("defaultActive") != null; - - if (name != null || sourceFormats != null || targetFormat != null || step1 != null || step2 != null) { - Transcoding transcoding = new Transcoding(null, name, sourceFormats, targetFormat, step1, step2, null, defaultActive); - if (name == null) { - map.put("error", "transcodingsettings.noname"); - } else if (sourceFormats == null) { - map.put("error", "transcodingsettings.nosourceformat"); - } else if (targetFormat == null) { - map.put("error", "transcodingsettings.notargetformat"); - } else if (step1 == null) { - map.put("error", "transcodingsettings.nostep1"); - } else { - transcodingService.createTranscoding(transcoding); - } - if (map.containsKey("error")) { - map.put("newTranscoding", transcoding); - } - } - } - - private String getParameter(HttpServletRequest request, String name, Integer id) { - return StringUtils.trimToNull(request.getParameter(name + "[" + id + "]")); - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UploadController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UploadController.java deleted file mode 100644 index de7bf8dd..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UploadController.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.*; -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.upload.*; -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.util.*; -import org.apache.commons.fileupload.*; -import org.apache.commons.fileupload.servlet.*; -import org.apache.commons.io.*; -import org.apache.tools.zip.*; -import org.springframework.web.servlet.*; -import org.springframework.web.servlet.mvc.*; - -import javax.servlet.http.*; -import java.io.*; -import java.util.*; - -/** - * Controller which receives uploaded files. - * - * @author Sindre Mehus - */ -public class UploadController extends ParameterizableViewController { - - private static final Logger LOG = Logger.getLogger(UploadController.class); - - private SecurityService securityService; - private PlayerService playerService; - private StatusService statusService; - private SettingsService settingsService; - public static final String UPLOAD_STATUS = "uploadStatus"; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - List uploadedFiles = new ArrayList(); - List unzippedFiles = new ArrayList(); - TransferStatus status = null; - - try { - - status = statusService.createUploadStatus(playerService.getPlayer(request, response, false, false)); - status.setBytesTotal(request.getContentLength()); - - request.getSession().setAttribute(UPLOAD_STATUS, status); - - // Check that we have a file upload request - if (!ServletFileUpload.isMultipartContent(request)) { - throw new Exception("Illegal request."); - } - - File dir = null; - boolean unzip = false; - - UploadListener listener = new UploadListenerImpl(status); - - FileItemFactory factory = new MonitoredDiskFileItemFactory(listener); - ServletFileUpload upload = new ServletFileUpload(factory); - - List items = upload.parseRequest(request); - - // First, look for "dir" and "unzip" parameters. - for (Object o : items) { - FileItem item = (FileItem) o; - - if (item.isFormField() && "dir".equals(item.getFieldName())) { - dir = new File(item.getString()); - } else if (item.isFormField() && "unzip".equals(item.getFieldName())) { - unzip = true; - } - } - - if (dir == null) { - throw new Exception("Missing 'dir' parameter."); - } - - // Look for file items. - for (Object o : items) { - FileItem item = (FileItem) o; - - if (!item.isFormField()) { - String fileName = item.getName(); - if (fileName.trim().length() > 0) { - - File targetFile = new File(dir, new File(fileName).getName()); - - if (!securityService.isUploadAllowed(targetFile)) { - throw new Exception("Permission denied: " + StringUtil.toHtml(targetFile.getPath())); - } - - if (!dir.exists()) { - dir.mkdirs(); - } - - item.write(targetFile); - uploadedFiles.add(targetFile); - LOG.info("Uploaded " + targetFile); - - if (unzip && targetFile.getName().toLowerCase().endsWith(".zip")) { - unzip(targetFile, unzippedFiles); - } - } - } - } - - } catch (Exception x) { - LOG.warn("Uploading failed.", x); - map.put("exception", x); - } finally { - if (status != null) { - statusService.removeUploadStatus(status); - request.getSession().removeAttribute(UPLOAD_STATUS); - User user = securityService.getCurrentUser(request); - securityService.updateUserByteCounts(user, 0L, 0L, status.getBytesTransfered()); - } - } - - map.put("uploadedFiles", uploadedFiles); - map.put("unzippedFiles", unzippedFiles); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - private void unzip(File file, List unzippedFiles) throws Exception { - LOG.info("Unzipping " + file); - - ZipFile zipFile = new ZipFile(file); - - try { - - Enumeration entries = zipFile.getEntries(); - - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - File entryFile = new File(file.getParentFile(), entry.getName()); - - if (!entry.isDirectory()) { - - if (!securityService.isUploadAllowed(entryFile)) { - throw new Exception("Permission denied: " + StringUtil.toHtml(entryFile.getPath())); - } - - entryFile.getParentFile().mkdirs(); - InputStream inputStream = null; - OutputStream outputStream = null; - try { - inputStream = zipFile.getInputStream(entry); - outputStream = new FileOutputStream(entryFile); - - byte[] buf = new byte[8192]; - while (true) { - int n = inputStream.read(buf); - if (n == -1) { - break; - } - outputStream.write(buf, 0, n); - } - - LOG.info("Unzipped " + entryFile); - unzippedFiles.add(entryFile); - } finally { - IOUtils.closeQuietly(inputStream); - IOUtils.closeQuietly(outputStream); - } - } - } - - zipFile.close(); - file.delete(); - - } finally { - zipFile.close(); - } - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - /** - * Receives callbacks as the file upload progresses. - */ - private class UploadListenerImpl implements UploadListener { - private TransferStatus status; - private long start; - - private UploadListenerImpl(TransferStatus status) { - this.status = status; - start = System.currentTimeMillis(); - } - - public void start(String fileName) { - status.setFile(new File(fileName)); - } - - public void bytesRead(long bytesRead) { - - // Throttle bitrate. - - long byteCount = status.getBytesTransfered() + bytesRead; - long bitCount = byteCount * 8L; - - float elapsedMillis = Math.max(1, System.currentTimeMillis() - start); - float elapsedSeconds = elapsedMillis / 1000.0F; - long maxBitsPerSecond = getBitrateLimit(); - - status.setBytesTransfered(byteCount); - - if (maxBitsPerSecond > 0) { - float sleepMillis = 1000.0F * (bitCount / maxBitsPerSecond - elapsedSeconds); - if (sleepMillis > 0) { - try { - Thread.sleep((long) sleepMillis); - } catch (InterruptedException x) { - LOG.warn("Failed to sleep.", x); - } - } - } - } - - private long getBitrateLimit() { - return 1024L * settingsService.getUploadBitrateLimit() / Math.max(1, statusService.getAllUploadStatuses().size()); - } - } - -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UserChartController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UserChartController.java deleted file mode 100644 index 0428eff8..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UserChartController.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.awt.Color; -import java.awt.GradientPaint; -import java.awt.Paint; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartUtilities; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.AxisLocation; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.LogarithmicAxis; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.BarRenderer; -import org.jfree.data.category.CategoryDataset; -import org.jfree.data.category.DefaultCategoryDataset; -import org.springframework.web.servlet.ModelAndView; - -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.service.SecurityService; - -/** - * Controller for generating a chart showing bitrate vs time. - * - * @author Sindre Mehus - */ -public class UserChartController extends AbstractChartController { - - private SecurityService securityService; - - public static final int IMAGE_WIDTH = 400; - public static final int IMAGE_MIN_HEIGHT = 200; - private static final long BYTES_PER_MB = 1024L * 1024L; - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - String type = request.getParameter("type"); - CategoryDataset dataset = createDataset(type); - JFreeChart chart = createChart(dataset, request); - - int imageHeight = Math.max(IMAGE_MIN_HEIGHT, 15 * dataset.getColumnCount()); - - ChartUtilities.writeChartAsPNG(response.getOutputStream(), chart, IMAGE_WIDTH, imageHeight); - return null; - } - - private CategoryDataset createDataset(String type) { - DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - List users = securityService.getAllUsers(); - for (User user : users) { - double value; - if ("stream".equals(type)) { - value = user.getBytesStreamed(); - } else if ("download".equals(type)) { - value = user.getBytesDownloaded(); - } else if ("upload".equals(type)) { - value = user.getBytesUploaded(); - } else if ("total".equals(type)) { - value = user.getBytesStreamed() + user.getBytesDownloaded() + user.getBytesUploaded(); - } else { - throw new RuntimeException("Illegal chart type: " + type); - } - - value /= BYTES_PER_MB; - dataset.addValue(value, "Series", user.getUsername()); - } - - return dataset; - } - - private JFreeChart createChart(CategoryDataset dataset, HttpServletRequest request) { - JFreeChart chart = ChartFactory.createBarChart(null, null, null, dataset, PlotOrientation.HORIZONTAL, false, false, false); - - CategoryPlot plot = chart.getCategoryPlot(); - Paint background = new GradientPaint(0, 0, Color.lightGray, 0, IMAGE_MIN_HEIGHT, Color.white); - plot.setBackgroundPaint(background); - plot.setDomainGridlinePaint(Color.white); - plot.setDomainGridlinesVisible(true); - plot.setRangeGridlinePaint(Color.white); - plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT); - - LogarithmicAxis rangeAxis = new LogarithmicAxis(null); - rangeAxis.setStrictValuesFlag(false); - rangeAxis.setAllowNegativesFlag(true); - plot.setRangeAxis(rangeAxis); - - // Disable bar outlines. - BarRenderer renderer = (BarRenderer) plot.getRenderer(); - renderer.setDrawBarOutline(false); - - // Set up gradient paint for series. - GradientPaint gp0 = new GradientPaint( - 0.0f, 0.0f, Color.blue, - 0.0f, 0.0f, new Color(0, 0, 64) - ); - renderer.setSeriesPaint(0, gp0); - - // Rotate labels. - CategoryAxis domainAxis = plot.getDomainAxis(); - domainAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0)); - - // Set theme-specific colors. - Color bgColor = getBackground(request); - Color fgColor = getForeground(request); - - chart.setBackgroundPaint(bgColor); - - domainAxis.setTickLabelPaint(fgColor); - domainAxis.setTickMarkPaint(fgColor); - domainAxis.setAxisLinePaint(fgColor); - - rangeAxis.setTickLabelPaint(fgColor); - rangeAxis.setTickMarkPaint(fgColor); - rangeAxis.setAxisLinePaint(fgColor); - - return chart; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UserSettingsController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UserSettingsController.java deleted file mode 100644 index 58848840..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/UserSettingsController.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.util.List; -import java.util.Date; - -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.command.*; -import org.springframework.web.servlet.mvc.*; -import org.springframework.web.bind.*; -import org.apache.commons.lang.StringUtils; - -import javax.servlet.http.*; - -/** - * Controller for the page used to administrate users. - * - * @author Sindre Mehus - */ -public class UserSettingsController extends SimpleFormController { - - private SecurityService securityService; - private SettingsService settingsService; - private TranscodingService transcodingService; - - @Override - protected Object formBackingObject(HttpServletRequest request) throws Exception { - UserSettingsCommand command = new UserSettingsCommand(); - - User user = getUser(request); - if (user != null) { - command.setUser(user); - command.setEmail(user.getEmail()); - command.setAdmin(User.USERNAME_ADMIN.equals(user.getUsername())); - UserSettings userSettings = settingsService.getUserSettings(user.getUsername()); - command.setTranscodeSchemeName(userSettings.getTranscodeScheme().name()); - - } else { - command.setNew(true); - command.setStreamRole(true); - command.setSettingsRole(true); - } - - command.setUsers(securityService.getAllUsers()); - command.setTranscodingSupported(transcodingService.isDownsamplingSupported(null)); - command.setTranscodeDirectory(transcodingService.getTranscodeDirectory().getPath()); - command.setTranscodeSchemes(TranscodeScheme.values()); - command.setLdapEnabled(settingsService.isLdapEnabled()); - - return command; - } - - private User getUser(HttpServletRequest request) throws ServletRequestBindingException { - Integer userIndex = ServletRequestUtils.getIntParameter(request, "userIndex"); - if (userIndex != null) { - List allUsers = securityService.getAllUsers(); - if (userIndex >= 0 && userIndex < allUsers.size()) { - return allUsers.get(userIndex); - } - } - return null; - } - - @Override - protected void doSubmitAction(Object comm) throws Exception { - UserSettingsCommand command = (UserSettingsCommand) comm; - - if (command.isDelete()) { - deleteUser(command); - } else if (command.isNew()) { - createUser(command); - } else { - updateUser(command); - } - resetCommand(command); - } - - private void deleteUser(UserSettingsCommand command) { - securityService.deleteUser(command.getUsername()); - } - - public void createUser(UserSettingsCommand command) { - User user = new User(command.getUsername(), command.getPassword(), StringUtils.trimToNull(command.getEmail())); - user.setLdapAuthenticated(command.isLdapAuthenticated()); - securityService.createUser(user); - updateUser(command); - } - - private void updateUser(UserSettingsCommand command) { - User user = securityService.getUserByName(command.getUsername()); - user.setEmail(StringUtils.trimToNull(command.getEmail())); - user.setLdapAuthenticated(command.isLdapAuthenticated()); - user.setAdminRole(command.isAdminRole()); - user.setDownloadRole(command.isDownloadRole()); - user.setUploadRole(command.isUploadRole()); - user.setCoverArtRole(command.isCoverArtRole()); - user.setCommentRole(command.isCommentRole()); - user.setPodcastRole(command.isPodcastRole()); - user.setStreamRole(command.isStreamRole()); - user.setJukeboxRole(command.isJukeboxRole()); - user.setSettingsRole(command.isSettingsRole()); - user.setShareRole(command.isShareRole()); - - if (command.isPasswordChange()) { - user.setPassword(command.getPassword()); - } - - securityService.updateUser(user); - - UserSettings userSettings = settingsService.getUserSettings(command.getUsername()); - userSettings.setTranscodeScheme(TranscodeScheme.valueOf(command.getTranscodeSchemeName())); - userSettings.setChanged(new Date()); - settingsService.updateUserSettings(userSettings); - } - - private void resetCommand(UserSettingsCommand command) { - command.setUser(null); - command.setUsers(securityService.getAllUsers()); - command.setDelete(false); - command.setPasswordChange(false); - command.setNew(true); - command.setStreamRole(true); - command.setSettingsRole(true); - command.setPassword(null); - command.setConfirmPassword(null); - command.setEmail(null); - command.setTranscodeSchemeName(null); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/VideoPlayerController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/VideoPlayerController.java deleted file mode 100644 index 1d7686eb..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/VideoPlayerController.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.util.StringUtil; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.ParameterizableViewController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Controller for the page used to play videos. - * - * @author Sindre Mehus - */ -public class VideoPlayerController extends ParameterizableViewController { - - public static final int DEFAULT_BIT_RATE = 1000; - public static final int[] BIT_RATES = {200, 300, 400, 500, 700, 1000, 1200, 1500, 2000, 3000, 5000}; - private static final long TRIAL_DAYS = 30L; - - private MediaFileService mediaFileService; - private SettingsService settingsService; - private PlayerService playerService; - - @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - int id = ServletRequestUtils.getRequiredIntParameter(request, "id"); - MediaFile file = mediaFileService.getMediaFile(id); - - int timeOffset = ServletRequestUtils.getIntParameter(request, "timeOffset", 0); - timeOffset = Math.max(0, timeOffset); - Integer duration = file.getDurationSeconds(); - if (duration != null) { - map.put("skipOffsets", createSkipOffsets(duration)); - timeOffset = Math.min(duration, timeOffset); - duration -= timeOffset; - } - - map.put("video", file); - map.put("player", playerService.getPlayer(request, response).getId()); - map.put("maxBitRate", ServletRequestUtils.getIntParameter(request, "maxBitRate", DEFAULT_BIT_RATE)); - map.put("popout", ServletRequestUtils.getBooleanParameter(request, "popout", false)); - map.put("duration", duration); - map.put("timeOffset", timeOffset); - map.put("bitRates", BIT_RATES); - - if (!settingsService.isLicenseValid() && settingsService.getVideoTrialExpires() == null) { - Date expiryDate = new Date(System.currentTimeMillis() + TRIAL_DAYS * 24L * 3600L * 1000L); - settingsService.setVideoTrialExpires(expiryDate); - settingsService.save(); - } - Date trialExpires = settingsService.getVideoTrialExpires(); - map.put("trialExpires", trialExpires); - map.put("trialExpired", trialExpires != null && trialExpires.before(new Date())); - map.put("trial", trialExpires != null && !settingsService.isLicenseValid()); - - ModelAndView result = super.handleRequestInternal(request, response); - result.addObject("model", map); - return result; - } - - public static Map createSkipOffsets(int durationSeconds) { - LinkedHashMap result = new LinkedHashMap(); - for (int i = 0; i < durationSeconds; i += 60) { - result.put(StringUtil.formatDuration(i), i); - } - return result; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/WapController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/WapController.java deleted file mode 100644 index 02509687..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/WapController.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.SortedSet; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.multiaction.MultiActionController; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.MusicIndex; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.RandomSearchCriteria; -import net.sourceforge.subsonic.domain.SearchCriteria; -import net.sourceforge.subsonic.domain.SearchResult; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.service.SearchService; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.MusicIndexService; -import net.sourceforge.subsonic.service.PlayerService; -import net.sourceforge.subsonic.service.PlaylistService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; - -/** - * Multi-controller used for wap pages. - * - * @author Sindre Mehus - */ -public class WapController extends MultiActionController { - - private SettingsService settingsService; - private PlayerService playerService; - private PlaylistService playlistService; - private SecurityService securityService; - private MusicIndexService musicIndexService; - private MediaFileService mediaFileService; - private SearchService searchService; - - public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception { - return wap(request, response); - } - - public ModelAndView wap(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - List folders = settingsService.getAllMusicFolders(); - - if (folders.isEmpty()) { - map.put("noMusic", true); - } else { - - SortedMap> allArtists = musicIndexService.getIndexedArtists(folders); - - // If an index is given as parameter, only show music files for this index. - String index = request.getParameter("index"); - if (index != null) { - SortedSet artists = allArtists.get(new MusicIndex(index)); - if (artists == null) { - map.put("noMusic", true); - } else { - map.put("artists", artists); - } - } - - // Otherwise, list all indexes. - else { - map.put("indexes", allArtists.keySet()); - } - } - - return new ModelAndView("wap/index", "model", map); - } - - public ModelAndView browse(HttpServletRequest request, HttpServletResponse response) throws Exception { - String path = request.getParameter("path"); - MediaFile parent = mediaFileService.getMediaFile(path); - - // Create array of file(s) to display. - List children; - if (parent.isDirectory()) { - children = mediaFileService.getChildrenOf(parent, true, true, true); - } else { - children = new ArrayList(); - children.add(parent); - } - - Map map = new HashMap(); - map.put("parent", parent); - map.put("children", children); - map.put("user", securityService.getCurrentUser(request)); - - return new ModelAndView("wap/browse", "model", map); - } - - public ModelAndView playlist(HttpServletRequest request, HttpServletResponse response) throws Exception { - // Create array of players to control. If the "player" attribute is set for this session, - // only the player with this ID is controlled. Otherwise, all players are controlled. - List players = playerService.getAllPlayers(); - - String playerId = (String) request.getSession().getAttribute("player"); - if (playerId != null) { - Player player = playerService.getPlayerById(playerId); - if (player != null) { - players = Arrays.asList(player); - } - } - - Map map = new HashMap(); - - for (Player player : players) { - PlayQueue playQueue = player.getPlayQueue(); - map.put("playlist", playQueue); - - if (request.getParameter("play") != null) { - MediaFile file = mediaFileService.getMediaFile(request.getParameter("play")); - playQueue.addFiles(false, file); - } else if (request.getParameter("add") != null) { - MediaFile file = mediaFileService.getMediaFile(request.getParameter("add")); - playQueue.addFiles(true, file); - } else if (request.getParameter("skip") != null) { - playQueue.setIndex(Integer.parseInt(request.getParameter("skip"))); - } else if (request.getParameter("clear") != null) { - playQueue.clear(); - } else if (request.getParameter("load") != null) { - List songs = playlistService.getFilesInPlaylist(ServletRequestUtils.getIntParameter(request, "id")); - playQueue.addFiles(false, songs); - } else if (request.getParameter("random") != null) { - List randomFiles = searchService.getRandomSongs(new RandomSearchCriteria(20, null, null, null, null)); - playQueue.addFiles(false, randomFiles); - } - } - - map.put("players", players); - return new ModelAndView("wap/playlist", "model", map); - } - - public ModelAndView loadPlaylist(HttpServletRequest request, HttpServletResponse response) throws Exception { - Map map = new HashMap(); - map.put("playlists", playlistService.getReadablePlaylistsForUser(securityService.getCurrentUsername(request))); - return new ModelAndView("wap/loadPlaylist", "model", map); - } - - public ModelAndView search(HttpServletRequest request, HttpServletResponse response) throws Exception { - return new ModelAndView("wap/search"); - } - - public ModelAndView searchResult(HttpServletRequest request, HttpServletResponse response) throws Exception { - String query = request.getParameter("query"); - - Map map = new HashMap(); - map.put("hits", search(query)); - - return new ModelAndView("wap/searchResult", "model", map); - } - - public ModelAndView settings(HttpServletRequest request, HttpServletResponse response) throws Exception { - String playerId = (String) request.getSession().getAttribute("player"); - - List allPlayers = playerService.getAllPlayers(); - User user = securityService.getCurrentUser(request); - List players = new ArrayList(); - Map map = new HashMap(); - - for (Player player : allPlayers) { - // Only display authorized players. - if (user.isAdminRole() || user.getUsername().equals(player.getUsername())) { - players.add(player); - } - - } - map.put("playerId", playerId); - map.put("players", players); - return new ModelAndView("wap/settings", "model", map); - } - - public ModelAndView selectPlayer(HttpServletRequest request, HttpServletResponse response) throws Exception { - request.getSession().setAttribute("player", request.getParameter("playerId")); - return settings(request, response); - } - - private List search(String query) throws IOException { - SearchCriteria criteria = new SearchCriteria(); - criteria.setQuery(query); - criteria.setOffset(0); - criteria.setCount(50); - - SearchResult result = searchService.search(criteria, SearchService.IndexType.SONG); - return result.getMediaFiles(); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public void setPlaylistService(PlaylistService playlistService) { - this.playlistService = playlistService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMusicIndexService(MusicIndexService musicIndexService) { - this.musicIndexService = musicIndexService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setSearchService(SearchService searchService) { - this.searchService = searchService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AbstractDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AbstractDao.java deleted file mode 100644 index de17f4d4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AbstractDao.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import java.util.Date; -import java.util.List; - -import org.springframework.jdbc.core.*; - -import net.sourceforge.subsonic.Logger; - -/** - * Abstract superclass for all DAO's. - * - * @author Sindre Mehus - */ -public class AbstractDao { - private static final Logger LOG = Logger.getLogger(AbstractDao.class); - - private DaoHelper daoHelper; - - /** - * Returns a JDBC template for performing database operations. - * @return A JDBC template. - */ - public JdbcTemplate getJdbcTemplate() { - return daoHelper.getJdbcTemplate(); - } - - protected String questionMarks(String columns) { - int count = columns.split(", ").length; - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < count; i++) { - builder.append('?'); - if (i < count - 1) { - builder.append(", "); - } - } - return builder.toString(); - } - - protected String prefix(String columns, String prefix) { - StringBuilder builder = new StringBuilder(); - for (String s : columns.split(", ")) { - builder.append(prefix).append(".").append(s).append(","); - } - if (builder.length() > 0) { - builder.setLength(builder.length() - 1); - } - return builder.toString(); - } - - protected int update(String sql, Object... args) { - long t = System.nanoTime(); - int result = getJdbcTemplate().update(sql, args); - log(sql, t); - return result; - } - - private void log(String sql, long startTimeNano) { -// long micros = (System.nanoTime() - startTimeNano) / 1000L; -// LOG.debug(micros + " " + sql); - } - - protected List query(String sql, RowMapper rowMapper, Object... args) { - long t = System.nanoTime(); - List result = getJdbcTemplate().query(sql, args, rowMapper); - log(sql, t); - return result; - } - - protected List queryForStrings(String sql, Object... args) { - long t = System.nanoTime(); - List result = getJdbcTemplate().queryForList(sql, args, String.class); - log(sql, t); - return result; - } - - protected Integer queryForInt(String sql, Integer defaultValue, Object... args) { - long t = System.nanoTime(); - List list = getJdbcTemplate().queryForList(sql, args, Integer.class); - Integer result = list.isEmpty() ? defaultValue : list.get(0) == null ? defaultValue : list.get(0); - log(sql, t); - return result; - } - - protected Date queryForDate(String sql, Date defaultValue, Object... args) { - long t = System.nanoTime(); - List list = getJdbcTemplate().queryForList(sql, args, Date.class); - Date result = list.isEmpty() ? defaultValue : list.get(0) == null ? defaultValue : list.get(0); - log(sql, t); - return result; - } - - protected Long queryForLong(String sql, Long defaultValue, Object... args) { - long t = System.nanoTime(); - List list = getJdbcTemplate().queryForList(sql, args, Long.class); - Long result = list.isEmpty() ? defaultValue : list.get(0) == null ? defaultValue : list.get(0); - log(sql, t); - return result; - } - - protected T queryOne(String sql, RowMapper rowMapper, Object... args) { - List list = query(sql, rowMapper, args); - return list.isEmpty() ? null : list.get(0); - } - - public void setDaoHelper(DaoHelper daoHelper) { - this.daoHelper = daoHelper; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AlbumDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AlbumDao.java deleted file mode 100644 index 603f6dad..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AlbumDao.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.Album; -import net.sourceforge.subsonic.domain.MediaFile; -import org.apache.commons.lang.ObjectUtils; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Date; -import java.util.List; - -/** - * Provides database services for albums. - * - * @author Sindre Mehus - */ -public class AlbumDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(AlbumDao.class); - private static final String COLUMNS = "id, path, name, artist, song_count, duration_seconds, cover_art_path, " + - "play_count, last_played, comment, created, last_scanned, present"; - - private final RowMapper rowMapper = new AlbumMapper(); - - /** - * Returns the album with the given artist and album name. - * - * @param artistName The artist name. - * @param albumName The album name. - * @return The album or null. - */ - public Album getAlbum(String artistName, String albumName) { - return queryOne("select " + COLUMNS + " from album where artist=? and name=?", rowMapper, artistName, albumName); - } - - /** - * Returns the album that the given file (most likely) is part of. - * - * @param file The media file. - * @return The album or null. - */ - public Album getAlbumForFile(MediaFile file) { - - // First, get all albums with the correct album name (irrespective of artist). - List candidates = query("select " + COLUMNS + " from album where name=?", rowMapper, file.getAlbumName()); - if (candidates.isEmpty()) { - return null; - } - - // Look for album with the correct artist. - for (Album candidate : candidates) { - if (ObjectUtils.equals(candidate.getArtist(), file.getArtist())) { - return candidate; - } - } - - // Look for album with the same path as the file. - for (Album candidate : candidates) { - if (ObjectUtils.equals(candidate.getPath(), file.getParentPath())) { - return candidate; - } - } - - // No appropriate album found. - return null; - } - - public Album getAlbum(int id) { - return queryOne("select " + COLUMNS + " from album where id=?", rowMapper, id); - } - - public List getAlbumsForArtist(String artist) { - return query("select " + COLUMNS + " from album where artist=? and present order by name", rowMapper, artist); - } - - /** - * Creates or updates an album. - * - * @param album The album to create/update. - */ - public synchronized void createOrUpdateAlbum(Album album) { - String sql = "update album set " + - "song_count=?," + - "duration_seconds=?," + - "cover_art_path=?," + - "play_count=?," + - "last_played=?," + - "comment=?," + - "created=?," + - "last_scanned=?," + - "present=? " + - "where artist=? and name=?"; - - int n = update(sql, album.getSongCount(), album.getDurationSeconds(), album.getCoverArtPath(), album.getPlayCount(), album.getLastPlayed(), - album.getComment(), album.getCreated(), album.getLastScanned(), album.isPresent(), album.getArtist(), album.getName()); - - if (n == 0) { - - update("insert into album (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")", null, album.getPath(), album.getName(), album.getArtist(), - album.getSongCount(), album.getDurationSeconds(), album.getCoverArtPath(), album.getPlayCount(), album.getLastPlayed(), - album.getComment(), album.getCreated(), album.getLastScanned(), album.isPresent()); - } - - int id = queryForInt("select id from album where artist=? and name=?", null, album.getArtist(), album.getName()); - album.setId(id); - } - - /** - * Returns albums in alphabetical order. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @param byArtist Whether to sort by artist name - * @return Albums in alphabetical order. - */ - public List getAlphabetialAlbums(int offset, int count, boolean byArtist) { - String orderBy = byArtist ? "artist, name" : "name"; - return query("select " + COLUMNS + " from album where present order by " + orderBy + " limit ? offset ?", rowMapper, count, offset); - } - - /** - * Returns the most frequently played albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most frequently played albums. - */ - public List getMostFrequentlyPlayedAlbums(int offset, int count) { - return query("select " + COLUMNS + " from album where play_count > 0 and present " + - "order by play_count desc limit ? offset ?", rowMapper, count, offset); - } - - /** - * Returns the most recently played albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most recently played albums. - */ - public List getMostRecentlyPlayedAlbums(int offset, int count) { - return query("select " + COLUMNS + " from album where last_played is not null and present " + - "order by last_played desc limit ? offset ?", rowMapper, count, offset); - } - - /** - * Returns the most recently added albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most recently added albums. - */ - public List getNewestAlbums(int offset, int count) { - return query("select " + COLUMNS + " from album where present order by created desc limit ? offset ?", - rowMapper, count, offset); - } - - /** - * Returns the most recently starred albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @param username Returns albums starred by this user. - * @return The most recently starred albums for this user. - */ - public List getStarredAlbums(int offset, int count, String username) { - return query("select " + prefix(COLUMNS, "album") + " from album, starred_album where album.id = starred_album.album_id and " + - "album.present and starred_album.username=? order by starred_album.created desc limit ? offset ?", - rowMapper, username, count, offset); - } - - public void markNonPresent(Date lastScanned) { - int minId = queryForInt("select id from album where true limit 1", 0); - int maxId = queryForInt("select max(id) from album", 0); - - final int batchSize = 1000; - for (int id = minId; id <= maxId; id += batchSize) { - update("update album set present=false where id between ? and ? and last_scanned != ? and present", id, id + batchSize, lastScanned); - } - } - - public void expunge() { - int minId = queryForInt("select id from album where true limit 1", 0); - int maxId = queryForInt("select max(id) from album", 0); - - final int batchSize = 1000; - for (int id = minId; id <= maxId; id += batchSize) { - update("delete from album where id between ? and ? and not present", id, id + batchSize); - } - } - - public void starAlbum(int albumId, String username) { - unstarAlbum(albumId, username); - update("insert into starred_album(album_id, username, created) values (?,?,?)", albumId, username, new Date()); - } - - public void unstarAlbum(int albumId, String username) { - update("delete from starred_album where album_id=? and username=?", albumId, username); - } - - public Date getAlbumStarredDate(int albumId, String username) { - return queryForDate("select created from starred_album where album_id=? and username=?", null, albumId, username); - } - - private static class AlbumMapper implements ParameterizedRowMapper { - public Album mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Album( - rs.getInt(1), - rs.getString(2), - rs.getString(3), - rs.getString(4), - rs.getInt(5), - rs.getInt(6), - rs.getString(7), - rs.getInt(8), - rs.getTimestamp(9), - rs.getString(10), - rs.getTimestamp(11), - rs.getTimestamp(12), - rs.getBoolean(13)); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/ArtistDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/ArtistDao.java deleted file mode 100644 index 41d57c33..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/ArtistDao.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.Artist; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Date; -import java.util.List; - -/** - * Provides database services for artists. - * - * @author Sindre Mehus - */ -public class ArtistDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(ArtistDao.class); - private static final String COLUMNS = "id, name, cover_art_path, album_count, last_scanned, present"; - - private final RowMapper rowMapper = new ArtistMapper(); - - /** - * Returns the artist with the given name. - * - * @param artistName The artist name. - * @return The artist or null. - */ - public Artist getArtist(String artistName) { - return queryOne("select " + COLUMNS + " from artist where name=?", rowMapper, artistName); - } - - /** - * Returns the artist with the given ID. - * - * @param id The artist ID. - * @return The artist or null. - */ - public Artist getArtist(int id) { - return queryOne("select " + COLUMNS + " from artist where id=?", rowMapper, id); - } - - /** - * Creates or updates an artist. - * - * @param artist The artist to create/update. - */ - public synchronized void createOrUpdateArtist(Artist artist) { - String sql = "update artist set " + - "cover_art_path=?," + - "album_count=?," + - "last_scanned=?," + - "present=? " + - "where name=?"; - - int n = update(sql, artist.getCoverArtPath(), artist.getAlbumCount(), artist.getLastScanned(), artist.isPresent(), artist.getName()); - - if (n == 0) { - - update("insert into artist (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")", null, - artist.getName(), artist.getCoverArtPath(), artist.getAlbumCount(), artist.getLastScanned(), artist.isPresent()); - } - - int id = queryForInt("select id from artist where name=?", null, artist.getName()); - artist.setId(id); - } - - /** - * Returns artists in alphabetical order. - * - * @param offset Number of artists to skip. - * @param count Maximum number of artists to return. - * @return Artists in alphabetical order. - */ - public List getAlphabetialArtists(int offset, int count) { - return query("select " + COLUMNS + " from artist where present order by name limit ? offset ?", rowMapper, count, offset); - } - - /** - * Returns the most recently starred artists. - * - * @param offset Number of artists to skip. - * @param count Maximum number of artists to return. - * @param username Returns artists starred by this user. - * @return The most recently starred artists for this user. - */ - public List getStarredArtists(int offset, int count, String username) { - return query("select " + prefix(COLUMNS, "artist") + " from artist, starred_artist where artist.id = starred_artist.artist_id and " + - "artist.present and starred_artist.username=? order by starred_artist.created desc limit ? offset ?", - rowMapper, username, count, offset); - } - - public void markPresent(String artistName, Date lastScanned) { - update("update artist set present=?, last_scanned=? where name=?", true, lastScanned, artistName); - } - - public void markNonPresent(Date lastScanned) { - int minId = queryForInt("select id from artist where true limit 1", 0); - int maxId = queryForInt("select max(id) from artist", 0); - - final int batchSize = 1000; - for (int id = minId; id <= maxId; id += batchSize) { - update("update artist set present=false where id between ? and ? and last_scanned != ? and present", id, id + batchSize, lastScanned); - } - } - - public void expunge() { - int minId = queryForInt("select id from artist where true limit 1", 0); - int maxId = queryForInt("select max(id) from artist", 0); - - final int batchSize = 1000; - for (int id = minId; id <= maxId; id += batchSize) { - update("delete from artist where id between ? and ? and not present", id, id + batchSize); - } - } - - public void starArtist(int artistId, String username) { - unstarArtist(artistId, username); - update("insert into starred_artist(artist_id, username, created) values (?,?,?)", artistId, username, new Date()); - } - - public void unstarArtist(int artistId, String username) { - update("delete from starred_artist where artist_id=? and username=?", artistId, username); - } - - public Date getArtistStarredDate(int artistId, String username) { - return queryForDate("select created from starred_artist where artist_id=? and username=?", null, artistId, username); - } - - private static class ArtistMapper implements ParameterizedRowMapper { - public Artist mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Artist( - rs.getInt(1), - rs.getString(2), - rs.getString(3), - rs.getInt(4), - rs.getTimestamp(5), - rs.getBoolean(6)); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AvatarDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AvatarDao.java deleted file mode 100644 index abdc118d..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/AvatarDao.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import net.sourceforge.subsonic.domain.Avatar; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; - -/** - * Provides database services for avatars. - * - * @author Sindre Mehus - */ -public class AvatarDao extends AbstractDao { - - private static final String COLUMNS = "id, name, created_date, mime_type, width, height, data"; - private final AvatarRowMapper rowMapper = new AvatarRowMapper(); - - /** - * Returns all system avatars. - * - * @return All system avatars. - */ - public List getAllSystemAvatars() { - String sql = "select " + COLUMNS + " from system_avatar"; - return query(sql, rowMapper); - } - - /** - * Returns the system avatar with the given ID. - * - * @param id The system avatar ID. - * @return The avatar or null if not found. - */ - public Avatar getSystemAvatar(int id) { - String sql = "select " + COLUMNS + " from system_avatar where id=" + id; - return queryOne(sql, rowMapper); - } - - /** - * Returns the custom avatar for the given user. - * - * @param username The username. - * @return The avatar or null if not found. - */ - public Avatar getCustomAvatar(String username) { - String sql = "select " + COLUMNS + " from custom_avatar where username=?"; - return queryOne(sql, rowMapper, username); - } - - /** - * Sets the custom avatar for the given user. - * - * @param avatar The avatar, or null to remove the avatar. - * @param username The username. - */ - public void setCustomAvatar(Avatar avatar, String username) { - String sql = "delete from custom_avatar where username=?"; - update(sql, username); - - if (avatar != null) { - update("insert into custom_avatar(" + COLUMNS + ", username) values(" + questionMarks(COLUMNS) + ", ?)", - null, avatar.getName(), avatar.getCreatedDate(), avatar.getMimeType(), - avatar.getWidth(), avatar.getHeight(), avatar.getData(), username); - } - } - - private static class AvatarRowMapper implements ParameterizedRowMapper { - public Avatar mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Avatar(rs.getInt(1), rs.getString(2), rs.getTimestamp(3), rs.getString(4), - rs.getInt(5), rs.getInt(6), rs.getBytes(7)); - } - } - -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/DaoHelper.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/DaoHelper.java deleted file mode 100644 index 802a5b3d..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/DaoHelper.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.schema.Schema; -import net.sourceforge.subsonic.dao.schema.Schema25; -import net.sourceforge.subsonic.dao.schema.Schema26; -import net.sourceforge.subsonic.dao.schema.Schema27; -import net.sourceforge.subsonic.dao.schema.Schema28; -import net.sourceforge.subsonic.dao.schema.Schema29; -import net.sourceforge.subsonic.dao.schema.Schema30; -import net.sourceforge.subsonic.dao.schema.Schema31; -import net.sourceforge.subsonic.dao.schema.Schema32; -import net.sourceforge.subsonic.dao.schema.Schema33; -import net.sourceforge.subsonic.dao.schema.Schema34; -import net.sourceforge.subsonic.dao.schema.Schema35; -import net.sourceforge.subsonic.dao.schema.Schema36; -import net.sourceforge.subsonic.dao.schema.Schema37; -import net.sourceforge.subsonic.dao.schema.Schema38; -import net.sourceforge.subsonic.dao.schema.Schema40; -import net.sourceforge.subsonic.dao.schema.Schema43; -import net.sourceforge.subsonic.dao.schema.Schema45; -import net.sourceforge.subsonic.dao.schema.Schema46; -import net.sourceforge.subsonic.dao.schema.Schema47; -import net.sourceforge.subsonic.service.SettingsService; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.datasource.DriverManagerDataSource; - -import javax.sql.DataSource; -import java.io.File; - -/** - * DAO helper class which creates the data source, and updates the database schema. - * - * @author Sindre Mehus - */ -public class DaoHelper { - - private static final Logger LOG = Logger.getLogger(DaoHelper.class); - - private Schema[] schemas = {new Schema25(), new Schema26(), new Schema27(), new Schema28(), new Schema29(), - new Schema30(), new Schema31(), new Schema32(), new Schema33(), new Schema34(), - new Schema35(), new Schema36(), new Schema37(), new Schema38(), new Schema40(), - new Schema43(), new Schema45(), new Schema46(), new Schema47()}; - private DataSource dataSource; - private static boolean shutdownHookAdded; - - public DaoHelper() { - dataSource = createDataSource(); - checkDatabase(); - addShutdownHook(); - } - - private void addShutdownHook() { - if (shutdownHookAdded) { - return; - } - shutdownHookAdded = true; - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - System.err.println("Shutting down database."); - getJdbcTemplate().execute("shutdown"); - System.err.println("Done."); - } - }); - } - - /** - * Returns a JDBC template for performing database operations. - * - * @return A JDBC template. - */ - public JdbcTemplate getJdbcTemplate() { - return new JdbcTemplate(dataSource); - } - - private DataSource createDataSource() { - File subsonicHome = SettingsService.getSubsonicHome(); - DriverManagerDataSource ds = new DriverManagerDataSource(); - ds.setDriverClassName("org.hsqldb.jdbcDriver"); - ds.setUrl("jdbc:hsqldb:file:" + subsonicHome.getPath() + "/db/subsonic"); - ds.setUsername("sa"); - ds.setPassword(""); - - return ds; - } - - private void checkDatabase() { - LOG.info("Checking database schema."); - try { - for (Schema schema : schemas) { - schema.execute(getJdbcTemplate()); - } - LOG.info("Done checking database schema."); - } catch (Exception x) { - LOG.error("Failed to initialize database.", x); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/InternetRadioDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/InternetRadioDao.java deleted file mode 100644 index c3c20a74..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/InternetRadioDao.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; - -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.InternetRadio; - -/** - * Provides database services for internet radio. - * - * @author Sindre Mehus - */ -public class InternetRadioDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(InternetRadioDao.class); - private static final String COLUMNS = "id, name, stream_url, homepage_url, enabled, changed"; - private final InternetRadioRowMapper rowMapper = new InternetRadioRowMapper(); - - /** - * Returns all internet radio stations. - * - * @return Possibly empty list of all internet radio stations. - */ - public List getAllInternetRadios() { - String sql = "select " + COLUMNS + " from internet_radio"; - return query(sql, rowMapper); - } - - /** - * Creates a new internet radio station. - * - * @param radio The internet radio station to create. - */ - public void createInternetRadio(InternetRadio radio) { - String sql = "insert into internet_radio (" + COLUMNS + ") values (null, ?, ?, ?, ?, ?)"; - update(sql, radio.getName(), radio.getStreamUrl(), radio.getHomepageUrl(), radio.isEnabled(), radio.getChanged()); - LOG.info("Created internet radio station " + radio.getName()); - } - - /** - * Deletes the internet radio station with the given ID. - * - * @param id The internet radio station ID. - */ - public void deleteInternetRadio(Integer id) { - String sql = "delete from internet_radio where id=?"; - update(sql, id); - LOG.info("Deleted internet radio station with ID " + id); - } - - /** - * Updates the given internet radio station. - * - * @param radio The internet radio station to update. - */ - public void updateInternetRadio(InternetRadio radio) { - String sql = "update internet_radio set name=?, stream_url=?, homepage_url=?, enabled=?, changed=? where id=?"; - update(sql, radio.getName(), radio.getStreamUrl(), radio.getHomepageUrl(), radio.isEnabled(), radio.getChanged(), radio.getId()); - } - - private static class InternetRadioRowMapper implements ParameterizedRowMapper { - public InternetRadio mapRow(ResultSet rs, int rowNum) throws SQLException { - return new InternetRadio(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getBoolean(5), rs.getTimestamp(6)); - } - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/MediaFileDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/MediaFileDao.java deleted file mode 100644 index e75bc7a6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/MediaFileDao.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MediaLibraryStatistics; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Date; -import java.util.List; - -import static net.sourceforge.subsonic.domain.MediaFile.MediaType; -import static net.sourceforge.subsonic.domain.MediaFile.MediaType.*; - -/** - * Provides database services for media files. - * - * @author Sindre Mehus - */ -public class MediaFileDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(MediaFileDao.class); - private static final String COLUMNS = "id, path, folder, type, format, title, album, artist, album_artist, disc_number, " + - "track_number, year, genre, bit_rate, variable_bit_rate, duration_seconds, file_size, width, height, cover_art_path, " + - "parent_path, play_count, last_played, comment, created, changed, last_scanned, children_last_updated, present, version"; - - private static final int VERSION = 1; - - private final RowMapper rowMapper = new MediaFileMapper(); - private final RowMapper musicFileInfoRowMapper = new MusicFileInfoMapper(); - - /** - * Returns the media file for the given path. - * - * @param path The path. - * @return The media file or null. - */ - public MediaFile getMediaFile(String path) { - return queryOne("select " + COLUMNS + " from media_file where path=?", rowMapper, path); - } - - /** - * Returns the media file for the given ID. - * - * @param id The ID. - * @return The media file or null. - */ - public MediaFile getMediaFile(int id) { - return queryOne("select " + COLUMNS + " from media_file where id=?", rowMapper, id); - } - - /** - * Returns the media file that are direct children of the given path. - * - * @param path The path. - * @return The list of children. - */ - public List getChildrenOf(String path) { - return query("select " + COLUMNS + " from media_file where parent_path=? and present", rowMapper, path); - } - - public List getFilesInPlaylist(int playlistId) { - return query("select " + prefix(COLUMNS, "media_file") + " from media_file, playlist_file where " + - "media_file.id = playlist_file.media_file_id and " + - "playlist_file.playlist_id = ? and " + - "media_file.present order by playlist_file.id", rowMapper, playlistId); - } - - public List getSongsForAlbum(String artist, String album) { - return query("select " + COLUMNS + " from media_file where album_artist=? and album=? and present and type in (?,?,?) order by track_number", rowMapper, - artist, album, MUSIC.name(), AUDIOBOOK.name(), PODCAST.name()); - } - - public List getVideos(int size, int offset) { - return query("select " + COLUMNS + " from media_file where type=? and present order by title limit ? offset ?", rowMapper, - VIDEO.name(), size, offset); - } - - /** - * Creates or updates a media file. - * - * @param file The media file to create/update. - */ - public synchronized void createOrUpdateMediaFile(MediaFile file) { - String sql = "update media_file set " + - "folder=?," + - "type=?," + - "format=?," + - "title=?," + - "album=?," + - "artist=?," + - "album_artist=?," + - "disc_number=?," + - "track_number=?," + - "year=?," + - "genre=?," + - "bit_rate=?," + - "variable_bit_rate=?," + - "duration_seconds=?," + - "file_size=?," + - "width=?," + - "height=?," + - "cover_art_path=?," + - "parent_path=?," + - "play_count=?," + - "last_played=?," + - "comment=?," + - "changed=?," + - "last_scanned=?," + - "children_last_updated=?," + - "present=?, " + - "version=? " + - "where path=?"; - - int n = update(sql, - file.getFolder(), file.getMediaType().name(), file.getFormat(), file.getTitle(), file.getAlbumName(), file.getArtist(), - file.getAlbumArtist(), file.getDiscNumber(), file.getTrackNumber(), file.getYear(), file.getGenre(), file.getBitRate(), - file.isVariableBitRate(), file.getDurationSeconds(), file.getFileSize(), file.getWidth(), file.getHeight(), - file.getCoverArtPath(), file.getParentPath(), file.getPlayCount(), file.getLastPlayed(), file.getComment(), - file.getChanged(), file.getLastScanned(), file.getChildrenLastUpdated(), file.isPresent(), VERSION, file.getPath()); - - if (n == 0) { - - // Copy values from obsolete table music_file_info. - MediaFile musicFileInfo = getMusicFileInfo(file.getPath()); - if (musicFileInfo != null) { - file.setComment(musicFileInfo.getComment()); - file.setLastPlayed(musicFileInfo.getLastPlayed()); - file.setPlayCount(musicFileInfo.getPlayCount()); - } - - update("insert into media_file (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")", null, - file.getPath(), file.getFolder(), file.getMediaType().name(), file.getFormat(), file.getTitle(), file.getAlbumName(), file.getArtist(), - file.getAlbumArtist(), file.getDiscNumber(), file.getTrackNumber(), file.getYear(), file.getGenre(), file.getBitRate(), - file.isVariableBitRate(), file.getDurationSeconds(), file.getFileSize(), file.getWidth(), file.getHeight(), - file.getCoverArtPath(), file.getParentPath(), file.getPlayCount(), file.getLastPlayed(), file.getComment(), - file.getCreated(), file.getChanged(), file.getLastScanned(), - file.getChildrenLastUpdated(), file.isPresent(), VERSION); - } - - int id = queryForInt("select id from media_file where path=?", null, file.getPath()); - file.setId(id); - } - - private MediaFile getMusicFileInfo(String path) { - return queryOne("select play_count, last_played, comment from music_file_info where path=?", musicFileInfoRowMapper, path); - } - - @Deprecated - public List getArtists() { - return queryForStrings("select distinct artist from media_file where artist is not null and present order by artist"); - } - - public void deleteMediaFile(String path) { - update("update media_file set present=false, children_last_updated=? where path=?", new Date(0L), path); - } - - public List getGenres() { - return queryForStrings("select distinct genre from media_file where genre is not null and present order by genre"); - } - - /** - * Returns the most frequently played albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most frequently played albums. - */ - public List getMostFrequentlyPlayedAlbums(int offset, int count) { - return query("select " + COLUMNS + " from media_file where type=? and play_count > 0 and present " + - "order by play_count desc limit ? offset ?", rowMapper, ALBUM.name(), count, offset); - } - - /** - * Returns the most recently played albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most recently played albums. - */ - public List getMostRecentlyPlayedAlbums(int offset, int count) { - return query("select " + COLUMNS + " from media_file where type=? and last_played is not null and present " + - "order by last_played desc limit ? offset ?", rowMapper, ALBUM.name(), count, offset); - } - - /** - * Returns the most recently added albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most recently added albums. - */ - public List getNewestAlbums(int offset, int count) { - return query("select " + COLUMNS + " from media_file where type=? and present order by created desc limit ? offset ?", - rowMapper, ALBUM.name(), count, offset); - } - - /** - * Returns albums in alphabetical order. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @param byArtist Whether to sort by artist name - * @return Albums in alphabetical order. - */ - public List getAlphabetialAlbums(int offset, int count, boolean byArtist) { - String orderBy = byArtist ? "artist, album" : "album"; - return query("select " + COLUMNS + " from media_file where type=? and artist != '' and present order by " + orderBy + " limit ? offset ?", - rowMapper, ALBUM.name(), count, offset); - } - - /** - * Returns the most recently starred albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @param username Returns albums starred by this user. - * @return The most recently starred albums for this user. - */ - public List getStarredAlbums(int offset, int count, String username) { - return query("select " + prefix(COLUMNS, "media_file") + " from media_file, starred_media_file where media_file.id = starred_media_file.media_file_id and " + - "media_file.present and media_file.type=? and starred_media_file.username=? order by starred_media_file.created desc limit ? offset ?", - rowMapper, ALBUM.name(), username, count, offset); - } - - /** - * Returns the most recently starred directories. - * - * @param offset Number of directories to skip. - * @param count Maximum number of directories to return. - * @param username Returns directories starred by this user. - * @return The most recently starred directories for this user. - */ - public List getStarredDirectories(int offset, int count, String username) { - return query("select " + prefix(COLUMNS, "media_file") + " from media_file, starred_media_file where media_file.id = starred_media_file.media_file_id and " + - "media_file.present and media_file.type=? and starred_media_file.username=? order by starred_media_file.created desc limit ? offset ?", - rowMapper, DIRECTORY.name(), username, count, offset); - } - - /** - * Returns the most recently starred files. - * - * @param offset Number of files to skip. - * @param count Maximum number of files to return. - * @param username Returns files starred by this user. - * @return The most recently starred files for this user. - */ - public List getStarredFiles(int offset, int count, String username) { - return query("select " + prefix(COLUMNS, "media_file") + " from media_file, starred_media_file where media_file.id = starred_media_file.media_file_id and " + - "media_file.present and media_file.type in (?,?,?,?) and starred_media_file.username=? order by starred_media_file.created desc limit ? offset ?", - rowMapper, MUSIC.name(), PODCAST.name(), AUDIOBOOK.name(), VIDEO.name(), username, count, offset); - } - - public void starMediaFile(int id, String username) { - unstarMediaFile(id, username); - update("insert into starred_media_file(media_file_id, username, created) values (?,?,?)", id, username, new Date()); - } - - public void unstarMediaFile(int id, String username) { - update("delete from starred_media_file where media_file_id=? and username=?", id, username); - } - - public Date getMediaFileStarredDate(int id, String username) { - return queryForDate("select created from starred_media_file where media_file_id=? and username=?", null, id, username); - } - - /** - * Returns media library statistics, including the number of artists, albums and songs. - * - * @return Media library statistics. - */ - public MediaLibraryStatistics getStatistics() { - int artistCount = queryForInt("select count(1) from artist where present", 0); - int albumCount = queryForInt("select count(1) from album where present", 0); - int songCount = queryForInt("select count(1) from media_file where type in (?, ?, ?, ?) and present", 0, VIDEO.name(), MUSIC.name(), AUDIOBOOK.name(), PODCAST.name()); - long totalLengthInBytes = queryForLong("select sum(file_size) from media_file where present", 0L); - long totalDurationInSeconds = queryForLong("select sum(duration_seconds) from media_file where present", 0L); - - return new MediaLibraryStatistics(artistCount, albumCount, songCount, totalLengthInBytes, totalDurationInSeconds); - } - - public void markPresent(String path, Date lastScanned) { - update("update media_file set present=?, last_scanned=? where path=?", true, lastScanned, path); - } - - public void markNonPresent(Date lastScanned) { - int minId = queryForInt("select id from media_file where true limit 1", 0); - int maxId = queryForInt("select max(id) from media_file", 0); - - final int batchSize = 1000; - Date childrenLastUpdated = new Date(0L); // Used to force a children rescan if file is later resurrected. - for (int id = minId; id <= maxId; id += batchSize) { - update("update media_file set present=false, children_last_updated=? where id between ? and ? and last_scanned != ? and present", - childrenLastUpdated, id, id + batchSize, lastScanned); - } - } - - public void expunge() { - int minId = queryForInt("select id from media_file where true limit 1", 0); - int maxId = queryForInt("select max(id) from media_file", 0); - - final int batchSize = 1000; - for (int id = minId; id <= maxId; id += batchSize) { - update("delete from media_file where id between ? and ? and not present", id, id + batchSize); - } - update("checkpoint"); - } - - private static class MediaFileMapper implements ParameterizedRowMapper { - public MediaFile mapRow(ResultSet rs, int rowNum) throws SQLException { - return new MediaFile( - rs.getInt(1), - rs.getString(2), - rs.getString(3), - MediaType.valueOf(rs.getString(4)), - rs.getString(5), - rs.getString(6), - rs.getString(7), - rs.getString(8), - rs.getString(9), - rs.getInt(10) == 0 ? null : rs.getInt(10), - rs.getInt(11) == 0 ? null : rs.getInt(11), - rs.getInt(12) == 0 ? null : rs.getInt(12), - rs.getString(13), - rs.getInt(14) == 0 ? null : rs.getInt(14), - rs.getBoolean(15), - rs.getInt(16) == 0 ? null : rs.getInt(16), - rs.getLong(17) == 0 ? null : rs.getLong(17), - rs.getInt(18) == 0 ? null : rs.getInt(18), - rs.getInt(19) == 0 ? null : rs.getInt(19), - rs.getString(20), - rs.getString(21), - rs.getInt(22), - rs.getTimestamp(23), - rs.getString(24), - rs.getTimestamp(25), - rs.getTimestamp(26), - rs.getTimestamp(27), - rs.getTimestamp(28), - rs.getBoolean(29)); - } - } - - private static class MusicFileInfoMapper implements ParameterizedRowMapper { - public MediaFile mapRow(ResultSet rs, int rowNum) throws SQLException { - MediaFile file = new MediaFile(); - file.setPlayCount(rs.getInt(1)); - file.setLastPlayed(rs.getTimestamp(2)); - file.setComment(rs.getString(3)); - return file; - } - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/MusicFolderDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/MusicFolderDao.java deleted file mode 100644 index a5205d71..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/MusicFolderDao.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import java.io.File; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; - -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MusicFolder; - -/** - * Provides database services for music folders. - * - * @author Sindre Mehus - */ -public class MusicFolderDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(MusicFolderDao.class); - private static final String COLUMNS = "id, path, name, enabled, changed"; - private final MusicFolderRowMapper rowMapper = new MusicFolderRowMapper(); - - /** - * Returns all music folders. - * - * @return Possibly empty list of all music folders. - */ - public List getAllMusicFolders() { - String sql = "select " + COLUMNS + " from music_folder"; - return query(sql, rowMapper); - } - - /** - * Creates a new music folder. - * - * @param musicFolder The music folder to create. - */ - public void createMusicFolder(MusicFolder musicFolder) { - String sql = "insert into music_folder (" + COLUMNS + ") values (null, ?, ?, ?, ?)"; - update(sql, musicFolder.getPath(), musicFolder.getName(), musicFolder.isEnabled(), musicFolder.getChanged()); - LOG.info("Created music folder " + musicFolder.getPath()); - } - - /** - * Deletes the music folder with the given ID. - * - * @param id The music folder ID. - */ - public void deleteMusicFolder(Integer id) { - String sql = "delete from music_folder where id=?"; - update(sql, id); - LOG.info("Deleted music folder with ID " + id); - } - - /** - * Updates the given music folder. - * - * @param musicFolder The music folder to update. - */ - public void updateMusicFolder(MusicFolder musicFolder) { - String sql = "update music_folder set path=?, name=?, enabled=?, changed=? where id=?"; - update(sql, musicFolder.getPath().getPath(), musicFolder.getName(), - musicFolder.isEnabled(), musicFolder.getChanged(), musicFolder.getId()); - } - - private static class MusicFolderRowMapper implements ParameterizedRowMapper { - public MusicFolder mapRow(ResultSet rs, int rowNum) throws SQLException { - return new MusicFolder(rs.getInt(1), new File(rs.getString(2)), rs.getString(3), rs.getBoolean(4), rs.getTimestamp(5)); - } - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PlayerDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PlayerDao.java deleted file mode 100644 index f129fa37..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PlayerDao.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Calendar; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.CoverArtScheme; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayerTechnology; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.TranscodeScheme; - -/** - * Provides player-related database services. - * - * @author Sindre Mehus - */ -public class PlayerDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(PlayerDao.class); - private static final String COLUMNS = "id, name, type, username, ip_address, auto_control_enabled, " + - "last_seen, cover_art_scheme, transcode_scheme, dynamic_ip, technology, client_id"; - - private PlayerRowMapper rowMapper = new PlayerRowMapper(); - private Map playlists = Collections.synchronizedMap(new HashMap()); - - /** - * Returns all players. - * - * @return Possibly empty list of all users. - */ - public List getAllPlayers() { - String sql = "select " + COLUMNS + " from player"; - return query(sql, rowMapper); - } - - /** - * Returns all players owned by the given username and client ID. - * - * @param username The name of the user. - * @param clientId The third-party client ID (used if this player is managed over the - * Subsonic REST API). May be null. - * @return All relevant players. - */ - public List getPlayersForUserAndClientId(String username, String clientId) { - if (clientId != null) { - String sql = "select " + COLUMNS + " from player where username=? and client_id=?"; - return query(sql, rowMapper, username, clientId); - } else { - String sql = "select " + COLUMNS + " from player where username=? and client_id is null"; - return query(sql, rowMapper, username); - } - } - - /** - * Returns the player with the given ID. - * - * @param id The unique player ID. - * @return The player with the given ID, or null if no such player exists. - */ - public Player getPlayerById(String id) { - String sql = "select " + COLUMNS + " from player where id=?"; - return queryOne(sql, rowMapper, id); - } - - /** - * Creates a new player. - * - * @param player The player to create. - */ - public synchronized void createPlayer(Player player) { - int id = getJdbcTemplate().queryForInt("select max(id) from player") + 1; - player.setId(String.valueOf(id)); - String sql = "insert into player (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")"; - update(sql, player.getId(), player.getName(), player.getType(), player.getUsername(), - player.getIpAddress(), player.isAutoControlEnabled(), - player.getLastSeen(), player.getCoverArtScheme().name(), - player.getTranscodeScheme().name(), player.isDynamicIp(), - player.getTechnology().name(), player.getClientId()); - addPlaylist(player); - - LOG.info("Created player " + id + '.'); - } - - /** - * Deletes the player with the given ID. - * - * @param id The player ID. - */ - public void deletePlayer(String id) { - String sql = "delete from player where id=?"; - update(sql, id); - playlists.remove(id); - } - - - /** - * Delete players that haven't been used for the given number of days, and which is not given a name - * or is used by a REST client. - * - * @param days Number of days. - */ - public void deleteOldPlayers(int days) { - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DATE, -days); - String sql = "delete from player where name is null and client_id is null and (last_seen is null or last_seen < ?)"; - int n = update(sql, cal.getTime()); - if (n > 0) { - LOG.info("Deleted " + n + " player(s) that haven't been used after " + cal.getTime()); - } - } - - /** - * Updates the given player. - * - * @param player The player to update. - */ - public void updatePlayer(Player player) { - String sql = "update player set " + - "name = ?," + - "type = ?," + - "username = ?," + - "ip_address = ?," + - "auto_control_enabled = ?," + - "last_seen = ?," + - "cover_art_scheme = ?," + - "transcode_scheme = ?, " + - "dynamic_ip = ?, " + - "technology = ?, " + - "client_id = ? " + - "where id = ?"; - update(sql, player.getName(), player.getType(), player.getUsername(), - player.getIpAddress(), player.isAutoControlEnabled(), - player.getLastSeen(), player.getCoverArtScheme().name(), - player.getTranscodeScheme().name(), player.isDynamicIp(), - player.getTechnology(), player.getClientId(), player.getId()); - } - - private void addPlaylist(Player player) { - PlayQueue playQueue = playlists.get(player.getId()); - if (playQueue == null) { - playQueue = new PlayQueue(); - playlists.put(player.getId(), playQueue); - } - player.setPlayQueue(playQueue); - } - - private class PlayerRowMapper implements ParameterizedRowMapper { - public Player mapRow(ResultSet rs, int rowNum) throws SQLException { - Player player = new Player(); - int col = 1; - player.setId(rs.getString(col++)); - player.setName(rs.getString(col++)); - player.setType(rs.getString(col++)); - player.setUsername(rs.getString(col++)); - player.setIpAddress(rs.getString(col++)); - player.setAutoControlEnabled(rs.getBoolean(col++)); - player.setLastSeen(rs.getTimestamp(col++)); - player.setCoverArtScheme(CoverArtScheme.valueOf(rs.getString(col++))); - player.setTranscodeScheme(TranscodeScheme.valueOf(rs.getString(col++))); - player.setDynamicIp(rs.getBoolean(col++)); - player.setTechnology(PlayerTechnology.valueOf(rs.getString(col++))); - player.setClientId(rs.getString(col++)); - - addPlaylist(player); - return player; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PlaylistDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PlaylistDao.java deleted file mode 100644 index 54cbaded..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PlaylistDao.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Playlist; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.SortedMap; -import java.util.TreeMap; - -/** - * Provides database services for playlists. - * - * @author Sindre Mehus - */ -public class PlaylistDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(PlaylistDao.class); - private static final String COLUMNS = "id, username, is_public, name, comment, file_count, duration_seconds, " + - "created, changed, imported_from"; - private final RowMapper rowMapper = new PlaylistMapper(); - - public List getReadablePlaylistsForUser(String username) { - - List result1 = getWritablePlaylistsForUser(username); - List result2 = query("select " + COLUMNS + " from playlist where is_public", rowMapper); - List result3 = query("select " + prefix(COLUMNS, "playlist") + " from playlist, playlist_user where " + - "playlist.id = playlist_user.playlist_id and " + - "playlist.username != ? and " + - "playlist_user.username = ?", rowMapper, username, username); - - // Put in sorted map to avoid duplicates. - SortedMap map = new TreeMap(); - for (Playlist playlist : result1) { - map.put(playlist.getId(), playlist); - } - for (Playlist playlist : result2) { - map.put(playlist.getId(), playlist); - } - for (Playlist playlist : result3) { - map.put(playlist.getId(), playlist); - } - return new ArrayList(map.values()); - } - - public List getWritablePlaylistsForUser(String username) { - return query("select " + COLUMNS + " from playlist where username=?", rowMapper, username); - } - - public Playlist getPlaylist(int id) { - return queryOne("select " + COLUMNS + " from playlist where id=?", rowMapper, id); - } - - public List getAllPlaylists() { - return query("select " + COLUMNS + " from playlist", rowMapper); - } - - public synchronized void createPlaylist(Playlist playlist) { - update("insert into playlist(" + COLUMNS + ") values(" + questionMarks(COLUMNS) + ")", - null, playlist.getUsername(), playlist.isPublic(), playlist.getName(), playlist.getComment(), - 0, 0, playlist.getCreated(), playlist.getChanged(), playlist.getImportedFrom()); - - int id = queryForInt("select max(id) from playlist", 0); - playlist.setId(id); - } - - public void setFilesInPlaylist(int id, List files) { - update("delete from playlist_file where playlist_id=?", id); - int duration = 0; - for (MediaFile file : files) { - update("insert into playlist_file (playlist_id, media_file_id) values (?, ?)", id, file.getId()); - if (file.getDurationSeconds() != null) { - duration += file.getDurationSeconds(); - } - } - update("update playlist set file_count=?, duration_seconds=?, changed=? where id=?", files.size(), duration, new Date(), id); - } - - public List getPlaylistUsers(int playlistId) { - return queryForStrings("select username from playlist_user where playlist_id=?", playlistId); - } - - public void addPlaylistUser(int playlistId, String username) { - if (!getPlaylistUsers(playlistId).contains(username)) { - update("insert into playlist_user(playlist_id,username) values (?,?)", playlistId, username); - } - } - - public void deletePlaylistUser(int playlistId, String username) { - update("delete from playlist_user where playlist_id=? and username=?", playlistId, username); - } - - public synchronized void deletePlaylist(int id) { - update("delete from playlist where id=?", id); - } - - public void updatePlaylist(Playlist playlist) { - update("update playlist set username=?, is_public=?, name=?, comment=?, changed=?, imported_from=? where id=?", - playlist.getUsername(), playlist.isPublic(), playlist.getName(), playlist.getComment(), - new Date(), playlist.getImportedFrom(), playlist.getId()); - } - - private static class PlaylistMapper implements ParameterizedRowMapper { - public Playlist mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Playlist( - rs.getInt(1), - rs.getString(2), - rs.getBoolean(3), - rs.getString(4), - rs.getString(5), - rs.getInt(6), - rs.getInt(7), - rs.getTimestamp(8), - rs.getTimestamp(9), - rs.getString(10)); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PodcastDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PodcastDao.java deleted file mode 100644 index 3f274ec6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/PodcastDao.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; - -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import net.sourceforge.subsonic.domain.PodcastChannel; -import net.sourceforge.subsonic.domain.PodcastEpisode; -import net.sourceforge.subsonic.domain.PodcastStatus; - -/** - * Provides database services for Podcast channels and episodes. - * - * @author Sindre Mehus - */ -public class PodcastDao extends AbstractDao { - - private static final String CHANNEL_COLUMNS = "id, url, title, description, status, error_message"; - private static final String EPISODE_COLUMNS = "id, channel_id, url, path, title, description, publish_date, " + - "duration, bytes_total, bytes_downloaded, status, error_message"; - - private PodcastChannelRowMapper channelRowMapper = new PodcastChannelRowMapper(); - private PodcastEpisodeRowMapper episodeRowMapper = new PodcastEpisodeRowMapper(); - - /** - * Creates a new Podcast channel. - * - * @param channel The Podcast channel to create. - * @return The ID of the newly created channel. - */ - public synchronized int createChannel(PodcastChannel channel) { - String sql = "insert into podcast_channel (" + CHANNEL_COLUMNS + ") values (" + questionMarks(CHANNEL_COLUMNS) + ")"; - update(sql, null, channel.getUrl(), channel.getTitle(), channel.getDescription(), - channel.getStatus().name(), channel.getErrorMessage()); - - return getJdbcTemplate().queryForInt("select max(id) from podcast_channel"); - } - - /** - * Returns all Podcast channels. - * - * @return Possibly empty list of all Podcast channels. - */ - public List getAllChannels() { - String sql = "select " + CHANNEL_COLUMNS + " from podcast_channel"; - return query(sql, channelRowMapper); - } - - /** - * Updates the given Podcast channel. - * - * @param channel The Podcast channel to update. - */ - public void updateChannel(PodcastChannel channel) { - String sql = "update podcast_channel set url=?, title=?, description=?, status=?, error_message=? where id=?"; - update(sql, channel.getUrl(), channel.getTitle(), channel.getDescription(), - channel.getStatus().name(), channel.getErrorMessage(), channel.getId()); - } - - /** - * Deletes the Podcast channel with the given ID. - * - * @param id The Podcast channel ID. - */ - public void deleteChannel(int id) { - String sql = "delete from podcast_channel where id=?"; - update(sql, id); - } - - /** - * Creates a new Podcast episode. - * - * @param episode The Podcast episode to create. - */ - public void createEpisode(PodcastEpisode episode) { - String sql = "insert into podcast_episode (" + EPISODE_COLUMNS + ") values (" + questionMarks(EPISODE_COLUMNS) + ")"; - update(sql, null, episode.getChannelId(), episode.getUrl(), episode.getPath(), - episode.getTitle(), episode.getDescription(), episode.getPublishDate(), - episode.getDuration(), episode.getBytesTotal(), episode.getBytesDownloaded(), - episode.getStatus().name(), episode.getErrorMessage()); - } - - /** - * Returns all Podcast episodes for a given channel. - * - * @return Possibly empty list of all Podcast episodes for the given channel, sorted in - * reverse chronological order (newest episode first). - */ - public List getEpisodes(int channelId) { - String sql = "select " + EPISODE_COLUMNS + " from podcast_episode where channel_id=? order by publish_date desc"; - return query(sql, episodeRowMapper, channelId); - } - - /** - * Returns the Podcast episode with the given ID. - * - * @param episodeId The Podcast episode ID. - * @return The episode or null if not found. - */ - public PodcastEpisode getEpisode(int episodeId) { - String sql = "select " + EPISODE_COLUMNS + " from podcast_episode where id=?"; - return queryOne(sql, episodeRowMapper, episodeId); - } - - /** - * Updates the given Podcast episode. - * - * @param episode The Podcast episode to update. - * @return The number of episodes updated (zero or one). - */ - public int updateEpisode(PodcastEpisode episode) { - String sql = "update podcast_episode set url=?, path=?, title=?, description=?, publish_date=?, duration=?, " + - "bytes_total=?, bytes_downloaded=?, status=?, error_message=? where id=?"; - return update(sql, episode.getUrl(), episode.getPath(), episode.getTitle(), - episode.getDescription(), episode.getPublishDate(), episode.getDuration(), - episode.getBytesTotal(), episode.getBytesDownloaded(), episode.getStatus().name(), - episode.getErrorMessage(), episode.getId()); - } - - /** - * Deletes the Podcast episode with the given ID. - * - * @param id The Podcast episode ID. - */ - public void deleteEpisode(int id) { - String sql = "delete from podcast_episode where id=?"; - update(sql, id); - } - - private static class PodcastChannelRowMapper implements RowMapper { - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - return new PodcastChannel(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4), - PodcastStatus.valueOf(rs.getString(5)), rs.getString(6)); - } - } - - private static class PodcastEpisodeRowMapper implements ParameterizedRowMapper { - public PodcastEpisode mapRow(ResultSet rs, int rowNum) throws SQLException { - return new PodcastEpisode(rs.getInt(1), rs.getInt(2), rs.getString(3), rs.getString(4), rs.getString(5), - rs.getString(6), rs.getTimestamp(7), rs.getString(8), (Long) rs.getObject(9), - (Long) rs.getObject(10), PodcastStatus.valueOf(rs.getString(11)), rs.getString(12)); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/RatingDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/RatingDao.java deleted file mode 100644 index 221fe889..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/RatingDao.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import net.sourceforge.subsonic.domain.MediaFile; -import org.springframework.dao.EmptyResultDataAccessException; - -import java.util.ArrayList; -import java.util.List; - -/** - * Provides database services for ratings. - * - * @author Sindre Mehus - */ -public class RatingDao extends AbstractDao { - - /** - * Returns paths for the highest rated music files. - * - * @param offset Number of files to skip. - * @param count Maximum number of files to return. - * @return Paths for the highest rated music files. - */ - public List getHighestRated(int offset, int count) { - if (count < 1) { - return new ArrayList(); - } - - String sql = "select user_rating.path from user_rating, media_file " + - "where user_rating.path=media_file.path and media_file.present " + - "group by path " + - "order by avg(rating) desc limit " + count + " offset " + offset; - return queryForStrings(sql); - } - - /** - * Sets the rating for a media file and a given user. - * - * @param username The user name. - * @param mediaFile The media file. - * @param rating The rating between 1 and 5, or null to remove the rating. - */ - public void setRatingForUser(String username, MediaFile mediaFile, Integer rating) { - if (rating != null && (rating < 1 || rating > 5)) { - return; - } - - update("delete from user_rating where username=? and path=?", username, mediaFile.getPath()); - if (rating != null) { - update("insert into user_rating values(?, ?, ?)", username, mediaFile.getPath(), rating); - } - } - - /** - * Returns the average rating for the given media file. - * - * @param mediaFile The media file. - * @return The average rating, or null if no ratings are set. - */ - public Double getAverageRating(MediaFile mediaFile) { - try { - return (Double) getJdbcTemplate().queryForObject("select avg(rating) from user_rating where path=?", new Object[]{mediaFile.getPath()}, Double.class); - } catch (EmptyResultDataAccessException x) { - return null; - } - } - - /** - * Returns the rating for the given user and media file. - * - * @param username The user name. - * @param mediaFile The media file. - * @return The rating, or null if no rating is set. - */ - public Integer getRatingForUser(String username, MediaFile mediaFile) { - try { - return getJdbcTemplate().queryForInt("select rating from user_rating where username=? and path=?", new Object[]{username, mediaFile.getPath()}); - } catch (EmptyResultDataAccessException x) { - return null; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/ShareDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/ShareDao.java deleted file mode 100644 index 17d4cd73..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/ShareDao.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; - -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import net.sourceforge.subsonic.domain.Share; - -/** - * Provides database services for shared media. - * - * @author Sindre Mehus - */ -public class ShareDao extends AbstractDao { - - private static final String COLUMNS = "id, name, description, username, created, expires, last_visited, visit_count"; - - private ShareRowMapper shareRowMapper = new ShareRowMapper(); - private ShareFileRowMapper shareFileRowMapper = new ShareFileRowMapper(); - - /** - * Creates a new share. - * - * @param share The share to create. The ID of the share will be set by this method. - */ - public synchronized void createShare(Share share) { - String sql = "insert into share (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")"; - update(sql, null, share.getName(), share.getDescription(), share.getUsername(), share.getCreated(), - share.getExpires(), share.getLastVisited(), share.getVisitCount()); - - int id = getJdbcTemplate().queryForInt("select max(id) from share"); - share.setId(id); - } - - /** - * Returns all shares. - * - * @return Possibly empty list of all shares. - */ - public List getAllShares() { - String sql = "select " + COLUMNS + " from share"; - return query(sql, shareRowMapper); - } - - public Share getShareByName(String shareName) { - String sql = "select " + COLUMNS + " from share where name=?"; - return queryOne(sql, shareRowMapper, shareName); - } - - public Share getShareById(int id) { - String sql = "select " + COLUMNS + " from share where id=?"; - return queryOne(sql, shareRowMapper, id); - } - - /** - * Updates the given share. - * - * @param share The share to update. - */ - public void updateShare(Share share) { - String sql = "update share set name=?, description=?, username=?, created=?, expires=?, last_visited=?, visit_count=? where id=?"; - update(sql, share.getName(), share.getDescription(), share.getUsername(), share.getCreated(), share.getExpires(), - share.getLastVisited(), share.getVisitCount(), share.getId()); - } - - /** - * Creates shared files. - * - * @param shareId The share ID. - * @param paths Paths of the files to share. - */ - public void createSharedFiles(int shareId, String... paths) { - String sql = "insert into share_file (share_id, path) values (?, ?)"; - for (String path : paths) { - update(sql, shareId, path); - } - } - - /** - * Returns files for a share. - * - * @param shareId The ID of the share. - * @return The paths of the shared files. - */ - public List getSharedFiles(int shareId) { - return query("select path from share_file where share_id=?", shareFileRowMapper, shareId); - } - - /** - * Deletes the share with the given ID. - * - * @param id The ID of the share to delete. - */ - public void deleteShare(Integer id) { - update("delete from share where id=?", id); - } - - private static class ShareRowMapper implements ParameterizedRowMapper { - public Share mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Share(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getTimestamp(5), - rs.getTimestamp(6), rs.getTimestamp(7), rs.getInt(8)); - } - } - - private static class ShareFileRowMapper implements ParameterizedRowMapper { - public String mapRow(ResultSet rs, int rowNum) throws SQLException { - return rs.getString(1); - } - - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/TranscodingDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/TranscodingDao.java deleted file mode 100644 index 22b8ae20..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/TranscodingDao.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; - -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.Transcoding; - -/** - * Provides database services for transcoding configurations. - * - * @author Sindre Mehus - */ -public class TranscodingDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(TranscodingDao.class); - private static final String COLUMNS = "id, name, source_formats, target_format, step1, step2, step3, default_active"; - private TranscodingRowMapper rowMapper = new TranscodingRowMapper(); - - /** - * Returns all transcodings. - * - * @return Possibly empty list of all transcodings. - */ - public List getAllTranscodings() { - String sql = "select " + COLUMNS + " from transcoding2"; - return query(sql, rowMapper); - } - - /** - * Returns all active transcodings for the given player. - * - * @param playerId The player ID. - * @return All active transcodings for the player. - */ - public List getTranscodingsForPlayer(String playerId) { - String sql = "select " + COLUMNS + " from transcoding2, player_transcoding2 " + - "where player_transcoding2.player_id = ? " + - "and player_transcoding2.transcoding_id = transcoding2.id"; - return query(sql, rowMapper, playerId); - } - - /** - * Sets the list of active transcodings for the given player. - * - * @param playerId The player ID. - * @param transcodingIds ID's of the active transcodings. - */ - public void setTranscodingsForPlayer(String playerId, int[] transcodingIds) { - update("delete from player_transcoding2 where player_id = ?", playerId); - String sql = "insert into player_transcoding2(player_id, transcoding_id) values (?, ?)"; - for (int transcodingId : transcodingIds) { - update(sql, playerId, transcodingId); - } - } - - /** - * Creates a new transcoding. - * - * @param transcoding The transcoding to create. - */ - public synchronized void createTranscoding(Transcoding transcoding) { - int id = getJdbcTemplate().queryForInt("select max(id) + 1 from transcoding2"); - transcoding.setId(id); - String sql = "insert into transcoding2 (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")"; - update(sql, transcoding.getId(), transcoding.getName(), transcoding.getSourceFormats(), - transcoding.getTargetFormat(), transcoding.getStep1(), - transcoding.getStep2(), transcoding.getStep3(), transcoding.isDefaultActive()); - LOG.info("Created transcoding " + transcoding.getName()); - } - - /** - * Deletes the transcoding with the given ID. - * - * @param id The transcoding ID. - */ - public void deleteTranscoding(Integer id) { - String sql = "delete from transcoding2 where id=?"; - update(sql, id); - LOG.info("Deleted transcoding with ID " + id); - } - - /** - * Updates the given transcoding. - * - * @param transcoding The transcoding to update. - */ - public void updateTranscoding(Transcoding transcoding) { - String sql = "update transcoding2 set name=?, source_formats=?, target_format=?, " + - "step1=?, step2=?, step3=?, default_active=? where id=?"; - update(sql, transcoding.getName(), transcoding.getSourceFormats(), - transcoding.getTargetFormat(), transcoding.getStep1(), transcoding.getStep2(), - transcoding.getStep3(), transcoding.isDefaultActive(), transcoding.getId()); - } - - private static class TranscodingRowMapper implements ParameterizedRowMapper { - public Transcoding mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Transcoding(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), - rs.getString(6), rs.getString(7), rs.getBoolean(8)); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/UserDao.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/UserDao.java deleted file mode 100644 index e7807765..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/UserDao.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; - -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.AvatarScheme; -import net.sourceforge.subsonic.domain.TranscodeScheme; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.util.StringUtil; - -/** - * Provides user-related database services. - * - * @author Sindre Mehus - */ -public class UserDao extends AbstractDao { - - private static final Logger LOG = Logger.getLogger(UserDao.class); - private static final String USER_COLUMNS = "username, password, email, ldap_authenticated, bytes_streamed, bytes_downloaded, bytes_uploaded"; - private static final String USER_SETTINGS_COLUMNS = "username, locale, theme_id, final_version_notification, beta_version_notification, " + - "main_caption_cutoff, main_track_number, main_artist, main_album, main_genre, " + - "main_year, main_bit_rate, main_duration, main_format, main_file_size, " + - "playlist_caption_cutoff, playlist_track_number, playlist_artist, playlist_album, playlist_genre, " + - "playlist_year, playlist_bit_rate, playlist_duration, playlist_format, playlist_file_size, " + - "last_fm_enabled, last_fm_username, last_fm_password, transcode_scheme, show_now_playing, selected_music_folder_id, " + - "party_mode_enabled, now_playing_allowed, avatar_scheme, system_avatar_id, changed, show_chat"; - - private static final Integer ROLE_ID_ADMIN = 1; - private static final Integer ROLE_ID_DOWNLOAD = 2; - private static final Integer ROLE_ID_UPLOAD = 3; - private static final Integer ROLE_ID_PLAYLIST = 4; - private static final Integer ROLE_ID_COVER_ART = 5; - private static final Integer ROLE_ID_COMMENT = 6; - private static final Integer ROLE_ID_PODCAST = 7; - private static final Integer ROLE_ID_STREAM = 8; - private static final Integer ROLE_ID_SETTINGS = 9; - private static final Integer ROLE_ID_JUKEBOX = 10; - private static final Integer ROLE_ID_SHARE = 11; - - private UserRowMapper userRowMapper = new UserRowMapper(); - private UserSettingsRowMapper userSettingsRowMapper = new UserSettingsRowMapper(); - - /** - * Returns the user with the given username. - * - * @param username The username used when logging in. - * @return The user, or null if not found. - */ - public User getUserByName(String username) { - String sql = "select " + USER_COLUMNS + " from user where username=?"; - return queryOne(sql, userRowMapper, username); - } - - /** - * Returns the user with the given email address. - * - * @param email The email address. - * @return The user, or null if not found. - */ - public User getUserByEmail(String email) { - String sql = "select " + USER_COLUMNS + " from user where email=?"; - return queryOne(sql, userRowMapper, email); - } - - /** - * Returns all users. - * - * @return Possibly empty array of all users. - */ - public List getAllUsers() { - String sql = "select " + USER_COLUMNS + " from user"; - return query(sql, userRowMapper); - } - - /** - * Creates a new user. - * - * @param user The user to create. - */ - public void createUser(User user) { - String sql = "insert into user (" + USER_COLUMNS + ") values (" + questionMarks(USER_COLUMNS) + ')'; - update(sql, user.getUsername(), encrypt(user.getPassword()), user.getEmail(), user.isLdapAuthenticated(), - user.getBytesStreamed(), user.getBytesDownloaded(), user.getBytesUploaded()); - writeRoles(user); - } - - /** - * Deletes the user with the given username. - * - * @param username The username. - */ - public void deleteUser(String username) { - if (User.USERNAME_ADMIN.equals(username)) { - throw new IllegalArgumentException("Can't delete admin user."); - } - - String sql = "delete from user_role where username=?"; - update(sql, username); - - sql = "delete from user where username=?"; - update(sql, username); - } - - /** - * Updates the given user. - * - * @param user The user to update. - */ - public void updateUser(User user) { - String sql = "update user set password=?, email=?, ldap_authenticated=?, bytes_streamed=?, bytes_downloaded=?, bytes_uploaded=? " + - "where username=?"; - getJdbcTemplate().update(sql, new Object[]{encrypt(user.getPassword()), user.getEmail(), user.isLdapAuthenticated(), - user.getBytesStreamed(), user.getBytesDownloaded(), user.getBytesUploaded(), - user.getUsername()}); - writeRoles(user); - } - - /** - * Returns the name of the roles for the given user. - * - * @param username The user name. - * @return Roles the user is granted. - */ - public String[] getRolesForUser(String username) { - String sql = "select r.name from role r, user_role ur " + - "where ur.username=? and ur.role_id=r.id"; - List roles = getJdbcTemplate().queryForList(sql, new Object[]{username}, String.class); - String[] result = new String[roles.size()]; - for (int i = 0; i < result.length; i++) { - result[i] = (String) roles.get(i); - } - return result; - } - - /** - * Returns settings for the given user. - * - * @param username The username. - * @return User-specific settings, or null if no such settings exist. - */ - public UserSettings getUserSettings(String username) { - String sql = "select " + USER_SETTINGS_COLUMNS + " from user_settings where username=?"; - return queryOne(sql, userSettingsRowMapper, username); - } - - /** - * Updates settings for the given username, creating it if necessary. - * - * @param settings The user-specific settings. - */ - public void updateUserSettings(UserSettings settings) { - getJdbcTemplate().update("delete from user_settings where username=?", new Object[]{settings.getUsername()}); - - String sql = "insert into user_settings (" + USER_SETTINGS_COLUMNS + ") values (" + questionMarks(USER_SETTINGS_COLUMNS) + ')'; - String locale = settings.getLocale() == null ? null : settings.getLocale().toString(); - UserSettings.Visibility main = settings.getMainVisibility(); - UserSettings.Visibility playlist = settings.getPlaylistVisibility(); - getJdbcTemplate().update(sql, new Object[]{settings.getUsername(), locale, settings.getThemeId(), - settings.isFinalVersionNotificationEnabled(), settings.isBetaVersionNotificationEnabled(), - main.getCaptionCutoff(), main.isTrackNumberVisible(), main.isArtistVisible(), main.isAlbumVisible(), - main.isGenreVisible(), main.isYearVisible(), main.isBitRateVisible(), main.isDurationVisible(), - main.isFormatVisible(), main.isFileSizeVisible(), - playlist.getCaptionCutoff(), playlist.isTrackNumberVisible(), playlist.isArtistVisible(), playlist.isAlbumVisible(), - playlist.isGenreVisible(), playlist.isYearVisible(), playlist.isBitRateVisible(), playlist.isDurationVisible(), - playlist.isFormatVisible(), playlist.isFileSizeVisible(), - settings.isLastFmEnabled(), settings.getLastFmUsername(), encrypt(settings.getLastFmPassword()), - settings.getTranscodeScheme().name(), settings.isShowNowPlayingEnabled(), - settings.getSelectedMusicFolderId(), settings.isPartyModeEnabled(), settings.isNowPlayingAllowed(), - settings.getAvatarScheme().name(), settings.getSystemAvatarId(), settings.getChanged(), settings.isShowChatEnabled()}); - } - - private static String encrypt(String s) { - if (s == null) { - return null; - } - try { - return "enc:" + StringUtil.utf8HexEncode(s); - } catch (Exception e) { - return s; - } - } - - private static String decrypt(String s) { - if (s == null) { - return null; - } - if (!s.startsWith("enc:")) { - return s; - } - try { - return StringUtil.utf8HexDecode(s.substring(4)); - } catch (Exception e) { - return s; - } - } - - private void readRoles(User user) { - synchronized (user.getUsername().intern()) { - String sql = "select role_id from user_role where username=?"; - List roles = getJdbcTemplate().queryForList(sql, new Object[]{user.getUsername()}, Integer.class); - for (Object role : roles) { - if (ROLE_ID_ADMIN.equals(role)) { - user.setAdminRole(true); - } else if (ROLE_ID_DOWNLOAD.equals(role)) { - user.setDownloadRole(true); - } else if (ROLE_ID_UPLOAD.equals(role)) { - user.setUploadRole(true); - } else if (ROLE_ID_PLAYLIST.equals(role)) { - user.setPlaylistRole(true); - } else if (ROLE_ID_COVER_ART.equals(role)) { - user.setCoverArtRole(true); - } else if (ROLE_ID_COMMENT.equals(role)) { - user.setCommentRole(true); - } else if (ROLE_ID_PODCAST.equals(role)) { - user.setPodcastRole(true); - } else if (ROLE_ID_STREAM.equals(role)) { - user.setStreamRole(true); - } else if (ROLE_ID_SETTINGS.equals(role)) { - user.setSettingsRole(true); - } else if (ROLE_ID_JUKEBOX.equals(role)) { - user.setJukeboxRole(true); - } else if (ROLE_ID_SHARE.equals(role)) { - user.setShareRole(true); - } else { - LOG.warn("Unknown role: '" + role + '\''); - } - } - } - } - - private void writeRoles(User user) { - synchronized (user.getUsername().intern()) { - String sql = "delete from user_role where username=?"; - getJdbcTemplate().update(sql, new Object[]{user.getUsername()}); - sql = "insert into user_role (username, role_id) values(?, ?)"; - if (user.isAdminRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_ADMIN}); - } - if (user.isDownloadRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_DOWNLOAD}); - } - if (user.isUploadRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_UPLOAD}); - } - if (user.isPlaylistRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_PLAYLIST}); - } - if (user.isCoverArtRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_COVER_ART}); - } - if (user.isCommentRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_COMMENT}); - } - if (user.isPodcastRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_PODCAST}); - } - if (user.isStreamRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_STREAM}); - } - if (user.isJukeboxRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_JUKEBOX}); - } - if (user.isSettingsRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_SETTINGS}); - } - if (user.isShareRole()) { - getJdbcTemplate().update(sql, new Object[]{user.getUsername(), ROLE_ID_SHARE}); - } - } - } - - private class UserRowMapper implements ParameterizedRowMapper { - public User mapRow(ResultSet rs, int rowNum) throws SQLException { - User user = new User(rs.getString(1), decrypt(rs.getString(2)), rs.getString(3), rs.getBoolean(4), - rs.getLong(5), rs.getLong(6), rs.getLong(7)); - readRoles(user); - return user; - } - } - - private static class UserSettingsRowMapper implements ParameterizedRowMapper { - public UserSettings mapRow(ResultSet rs, int rowNum) throws SQLException { - int col = 1; - UserSettings settings = new UserSettings(rs.getString(col++)); - settings.setLocale(StringUtil.parseLocale(rs.getString(col++))); - settings.setThemeId(rs.getString(col++)); - settings.setFinalVersionNotificationEnabled(rs.getBoolean(col++)); - settings.setBetaVersionNotificationEnabled(rs.getBoolean(col++)); - - settings.getMainVisibility().setCaptionCutoff(rs.getInt(col++)); - settings.getMainVisibility().setTrackNumberVisible(rs.getBoolean(col++)); - settings.getMainVisibility().setArtistVisible(rs.getBoolean(col++)); - settings.getMainVisibility().setAlbumVisible(rs.getBoolean(col++)); - settings.getMainVisibility().setGenreVisible(rs.getBoolean(col++)); - settings.getMainVisibility().setYearVisible(rs.getBoolean(col++)); - settings.getMainVisibility().setBitRateVisible(rs.getBoolean(col++)); - settings.getMainVisibility().setDurationVisible(rs.getBoolean(col++)); - settings.getMainVisibility().setFormatVisible(rs.getBoolean(col++)); - settings.getMainVisibility().setFileSizeVisible(rs.getBoolean(col++)); - - settings.getPlaylistVisibility().setCaptionCutoff(rs.getInt(col++)); - settings.getPlaylistVisibility().setTrackNumberVisible(rs.getBoolean(col++)); - settings.getPlaylistVisibility().setArtistVisible(rs.getBoolean(col++)); - settings.getPlaylistVisibility().setAlbumVisible(rs.getBoolean(col++)); - settings.getPlaylistVisibility().setGenreVisible(rs.getBoolean(col++)); - settings.getPlaylistVisibility().setYearVisible(rs.getBoolean(col++)); - settings.getPlaylistVisibility().setBitRateVisible(rs.getBoolean(col++)); - settings.getPlaylistVisibility().setDurationVisible(rs.getBoolean(col++)); - settings.getPlaylistVisibility().setFormatVisible(rs.getBoolean(col++)); - settings.getPlaylistVisibility().setFileSizeVisible(rs.getBoolean(col++)); - - settings.setLastFmEnabled(rs.getBoolean(col++)); - settings.setLastFmUsername(rs.getString(col++)); - settings.setLastFmPassword(decrypt(rs.getString(col++))); - - settings.setTranscodeScheme(TranscodeScheme.valueOf(rs.getString(col++))); - settings.setShowNowPlayingEnabled(rs.getBoolean(col++)); - settings.setSelectedMusicFolderId(rs.getInt(col++)); - settings.setPartyModeEnabled(rs.getBoolean(col++)); - settings.setNowPlayingAllowed(rs.getBoolean(col++)); - settings.setAvatarScheme(AvatarScheme.valueOf(rs.getString(col++))); - settings.setSystemAvatarId((Integer) rs.getObject(col++)); - settings.setChanged(rs.getTimestamp(col++)); - settings.setShowChatEnabled(rs.getBoolean(col++)); - - return settings; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema.java deleted file mode 100644 index 674f85ca..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import org.springframework.jdbc.core.*; - -/** - * Used for creating and evolving the database schema. - * - * @author Sindre Mehus - */ -public abstract class Schema { - - /** - * Executes this schema. - * @param template The JDBC template to use. - */ - public abstract void execute(JdbcTemplate template); - - /** - * Returns whether the given table exists. - * @param template The JDBC template to use. - * @param table The table in question. - * @return Whether the table exists. - */ - protected boolean tableExists(JdbcTemplate template, String table) { - try { - template.execute("select 1 from " + table); - } catch (Exception x) { - return false; - } - return true; - } - - /** - * Returns whether the given column in the given table exists. - * @param template The JDBC template to use. - * @param column The column in question. - * @param table The table in question. - * @return Whether the column exists. - */ - protected boolean columnExists(JdbcTemplate template, String column, String table) { - try { - template.execute("select " + column + " from " + table + " where 1 = 0"); - } catch (Exception x) { - return false; - } - return true; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema25.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema25.java deleted file mode 100644 index 33cc2525..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema25.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import org.springframework.jdbc.core.*; -import net.sourceforge.subsonic.*; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 2.5. - * - * @author Sindre Mehus - */ -public class Schema25 extends Schema{ - private static final Logger LOG = Logger.getLogger(Schema25.class); - - public void execute(JdbcTemplate template) { - if (!tableExists(template, "version")) { - LOG.info("Database table 'version' not found. Creating it."); - template.execute("create table version (version int not null)"); - template.execute("insert into version values (1)"); - LOG.info("Database table 'version' was created successfully."); - } - - if (!tableExists(template, "role")) { - LOG.info("Database table 'role' not found. Creating it."); - template.execute("create table role (" + - "id int not null," + - "name varchar not null," + - "primary key (id))"); - template.execute("insert into role values (1, 'admin')"); - template.execute("insert into role values (2, 'download')"); - template.execute("insert into role values (3, 'upload')"); - template.execute("insert into role values (4, 'playlist')"); - template.execute("insert into role values (5, 'coverart')"); - LOG.info("Database table 'role' was created successfully."); - } - - if (!tableExists(template, "user")) { - LOG.info("Database table 'user' not found. Creating it."); - template.execute("create table user (" + - "username varchar not null," + - "password varchar not null," + - "primary key (username))"); - template.execute("insert into user values ('admin', 'admin')"); - LOG.info("Database table 'user' was created successfully."); - } - - if (!tableExists(template, "user_role")) { - LOG.info("Database table 'user_role' not found. Creating it."); - template.execute("create table user_role (" + - "username varchar not null," + - "role_id int not null," + - "primary key (username, role_id)," + - "foreign key (username) references user(username)," + - "foreign key (role_id) references role(id))"); - template.execute("insert into user_role values ('admin', 1)"); - template.execute("insert into user_role values ('admin', 2)"); - template.execute("insert into user_role values ('admin', 3)"); - template.execute("insert into user_role values ('admin', 4)"); - template.execute("insert into user_role values ('admin', 5)"); - LOG.info("Database table 'user_role' was created successfully."); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema26.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema26.java deleted file mode 100644 index 6d60b29b..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema26.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.*; -import net.sourceforge.subsonic.util.Util; -import org.springframework.jdbc.core.*; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 2.6. - * - * @author Sindre Mehus - */ -public class Schema26 extends Schema{ - private static final Logger LOG = Logger.getLogger(Schema26.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 2") == 0) { - LOG.info("Updating database schema to version 2."); - template.execute("insert into version values (2)"); - } - - if (!tableExists(template, "music_folder")) { - LOG.info("Database table 'music_folder' not found. Creating it."); - template.execute("create table music_folder (" + - "id identity," + - "path varchar not null," + - "name varchar not null," + - "enabled boolean not null)"); - template.execute("insert into music_folder values (null, '" + Util.getDefaultMusicFolder() + "', 'Music', true)"); - LOG.info("Database table 'music_folder' was created successfully."); - } - - if (!tableExists(template, "music_file_info")) { - LOG.info("Database table 'music_file_info' not found. Creating it."); - template.execute("create cached table music_file_info (" + - "id identity," + - "path varchar not null," + - "rating int," + - "comment varchar," + - "play_count int," + - "last_played datetime)"); - template.execute("create index idx_music_file_info_path on music_file_info(path)"); - LOG.info("Database table 'music_file_info' was created successfully."); - } - - if (!tableExists(template, "internet_radio")) { - LOG.info("Database table 'internet_radio' not found. Creating it."); - template.execute("create table internet_radio (" + - "id identity," + - "name varchar not null," + - "stream_url varchar not null," + - "homepage_url varchar," + - "enabled boolean not null)"); - LOG.info("Database table 'internet_radio' was created successfully."); - } - - if (!tableExists(template, "player")) { - LOG.info("Database table 'player' not found. Creating it."); - template.execute("create table player (" + - "id int not null," + - "name varchar," + - "type varchar," + - "username varchar," + - "ip_address varchar," + - "auto_control_enabled boolean not null," + - "last_seen datetime," + - "cover_art_scheme varchar not null," + - "transcode_scheme varchar not null," + - "primary key (id))"); - LOG.info("Database table 'player' was created successfully."); - } - - // 'dynamic_ip' was added in 2.6.beta2 - if (!columnExists(template, "dynamic_ip", "player")) { - LOG.info("Database column 'player.dynamic_ip' not found. Creating it."); - template.execute("alter table player " + - "add dynamic_ip boolean default true not null"); - LOG.info("Database column 'player.dynamic_ip' was added successfully."); - } - - if (template.queryForInt("select count(*) from role where id = 6") == 0) { - LOG.info("Role 'comment' not found in database. Creating it."); - template.execute("insert into role values (6, 'comment')"); - template.execute("insert into user_role " + - "select distinct u.username, 6 from user u, user_role ur " + - "where u.username = ur.username and ur.role_id in (1, 5)"); - LOG.info("Role 'comment' was created successfully."); - } - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema27.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema27.java deleted file mode 100644 index 4057622e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema27.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.*; -import org.springframework.jdbc.core.*; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 2.7. - * - * @author Sindre Mehus - */ -public class Schema27 extends Schema{ - private static final Logger LOG = Logger.getLogger(Schema27.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 3") == 0) { - LOG.info("Updating database schema to version 3."); - template.execute("insert into version values (3)"); - - LOG.info("Converting database column 'music_file_info.path' to varchar_ignorecase."); - template.execute("drop index idx_music_file_info_path"); - template.execute("alter table music_file_info alter column path varchar_ignorecase not null"); - template.execute("create index idx_music_file_info_path on music_file_info(path)"); - LOG.info("Database column 'music_file_info.path' was converted successfully."); - } - - if (!columnExists(template, "bytes_streamed", "user")) { - LOG.info("Database columns 'user.bytes_streamed/downloaded/uploaded' not found. Creating them."); - template.execute("alter table user add bytes_streamed bigint default 0 not null"); - template.execute("alter table user add bytes_downloaded bigint default 0 not null"); - template.execute("alter table user add bytes_uploaded bigint default 0 not null"); - LOG.info("Database columns 'user.bytes_streamed/downloaded/uploaded' were added successfully."); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema28.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema28.java deleted file mode 100644 index dbee6730..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema28.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.*; -import org.springframework.jdbc.core.*; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 2.8. - * - * @author Sindre Mehus - */ -public class Schema28 extends Schema { - private static final Logger LOG = Logger.getLogger(Schema28.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 4") == 0) { - LOG.info("Updating database schema to version 4."); - template.execute("insert into version values (4)"); - } - - if (!tableExists(template, "user_settings")) { - LOG.info("Database table 'user_settings' not found. Creating it."); - template.execute("create table user_settings (" + - "username varchar not null," + - "locale varchar," + - "theme_id varchar," + - "final_version_notification boolean default true not null," + - "beta_version_notification boolean default false not null," + - "main_caption_cutoff int default 35 not null," + - "main_track_number boolean default true not null," + - "main_artist boolean default true not null," + - "main_album boolean default false not null," + - "main_genre boolean default false not null," + - "main_year boolean default false not null," + - "main_bit_rate boolean default false not null," + - "main_duration boolean default true not null," + - "main_format boolean default false not null," + - "main_file_size boolean default false not null," + - "playlist_caption_cutoff int default 35 not null," + - "playlist_track_number boolean default false not null," + - "playlist_artist boolean default true not null," + - "playlist_album boolean default true not null," + - "playlist_genre boolean default false not null," + - "playlist_year boolean default true not null," + - "playlist_bit_rate boolean default false not null," + - "playlist_duration boolean default true not null," + - "playlist_format boolean default true not null," + - "playlist_file_size boolean default true not null," + - "primary key (username)," + - "foreign key (username) references user(username) on delete cascade)"); - LOG.info("Database table 'user_settings' was created successfully."); - } - - if (!tableExists(template, "transcoding")) { - LOG.info("Database table 'transcoding' not found. Creating it."); - template.execute("create table transcoding (" + - "id identity," + - "name varchar not null," + - "source_format varchar not null," + - "target_format varchar not null," + - "step1 varchar not null," + - "step2 varchar," + - "step3 varchar," + - "enabled boolean not null)"); - - template.execute("insert into transcoding values(null,'wav > mp3', 'wav', 'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,true)"); - template.execute("insert into transcoding values(null,'flac > mp3','flac','mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,true)"); - template.execute("insert into transcoding values(null,'ogg > mp3' ,'ogg' ,'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,true)"); - template.execute("insert into transcoding values(null,'wma > mp3' ,'wma' ,'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,true)"); - template.execute("insert into transcoding values(null,'m4a > mp3' ,'m4a' ,'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,false)"); - template.execute("insert into transcoding values(null,'aac > mp3' ,'aac' ,'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,false)"); - template.execute("insert into transcoding values(null,'ape > mp3' ,'ape' ,'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,true)"); - template.execute("insert into transcoding values(null,'mpc > mp3' ,'mpc' ,'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,true)"); - template.execute("insert into transcoding values(null,'mv > mp3' ,'mv' ,'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,true)"); - template.execute("insert into transcoding values(null,'shn > mp3' ,'shn' ,'mp3','ffmpeg -i %s -v 0 -f wav -','lame -b %b --tt %t --ta %a --tl %l -S --resample 44.1 - -',null,true)"); - - LOG.info("Database table 'transcoding' was created successfully."); - } - - if (!tableExists(template, "player_transcoding")) { - LOG.info("Database table 'player_transcoding' not found. Creating it."); - template.execute("create table player_transcoding (" + - "player_id int not null," + - "transcoding_id int not null," + - "primary key (player_id, transcoding_id)," + - "foreign key (player_id) references player(id) on delete cascade," + - "foreign key (transcoding_id) references transcoding(id) on delete cascade)"); - LOG.info("Database table 'player_transcoding' was created successfully."); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema29.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema29.java deleted file mode 100644 index dd4748d1..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema29.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.*; -import org.springframework.jdbc.core.*; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 2.9. - * - * @author Sindre Mehus - */ -public class Schema29 extends Schema { - private static final Logger LOG = Logger.getLogger(Schema29.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 5") == 0) { - LOG.info("Updating database schema to version 5."); - template.execute("insert into version values (5)"); - } - - if (!tableExists(template, "user_rating")) { - LOG.info("Database table 'user_rating' not found. Creating it."); - template.execute("create table user_rating (" + - "username varchar not null," + - "path varchar not null," + - "rating double not null," + - "primary key (username, path)," + - "foreign key (username) references user(username) on delete cascade)"); - LOG.info("Database table 'user_rating' was created successfully."); - - template.execute("insert into user_rating select 'admin', path, rating from music_file_info " + - "where rating is not null and rating > 0"); - LOG.info("Migrated data from 'music_file_info' to 'user_rating'."); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema30.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema30.java deleted file mode 100644 index cdea199b..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema30.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.*; -import net.sourceforge.subsonic.domain.TranscodeScheme; -import org.springframework.jdbc.core.*; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 3.0. - * - * @author Sindre Mehus - */ -public class Schema30 extends Schema { - private static final Logger LOG = Logger.getLogger(Schema30.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 6") == 0) { - LOG.info("Updating database schema to version 6."); - template.execute("insert into version values (6)"); - } - - if (!columnExists(template, "last_fm_enabled", "user_settings")) { - LOG.info("Database columns 'user_settings.last_fm_*' not found. Creating them."); - template.execute("alter table user_settings add last_fm_enabled boolean default false not null"); - template.execute("alter table user_settings add last_fm_username varchar null"); - template.execute("alter table user_settings add last_fm_password varchar null"); - LOG.info("Database columns 'user_settings.last_fm_*' were added successfully."); - } - - if (!columnExists(template, "transcode_scheme", "user_settings")) { - LOG.info("Database column 'user_settings.transcode_scheme' not found. Creating it."); - template.execute("alter table user_settings add transcode_scheme varchar default '" + - TranscodeScheme.OFF.name() + "' not null"); - LOG.info("Database column 'user_settings.transcode_scheme' was added successfully."); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema31.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema31.java deleted file mode 100644 index 00fb0c87..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema31.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 3.1. - * - * @author Sindre Mehus - */ -public class Schema31 extends Schema { - private static final Logger LOG = Logger.getLogger(Schema31.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 7") == 0) { - LOG.info("Updating database schema to version 7."); - template.execute("insert into version values (7)"); - } - - if (!columnExists(template, "enabled", "music_file_info")) { - LOG.info("Database column 'music_file_info.enabled' not found. Creating it."); - template.execute("alter table music_file_info add enabled boolean default true not null"); - LOG.info("Database column 'music_file_info.enabled' was added successfully."); - } - - if (!columnExists(template, "default_active", "transcoding")) { - LOG.info("Database column 'transcoding.default_active' not found. Creating it."); - template.execute("alter table transcoding add default_active boolean default true not null"); - LOG.info("Database column 'transcoding.default_active' was added successfully."); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema32.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema32.java deleted file mode 100644 index a1439bb0..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema32.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 3.2. - * - * @author Sindre Mehus - */ -public class Schema32 extends Schema { - private static final Logger LOG = Logger.getLogger(Schema32.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 8") == 0) { - LOG.info("Updating database schema to version 8."); - template.execute("insert into version values (8)"); - } - - if (!columnExists(template, "show_now_playing", "user_settings")) { - LOG.info("Database column 'user_settings.show_now_playing' not found. Creating it."); - template.execute("alter table user_settings add show_now_playing boolean default true not null"); - LOG.info("Database column 'user_settings.show_now_playing' was added successfully."); - } - - if (!columnExists(template, "selected_music_folder_id", "user_settings")) { - LOG.info("Database column 'user_settings.selected_music_folder_id' not found. Creating it."); - template.execute("alter table user_settings add selected_music_folder_id int default -1 not null"); - LOG.info("Database column 'user_settings.selected_music_folder_id' was added successfully."); - } - - if (!tableExists(template, "podcast_channel")) { - LOG.info("Database table 'podcast_channel' not found. Creating it."); - template.execute("create table podcast_channel (" + - "id identity," + - "url varchar not null," + - "title varchar," + - "description varchar," + - "status varchar not null," + - "error_message varchar)"); - LOG.info("Database table 'podcast_channel' was created successfully."); - } - - if (!tableExists(template, "podcast_episode")) { - LOG.info("Database table 'podcast_episode' not found. Creating it."); - template.execute("create table podcast_episode (" + - "id identity," + - "channel_id int not null," + - "url varchar not null," + - "path varchar," + - "title varchar," + - "description varchar," + - "publish_date datetime," + - "duration varchar," + - "bytes_total bigint," + - "bytes_downloaded bigint," + - "status varchar not null," + - "error_message varchar," + - "foreign key (channel_id) references podcast_channel(id) on delete cascade)"); - LOG.info("Database table 'podcast_episode' was created successfully."); - } - - if (template.queryForInt("select count(*) from role where id = 7") == 0) { - LOG.info("Role 'podcast' not found in database. Creating it."); - template.execute("insert into role values (7, 'podcast')"); - template.execute("insert into user_role " + - "select distinct u.username, 7 from user u, user_role ur " + - "where u.username = ur.username and ur.role_id = 1"); - LOG.info("Role 'podcast' was created successfully."); - } - - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema33.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema33.java deleted file mode 100644 index 6f754306..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema33.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 3.3. - * - * @author Sindre Mehus - */ -public class Schema33 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema33.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 9") == 0) { - LOG.info("Updating database schema to version 9."); - template.execute("insert into version values (9)"); - } - - if (!columnExists(template, "client_side_playlist", "player")) { - LOG.info("Database column 'player.client_side_playlist' not found. Creating it."); - template.execute("alter table player add client_side_playlist boolean default false not null"); - LOG.info("Database column 'player.client_side_playlist' was added successfully."); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema34.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema34.java deleted file mode 100644 index daaf98ca..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema34.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 3.4. - * - * @author Sindre Mehus - */ -public class Schema34 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema34.class); - - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 10") == 0) { - LOG.info("Updating database schema to version 10."); - template.execute("insert into version values (10)"); - } - - if (!columnExists(template, "ldap_authenticated", "user")) { - LOG.info("Database column 'user.ldap_authenticated' not found. Creating it."); - template.execute("alter table user add ldap_authenticated boolean default false not null"); - LOG.info("Database column 'user.ldap_authenticated' was added successfully."); - } - - if (!columnExists(template, "party_mode_enabled", "user_settings")) { - LOG.info("Database column 'user_settings.party_mode_enabled' not found. Creating it."); - template.execute("alter table user_settings add party_mode_enabled boolean default false not null"); - LOG.info("Database column 'user_settings.party_mode_enabled' was added successfully."); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema35.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema35.java deleted file mode 100644 index 56b5073d..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema35.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.apache.commons.io.IOUtils; -import org.springframework.jdbc.core.JdbcTemplate; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Date; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 3.5. - * - * @author Sindre Mehus - */ -public class Schema35 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema35.class); - - private static final String[] AVATARS = { - "Formal", "Engineer", "Footballer", "Green-Boy", - - "Linux-Zealot", "Mac-Zealot", "Windows-Zealot", "Army-Officer", "Beatnik", - "All-Caps", "Clown", "Commie-Pinko", "Forum-Flirt", "Gamer", "Hopelessly-Addicted", - "Jekyll-And-Hyde", "Joker", "Lurker", "Moderator", "Newbie", "No-Dissent", - "Performer", "Push-My-Button", "Ray-Of-Sunshine", "Red-Hot-Chili-Peppers-1", - "Red-Hot-Chili-Peppers-2", "Red-Hot-Chili-Peppers-3", "Red-Hot-Chili-Peppers-4", - "Ringmaster", "Rumor-Junkie", "Sozzled-Surfer", "Statistician", "Tech-Support", - "The-Guru", "The-Referee", "Troll", "Uptight", - - "Fire-Guitar", "Drum", "Headphones", "Mic", "Turntable", "Vinyl", - - "Cool", "Laugh", "Study" - }; - - @Override - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 11") == 0) { - LOG.info("Updating database schema to version 11."); - template.execute("insert into version values (11)"); - } - - if (!columnExists(template, "now_playing_allowed", "user_settings")) { - LOG.info("Database column 'user_settings.now_playing_allowed' not found. Creating it."); - template.execute("alter table user_settings add now_playing_allowed boolean default true not null"); - LOG.info("Database column 'user_settings.now_playing_allowed' was added successfully."); - } - - if (!columnExists(template, "web_player_default", "user_settings")) { - LOG.info("Database column 'user_settings.web_player_default' not found. Creating it."); - template.execute("alter table user_settings add web_player_default boolean default false not null"); - LOG.info("Database column 'user_settings.web_player_default' was added successfully."); - } - - if (template.queryForInt("select count(*) from role where id = 8") == 0) { - LOG.info("Role 'stream' not found in database. Creating it."); - template.execute("insert into role values (8, 'stream')"); - template.execute("insert into user_role select distinct u.username, 8 from user u"); - LOG.info("Role 'stream' was created successfully."); - } - - if (!tableExists(template, "system_avatar")) { - LOG.info("Database table 'system_avatar' not found. Creating it."); - template.execute("create table system_avatar (" + - "id identity," + - "name varchar," + - "created_date datetime not null," + - "mime_type varchar not null," + - "width int not null," + - "height int not null," + - "data binary not null)"); - LOG.info("Database table 'system_avatar' was created successfully."); - } - - for (String avatar : AVATARS) { - createAvatar(template, avatar); - } - - if (!tableExists(template, "custom_avatar")) { - LOG.info("Database table 'custom_avatar' not found. Creating it."); - template.execute("create table custom_avatar (" + - "id identity," + - "name varchar," + - "created_date datetime not null," + - "mime_type varchar not null," + - "width int not null," + - "height int not null," + - "data binary not null," + - "username varchar not null," + - "foreign key (username) references user(username) on delete cascade)"); - LOG.info("Database table 'custom_avatar' was created successfully."); - } - - if (!columnExists(template, "avatar_scheme", "user_settings")) { - LOG.info("Database column 'user_settings.avatar_scheme' not found. Creating it."); - template.execute("alter table user_settings add avatar_scheme varchar default 'NONE' not null"); - LOG.info("Database column 'user_settings.avatar_scheme' was added successfully."); - } - - if (!columnExists(template, "system_avatar_id", "user_settings")) { - LOG.info("Database column 'user_settings.system_avatar_id' not found. Creating it."); - template.execute("alter table user_settings add system_avatar_id int"); - template.execute("alter table user_settings add foreign key (system_avatar_id) references system_avatar(id)"); - LOG.info("Database column 'user_settings.system_avatar_id' was added successfully."); - } - - if (!columnExists(template, "jukebox", "player")) { - LOG.info("Database column 'player.jukebox' not found. Creating it."); - template.execute("alter table player add jukebox boolean default false not null"); - LOG.info("Database column 'player.jukebox' was added successfully."); - } - } - - private void createAvatar(JdbcTemplate template, String avatar) { - if (template.queryForInt("select count(*) from system_avatar where name = ?", new Object[]{avatar}) == 0) { - - InputStream in = null; - try { - in = getClass().getResourceAsStream(avatar + ".png"); - byte[] imageData = IOUtils.toByteArray(in); - template.update("insert into system_avatar values (null, ?, ?, ?, ?, ?, ?)", - new Object[]{avatar, new Date(), "image/png", 48, 48, imageData}); - LOG.info("Created avatar '" + avatar + "'."); - } catch (IOException x) { - LOG.error("Failed to create avatar '" + avatar + "'.", x); - } finally { - IOUtils.closeQuietly(in); - } - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema36.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema36.java deleted file mode 100644 index caed6cdb..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema36.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implementes the database schema for Subsonic version 3.6. - * - * @author Sindre Mehus - */ -public class Schema36 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema36.class); - - @Override - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 12") == 0) { - LOG.info("Updating database schema to version 12."); - template.execute("insert into version values (12)"); - } - - if (!columnExists(template, "technology", "player")) { - LOG.info("Database column 'player.technology' not found. Creating it."); - template.execute("alter table player add technology varchar default 'WEB' not null"); - LOG.info("Database column 'player.technology' was added successfully."); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema37.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema37.java deleted file mode 100644 index afb8fb6e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema37.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implements the database schema for Subsonic version 3.7. - * - * @author Sindre Mehus - */ -public class Schema37 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema37.class); - - @Override - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 13") == 0) { - LOG.info("Updating database schema to version 13."); - template.execute("insert into version values (13)"); - } - - if (template.queryForInt("select count(*) from role where id = 9") == 0) { - LOG.info("Role 'settings' not found in database. Creating it."); - template.execute("insert into role values (9, 'settings')"); - template.execute("insert into user_role select distinct u.username, 9 from user u"); - LOG.info("Role 'settings' was created successfully."); - } - - if (template.queryForInt("select count(*) from role where id = 10") == 0) { - LOG.info("Role 'jukebox' not found in database. Creating it."); - template.execute("insert into role values (10, 'jukebox')"); - template.execute("insert into user_role " + - "select distinct u.username, 10 from user u, user_role ur " + - "where u.username = ur.username and ur.role_id = 1"); - LOG.info("Role 'jukebox' was created successfully."); - } - - if (!columnExists(template, "changed", "music_folder")) { - LOG.info("Database column 'music_folder.changed' not found. Creating it."); - template.execute("alter table music_folder add changed datetime default 0 not null"); - LOG.info("Database column 'music_folder.changed' was added successfully."); - } - - if (!columnExists(template, "changed", "internet_radio")) { - LOG.info("Database column 'internet_radio.changed' not found. Creating it."); - template.execute("alter table internet_radio add changed datetime default 0 not null"); - LOG.info("Database column 'internet_radio.changed' was added successfully."); - } - - if (!columnExists(template, "changed", "user_settings")) { - LOG.info("Database column 'user_settings.changed' not found. Creating it."); - template.execute("alter table user_settings add changed datetime default 0 not null"); - LOG.info("Database column 'user_settings.changed' was added successfully."); - } - - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema38.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema38.java deleted file mode 100644 index fac49511..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema38.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implements the database schema for Subsonic version 3.8. - * - * @author Sindre Mehus - */ -public class Schema38 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema38.class); - - @Override - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 14") == 0) { - LOG.info("Updating database schema to version 14."); - template.execute("insert into version values (14)"); - } - - if (!columnExists(template, "client_id", "player")) { - LOG.info("Database column 'player.client_id' not found. Creating it."); - template.execute("alter table player add client_id varchar"); - LOG.info("Database column 'player.client_id' was added successfully."); - } - - if (!columnExists(template, "show_chat", "user_settings")) { - LOG.info("Database column 'user_settings.show_chat' not found. Creating it."); - template.execute("alter table user_settings add show_chat boolean default true not null"); - LOG.info("Database column 'user_settings.show_chat' was added successfully."); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema40.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema40.java deleted file mode 100644 index e01d1ef0..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema40.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implements the database schema for Subsonic version 4.0. - * - * @author Sindre Mehus - */ -public class Schema40 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema40.class); - - @Override - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 15") == 0) { - LOG.info("Updating database schema to version 15."); - template.execute("insert into version values (15)"); - - // Reset stream byte count since they have been wrong in earlier releases. - template.execute("update user set bytes_streamed = 0"); - LOG.info("Reset stream byte count statistics."); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema43.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema43.java deleted file mode 100644 index cba1572c..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema43.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import org.springframework.jdbc.core.JdbcTemplate; - -import net.sourceforge.subsonic.Logger; - -import java.util.Arrays; - -/** - * Used for creating and evolving the database schema. - * This class implements the database schema for Subsonic version 4.3. - * - * @author Sindre Mehus - */ -public class Schema43 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema43.class); - - @Override - public void execute(JdbcTemplate template) { - - // version 16 was used for 4.3.beta1 - if (template.queryForInt("select count(*) from version where version = 16") == 0) { - LOG.info("Updating database schema to version 16."); - template.execute("insert into version values (16)"); - } - - if (template.queryForInt("select count(*) from version where version = 17") == 0) { - LOG.info("Updating database schema to version 17."); - template.execute("insert into version values (17)"); - - for (String format : Arrays.asList("avi", "mpg", "mpeg", "mp4", "m4v", "mkv", "mov", "wmv", "ogv")) { - template.update("delete from transcoding where source_format=? and target_format=?", new Object[] {format, "flv"}); - template.execute("insert into transcoding values(null,'" + format + " > flv' ,'" + format + "' ,'flv','ffmpeg -ss %o -i %s -async 1 -b %bk -s %wx%h -ar 44100 -ac 2 -v 0 -f flv -',null,null,true,true)"); - template.execute("insert into player_transcoding select p.id as player_id, t.id as transaction_id from player p, transcoding t where t.name = '" + format + " > flv'"); - } - LOG.info("Created video transcoding configuration."); - } - - if (!columnExists(template, "email", "user")) { - LOG.info("Database column 'user.email' not found. Creating it."); - template.execute("alter table user add email varchar"); - LOG.info("Database column 'user.email' was added successfully."); - } - - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema45.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema45.java deleted file mode 100644 index d82f2a92..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema45.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implements the database schema for Subsonic version 4.5. - * - * @author Sindre Mehus - */ -public class Schema45 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema45.class); - - @Override - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 18") == 0) { - LOG.info("Updating database schema to version 18."); - template.execute("insert into version values (18)"); - } - - if (template.queryForInt("select count(*) from role where id = 11") == 0) { - LOG.info("Role 'share' not found in database. Creating it."); - template.execute("insert into role values (11, 'share')"); - template.execute("insert into user_role " + - "select distinct u.username, 11 from user u, user_role ur " + - "where u.username = ur.username and ur.role_id = 1"); - LOG.info("Role 'share' was created successfully."); - } - - if (!tableExists(template, "share")) { - LOG.info("Table 'share' not found in database. Creating it."); - template.execute("create cached table share (" + - "id identity," + - "name varchar not null," + - "description varchar," + - "username varchar not null," + - "created datetime not null," + - "expires datetime," + - "last_visited datetime," + - "visit_count int default 0 not null," + - "unique (name)," + - "foreign key (username) references user(username) on delete cascade)"); - template.execute("create index idx_share_name on share(name)"); - - LOG.info("Table 'share' was created successfully."); - LOG.info("Table 'share_file' not found in database. Creating it."); - template.execute("create cached table share_file (" + - "id identity," + - "share_id int not null," + - "path varchar not null," + - "foreign key (share_id) references share(id) on delete cascade)"); - LOG.info("Table 'share_file' was created successfully."); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema46.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema46.java deleted file mode 100644 index c1fcf357..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema46.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import org.springframework.jdbc.core.JdbcTemplate; - -import net.sourceforge.subsonic.Logger; - -/** - * Used for creating and evolving the database schema. - * This class implements the database schema for Subsonic version 4.6. - * - * @author Sindre Mehus - */ -public class Schema46 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema46.class); - - @Override - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 19") == 0) { - LOG.info("Updating database schema to version 19."); - template.execute("insert into version values (19)"); - } - - if (!tableExists(template, "transcoding2")) { - LOG.info("Database table 'transcoding2' not found. Creating it."); - template.execute("create table transcoding2 (" + - "id identity," + - "name varchar not null," + - "source_formats varchar not null," + - "target_format varchar not null," + - "step1 varchar not null," + - "step2 varchar," + - "step3 varchar)"); - - template.execute("insert into transcoding2 values(null,'mp3 audio'," + - "'ogg oga aac m4a flac wav wma aif aiff ape mpc shn', 'mp3', " + - "'ffmpeg -i %s -ab %bk -v 0 -f mp3 -', null, null)"); - - template.execute("insert into transcoding2 values(null,'flv/h264 video', " + - "'avi mpg mpeg mp4 m4v mkv mov wmv ogv divx m2ts', 'flv', " + - "'ffmpeg -ss %o -i %s -async 1 -b %bk -s %wx%h -ar 44100 -ac 2 -v 0 -f flv -vcodec libx264 -preset superfast -threads 0 -', null, null)"); - - LOG.info("Database table 'transcoding2' was created successfully."); - } - - if (!tableExists(template, "player_transcoding2")) { - LOG.info("Database table 'player_transcoding2' not found. Creating it."); - template.execute("create table player_transcoding2 (" + - "player_id int not null," + - "transcoding_id int not null," + - "primary key (player_id, transcoding_id)," + - "foreign key (player_id) references player(id) on delete cascade," + - "foreign key (transcoding_id) references transcoding2(id) on delete cascade)"); - - template.execute("insert into player_transcoding2(player_id, transcoding_id) " + - "select distinct p.id, t.id from player p, transcoding2 t"); - - LOG.info("Database table 'player_transcoding2' was created successfully."); - } - - if (!columnExists(template, "default_active", "transcoding2")) { - LOG.info("Database column 'transcoding2.default_active' not found. Creating it."); - template.execute("alter table transcoding2 add default_active boolean default true not null"); - LOG.info("Database column 'transcoding2.default_active' was added successfully."); - } - } - -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema47.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema47.java deleted file mode 100644 index 8b290b47..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/dao/schema/Schema47.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.dao.schema; - -import net.sourceforge.subsonic.Logger; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Used for creating and evolving the database schema. - * This class implements the database schema for Subsonic version 4.7. - * - * @author Sindre Mehus - */ -public class Schema47 extends Schema { - - private static final Logger LOG = Logger.getLogger(Schema47.class); - - @Override - public void execute(JdbcTemplate template) { - - if (template.queryForInt("select count(*) from version where version = 20") == 0) { - LOG.info("Updating database schema to version 20."); - template.execute("insert into version values (20)"); - } - - if (!tableExists(template, "media_file")) { - LOG.info("Database table 'media_file' not found. Creating it."); - template.execute("create cached table media_file (" + - "id identity," + - "path varchar not null," + - "folder varchar," + - "type varchar not null," + - "format varchar," + - "title varchar," + - "album varchar," + - "artist varchar," + - "album_artist varchar," + - "disc_number int," + - "track_number int," + - "year int," + - "genre varchar," + - "bit_rate int," + - "variable_bit_rate boolean not null," + - "duration_seconds int," + - "file_size bigint," + - "width int," + - "height int," + - "cover_art_path varchar," + - "parent_path varchar," + - "play_count int not null," + - "last_played datetime," + - "comment varchar," + - "created datetime not null," + - "changed datetime not null," + - "last_scanned datetime not null," + - "children_last_updated datetime not null," + - "present boolean not null," + - "version int not null," + - "unique (path))"); - - template.execute("create index idx_media_file_path on media_file(path)"); - template.execute("create index idx_media_file_parent_path on media_file(parent_path)"); - template.execute("create index idx_media_file_type on media_file(type)"); - template.execute("create index idx_media_file_album on media_file(album)"); - template.execute("create index idx_media_file_artist on media_file(artist)"); - template.execute("create index idx_media_file_album_artist on media_file(album_artist)"); - template.execute("create index idx_media_file_present on media_file(present)"); - template.execute("create index idx_media_file_genre on media_file(genre)"); - template.execute("create index idx_media_file_play_count on media_file(play_count)"); - template.execute("create index idx_media_file_created on media_file(created)"); - template.execute("create index idx_media_file_last_played on media_file(last_played)"); - - LOG.info("Database table 'media_file' was created successfully."); - } - - if (!tableExists(template, "artist")) { - LOG.info("Database table 'artist' not found. Creating it."); - template.execute("create cached table artist (" + - "id identity," + - "name varchar not null," + - "cover_art_path varchar," + - "album_count int default 0 not null," + - "last_scanned datetime not null," + - "present boolean not null," + - "unique (name))"); - - template.execute("create index idx_artist_name on artist(name)"); - template.execute("create index idx_artist_present on artist(present)"); - - LOG.info("Database table 'artist' was created successfully."); - } - - if (!tableExists(template, "album")) { - LOG.info("Database table 'album' not found. Creating it."); - template.execute("create cached table album (" + - "id identity," + - "path varchar not null," + - "name varchar not null," + - "artist varchar not null," + - "song_count int default 0 not null," + - "duration_seconds int default 0 not null," + - "cover_art_path varchar," + - "play_count int default 0 not null," + - "last_played datetime," + - "comment varchar," + - "created datetime not null," + - "last_scanned datetime not null," + - "present boolean not null," + - "unique (artist, name))"); - - template.execute("create index idx_album_artist_name on album(artist, name)"); - template.execute("create index idx_album_play_count on album(play_count)"); - template.execute("create index idx_album_last_played on album(last_played)"); - template.execute("create index idx_album_present on album(present)"); - - LOG.info("Database table 'album' was created successfully."); - } - - if (!tableExists(template, "starred_media_file")) { - LOG.info("Database table 'starred_media_file' not found. Creating it."); - template.execute("create table starred_media_file (" + - "id identity," + - "media_file_id int not null," + - "username varchar not null," + - "created datetime not null," + - "foreign key (media_file_id) references media_file(id) on delete cascade,"+ - "foreign key (username) references user(username) on delete cascade," + - "unique (media_file_id, username))"); - - template.execute("create index idx_starred_media_file_media_file_id on starred_media_file(media_file_id)"); - template.execute("create index idx_starred_media_file_username on starred_media_file(username)"); - - LOG.info("Database table 'starred_media_file' was created successfully."); - } - - if (!tableExists(template, "starred_album")) { - LOG.info("Database table 'starred_album' not found. Creating it."); - template.execute("create table starred_album (" + - "id identity," + - "album_id int not null," + - "username varchar not null," + - "created datetime not null," + - "foreign key (album_id) references album(id) on delete cascade," + - "foreign key (username) references user(username) on delete cascade," + - "unique (album_id, username))"); - - template.execute("create index idx_starred_album_album_id on starred_album(album_id)"); - template.execute("create index idx_starred_album_username on starred_album(username)"); - - LOG.info("Database table 'starred_album' was created successfully."); - } - - if (!tableExists(template, "starred_artist")) { - LOG.info("Database table 'starred_artist' not found. Creating it."); - template.execute("create table starred_artist (" + - "id identity," + - "artist_id int not null," + - "username varchar not null," + - "created datetime not null," + - "foreign key (artist_id) references artist(id) on delete cascade,"+ - "foreign key (username) references user(username) on delete cascade," + - "unique (artist_id, username))"); - - template.execute("create index idx_starred_artist_artist_id on starred_artist(artist_id)"); - template.execute("create index idx_starred_artist_username on starred_artist(username)"); - - LOG.info("Database table 'starred_artist' was created successfully."); - } - - if (!tableExists(template, "playlist")) { - LOG.info("Database table 'playlist' not found. Creating it."); - template.execute("create table playlist (" + - "id identity," + - "username varchar not null," + - "is_public boolean not null," + - "name varchar not null," + - "comment varchar," + - "file_count int default 0 not null," + - "duration_seconds int default 0 not null," + - "created datetime not null," + - "changed datetime not null," + - "foreign key (username) references user(username) on delete cascade)"); - - LOG.info("Database table 'playlist' was created successfully."); - } - - if (!columnExists(template, "imported_from", "playlist")) { - LOG.info("Database column 'playlist.imported_from' not found. Creating it."); - template.execute("alter table playlist add imported_from varchar"); - LOG.info("Database column 'playlist.imported_from' was added successfully."); - } - - if (!tableExists(template, "playlist_file")) { - LOG.info("Database table 'playlist_file' not found. Creating it."); - template.execute("create cached table playlist_file (" + - "id identity," + - "playlist_id int not null," + - "media_file_id int not null," + - "foreign key (playlist_id) references playlist(id) on delete cascade," + - "foreign key (media_file_id) references media_file(id) on delete cascade)"); - - LOG.info("Database table 'playlist_file' was created successfully."); - } - - if (!tableExists(template, "playlist_user")) { - LOG.info("Database table 'playlist_user' not found. Creating it."); - template.execute("create table playlist_user (" + - "id identity," + - "playlist_id int not null," + - "username varchar not null," + - "unique(playlist_id, username)," + - "foreign key (playlist_id) references playlist(id) on delete cascade," + - "foreign key (username) references user(username) on delete cascade)"); - - LOG.info("Database table 'playlist_user' was created successfully."); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Album.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Album.java deleted file mode 100644 index 23e8afaf..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Album.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.Date; - -/** - * @author Sindre Mehus - * @version $Id$ - */ -public class Album { - - private int id; - private String path; - private String name; - private String artist; - private int songCount; - private int durationSeconds; - private String coverArtPath; - private int playCount; - private Date lastPlayed; - private String comment; - private Date created; - private Date lastScanned; - private boolean present; - - public Album() { - } - - public Album(int id, String path, String name, String artist, int songCount, int durationSeconds, String coverArtPath, - int playCount, Date lastPlayed, String comment, Date created, Date lastScanned, boolean present) { - this.id = id; - this.path = path; - this.name = name; - this.artist = artist; - this.songCount = songCount; - this.durationSeconds = durationSeconds; - this.coverArtPath = coverArtPath; - this.playCount = playCount; - this.lastPlayed = lastPlayed; - this.comment = comment; - this.created = created; - this.lastScanned = lastScanned; - this.present = present; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getArtist() { - return artist; - } - - public void setArtist(String artist) { - this.artist = artist; - } - - public int getSongCount() { - return songCount; - } - - public void setSongCount(int songCount) { - this.songCount = songCount; - } - - public int getDurationSeconds() { - return durationSeconds; - } - - public void setDurationSeconds(int durationSeconds) { - this.durationSeconds = durationSeconds; - } - - public String getCoverArtPath() { - return coverArtPath; - } - - public void setCoverArtPath(String coverArtPath) { - this.coverArtPath = coverArtPath; - } - - public int getPlayCount() { - return playCount; - } - - public void setPlayCount(int playCount) { - this.playCount = playCount; - } - - public Date getLastPlayed() { - return lastPlayed; - } - - public void setLastPlayed(Date lastPlayed) { - this.lastPlayed = lastPlayed; - } - - public String getComment() { - return comment; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - public Date getLastScanned() { - return lastScanned; - } - - public void setLastScanned(Date lastScanned) { - this.lastScanned = lastScanned; - } - - public boolean isPresent() { - return present; - } - - public void setPresent(boolean present) { - this.present = present; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Artist.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Artist.java deleted file mode 100644 index e6141f78..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Artist.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.Date; - -/** - * @author Sindre Mehus - * @version $Id$ - */ -public class Artist { - - private int id; - private String name; - private String coverArtPath; - private int albumCount; - private Date lastScanned; - private boolean present; - - public Artist() { - } - - public Artist(int id, String name, String coverArtPath, int albumCount, Date lastScanned, boolean present) { - this.id = id; - this.name = name; - this.coverArtPath = coverArtPath; - this.albumCount = albumCount; - this.lastScanned = lastScanned; - this.present = present; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCoverArtPath() { - return coverArtPath; - } - - public void setCoverArtPath(String coverArtPath) { - this.coverArtPath = coverArtPath; - } - - public int getAlbumCount() { - return albumCount; - } - - public void setAlbumCount(int albumCount) { - this.albumCount = albumCount; - } - - public Date getLastScanned() { - return lastScanned; - } - - public void setLastScanned(Date lastScanned) { - this.lastScanned = lastScanned; - } - - public boolean isPresent() { - return present; - } - - public void setPresent(boolean present) { - this.present = present; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Avatar.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Avatar.java deleted file mode 100644 index 0089a8a3..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Avatar.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.Date; - -/** - * An icon representing a user. - * - * @author Sindre Mehus - */ -public class Avatar { - - private int id; - private String name; - private Date createdDate; - private String mimeType; - private int width; - private int height; - private byte[] data; - - public Avatar(int id, String name, Date createdDate, String mimeType, int width, int height, byte[] data) { - this.id = id; - this.name = name; - this.createdDate = createdDate; - this.mimeType = mimeType; - this.width = width; - this.height = height; - this.data = data; - } - - public int getId() { - return id; - } - - public String getName() { - return name; - } - - public Date getCreatedDate() { - return createdDate; - } - - public String getMimeType() { - return mimeType; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public byte[] getData() { - return data; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/AvatarScheme.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/AvatarScheme.java deleted file mode 100644 index 024dcb24..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/AvatarScheme.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Enumeration of avatar schemes. - * - * @author Sindre Mehus - */ -public enum AvatarScheme { - - /** - * No avatar should be displayed. - */ - NONE(-1), - - /** - * One of the system avatars should be displayed. - */ - SYSTEM(0), - - /** - * The custom avatar should be displayed. - */ - CUSTOM(-2); - - private final int code; - - AvatarScheme(int code) { - this.code = code; - } - - public int getCode() { - return code; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/CacheElement.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/CacheElement.java deleted file mode 100644 index bb52eff7..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/CacheElement.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * @author Sindre Mehus - * @version $Id$ - */ -public class CacheElement { - - private final long id; - private final int type; - private final String key; - private final Object value; - private final long created; - - public CacheElement(int type, String key, Object value, long created) { - this.type = type; - this.key = key; - this.value = value; - this.created = created; - - id = createId(type, key); - } - - public static long createId(int type, String key) { - return ((long) type << 32) | Math.abs(key.hashCode()); - } - - public long getId() { - return id; - } - - public int getType() { - return type; - } - - public String getKey() { - return key; - } - - public Object getValue() { - return value; - } - - public long getCreated() { - return created; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/CoverArtScheme.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/CoverArtScheme.java deleted file mode 100644 index 91293e9f..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/CoverArtScheme.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Enumeration of cover art schemes. Each value contains a size, which indicates how big the - * scaled covert art images should be. - * - * @author Sindre Mehus - * @version $Revision: 1.3 $ $Date: 2005/06/15 18:10:40 $ - */ -public enum CoverArtScheme { - - OFF(0), - SMALL(70), - MEDIUM(100), - LARGE(150); - - private int size; - - CoverArtScheme(int size) { - this.size = size; - } - - /** - * Returns the covert art size for this scheme. - * @return the covert art size for this scheme. - */ - public int getSize() { - return size; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/InternetRadio.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/InternetRadio.java deleted file mode 100644 index ae0c1f67..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/InternetRadio.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.Date; - -/** - * Represents an internet radio station. - * - * @author Sindre Mehus - * @version $Revision: 1.2 $ $Date: 2005/12/25 13:48:46 $ - */ -public class InternetRadio { - - private Integer id; - private String name; - private String streamUrl; - private String homepageUrl; - private boolean isEnabled; - private Date changed; - - /** - * Creates a new internet radio station. - * - * @param id The system-generated ID. - * @param name The user-defined name. - * @param streamUrl The stream URL for the station. - * @param homepageUrl The home page URL for the station. - * @param isEnabled Whether the station is enabled. - * @param changed When the corresponding database entry was last changed. - */ - public InternetRadio(Integer id, String name, String streamUrl, String homepageUrl, boolean isEnabled, Date changed) { - this.id = id; - this.name = name; - this.streamUrl = streamUrl; - this.homepageUrl = homepageUrl; - this.isEnabled = isEnabled; - this.changed = changed; - } - - /** - * Creates a new internet radio station. - * - * @param name The user-defined name. - * @param streamUrl The URL for the station. - * @param homepageUrl The home page URL for the station. - * @param isEnabled Whether the station is enabled. - * @param changed When the corresponding database entry was last changed. - */ - public InternetRadio(String name, String streamUrl, String homepageUrl, boolean isEnabled, Date changed) { - this(null, name, streamUrl, homepageUrl, isEnabled, changed); - } - - /** - * Returns the system-generated ID. - * - * @return The system-generated ID. - */ - public Integer getId() { - return id; - } - - /** - * Returns the user-defined name. - * - * @return The user-defined name. - */ - public String getName() { - return name; - } - - /** - * Sets the user-defined name. - * - * @param name The user-defined name. - */ - public void setName(String name) { - this.name = name; - } - - /** - * Returns the stream URL of the radio station. - * - * @return The stream URL of the radio station. - */ - public String getStreamUrl() { - return streamUrl; - } - - /** - * Sets the stream URL of the radio station. - * - * @param streamUrl The stream URL of the radio station. - */ - public void setStreamUrl(String streamUrl) { - this.streamUrl = streamUrl; - } - - /** - * Returns the homepage URL of the radio station. - * - * @return The homepage URL of the radio station. - */ - public String getHomepageUrl() { - return homepageUrl; - } - - /** - * Sets the home page URL of the radio station. - * - * @param homepageUrl The home page URL of the radio station. - */ - public void setHomepageUrl(String homepageUrl) { - this.homepageUrl = homepageUrl; - } - - /** - * Returns whether the radio station is enabled. - * - * @return Whether the radio station is enabled. - */ - public boolean isEnabled() { - return isEnabled; - } - - /** - * Sets whether the radio station is enabled. - * - * @param enabled Whether the radio station is enabled. - */ - public void setEnabled(boolean enabled) { - isEnabled = enabled; - } - - /** - * Returns when the corresponding database entry was last changed. - * - * @return When the corresponding database entry was last changed. - */ - public Date getChanged() { - return changed; - } - - /** - * Sets when the corresponding database entry was last changed. - * - * @param changed When the corresponding database entry was last changed. - */ - public void setChanged(Date changed) { - this.changed = changed; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFile.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFile.java deleted file mode 100644 index 4f315028..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFile.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import net.sourceforge.subsonic.util.FileUtil; -import org.apache.commons.io.FilenameUtils; - -import java.io.File; -import java.util.Date; - -/** - * A media file (audio, video or directory) with an assortment of its meta data. - * - * @author Sindre Mehus - * @version $Id$ - */ -public class MediaFile { - - private int id; - private String path; - private String folder; - private MediaType mediaType; - private String format; - private String title; - private String albumName; - private String artist; - private String albumArtist; - private Integer discNumber; - private Integer trackNumber; - private Integer year; - private String genre; - private Integer bitRate; - private boolean variableBitRate; - private Integer durationSeconds; - private Long fileSize; - private Integer width; - private Integer height; - private String coverArtPath; - private String parentPath; - private int playCount; - private Date lastPlayed; - private String comment; - private Date created; - private Date changed; - private Date lastScanned; - private Date starredDate; - private Date childrenLastUpdated; - private boolean present; - - public MediaFile(int id, String path, String folder, MediaType mediaType, String format, String title, - String albumName, String artist, String albumArtist, Integer discNumber, Integer trackNumber, Integer year, String genre, Integer bitRate, - boolean variableBitRate, Integer durationSeconds, Long fileSize, Integer width, Integer height, String coverArtPath, - String parentPath, int playCount, Date lastPlayed, String comment, Date created, Date changed, Date lastScanned, - Date childrenLastUpdated, boolean present) { - this.id = id; - this.path = path; - this.folder = folder; - this.mediaType = mediaType; - this.format = format; - this.title = title; - this.albumName = albumName; - this.artist = artist; - this.albumArtist = albumArtist; - this.discNumber = discNumber; - this.trackNumber = trackNumber; - this.year = year; - this.genre = genre; - this.bitRate = bitRate; - this.variableBitRate = variableBitRate; - this.durationSeconds = durationSeconds; - this.fileSize = fileSize; - this.width = width; - this.height = height; - this.coverArtPath = coverArtPath; - this.parentPath = parentPath; - this.playCount = playCount; - this.lastPlayed = lastPlayed; - this.comment = comment; - this.created = created; - this.changed = changed; - this.lastScanned = lastScanned; - this.childrenLastUpdated = childrenLastUpdated; - this.present = present; - } - - public MediaFile() { - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getFolder() { - return folder; - } - - public void setFolder(String folder) { - this.folder = folder; - } - - public File getFile() { - // TODO: Optimize - return new File(path); - } - - public boolean exists() { - return FileUtil.exists(getFile()); - } - - public MediaType getMediaType() { - return mediaType; - } - - public void setMediaType(MediaType mediaType) { - this.mediaType = mediaType; - } - - public boolean isVideo() { - return mediaType == MediaType.VIDEO; - } - - public boolean isAudio() { - return mediaType == MediaType.MUSIC || mediaType == MediaType.AUDIOBOOK || mediaType == MediaType.PODCAST; - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - public boolean isDirectory() { - return !isFile(); - } - - public boolean isFile() { - return mediaType != MediaType.DIRECTORY && mediaType != MediaType.ALBUM; - } - - public boolean isAlbum() { - return mediaType == MediaType.ALBUM; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getAlbumName() { - return albumName; - } - - public void setAlbumName(String album) { - this.albumName = album; - } - - public String getArtist() { - return artist; - } - - public void setArtist(String artist) { - this.artist = artist; - } - - public String getAlbumArtist() { - return albumArtist; - } - - public void setAlbumArtist(String albumArtist) { - this.albumArtist = albumArtist; - } - - public String getName() { - if (isFile()) { - return title != null ? title : FilenameUtils.getBaseName(path); - } - - return FilenameUtils.getName(path); - } - - public Integer getDiscNumber() { - return discNumber; - } - - public void setDiscNumber(Integer discNumber) { - this.discNumber = discNumber; - } - - public Integer getTrackNumber() { - return trackNumber; - } - - public void setTrackNumber(Integer trackNumber) { - this.trackNumber = trackNumber; - } - - public Integer getYear() { - return year; - } - - public void setYear(Integer year) { - this.year = year; - } - - public String getGenre() { - return genre; - } - - public void setGenre(String genre) { - this.genre = genre; - } - - public Integer getBitRate() { - return bitRate; - } - - public void setBitRate(Integer bitRate) { - this.bitRate = bitRate; - } - - public boolean isVariableBitRate() { - return variableBitRate; - } - - public void setVariableBitRate(boolean variableBitRate) { - this.variableBitRate = variableBitRate; - } - - public Integer getDurationSeconds() { - return durationSeconds; - } - - public void setDurationSeconds(Integer durationSeconds) { - this.durationSeconds = durationSeconds; - } - - public String getDurationString() { - if (durationSeconds == null) { - return null; - } - - StringBuilder result = new StringBuilder(8); - - int seconds = durationSeconds; - - int hours = seconds / 3600; - seconds -= hours * 3600; - - int minutes = seconds / 60; - seconds -= minutes * 60; - - if (hours > 0) { - result.append(hours).append(':'); - if (minutes < 10) { - result.append('0'); - } - } - - result.append(minutes).append(':'); - if (seconds < 10) { - result.append('0'); - } - result.append(seconds); - - return result.toString(); - } - - public Long getFileSize() { - return fileSize; - } - - public void setFileSize(Long fileSize) { - this.fileSize = fileSize; - } - - public Integer getWidth() { - return width; - } - - public void setWidth(Integer width) { - this.width = width; - } - - public Integer getHeight() { - return height; - } - - public void setHeight(Integer height) { - this.height = height; - } - - public String getCoverArtPath() { - return coverArtPath; - } - - public void setCoverArtPath(String coverArtPath) { - this.coverArtPath = coverArtPath; - } - - - public String getParentPath() { - return parentPath; - } - - public void setParentPath(String parentPath) { - this.parentPath = parentPath; - } - - public File getParentFile() { - return getFile().getParentFile(); - } - - public int getPlayCount() { - return playCount; - } - - public void setPlayCount(int playCount) { - this.playCount = playCount; - } - - public Date getLastPlayed() { - return lastPlayed; - } - - public void setLastPlayed(Date lastPlayed) { - this.lastPlayed = lastPlayed; - } - - public String getComment() { - return comment; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - public Date getChanged() { - return changed; - } - - public void setChanged(Date changed) { - this.changed = changed; - } - - public Date getLastScanned() { - return lastScanned; - } - - public void setLastScanned(Date lastScanned) { - this.lastScanned = lastScanned; - } - - public Date getStarredDate() { - return starredDate; - } - - public void setStarredDate(Date starredDate) { - this.starredDate = starredDate; - } - - /** - * Returns when the children was last updated in the database. - */ - public Date getChildrenLastUpdated() { - return childrenLastUpdated; - } - - public void setChildrenLastUpdated(Date childrenLastUpdated) { - this.childrenLastUpdated = childrenLastUpdated; - } - - public boolean isPresent() { - return present; - } - - public void setPresent(boolean present) { - this.present = present; - } - - @Override - public boolean equals(Object o) { - return o instanceof MediaFile && ((MediaFile) o).path.equals(path); - } - - @Override - public int hashCode() { - return path.hashCode(); - } - - public File getCoverArtFile() { - // TODO: Optimize - return coverArtPath == null ? null : new File(coverArtPath); - } - - @Override - public String toString() { - return getName(); - } - - public static enum MediaType { - MUSIC, - PODCAST, - AUDIOBOOK, - VIDEO, - DIRECTORY, - ALBUM - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java deleted file mode 100644 index 13b5bbbd..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.Comparator; - -import static net.sourceforge.subsonic.domain.MediaFile.MediaType.DIRECTORY; - -/** - * Comparator for sorting media files. - */ -public class MediaFileComparator implements Comparator { - - private final boolean sortAlbumsByYear; - - public MediaFileComparator(boolean sortAlbumsByYear) { - this.sortAlbumsByYear = sortAlbumsByYear; - } - - public int compare(MediaFile a, MediaFile b) { - - // Directories before files. - if (a.isFile() && b.isDirectory()) { - return 1; - } - if (a.isDirectory() && b.isFile()) { - return -1; - } - - // Non-album directories before album directories. - if (a.isAlbum() && b.getMediaType() == DIRECTORY) { - return 1; - } - if (a.getMediaType() == DIRECTORY && b.isAlbum()) { - return -1; - } - - // Sort albums by year - if (sortAlbumsByYear && a.isAlbum() && b.isAlbum()) { - int i = nullSafeCompare(a.getYear(), b.getYear(), false); - if (i != 0) { - return i; - } - } - - if (a.isDirectory() && b.isDirectory()) { - return a.getName().compareToIgnoreCase(b.getName()); - } - - // Compare by disc and track numbers, if present. - Integer trackA = getSortableDiscAndTrackNumber(a); - Integer trackB = getSortableDiscAndTrackNumber(b); - int i = nullSafeCompare(trackA, trackB, false); - if (i != 0) { - return i; - } - - return a.getName().compareToIgnoreCase(b.getName()); - } - - private > int nullSafeCompare(T a, T b, boolean nullIsSmaller) { - if (a == null && b == null) { - return 0; - } - if (a == null) { - return nullIsSmaller ? -1 : 1; - } - if (b == null) { - return nullIsSmaller ? 1 : -1; - } - return a.compareTo(b); - } - - private Integer getSortableDiscAndTrackNumber(MediaFile file) { - if (file.getTrackNumber() == null) { - return null; - } - - int discNumber = file.getDiscNumber() == null ? 1 : file.getDiscNumber(); - return discNumber * 1000 + file.getTrackNumber(); - } -} - diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaLibraryStatistics.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaLibraryStatistics.java deleted file mode 100644 index c8b0cdd9..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaLibraryStatistics.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Contains media libaray statistics, including the number of artists, albums and songs. - * - * @author Sindre Mehus - * @version $Revision: 1.1 $ $Date: 2005/11/17 18:29:03 $ - */ -public class MediaLibraryStatistics { - - private int artistCount; - private int albumCount; - private int songCount; - private long totalLengthInBytes; - private long totalDurationInSeconds; - - public MediaLibraryStatistics(int artistCount, int albumCount, int songCount, long totalLengthInBytes, long totalDurationInSeconds) { - this.artistCount = artistCount; - this.albumCount = albumCount; - this.songCount = songCount; - this.totalLengthInBytes = totalLengthInBytes; - this.totalDurationInSeconds = totalDurationInSeconds; - } - - public int getArtistCount() { - return artistCount; - } - - public int getAlbumCount() { - return albumCount; - } - - public int getSongCount() { - return songCount; - } - - public long getTotalLengthInBytes() { - return totalLengthInBytes; - } - - public long getTotalDurationInSeconds() { - return totalDurationInSeconds; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MusicFolder.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MusicFolder.java deleted file mode 100644 index 613b0a7f..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MusicFolder.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.io.File; -import java.io.Serializable; -import java.util.Date; - -/** - * Represents a top level directory in which music or other media is stored. - * - * @author Sindre Mehus - * @version $Revision: 1.1 $ $Date: 2005/11/27 14:32:05 $ - */ -public class MusicFolder implements Serializable { - - private Integer id; - private File path; - private String name; - private boolean isEnabled; - private Date changed; - - /** - * Creates a new music folder. - * - * @param id The system-generated ID. - * @param path The path of the music folder. - * @param name The user-defined name. - * @param enabled Whether the folder is enabled. - * @param changed When the corresponding database entry was last changed. - */ - public MusicFolder(Integer id, File path, String name, boolean enabled, Date changed) { - this.id = id; - this.path = path; - this.name = name; - isEnabled = enabled; - this.changed = changed; - } - - /** - * Creates a new music folder. - * - * @param path The path of the music folder. - * @param name The user-defined name. - * @param enabled Whether the folder is enabled. - * @param changed When the corresponding database entry was last changed. - */ - public MusicFolder(File path, String name, boolean enabled, Date changed) { - this(null, path, name, enabled, changed); - } - - /** - * Returns the system-generated ID. - * - * @return The system-generated ID. - */ - public Integer getId() { - return id; - } - - /** - * Returns the path of the music folder. - * - * @return The path of the music folder. - */ - public File getPath() { - return path; - } - - /** - * Sets the path of the music folder. - * - * @param path The path of the music folder. - */ - public void setPath(File path) { - this.path = path; - } - - /** - * Returns the user-defined name. - * - * @return The user-defined name. - */ - public String getName() { - return name; - } - - /** - * Sets the user-defined name. - * - * @param name The user-defined name. - */ - public void setName(String name) { - this.name = name; - } - - /** - * Returns whether the folder is enabled. - * - * @return Whether the folder is enabled. - */ - public boolean isEnabled() { - return isEnabled; - } - - /** - * Sets whether the folder is enabled. - * - * @param enabled Whether the folder is enabled. - */ - public void setEnabled(boolean enabled) { - isEnabled = enabled; - } - - /** - * Returns when the corresponding database entry was last changed. - * - * @return When the corresponding database entry was last changed. - */ - public Date getChanged() { - return changed; - } - - /** - * Sets when the corresponding database entry was last changed. - * - * @param changed When the corresponding database entry was last changed. - */ - public void setChanged(Date changed) { - this.changed = changed; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MusicIndex.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MusicIndex.java deleted file mode 100644 index 5753fa4d..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MusicIndex.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.ArrayList; -import java.util.List; -import java.io.Serializable; - -/** - * A music index is a mapping from an index string to a list of prefixes. A complete index consists of a list of - * MusicIndex instances.

- *

- * For a normal alphabetical index, such a mapping would typically be "A" -> ["A"]. The index can also be used - * to group less frequently used letters, such as "X-Å" -> ["X", "Y", "Z", "Æ", "Ø", "Å"], or to make multiple - * indexes for frequently used letters, such as "SA" -> ["SA"] and "SO" -> ["SO"]

- *

- * Clicking on an index in the user interface will typically bring up a list of all music files that are categorized - * under that index. - * - * @author Sindre Mehus - */ -public class MusicIndex implements Serializable { - - public static final MusicIndex OTHER = new MusicIndex("#"); - - private final String index; - private final List prefixes = new ArrayList(); - - /** - * Creates a new index with the given index string. - * - * @param index The index string, e.g., "A" or "The". - */ - public MusicIndex(String index) { - this.index = index; - } - - /** - * Adds a prefix to this index. Music files that starts with this prefix will be categorized under this index entry. - * - * @param prefix The prefix. - */ - public void addPrefix(String prefix) { - prefixes.add(prefix); - } - - /** - * Returns the index name. - * - * @return The index name. - */ - public String getIndex() { - return index; - } - - /** - * Returns the list of prefixes. - * - * @return The list of prefixes. - */ - public List getPrefixes() { - return prefixes; - } - - /** - * Returns whether this object is equal to another one. - * - * @param o Object to compare to. - * @return true if, and only if, the other object is a MusicIndex with the same - * index name as this one. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof MusicIndex)) { - return false; - } - - final MusicIndex musicIndex = (MusicIndex) o; - - if (index != null ? !index.equals(musicIndex.index) : musicIndex.index != null) { - return false; - } - - return true; - } - - /** - * Returns a hash code for this object. - * - * @return A hash code for this object. - */ - @Override - public int hashCode() { - return (index != null ? index.hashCode() : 0); - } - - /** - * An artist in an index. - */ - public static class Artist implements Comparable, Serializable { - - private final String name; - private final String sortableName; - private final List mediaFiles = new ArrayList(); - - public Artist(String name, String sortableName) { - this.name = name; - this.sortableName = sortableName; - } - - public void addMediaFile(MediaFile mediaFile) { - mediaFiles.add(mediaFile); - } - - public String getName() { - return name; - } - - public String getSortableName() { - return sortableName; - } - - public List getMediaFiles() { - return mediaFiles; - } - - public int compareTo(Artist artist) { - return sortableName.compareToIgnoreCase(artist.sortableName); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Artist artist = (Artist) o; - return sortableName.equalsIgnoreCase(artist.sortableName); - } - - @Override - public int hashCode() { - return sortableName.hashCode(); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/NATPMPRouter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/NATPMPRouter.java deleted file mode 100644 index ef3821a1..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/NATPMPRouter.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import com.hoodcomputing.natpmp.MapRequestMessage; -import com.hoodcomputing.natpmp.NatPmpDevice; - -/** - * @author Sindre Mehus - * @version $Id$ - */ -public class NATPMPRouter implements Router { - - private final NatPmpDevice device; - - private NATPMPRouter(NatPmpDevice device) { - this.device = device; - } - - public static NATPMPRouter findRouter() { - try { - return new NATPMPRouter(new NatPmpDevice(false)); - } catch (Exception x) { - return null; - } - } - - public void addPortMapping(int externalPort, int internalPort, int leaseDuration) throws Exception { - - // Use one week if lease duration is "forever". - if (leaseDuration == 0) { - leaseDuration = 7 * 24 * 3600; - } - - MapRequestMessage map = new MapRequestMessage(true, internalPort, externalPort, leaseDuration, null); - device.enqueueMessage(map); - device.waitUntilQueueEmpty(); - } - - public void deletePortMapping(int externalPort, int internalPort) throws Exception { - MapRequestMessage map = new MapRequestMessage(true, internalPort, externalPort, 0, null); - device.enqueueMessage(map); - device.waitUntilQueueEmpty(); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PlayQueue.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PlayQueue.java deleted file mode 100644 index 97748f72..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PlayQueue.java +++ /dev/null @@ -1,417 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import net.sourceforge.subsonic.util.FileUtil; -import org.apache.commons.lang.StringUtils; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * A playlist is a list of music files that are associated to a remote player. - * - * @author Sindre Mehus - */ -public class PlayQueue { - - private List files = new ArrayList(); - private boolean repeatEnabled; - private String name = "(unnamed)"; - private Status status = Status.PLAYING; - private RandomSearchCriteria randomSearchCriteria; - - /** - * The index of the current song, or -1 is the end of the playlist is reached. - * Note that both the index and the playlist size can be zero. - */ - private int index = 0; - - /** - * Used for undo functionality. - */ - private List filesBackup = new ArrayList(); - private int indexBackup = 0; - - /** - * Returns the user-defined name of the playlist. - * - * @return The name of the playlist, or null if no name has been assigned. - */ - public synchronized String getName() { - return name; - } - - /** - * Sets the user-defined name of the playlist. - * - * @param name The name of the playlist. - */ - public synchronized void setName(String name) { - this.name = name; - } - - /** - * Returns the current song in the playlist. - * - * @return The current song in the playlist, or null if no current song exists. - */ - public synchronized MediaFile getCurrentFile() { - if (index == -1 || index == 0 && size() == 0) { - setStatus(Status.STOPPED); - return null; - } else { - MediaFile file = files.get(index); - - // Remove file from playlist if it doesn't exist. - if (!file.exists()) { - files.remove(index); - index = Math.max(0, Math.min(index, size() - 1)); - return getCurrentFile(); - } - - return file; - } - } - - /** - * Returns all music files in the playlist. - * - * @return All music files in the playlist. - */ - public synchronized List getFiles() { - return files; - } - - /** - * Returns the music file at the given index. - * - * @param index The index. - * @return The music file at the given index. - * @throws IndexOutOfBoundsException If the index is out of range. - */ - public synchronized MediaFile getFile(int index) { - return files.get(index); - } - - /** - * Skip to the next song in the playlist. - */ - public synchronized void next() { - index++; - - // Reached the end? - if (index >= size()) { - index = isRepeatEnabled() ? 0 : -1; - } - } - - /** - * Returns the number of songs in the playlists. - * - * @return The number of songs in the playlists. - */ - public synchronized int size() { - return files.size(); - } - - /** - * Returns whether the playlist is empty. - * - * @return Whether the playlist is empty. - */ - public synchronized boolean isEmpty() { - return files.isEmpty(); - } - - /** - * Returns the index of the current song. - * - * @return The index of the current song, or -1 if the end of the playlist is reached. - */ - public synchronized int getIndex() { - return index; - } - - /** - * Sets the index of the current song. - * - * @param index The index of the current song. - */ - public synchronized void setIndex(int index) { - makeBackup(); - this.index = Math.max(0, Math.min(index, size() - 1)); - setStatus(Status.PLAYING); - } - - /** - * Adds one or more music file to the playlist. - * - * @param append Whether existing songs in the playlist should be kept. - * @param mediaFiles The music files to add. - * @throws IOException If an I/O error occurs. - */ - public synchronized void addFiles(boolean append, Iterable mediaFiles) throws IOException { - makeBackup(); - if (!append) { - index = 0; - files.clear(); - } - for (MediaFile mediaFile : mediaFiles) { - files.add(mediaFile); - } - setStatus(Status.PLAYING); - } - - /** - * Convenience method, equivalent to {@link #addFiles(boolean, Iterable)}. - */ - public synchronized void addFiles(boolean append, MediaFile... mediaFiles) throws IOException { - addFiles(append, Arrays.asList(mediaFiles)); - } - - /** - * Removes the music file at the given index. - * - * @param index The playlist index. - */ - public synchronized void removeFileAt(int index) { - makeBackup(); - index = Math.max(0, Math.min(index, size() - 1)); - if (this.index > index) { - this.index--; - } - files.remove(index); - - if (index != -1) { - this.index = Math.max(0, Math.min(this.index, size() - 1)); - } - } - - /** - * Clears the playlist. - */ - public synchronized void clear() { - makeBackup(); - files.clear(); - index = 0; - } - - /** - * Shuffles the playlist. - */ - public synchronized void shuffle() { - makeBackup(); - MediaFile currentFile = getCurrentFile(); - Collections.shuffle(files); - if (currentFile != null) { - index = files.indexOf(currentFile); - } - } - - /** - * Sorts the playlist according to the given sort order. - */ - public synchronized void sort(final SortOrder sortOrder) { - makeBackup(); - MediaFile currentFile = getCurrentFile(); - - Comparator comparator = new Comparator() { - public int compare(MediaFile a, MediaFile b) { - switch (sortOrder) { - case TRACK: - Integer trackA = a.getTrackNumber(); - Integer trackB = b.getTrackNumber(); - if (trackA == null) { - trackA = 0; - } - if (trackB == null) { - trackB = 0; - } - return trackA.compareTo(trackB); - - case ARTIST: - String artistA = StringUtils.trimToEmpty(a.getArtist()); - String artistB = StringUtils.trimToEmpty(b.getArtist()); - return artistA.compareTo(artistB); - - case ALBUM: - String albumA = StringUtils.trimToEmpty(a.getAlbumName()); - String albumB = StringUtils.trimToEmpty(b.getAlbumName()); - return albumA.compareTo(albumB); - default: - return 0; - } - } - }; - - Collections.sort(files, comparator); - if (currentFile != null) { - index = files.indexOf(currentFile); - } - } - - /** - * Moves the song at the given index one step up. - * - * @param index The playlist index. - */ - public synchronized void moveUp(int index) { - makeBackup(); - if (index <= 0 || index >= size()) { - return; - } - Collections.swap(files, index, index - 1); - - if (this.index == index) { - this.index--; - } else if (this.index == index - 1) { - this.index++; - } - } - - /** - * Moves the song at the given index one step down. - * - * @param index The playlist index. - */ - public synchronized void moveDown(int index) { - makeBackup(); - if (index < 0 || index >= size() - 1) { - return; - } - Collections.swap(files, index, index + 1); - - if (this.index == index) { - this.index++; - } else if (this.index == index + 1) { - this.index--; - } - } - - /** - * Returns whether the playlist is repeating. - * - * @return Whether the playlist is repeating. - */ - public synchronized boolean isRepeatEnabled() { - return repeatEnabled; - } - - /** - * Sets whether the playlist is repeating. - * - * @param repeatEnabled Whether the playlist is repeating. - */ - public synchronized void setRepeatEnabled(boolean repeatEnabled) { - this.repeatEnabled = repeatEnabled; - } - - /** - * Revert the last operation. - */ - public synchronized void undo() { - List filesTmp = new ArrayList(files); - int indexTmp = index; - - index = indexBackup; - files = filesBackup; - - indexBackup = indexTmp; - filesBackup = filesTmp; - } - - /** - * Returns the playlist status. - * - * @return The playlist status. - */ - public synchronized Status getStatus() { - return status; - } - - /** - * Sets the playlist status. - * - * @param status The playlist status. - */ - public synchronized void setStatus(Status status) { - this.status = status; - if (index == -1) { - index = Math.max(0, Math.min(index, size() - 1)); - } - } - - /** - * Returns the criteria used to generate this random playlist. - * - * @return The search criteria, or null if this is not a random playlist. - */ - public synchronized RandomSearchCriteria getRandomSearchCriteria() { - return randomSearchCriteria; - } - - /** - * Sets the criteria used to generate this random playlist. - * - * @param randomSearchCriteria The search criteria, or null if this is not a random playlist. - */ - public synchronized void setRandomSearchCriteria(RandomSearchCriteria randomSearchCriteria) { - this.randomSearchCriteria = randomSearchCriteria; - } - - /** - * Returns the total length in bytes. - * - * @return The total length in bytes. - */ - public synchronized long length() { - long length = 0; - for (MediaFile mediaFile : files) { - length += mediaFile.getFileSize(); - } - return length; - } - - private void makeBackup() { - filesBackup = new ArrayList(files); - indexBackup = index; - } - - /** - * Playlist status. - */ - public enum Status { - PLAYING, - STOPPED - } - - /** - * Playlist sort order. - */ - public enum SortOrder { - TRACK, - ARTIST, - ALBUM - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Player.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Player.java deleted file mode 100644 index e1780936..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Player.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import org.apache.commons.lang.StringUtils; - -import java.util.Date; - -/** - * Represens a remote player. A player has a unique ID, a user-defined name, a logged-on user, - * miscellaneous identifiers, and an associated playlist. - * - * @author Sindre Mehus - */ -public class Player { - - private String id; - private String name; - private PlayerTechnology technology = PlayerTechnology.WEB; - private String clientId; - private String type; - private String username; - private String ipAddress; - private boolean isDynamicIp = true; - private boolean isAutoControlEnabled = true; - private Date lastSeen; - private CoverArtScheme coverArtScheme = CoverArtScheme.MEDIUM; - private TranscodeScheme transcodeScheme = TranscodeScheme.OFF; - private PlayQueue playQueue; - - /** - * Returns the player ID. - * - * @return The player ID. - */ - public String getId() { - return id; - } - - /** - * Sets the player ID. - * - * @param id The player ID. - */ - public void setId(String id) { - this.id = id; - } - - /** - * Returns the user-defined player name. - * - * @return The user-defined player name. - */ - public String getName() { - return name; - } - - /** - * Sets the user-defined player name. - * - * @param name The user-defined player name. - */ - public void setName(String name) { - this.name = name; - } - - /** - * Returns the player "technology", e.g., web, external or jukebox. - * - * @return The player technology. - */ - public PlayerTechnology getTechnology() { - return technology; - } - - /** - * Returns the third-party client ID (used if this player is managed over the - * Subsonic REST API). - * - * @return The client ID. - */ - public String getClientId() { - return clientId; - } - - /** - * Sets the third-party client ID (used if this player is managed over the - * Subsonic REST API). - * - * @param clientId The client ID. - */ - public void setClientId(String clientId) { - this.clientId = clientId; - } - - /** - * Sets the player "technology", e.g., web, external or jukebox. - * - * @param technology The player technology. - */ - public void setTechnology(PlayerTechnology technology) { - this.technology = technology; - } - - public boolean isJukebox() { - return technology == PlayerTechnology.JUKEBOX; - } - - public boolean isExternal() { - return technology == PlayerTechnology.EXTERNAL; - } - - public boolean isExternalWithPlaylist() { - return technology == PlayerTechnology.EXTERNAL_WITH_PLAYLIST; - } - - public boolean isWeb() { - return technology == PlayerTechnology.WEB; - } - - /** - * Returns the player type, e.g., WinAmp, iTunes. - * - * @return The player type. - */ - public String getType() { - return type; - } - - /** - * Sets the player type, e.g., WinAmp, iTunes. - * - * @param type The player type. - */ - public void setType(String type) { - this.type = type; - } - - /** - * Returns the logged-in user. - * - * @return The logged-in user. - */ - public String getUsername() { - return username; - } - - /** - * Sets the logged-in username. - * - * @param username The logged-in username. - */ - public void setUsername(String username) { - this.username = username; - } - - /** - * Returns whether the player is automatically started. - * - * @return Whether the player is automatically started. - */ - public boolean isAutoControlEnabled() { - return isAutoControlEnabled; - } - - /** - * Sets whether the player is automatically started. - * - * @param isAutoControlEnabled Whether the player is automatically started. - */ - public void setAutoControlEnabled(boolean isAutoControlEnabled) { - this.isAutoControlEnabled = isAutoControlEnabled; - } - - /** - * Returns the time when the player was last seen. - * - * @return The time when the player was last seen. - */ - public Date getLastSeen() { - return lastSeen; - } - - /** - * Sets the time when the player was last seen. - * - * @param lastSeen The time when the player was last seen. - */ - public void setLastSeen(Date lastSeen) { - this.lastSeen = lastSeen; - } - - /** - * Returns the cover art scheme. - * - * @return The cover art scheme. - */ - public CoverArtScheme getCoverArtScheme() { - return coverArtScheme; - } - - /** - * Sets the cover art scheme. - * - * @param coverArtScheme The cover art scheme. - */ - public void setCoverArtScheme(CoverArtScheme coverArtScheme) { - this.coverArtScheme = coverArtScheme; - } - - /** - * Returns the transcode scheme. - * - * @return The transcode scheme. - */ - public TranscodeScheme getTranscodeScheme() { - return transcodeScheme; - } - - /** - * Sets the transcode scheme. - * - * @param transcodeScheme The transcode scheme. - */ - public void setTranscodeScheme(TranscodeScheme transcodeScheme) { - this.transcodeScheme = transcodeScheme; - } - - /** - * Returns the IP address of the player. - * - * @return The IP address of the player. - */ - public String getIpAddress() { - return ipAddress; - } - - /** - * Sets the IP address of the player. - * - * @param ipAddress The IP address of the player. - */ - public void setIpAddress(String ipAddress) { - this.ipAddress = ipAddress; - } - - /** - * Returns whether this player has a dynamic IP address. - * - * @return Whether this player has a dynamic IP address. - */ - public boolean isDynamicIp() { - return isDynamicIp; - } - - /** - * Sets whether this player has a dynamic IP address. - * - * @param dynamicIp Whether this player has a dynamic IP address. - */ - public void setDynamicIp(boolean dynamicIp) { - isDynamicIp = dynamicIp; - } - - /** - * Returns the player's playlist. - * - * @return The player's playlist - */ - public PlayQueue getPlayQueue() { - return playQueue; - } - - /** - * Sets the player's playlist. - * - * @param playQueue The player's playlist. - */ - public void setPlayQueue(PlayQueue playQueue) { - this.playQueue = playQueue; - } - - /** - * Returns a long description of the player, e.g., Player 3 [admin] - * - * @return A long description of the player. - */ - public String getDescription() { - StringBuilder builder = new StringBuilder(); - if (name != null) { - builder.append(name); - } else { - builder.append("Player ").append(id); - } - - builder.append(" [").append(username).append(']'); - return builder.toString(); - } - - /** - * Returns a short description of the player, e.g., Player 3 - * - * @return A short description of the player. - */ - public String getShortDescription() { - if (StringUtils.isNotBlank(name)) { - return name; - } - return "Player " + id; - } - - /** - * Returns a string representation of the player. - * - * @return A string representation of the player. - * @see #getDescription() - */ - @Override - public String toString() { - return getDescription(); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PlayerTechnology.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PlayerTechnology.java deleted file mode 100644 index 5ba3ff71..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PlayerTechnology.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Enumeration of player technologies. - * - * @author Sindre Mehus - */ -public enum PlayerTechnology { - - /** - * Plays music directly in the web browser using the integrated Flash player. - */ - WEB, - - /** - * Plays music in an external player, such as WinAmp or Windows Media Player. - */ - EXTERNAL, - - /** - * Same as above, but the playlist is managed by the player, rather than the Subsonic server. - * In this mode, skipping within songs is possible. - */ - EXTERNAL_WITH_PLAYLIST, - - /** - * Plays music directly on the audio device of the Subsonic server. - */ - JUKEBOX - -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Playlist.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Playlist.java deleted file mode 100644 index 80555ec7..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Playlist.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import net.sourceforge.subsonic.util.StringUtil; - -import java.util.Date; - -/** - * @author Sindre Mehus - */ -public class Playlist { - - private int id; - private String username; - private boolean isPublic; - private String name; - private String comment; - private int fileCount; - private int durationSeconds; - private Date created; - private Date changed; - private String importedFrom; - - public Playlist() { - } - - public Playlist(int id, String username, boolean isPublic, String name, String comment, int fileCount, - int durationSeconds, Date created, Date changed, String importedFrom) { - this.id = id; - this.username = username; - this.isPublic = isPublic; - this.name = name; - this.comment = comment; - this.fileCount = fileCount; - this.durationSeconds = durationSeconds; - this.created = created; - this.changed = changed; - this.importedFrom = importedFrom; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public boolean isPublic() { - return isPublic; - } - - public void setPublic(boolean isPublic) { - this.isPublic = isPublic; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getComment() { - return comment; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public int getFileCount() { - return fileCount; - } - - public void setFileCount(int fileCount) { - this.fileCount = fileCount; - } - - public int getDurationSeconds() { - return durationSeconds; - } - - public void setDurationSeconds(int durationSeconds) { - this.durationSeconds = durationSeconds; - } - - public String getDurationAsString() { - return StringUtil.formatDuration(durationSeconds); - } - - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - public Date getChanged() { - return changed; - } - - public void setChanged(Date changed) { - this.changed = changed; - } - - public String getImportedFrom() { - return importedFrom; - } - - public void setImportedFrom(String importedFrom) { - this.importedFrom = importedFrom; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastChannel.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastChannel.java deleted file mode 100644 index 1127a5cb..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastChannel.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import net.sourceforge.subsonic.util.StringUtil; - -/** - * A Podcast channel. Each channel contain several episodes. - * - * @author Sindre Mehus - * @see PodcastEpisode - */ -public class PodcastChannel { - - private Integer id; - private String url; - private String title; - private String description; - private PodcastStatus status; - private String errorMessage; - - public PodcastChannel(Integer id, String url, String title, String description, - PodcastStatus status, String errorMessage) { - this.id = id; - this.url = url; - this.title = StringUtil.removeMarkup(title); - this.description = StringUtil.removeMarkup(description); - this.status = status; - this.errorMessage = errorMessage; - } - - public PodcastChannel(String url) { - this.url = url; - status = PodcastStatus.NEW; - } - - public Integer getId() { - return id; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public PodcastStatus getStatus() { - return status; - } - - public void setStatus(PodcastStatus status) { - this.status = status; - } - - public String getErrorMessage() { - return errorMessage; - } - - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastEpisode.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastEpisode.java deleted file mode 100644 index b5a835cb..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastEpisode.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.Date; - -import net.sourceforge.subsonic.util.StringUtil; - -/** - * A Podcast episode belonging to a channel. - * - * @author Sindre Mehus - * @see PodcastChannel - */ -public class PodcastEpisode { - - private Integer id; - private Integer mediaFileId; - private Integer channelId; - private String url; - private String path; - private String title; - private String description; - private Date publishDate; - private String duration; - private Long bytesTotal; - private Long bytesDownloaded; - private PodcastStatus status; - private String errorMessage; - - public PodcastEpisode(Integer id, Integer channelId, String url, String path, String title, - String description, Date publishDate, String duration, Long length, Long bytesDownloaded, - PodcastStatus status, String errorMessage) { - this.id = id; - this.channelId = channelId; - this.url = url; - this.path = path; - this.title = StringUtil.removeMarkup(title); - this.description = StringUtil.removeMarkup(description); - this.publishDate = publishDate; - this.duration = duration; - this.bytesTotal = length; - this.bytesDownloaded = bytesDownloaded; - this.status = status; - this.errorMessage = errorMessage; - } - - public Integer getId() { - return id; - } - - public Integer getChannelId() { - return channelId; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Date getPublishDate() { - return publishDate; - } - - public void setPublishDate(Date publishDate) { - this.publishDate = publishDate; - } - - public String getDuration() { - return duration; - } - - public void setDuration(String duration) { - this.duration = duration; - } - - public Long getBytesTotal() { - return bytesTotal; - } - - public void setBytesTotal(Long bytesTotal) { - this.bytesTotal = bytesTotal; - } - - public Long getBytesDownloaded() { - return bytesDownloaded; - } - - public Double getCompletionRate() { - if (bytesTotal == null || bytesTotal == 0) { - return null; - } - if (bytesDownloaded == null) { - return 0.0; - } - - double d = bytesDownloaded; - double t = bytesTotal; - return d / t; - } - - public void setBytesDownloaded(Long bytesDownloaded) { - this.bytesDownloaded = bytesDownloaded; - } - - public PodcastStatus getStatus() { - return status; - } - - public void setStatus(PodcastStatus status) { - this.status = status; - } - - public String getErrorMessage() { - return errorMessage; - } - - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } - - public Integer getMediaFileId() { - return mediaFileId; - } - - public void setMediaFileId(Integer mediaFileId) { - this.mediaFileId = mediaFileId; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastStatus.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastStatus.java deleted file mode 100644 index 57cad155..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/PodcastStatus.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Enumeration of statuses for {@link PodcastChannel} and - * {@link PodcastEpisode}. - * - * @author Sindre Mehus - */ -public enum PodcastStatus { - NEW, DOWNLOADING, COMPLETED, ERROR, DELETED, SKIPPED -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/RandomSearchCriteria.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/RandomSearchCriteria.java deleted file mode 100644 index d52cec39..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/RandomSearchCriteria.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Defines criteria used when generating random playlists. - * - * @author Sindre Mehus - * @see net.sourceforge.subsonic.service.SearchService#getRandomSongs - */ -public class RandomSearchCriteria { - private final int count; - private final String genre; - private final Integer fromYear; - private final Integer toYear; - private final Integer musicFolderId; - - /** - * Creates a new instance. - * - * @param count Maximum number of songs to return. - * @param genre Only return songs of the given genre. May be null. - * @param fromYear Only return songs released after (or in) this year. May be null. - * @param toYear Only return songs released before (or in) this year. May be null. - * @param musicFolderId Only return songs from this music folder. May be null. - */ - public RandomSearchCriteria(int count, String genre, Integer fromYear, Integer toYear, Integer musicFolderId) { - this.count = count; - this.genre = genre; - this.fromYear = fromYear; - this.toYear = toYear; - this.musicFolderId = musicFolderId; - } - - public int getCount() { - return count; - } - - public String getGenre() { - return genre; - } - - public Integer getFromYear() { - return fromYear; - } - - public Integer getToYear() { - return toYear; - } - - public Integer getMusicFolderId() { - return musicFolderId; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Router.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Router.java deleted file mode 100644 index ede9d19e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Router.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * @author Sindre Mehus - * @version $Id$ - */ -public interface Router { - - /** - * Adds a NAT entry on the UPNP device. - * - * @param externalPort The external port to open on the UPNP device an map on the internal client. - * @param internalPort The internal client port where data should be redirected. - * @param leaseDuration Seconds the lease duration in seconds, or 0 for an infinite time. - */ - void addPortMapping(int externalPort, int internalPort, int leaseDuration) throws Exception; - - /** - * Deletes a NAT entry on the UPNP device. - * - * @param externalPort The external port of the NAT entry to delete. - * @param internalPort The internal port of the NAT entry to delete. - */ - void deletePortMapping(int externalPort, int internalPort) throws Exception; -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SBBIRouter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SBBIRouter.java deleted file mode 100644 index a639e665..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SBBIRouter.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import net.sbbi.upnp.impls.InternetGatewayDevice; - -import java.io.IOException; -import java.net.InetAddress; - -/** - * @author Sindre Mehus - */ -public class SBBIRouter implements Router { - - // The timeout in milliseconds for finding a router device. - private static final int DISCOVERY_TIMEOUT = 3000; - - private final InternetGatewayDevice device; - - private SBBIRouter(InternetGatewayDevice device) { - this.device = device; - } - - public static SBBIRouter findRouter() throws Exception { - InternetGatewayDevice[] devices; - try { - devices = InternetGatewayDevice.getDevices(DISCOVERY_TIMEOUT); - } catch (IOException e) { - throw new Exception("Could not find router", e); - } - - if (devices == null || devices.length == 0) { - return null; - } - - return new SBBIRouter(devices[0]); - } - - public void addPortMapping(int externalPort, int internalPort, int leaseDuration) throws Exception { - String localIp = InetAddress.getLocalHost().getHostAddress(); - device.addPortMapping("Subsonic", null, internalPort, externalPort, localIp, leaseDuration, "TCP"); - } - - public void deletePortMapping(int externalPort, int internal) throws Exception { - device.deletePortMapping(null, externalPort, "TCP"); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SearchCriteria.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SearchCriteria.java deleted file mode 100644 index f06a6512..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SearchCriteria.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import net.sourceforge.subsonic.service.MediaScannerService; -import net.sourceforge.subsonic.service.SearchService; - -/** - * Defines criteria used when searching. - * - * @author Sindre Mehus - * @see SearchService#search - */ -public class SearchCriteria { - - private String query; - private int offset; - private int count; - - public void setQuery(String query) { - this.query = query; - } - - public String getQuery() { - return query; - } - - public int getOffset() { - return offset; - } - - public void setOffset(int offset) { - this.offset = offset; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SearchResult.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SearchResult.java deleted file mode 100644 index bf4b370a..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/SearchResult.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.ArrayList; -import java.util.List; - -import net.sourceforge.subsonic.service.MediaScannerService; -import net.sourceforge.subsonic.service.SearchService; - -/** - * The outcome of a search. - * - * @author Sindre Mehus - * @see SearchService#search - */ -public class SearchResult { - - private final List mediaFiles = new ArrayList(); - private final List artists = new ArrayList(); - private final List albums = new ArrayList(); - - private int offset; - private int totalHits; - - public List getMediaFiles() { - return mediaFiles; - } - - public List getArtists() { - return artists; - } - - public List getAlbums() { - return albums; - } - - public int getOffset() { - return offset; - } - - public void setOffset(int offset) { - this.offset = offset; - } - - public int getTotalHits() { - return totalHits; - } - - public void setTotalHits(int totalHits) { - this.totalHits = totalHits; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Share.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Share.java deleted file mode 100644 index 7494769b..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Share.java +++ /dev/null @@ -1,100 +0,0 @@ -package net.sourceforge.subsonic.domain; - -import java.util.Date; - -/** - * A collection of media files that is shared with someone, and accessible via a direct URL. - * - * @author Sindre Mehus - * @version $Id$ - */ -public class Share { - - private int id; - private String name; - private String description; - private String username; - private Date created; - private Date expires; - private Date lastVisited; - private int visitCount; - - public Share() { - } - - public Share(int id, String name, String description, String username, Date created, - Date expires, Date lastVisited, int visitCount) { - this.id = id; - this.name = name; - this.description = description; - this.username = username; - this.created = created; - this.expires = expires; - this.lastVisited = lastVisited; - this.visitCount = visitCount; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - public Date getExpires() { - return expires; - } - - public void setExpires(Date expires) { - this.expires = expires; - } - - public Date getLastVisited() { - return lastVisited; - } - - public void setLastVisited(Date lastVisited) { - this.lastVisited = lastVisited; - } - - public int getVisitCount() { - return visitCount; - } - - public void setVisitCount(int visitCount) { - this.visitCount = visitCount; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Theme.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Theme.java deleted file mode 100644 index f8bd66bd..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Theme.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Contains the ID and name for a theme. - * - * @author Sindre Mehus - */ -public class Theme { - private String id; - private String name; - - public Theme(String id, String name) { - this.id = id; - this.name = name; - } - - public String getId() { - return id; - } - - public String getName() { - return name; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/TranscodeScheme.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/TranscodeScheme.java deleted file mode 100644 index f45b452a..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/TranscodeScheme.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Enumeration of transcoding schemes. Transcoding is the process of - * converting an audio stream to a lower bit rate. - * - * @author Sindre Mehus - */ -public enum TranscodeScheme { - - OFF(0), - MAX_32(32), - MAX_40(40), - MAX_48(48), - MAX_56(56), - MAX_64(64), - MAX_80(80), - MAX_96(96), - MAX_112(112), - MAX_128(128), - MAX_160(160), - MAX_192(192), - MAX_224(224), - MAX_256(256), - MAX_320(320); - - private int maxBitRate; - - TranscodeScheme(int maxBitRate) { - this.maxBitRate = maxBitRate; - } - - /** - * Returns the maximum bit rate for this transcoding scheme. - * - * @return The maximum bit rate for this transcoding scheme. - */ - public int getMaxBitRate() { - return maxBitRate; - } - - /** - * Returns the strictest transcode scheme (i.e., the scheme with the lowest max bitrate). - * - * @param other The other transcode scheme. May be null, in which case 'this' is returned. - * @return The strictest scheme. - */ - public TranscodeScheme strictest(TranscodeScheme other) { - if (other == null || other == TranscodeScheme.OFF) { - return this; - } - - if (this == TranscodeScheme.OFF) { - return other; - } - - return maxBitRate < other.maxBitRate ? this : other; - } - - /** - * Returns a human-readable string representation of this object. - * - * @return A human-readable string representation of this object. - */ - public String toString() { - if (this == OFF) { - return "No limit"; - } - return "" + getMaxBitRate() + " Kbps"; - } - - /** - * Returns the enum constant which corresponds to the given max bit rate. - * - * @param maxBitRate The max bit rate. - * @return The corresponding enum, or null if not found. - */ - public static TranscodeScheme valueOf(int maxBitRate) { - for (TranscodeScheme scheme : values()) { - if (scheme.getMaxBitRate() == maxBitRate) { - return scheme; - } - } - return null; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Transcoding.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Transcoding.java deleted file mode 100644 index 57c8316f..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Transcoding.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import net.sourceforge.subsonic.util.StringUtil; - -/** - * Contains the configuration for a transcoding, i.e., a specification of how a given media format - * should be converted to another. - *
- * A transcoding may contain up to three steps. Typically you need to convert in several steps, for - * instance from OGG to WAV to MP3. - * - * @author Sindre Mehus - */ -public class Transcoding { - - private Integer id; - private String name; - private String sourceFormats; - private String targetFormat; - private String step1; - private String step2; - private String step3; - private boolean defaultActive; - - /** - * Creates a new transcoding specification. - * - * @param id The system-generated ID. - * @param name The user-defined name. - * @param sourceFormats The source formats, e.g., "ogg wav aac". - * @param targetFormat The target format, e.g., "mp3". - * @param step1 The command to execute in step 1. - * @param step2 The command to execute in step 2. - * @param step3 The command to execute in step 3. - * @param defaultActive Whether the transcoding should be automatically activated for all players. - */ - public Transcoding(Integer id, String name, String sourceFormats, String targetFormat, String step1, - String step2, String step3, boolean defaultActive) { - this.id = id; - this.name = name; - this.sourceFormats = sourceFormats; - this.targetFormat = targetFormat; - this.step1 = step1; - this.step2 = step2; - this.step3 = step3; - this.defaultActive = defaultActive; - } - - /** - * Returns the system-generated ID. - * - * @return The system-generated ID. - */ - public Integer getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - /** - * Returns the user-defined name. - * - * @return The user-defined name. - */ - public String getName() { - return name; - } - - /** - * Sets the user-defined name. - * - * @param name The user-defined name. - */ - public void setName(String name) { - this.name = name; - } - - /** - * Returns the source format, e.g., "ogg wav aac". - * - * @return The source format, e.g., "ogg wav aac". - */ - public String getSourceFormats() { - return sourceFormats; - } - - public String[] getSourceFormatsAsArray() { - return StringUtil.split(sourceFormats); - } - - /** - * Sets the source formats, e.g., "ogg wav aac". - * - * @param sourceFormats The source formats, e.g., "ogg wav aac". - */ - public void setSourceFormats(String sourceFormats) { - this.sourceFormats = sourceFormats; - } - - /** - * Returns the target format, e.g., mp3. - * - * @return The target format, e.g., mp3. - */ - public String getTargetFormat() { - return targetFormat; - } - - /** - * Sets the target format, e.g., mp3. - * - * @param targetFormat The target format, e.g., mp3. - */ - public void setTargetFormat(String targetFormat) { - this.targetFormat = targetFormat; - } - - /** - * Returns the command to execute in step 1. - * - * @return The command to execute in step 1. - */ - public String getStep1() { - return step1; - } - - /** - * Sets the command to execute in step 1. - * - * @param step1 The command to execute in step 1. - */ - public void setStep1(String step1) { - this.step1 = step1; - } - - /** - * Returns the command to execute in step 2. - * - * @return The command to execute in step 2. - */ - public String getStep2() { - return step2; - } - - /** - * Sets the command to execute in step 2. - * - * @param step2 The command to execute in step 2. - */ - public void setStep2(String step2) { - this.step2 = step2; - } - - /** - * Returns the command to execute in step 3. - * - * @return The command to execute in step 3. - */ - public String getStep3() { - return step3; - } - - /** - * Sets the command to execute in step 3. - * - * @param step3 The command to execute in step 3. - */ - public void setStep3(String step3) { - this.step3 = step3; - } - - /** - * Returns whether the transcoding should be automatically activated for all players - */ - public boolean isDefaultActive() { - return defaultActive; - } - - /** - * Sets whether the transcoding should be automatically activated for all players - */ - public void setDefaultActive(boolean defaultActive) { - this.defaultActive = defaultActive; - } - - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Transcoding that = (Transcoding) o; - return !(id != null ? !id.equals(that.id) : that.id != null); - } - - public int hashCode() { - return (id != null ? id.hashCode() : 0); - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/TransferStatus.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/TransferStatus.java deleted file mode 100644 index 06930ae3..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/TransferStatus.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.io.File; - -import net.sourceforge.subsonic.util.BoundedList; - -/** - * Status for a single transfer (stream, download or upload). - * - * @author Sindre Mehus - */ -public class TransferStatus { - - private static final int HISTORY_LENGTH = 200; - private static final long SAMPLE_INTERVAL_MILLIS = 5000; - - private Player player; - private File file; - private long bytesTransfered; - private long bytesSkipped; - private long bytesTotal; - private final SampleHistory history = new SampleHistory(); - private boolean terminated; - private boolean active = true; - - /** - * Return the number of bytes transferred. - * - * @return The number of bytes transferred. - */ - public synchronized long getBytesTransfered() { - return bytesTransfered; - } - - /** - * Adds the given byte count to the total number of bytes transferred. - * - * @param byteCount The byte count. - */ - public synchronized void addBytesTransfered(long byteCount) { - setBytesTransfered(bytesTransfered + byteCount); - } - - /** - * Sets the number of bytes transferred. - * - * @param bytesTransfered The number of bytes transferred. - */ - public synchronized void setBytesTransfered(long bytesTransfered) { - this.bytesTransfered = bytesTransfered; - createSample(bytesTransfered, false); - } - - private void createSample(long bytesTransfered, boolean force) { - long now = System.currentTimeMillis(); - - if (history.isEmpty()) { - history.add(new Sample(bytesTransfered, now)); - } else { - Sample lastSample = history.getLast(); - if (force || now - lastSample.getTimestamp() > TransferStatus.SAMPLE_INTERVAL_MILLIS) { - history.add(new Sample(bytesTransfered, now)); - } - } - } - - /** - * Returns the number of milliseconds since the transfer status was last updated. - * - * @return Number of milliseconds, or 0 if never updated. - */ - public synchronized long getMillisSinceLastUpdate() { - if (history.isEmpty()) { - return 0L; - } - return System.currentTimeMillis() - history.getLast().timestamp; - } - - /** - * Returns the total number of bytes, or 0 if unknown. - * - * @return The total number of bytes, or 0 if unknown. - */ - public long getBytesTotal() { - return bytesTotal; - } - - /** - * Sets the total number of bytes, or 0 if unknown. - * - * @param bytesTotal The total number of bytes, or 0 if unknown. - */ - public void setBytesTotal(long bytesTotal) { - this.bytesTotal = bytesTotal; - } - - /** - * Returns the number of bytes that has been skipped (for instance when - * resuming downloads). - * - * @return The number of skipped bytes. - */ - public synchronized long getBytesSkipped() { - return bytesSkipped; - } - - /** - * Sets the number of bytes that has been skipped (for instance when - * resuming downloads). - * - * @param bytesSkipped The number of skipped bytes. - */ - public synchronized void setBytesSkipped(long bytesSkipped) { - this.bytesSkipped = bytesSkipped; - } - - - /** - * Adds the given byte count to the total number of bytes skipped. - * - * @param byteCount The byte count. - */ - public synchronized void addBytesSkipped(long byteCount) { - bytesSkipped += byteCount; - } - - /** - * Returns the file that is currently being transferred. - * - * @return The file that is currently being transferred. - */ - public synchronized File getFile() { - return file; - } - - /** - * Sets the file that is currently being transferred. - * - * @param file The file that is currently being transferred. - */ - public synchronized void setFile(File file) { - this.file = file; - } - - /** - * Returns the remote player for the stream. - * - * @return The remote player for the stream. - */ - public synchronized Player getPlayer() { - return player; - } - - /** - * Sets the remote player for the stream. - * - * @param player The remote player for the stream. - */ - public synchronized void setPlayer(Player player) { - this.player = player; - } - - /** - * Returns a history of samples for the stream - * - * @return A (copy of) the history list of samples. - */ - public synchronized SampleHistory getHistory() { - return new SampleHistory(history); - } - - /** - * Returns the history length in milliseconds. - * - * @return The history length in milliseconds. - */ - public long getHistoryLengthMillis() { - return TransferStatus.SAMPLE_INTERVAL_MILLIS * (TransferStatus.HISTORY_LENGTH - 1); - } - - /** - * Indicate that the stream should be terminated. - */ - public void terminate() { - terminated = true; - } - - /** - * Returns whether this stream has been terminated. - * Not that the terminated status is cleared by this method. - * - * @return Whether this stream has been terminated. - */ - public boolean terminated() { - boolean result = terminated; - terminated = false; - return result; - } - - /** - * Returns whether this transfer is active, i.e., if the connection is still established. - * - * @return Whether this transfer is active. - */ - public boolean isActive() { - return active; - } - - /** - * Sets whether this transfer is active, i.e., if the connection is still established. - * - * @param active Whether this transfer is active. - */ - public void setActive(boolean active) { - this.active = active; - - if (active) { - setBytesSkipped(0L); - setBytesTotal(0L); - setBytesTransfered(0L); - } else { - createSample(getBytesTransfered(), true); - } - } - - /** - * A sample containing a timestamp and the number of bytes transferred up to that point in time. - */ - public static class Sample { - private long bytesTransfered; - private long timestamp; - - /** - * Creates a new sample. - * - * @param bytesTransfered The total number of bytes transferred. - * @param timestamp A point in time, in milliseconds. - */ - public Sample(long bytesTransfered, long timestamp) { - this.bytesTransfered = bytesTransfered; - this.timestamp = timestamp; - } - - /** - * Returns the number of bytes transferred. - * - * @return The number of bytes transferred. - */ - public long getBytesTransfered() { - return bytesTransfered; - } - - /** - * Returns the timestamp of the sample. - * - * @return The timestamp in milliseconds. - */ - public long getTimestamp() { - return timestamp; - } - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("TransferStatus-").append(hashCode()).append(" [player: ").append(player.getId()).append(", file: "); - builder.append(file).append(", terminated: ").append(terminated).append(", active: ").append(active).append("]"); - return builder.toString(); - } - - /** - * Contains recent history of samples. - */ - public static class SampleHistory extends BoundedList { - - public SampleHistory() { - super(HISTORY_LENGTH); - } - - public SampleHistory(SampleHistory other) { - super(HISTORY_LENGTH); - addAll(other); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/User.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/User.java deleted file mode 100644 index 95e51004..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/User.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Represent a user. - * - * @author Sindre Mehus - */ -public class User { - - public static final String USERNAME_ADMIN = "admin"; - - private final String username; - private String password; - private String email; - private boolean ldapAuthenticated; - private long bytesStreamed; - private long bytesDownloaded; - private long bytesUploaded; - - private boolean isAdminRole; - private boolean isSettingsRole; - private boolean isDownloadRole; - private boolean isUploadRole; - private boolean isPlaylistRole; - private boolean isCoverArtRole; - private boolean isCommentRole; - private boolean isPodcastRole; - private boolean isStreamRole; - private boolean isJukeboxRole; - private boolean isShareRole; - - public User(String username, String password, String email, boolean ldapAuthenticated, - long bytesStreamed, long bytesDownloaded, long bytesUploaded) { - this.username = username; - this.password = password; - this.email = email; - this.ldapAuthenticated = ldapAuthenticated; - this.bytesStreamed = bytesStreamed; - this.bytesDownloaded = bytesDownloaded; - this.bytesUploaded = bytesUploaded; - } - - public User(String username, String password, String email) { - this(username, password, email, false, 0, 0, 0); - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public boolean isLdapAuthenticated() { - return ldapAuthenticated; - } - - public void setLdapAuthenticated(boolean ldapAuthenticated) { - this.ldapAuthenticated = ldapAuthenticated; - } - - public long getBytesStreamed() { - return bytesStreamed; - } - - public void setBytesStreamed(long bytesStreamed) { - this.bytesStreamed = bytesStreamed; - } - - public long getBytesDownloaded() { - return bytesDownloaded; - } - - public void setBytesDownloaded(long bytesDownloaded) { - this.bytesDownloaded = bytesDownloaded; - } - - public long getBytesUploaded() { - return bytesUploaded; - } - - public void setBytesUploaded(long bytesUploaded) { - this.bytesUploaded = bytesUploaded; - } - - public boolean isAdminRole() { - return isAdminRole; - } - - public void setAdminRole(boolean isAdminRole) { - this.isAdminRole = isAdminRole; - } - - public boolean isSettingsRole() { - return isSettingsRole; - } - - public void setSettingsRole(boolean isSettingsRole) { - this.isSettingsRole = isSettingsRole; - } - - public boolean isCommentRole() { - return isCommentRole; - } - - public void setCommentRole(boolean isCommentRole) { - this.isCommentRole = isCommentRole; - } - - public boolean isDownloadRole() { - return isDownloadRole; - } - - public void setDownloadRole(boolean isDownloadRole) { - this.isDownloadRole = isDownloadRole; - } - - public boolean isUploadRole() { - return isUploadRole; - } - - public void setUploadRole(boolean isUploadRole) { - this.isUploadRole = isUploadRole; - } - - public boolean isPlaylistRole() { - return isPlaylistRole; - } - - public void setPlaylistRole(boolean isPlaylistRole) { - this.isPlaylistRole = isPlaylistRole; - } - - public boolean isCoverArtRole() { - return isCoverArtRole; - } - - public void setCoverArtRole(boolean isCoverArtRole) { - this.isCoverArtRole = isCoverArtRole; - } - - public boolean isPodcastRole() { - return isPodcastRole; - } - - public void setPodcastRole(boolean isPodcastRole) { - this.isPodcastRole = isPodcastRole; - } - - public boolean isStreamRole() { - return isStreamRole; - } - - public void setStreamRole(boolean streamRole) { - isStreamRole = streamRole; - } - - public boolean isJukeboxRole() { - return isJukeboxRole; - } - - public void setJukeboxRole(boolean jukeboxRole) { - isJukeboxRole = jukeboxRole; - } - - public boolean isShareRole() { - return isShareRole; - } - - public void setShareRole(boolean shareRole) { - isShareRole = shareRole; - } - - @Override - public String toString() { - StringBuffer result = new StringBuffer(username); - - if (isAdminRole) { - result.append(" [admin]"); - } - if (isSettingsRole) { - result.append(" [settings]"); - } - if (isDownloadRole) { - result.append(" [download]"); - } - if (isUploadRole) { - result.append(" [upload]"); - } - if (isPlaylistRole) { - result.append(" [playlist]"); - } - if (isCoverArtRole) { - result.append(" [coverart]"); - } - if (isCommentRole) { - result.append(" [comment]"); - } - if (isPodcastRole) { - result.append(" [podcast]"); - } - if (isStreamRole) { - result.append(" [stream]"); - } - if (isJukeboxRole) { - result.append(" [jukebox]"); - } - if (isShareRole) { - result.append(" [share]"); - } - - return result.toString(); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/UserSettings.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/UserSettings.java deleted file mode 100644 index 856591bc..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/UserSettings.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import java.util.*; - -/** - * Represent user-specific settings. - * - * @author Sindre Mehus - */ -public class UserSettings { - - private String username; - private Locale locale; - private String themeId; - private boolean showNowPlayingEnabled; - private boolean showChatEnabled; - private boolean finalVersionNotificationEnabled; - private boolean betaVersionNotificationEnabled; - private Visibility mainVisibility = new Visibility(); - private Visibility playlistVisibility = new Visibility(); - private boolean lastFmEnabled; - private String lastFmUsername; - private String lastFmPassword; - private TranscodeScheme transcodeScheme = TranscodeScheme.OFF; - private int selectedMusicFolderId = -1; - private boolean partyModeEnabled; - private boolean nowPlayingAllowed; - private AvatarScheme avatarScheme = AvatarScheme.NONE; - private Integer systemAvatarId; - private Date changed = new Date(); - - public UserSettings(String username) { - this.username = username; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public Locale getLocale() { - return locale; - } - - public void setLocale(Locale locale) { - this.locale = locale; - } - - public String getThemeId() { - return themeId; - } - - public void setThemeId(String themeId) { - this.themeId = themeId; - } - - public boolean isShowNowPlayingEnabled() { - return showNowPlayingEnabled; - } - - public void setShowNowPlayingEnabled(boolean showNowPlayingEnabled) { - this.showNowPlayingEnabled = showNowPlayingEnabled; - } - - public boolean isShowChatEnabled() { - return showChatEnabled; - } - - public void setShowChatEnabled(boolean showChatEnabled) { - this.showChatEnabled = showChatEnabled; - } - - public boolean isFinalVersionNotificationEnabled() { - return finalVersionNotificationEnabled; - } - - public void setFinalVersionNotificationEnabled(boolean finalVersionNotificationEnabled) { - this.finalVersionNotificationEnabled = finalVersionNotificationEnabled; - } - - public boolean isBetaVersionNotificationEnabled() { - return betaVersionNotificationEnabled; - } - - public void setBetaVersionNotificationEnabled(boolean betaVersionNotificationEnabled) { - this.betaVersionNotificationEnabled = betaVersionNotificationEnabled; - } - - public Visibility getMainVisibility() { - return mainVisibility; - } - - public void setMainVisibility(Visibility mainVisibility) { - this.mainVisibility = mainVisibility; - } - - public Visibility getPlaylistVisibility() { - return playlistVisibility; - } - - public void setPlaylistVisibility(Visibility playlistVisibility) { - this.playlistVisibility = playlistVisibility; - } - - public boolean isLastFmEnabled() { - return lastFmEnabled; - } - - public void setLastFmEnabled(boolean lastFmEnabled) { - this.lastFmEnabled = lastFmEnabled; - } - - public String getLastFmUsername() { - return lastFmUsername; - } - - public void setLastFmUsername(String lastFmUsername) { - this.lastFmUsername = lastFmUsername; - } - - public String getLastFmPassword() { - return lastFmPassword; - } - - public void setLastFmPassword(String lastFmPassword) { - this.lastFmPassword = lastFmPassword; - } - - public TranscodeScheme getTranscodeScheme() { - return transcodeScheme; - } - - public void setTranscodeScheme(TranscodeScheme transcodeScheme) { - this.transcodeScheme = transcodeScheme; - } - - public int getSelectedMusicFolderId() { - return selectedMusicFolderId; - } - - public void setSelectedMusicFolderId(int selectedMusicFolderId) { - this.selectedMusicFolderId = selectedMusicFolderId; - } - - public boolean isPartyModeEnabled() { - return partyModeEnabled; - } - - public void setPartyModeEnabled(boolean partyModeEnabled) { - this.partyModeEnabled = partyModeEnabled; - } - - public boolean isNowPlayingAllowed() { - return nowPlayingAllowed; - } - - public void setNowPlayingAllowed(boolean nowPlayingAllowed) { - this.nowPlayingAllowed = nowPlayingAllowed; - } - - public AvatarScheme getAvatarScheme() { - return avatarScheme; - } - - public void setAvatarScheme(AvatarScheme avatarScheme) { - this.avatarScheme = avatarScheme; - } - - public Integer getSystemAvatarId() { - return systemAvatarId; - } - - public void setSystemAvatarId(Integer systemAvatarId) { - this.systemAvatarId = systemAvatarId; - } - - /** - * Returns when the corresponding database entry was last changed. - * - * @return When the corresponding database entry was last changed. - */ - public Date getChanged() { - return changed; - } - - /** - * Sets when the corresponding database entry was last changed. - * - * @param changed When the corresponding database entry was last changed. - */ - public void setChanged(Date changed) { - this.changed = changed; - } - - /** - * Configuration of what information to display about a song. - */ - public static class Visibility { - private int captionCutoff; - private boolean isTrackNumberVisible; - private boolean isArtistVisible; - private boolean isAlbumVisible; - private boolean isGenreVisible; - private boolean isYearVisible; - private boolean isBitRateVisible; - private boolean isDurationVisible; - private boolean isFormatVisible; - private boolean isFileSizeVisible; - - public Visibility() {} - - public Visibility(int captionCutoff, boolean trackNumberVisible, boolean artistVisible, boolean albumVisible, - boolean genreVisible, boolean yearVisible, boolean bitRateVisible, - boolean durationVisible, boolean formatVisible, boolean fileSizeVisible) { - this.captionCutoff = captionCutoff; - isTrackNumberVisible = trackNumberVisible; - isArtistVisible = artistVisible; - isAlbumVisible = albumVisible; - isGenreVisible = genreVisible; - isYearVisible = yearVisible; - isBitRateVisible = bitRateVisible; - isDurationVisible = durationVisible; - isFormatVisible = formatVisible; - isFileSizeVisible = fileSizeVisible; - } - - public int getCaptionCutoff() { - return captionCutoff; - } - - public void setCaptionCutoff(int captionCutoff) { - this.captionCutoff = captionCutoff; - } - - public boolean isTrackNumberVisible() { - return isTrackNumberVisible; - } - - public void setTrackNumberVisible(boolean trackNumberVisible) { - isTrackNumberVisible = trackNumberVisible; - } - - public boolean isArtistVisible() { - return isArtistVisible; - } - - public void setArtistVisible(boolean artistVisible) { - isArtistVisible = artistVisible; - } - - public boolean isAlbumVisible() { - return isAlbumVisible; - } - - public void setAlbumVisible(boolean albumVisible) { - isAlbumVisible = albumVisible; - } - - public boolean isGenreVisible() { - return isGenreVisible; - } - - public void setGenreVisible(boolean genreVisible) { - isGenreVisible = genreVisible; - } - - public boolean isYearVisible() { - return isYearVisible; - } - - public void setYearVisible(boolean yearVisible) { - isYearVisible = yearVisible; - } - - public boolean isBitRateVisible() { - return isBitRateVisible; - } - - public void setBitRateVisible(boolean bitRateVisible) { - isBitRateVisible = bitRateVisible; - } - - public boolean isDurationVisible() { - return isDurationVisible; - } - - public void setDurationVisible(boolean durationVisible) { - isDurationVisible = durationVisible; - } - - public boolean isFormatVisible() { - return isFormatVisible; - } - - public void setFormatVisible(boolean formatVisible) { - isFormatVisible = formatVisible; - } - - public boolean isFileSizeVisible() { - return isFileSizeVisible; - } - - public void setFileSizeVisible(boolean fileSizeVisible) { - isFileSizeVisible = fileSizeVisible; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Version.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Version.java deleted file mode 100644 index c4d42a99..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/Version.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Represents the version number of Subsonic. - * - * @author Sindre Mehus - * @version $Revision: 1.3 $ $Date: 2006/01/20 21:25:16 $ - */ -public class Version implements Comparable { - private int major; - private int minor; - private int beta; - private int bugfix; - - /** - * Creates a new version instance by parsing the given string. - * @param version A string of the format "1.27", "1.27.2" or "1.27.beta3". - */ - public Version(String version) { - String[] s = version.split("\\."); - major = Integer.valueOf(s[0]); - minor = Integer.valueOf(s[1]); - - if (s.length > 2) { - if (s[2].contains("beta")) { - beta = Integer.valueOf(s[2].replace("beta", "")); - } else { - bugfix = Integer.valueOf(s[2]); - } - } - } - - public int getMajor() { - return major; - } - - public int getMinor() { - return minor; - } - - /** - * Return whether this object is equal to another. - * @param o Object to compare to. - * @return Whether this object is equals to another. - */ - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final Version version = (Version) o; - - if (beta != version.beta) return false; - if (bugfix != version.bugfix) return false; - if (major != version.major) return false; - return minor == version.minor; - } - - /** - * Returns a hash code for this object. - * @return A hash code for this object. - */ - public int hashCode() { - int result; - result = major; - result = 29 * result + minor; - result = 29 * result + beta; - result = 29 * result + bugfix; - return result; - } - - /** - * Returns a string representation of the form "1.27", "1.27.2" or "1.27.beta3". - * @return A string representation of the form "1.27", "1.27.2" or "1.27.beta3". - */ - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append(major).append('.').append(minor); - if (beta != 0) { - buf.append(".beta").append(beta); - } else if (bugfix != 0) { - buf.append('.').append(bugfix); - } - - return buf.toString(); - } - - /** - * Compares this object with the specified object for order. - * @param version The object to compare to. - * @return A negative integer, zero, or a positive integer as this object is less than, equal to, or - * greater than the specified object. - */ - public int compareTo(Version version) { - if (major < version.major) { - return -1; - } else if (major > version.major) { - return 1; - } - - if (minor < version.minor) { - return -1; - } else if (minor > version.minor) { - return 1; - } - - if (bugfix < version.bugfix) { - return -1; - } else if (bugfix > version.bugfix) { - return 1; - } - - int thisBeta = beta == 0 ? Integer.MAX_VALUE : beta; - int otherBeta = version.beta == 0 ? Integer.MAX_VALUE : version.beta; - - if (thisBeta < otherBeta) { - return -1; - } else if (thisBeta > otherBeta) { - return 1; - } - - return 0; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/VideoTranscodingSettings.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/VideoTranscodingSettings.java deleted file mode 100644 index 18661ba4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/VideoTranscodingSettings.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -/** - * Parameters used when transcoding videos. - * - * @author Sindre Mehus - * @version $Id$ - */ -public class VideoTranscodingSettings { - - private final int width; - private final int height; - private final int timeOffset; - - public VideoTranscodingSettings(int width, int height, int timeOffset) { - this.width = width; - this.height = height; - this.timeOffset = timeOffset; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public int getTimeOffset() { - return timeOffset; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/WeUPnPRouter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/WeUPnPRouter.java deleted file mode 100644 index e36701e8..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/WeUPnPRouter.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.domain; - -import org.wetorrent.upnp.GatewayDevice; -import org.wetorrent.upnp.GatewayDiscover; - -import java.net.InetAddress; - -/** - * @author Sindre Mehus - * @version $Id$ - */ -public class WeUPnPRouter implements Router { - private final GatewayDevice device; - - private WeUPnPRouter(GatewayDevice device) { - this.device = device; - } - - public static WeUPnPRouter findRouter() throws Exception { - GatewayDiscover discover = new GatewayDiscover(); - discover.discover(); - GatewayDevice device = discover.getValidGateway(); - if (device == null) { - return null; - } - - return new WeUPnPRouter(device); - } - - public void addPortMapping(int externalPort, int internalPort, int leaseDuration) throws Exception { - String localIp = InetAddress.getLocalHost().getHostAddress(); - device.addPortMapping(externalPort, internalPort, localIp, "TCP", "Subsonic"); - } - - public void deletePortMapping(int externalPort, int internalPort) throws Exception { - device.deletePortMapping(externalPort, "TCP"); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/BootstrapVerificationFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/BootstrapVerificationFilter.java deleted file mode 100644 index c93d0603..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/BootstrapVerificationFilter.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.filter; - -import net.sourceforge.subsonic.service.SettingsService; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import java.io.File; -import java.io.IOException; - -/** - * This filter is executed very early in the filter chain. It verifies that - * the Subsonic home directory (c:\subsonic or /var/subsonic) exists and - * is writable. If not, a proper error message is given to the user. - *

- * (The Subsonic home directory is usually created automatically, but a common - * problem on Linux is that the Tomcat user does not have the necessary - * privileges). - * - * @author Sindre Mehus - */ -public class BootstrapVerificationFilter implements Filter { - - private boolean subsonicHomeVerified = false; - - - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) - throws IOException, ServletException { - - // Already verified? - if (subsonicHomeVerified) { - chain.doFilter(req, res); - return; - } - - File home = SettingsService.getSubsonicHome(); - if (!directoryExists(home)) { - error(res, "

The directory " + home + " does not exist. Please create it and make it writable, " + - "then restart the servlet container.

" + - "

(You can override the directory location by specifying -Dsubsonic.home=... when " + - "starting the servlet container.)

"); - - } else if (!directoryWritable(home)) { - error(res, "

The directory " + home + " is not writable. Please change file permissions, " + - "then restart the servlet container.

" + - "

(You can override the directory location by specifying -Dsubsonic.home=... when " + - "starting the servlet container.)

"); - - } else { - subsonicHomeVerified = true; - chain.doFilter(req, res); - } - } - - private boolean directoryExists(File dir) { - return dir.exists() && dir.isDirectory(); - } - - private boolean directoryWritable(File dir) { - try { - File tempFile = File.createTempFile("test", null, dir); - tempFile.delete(); - return true; - } catch (IOException x) { - return false; - } - } - - private void error(ServletResponse res, String error) throws IOException { - ServletOutputStream out = res.getOutputStream(); - out.println("" + - "Subsonic Error" + - "" + - "

Subsonic Error

" + - error + - "" + - ""); - } - - public void init(FilterConfig filterConfig) { - } - - public void destroy() { - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ParameterDecodingFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ParameterDecodingFilter.java deleted file mode 100644 index 52a98ad0..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ParameterDecodingFilter.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.filter; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.util.StringUtil; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import java.io.IOException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.Vector; - -/** - * Servlet filter which decodes HTTP request parameters. If a parameter name ends with - * "Utf8Hex" ({@link #PARAM_SUFFIX}) , the corresponding parameter value is assumed to be the - * hexadecimal representation of the UTF-8 bytes of the value. - *

- * Used to support request parameter values of any character encoding. - * - * @author Sindre Mehus - */ -public class ParameterDecodingFilter implements Filter { - - public static final String PARAM_SUFFIX = "Utf8Hex"; - private static final Logger LOG = Logger.getLogger(ParameterDecodingFilter.class); - - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - - // Wrap request in decoder. - ServletRequest decodedRequest = new DecodingServletRequestWrapper((HttpServletRequest) request); - - // Pass the request/response on - chain.doFilter(decodedRequest, response); - } - - public void init(FilterConfig filterConfig) { - } - - public void destroy() { - } - - private static class DecodingServletRequestWrapper extends HttpServletRequestWrapper { - - public DecodingServletRequestWrapper(HttpServletRequest servletRequest) { - super(servletRequest); - } - - @Override - public String getParameter(String name) { - String[] values = getParameterValues(name); - if (values == null || values.length == 0) { - return null; - } - return values[0]; - } - - @Override - public Map getParameterMap() { - Map map = super.getParameterMap(); - Map result = new HashMap(); - - for (Object o : map.entrySet()) { - Map.Entry entry = (Map.Entry) o; - String name = (String) entry.getKey(); - String[] values = (String[]) entry.getValue(); - - if (name.endsWith(PARAM_SUFFIX)) { - result.put(name.replace(PARAM_SUFFIX, ""), decode(values)); - } else { - result.put(name, values); - } - } - return result; - } - - @Override - public Enumeration getParameterNames() { - Enumeration e = super.getParameterNames(); - Vector v = new Vector(); - while (e.hasMoreElements()) { - String name = (String) e.nextElement(); - if (name.endsWith(PARAM_SUFFIX)) { - name = name.replace(PARAM_SUFFIX, ""); - } - v.add(name); - } - - return v.elements(); - } - - @Override - public String[] getParameterValues(String name) { - String[] values = super.getParameterValues(name); - if (values != null) { - return values; - } - - values = super.getParameterValues(name + PARAM_SUFFIX); - if (values != null) { - return decode(values); - } - - return null; - } - - private String[] decode(String[] values) { - if (values == null) { - return null; - } - - String[] result = new String[values.length]; - for (int i = 0; i < values.length; i++) { - try { - result[i] = StringUtil.utf8HexDecode(values[i]); - } catch (Exception x) { - LOG.error("Failed to decode parameter value '" + values[i] + "'"); - result[i] = values[i]; - } - } - - return result; - } - - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/RequestEncodingFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/RequestEncodingFilter.java deleted file mode 100644 index 3b37e8d4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/RequestEncodingFilter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.filter; - -import javax.servlet.*; -import javax.servlet.http.*; -import java.io.*; - -/** - * Configurable filter for setting the character encoding to use for the HTTP request. - * Typically used to set UTF-8 encoding when reading request parameters with non-Latin - * content. - * - * @author Sindre Mehus - * @version $Revision: 1.1 $ $Date: 2006/03/01 16:58:08 $ - */ -public class RequestEncodingFilter implements Filter { - - private String encoding; - - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) - throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) req; - request.setCharacterEncoding(encoding); - - // Pass the request/response on - chain.doFilter(req, res); - } - - public void init(FilterConfig filterConfig) { - encoding = filterConfig.getInitParameter("encoding"); - } - - public void destroy() { - encoding = null; - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ResponseHeaderFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ResponseHeaderFilter.java deleted file mode 100644 index 33f60f83..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/filter/ResponseHeaderFilter.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.filter; - -import javax.servlet.*; -import javax.servlet.http.*; -import java.io.*; -import java.util.*; - -/** - * Configurable filter for setting HTTP response headers. Can be used, for instance, to - * set cache control directives for certain resources. - * - * @author Sindre Mehus - * @version $Revision: 1.1 $ $Date: 2005/08/14 13:14:47 $ - */ -public class ResponseHeaderFilter implements Filter { - private FilterConfig filterConfig; - - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) - throws IOException, ServletException { - HttpServletResponse response = (HttpServletResponse) res; - - // Sets the provided HTTP response parameters - for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) { - String headerName = (String) e.nextElement(); - response.addHeader(headerName, filterConfig.getInitParameter(headerName)); - } - - // pass the request/response on - chain.doFilter(req, response); - } - - public void init(FilterConfig filterConfig) { - this.filterConfig = filterConfig; - } - - public void destroy() { - this.filterConfig = null; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/i18n/SubsonicLocaleResolver.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/i18n/SubsonicLocaleResolver.java deleted file mode 100644 index 231ad6e7..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/i18n/SubsonicLocaleResolver.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.i18n; - -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.domain.*; -import org.springframework.web.servlet.*; - -import javax.servlet.http.*; -import java.util.*; - -/** - * Locale resolver implementation which returns the locale selected in the settings. - * - * @author Sindre Mehus - */ -public class SubsonicLocaleResolver implements LocaleResolver { - - private SecurityService securityService; - private SettingsService settingsService; - private Set locales; - - /** - * Resolve the current locale via the given request. - * - * @param request Request to be used for resolution. - * @return The current locale. - */ - public Locale resolveLocale(HttpServletRequest request) { - Locale locale = (Locale) request.getAttribute("subsonic.locale"); - if (locale != null) { - return locale; - } - - // Optimization: Cache locale in the request. - locale = doResolveLocale(request); - request.setAttribute("subsonic.locale", locale); - - return locale; - } - - private Locale doResolveLocale(HttpServletRequest request) { - Locale locale = null; - - // Look for user-specific locale. - String username = securityService.getCurrentUsername(request); - if (username != null) { - UserSettings userSettings = settingsService.getUserSettings(username); - if (userSettings != null) { - locale = userSettings.getLocale(); - } - } - - if (locale != null && localeExists(locale)) { - return locale; - } - - // Return system locale. - locale = settingsService.getLocale(); - return localeExists(locale) ? locale : Locale.ENGLISH; - } - - /** - * Returns whether the given locale exists. - * @param locale The locale. - * @return Whether the locale exists. - */ - private synchronized boolean localeExists(Locale locale) { - // Lazily create set of locales. - if (locales == null) { - locales = new HashSet(Arrays.asList(settingsService.getAvailableLocales())); - } - - return locales.contains(locale); - } - - public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { - throw new UnsupportedOperationException("Cannot change locale - use a different locale resolution strategy"); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/InputStreamReaderThread.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/io/InputStreamReaderThread.java deleted file mode 100644 index 1019f73a..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/InputStreamReaderThread.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.io; - -import net.sourceforge.subsonic.*; -import org.apache.commons.io.*; - -import java.io.*; - -/** - * Utility class which reads everything from an input stream and optionally logs it. - * - * @see TranscodeInputStream - * @author Sindre Mehus - */ -public class InputStreamReaderThread extends Thread { - - private static final Logger LOG = Logger.getLogger(InputStreamReaderThread.class); - - private InputStream input; - private String name; - private boolean log; - - public InputStreamReaderThread(InputStream input, String name, boolean log) { - super(name + " InputStreamLogger"); - this.input = input; - this.name = name; - this.log = log; - } - - public void run() { - BufferedReader reader = null; - try { - reader = new BufferedReader(new InputStreamReader(input)); - for (String line = reader.readLine(); line != null; line = reader.readLine()) { - if (log) { - LOG.debug('(' + name + ") " + line); - } - } - } catch (IOException x) { - // Intentionally ignored. - } finally { - IOUtils.closeQuietly(reader); - IOUtils.closeQuietly(input); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java deleted file mode 100644 index 3be7fdd9..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/PlayQueueInputStream.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.io; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.VideoTranscodingSettings; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.SearchService; -import net.sourceforge.subsonic.util.FileUtil; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.service.AudioScrobblerService; -import net.sourceforge.subsonic.service.TranscodingService; - -import java.io.IOException; -import java.io.InputStream; -import java.util.List; - -/** - * Implementation of {@link InputStream} which reads from a {@link net.sourceforge.subsonic.domain.PlayQueue}. - * - * @author Sindre Mehus - */ -public class PlayQueueInputStream extends InputStream { - - private static final Logger LOG = Logger.getLogger(PlayQueueInputStream.class); - - private final Player player; - private final TransferStatus status; - private final Integer maxBitRate; - private final String preferredTargetFormat; - private final VideoTranscodingSettings videoTranscodingSettings; - private final TranscodingService transcodingService; - private final AudioScrobblerService audioScrobblerService; - private final MediaFileService mediaFileService; - private MediaFile currentFile; - private InputStream currentInputStream; - private SearchService searchService; - - public PlayQueueInputStream(Player player, TransferStatus status, Integer maxBitRate, String preferredTargetFormat, - VideoTranscodingSettings videoTranscodingSettings, TranscodingService transcodingService, - AudioScrobblerService audioScrobblerService, MediaFileService mediaFileService, SearchService searchService) { - this.player = player; - this.status = status; - this.maxBitRate = maxBitRate; - this.preferredTargetFormat = preferredTargetFormat; - this.videoTranscodingSettings = videoTranscodingSettings; - this.transcodingService = transcodingService; - this.audioScrobblerService = audioScrobblerService; - this.mediaFileService = mediaFileService; - this.searchService = searchService; - } - - @Override - public int read() throws IOException { - byte[] b = new byte[1]; - int n = read(b); - return n == -1 ? -1 : b[0]; - } - - @Override - public int read(byte[] b) throws IOException { - return read(b, 0, b.length); - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - prepare(); - if (currentInputStream == null || player.getPlayQueue().getStatus() == PlayQueue.Status.STOPPED) { - return -1; - } - - int n = currentInputStream.read(b, off, len); - - // If end of song reached, skip to next song and call read() again. - if (n == -1) { - player.getPlayQueue().next(); - close(); - return read(b, off, len); - } else { - status.addBytesTransfered(n); - } - return n; - } - - private void prepare() throws IOException { - PlayQueue playQueue = player.getPlayQueue(); - - // If playlist is in auto-random mode, populate it with new random songs. - if (playQueue.getIndex() == -1 && playQueue.getRandomSearchCriteria() != null) { - populateRandomPlaylist(playQueue); - } - - MediaFile result; - synchronized (playQueue) { - result = playQueue.getCurrentFile(); - } - MediaFile file = result; - if (file == null) { - close(); - } else if (!file.equals(currentFile)) { - close(); - LOG.info(player.getUsername() + " listening to \"" + FileUtil.getShortPath(file.getFile()) + "\""); - mediaFileService.incrementPlayCount(file); - if (player.getClientId() == null) { // Don't scrobble REST players. - audioScrobblerService.register(file, player.getUsername(), false); - } - - TranscodingService.Parameters parameters = transcodingService.getParameters(file, player, maxBitRate, preferredTargetFormat, videoTranscodingSettings); - currentInputStream = transcodingService.getTranscodedInputStream(parameters); - currentFile = file; - status.setFile(currentFile.getFile()); - } - } - - private void populateRandomPlaylist(PlayQueue playQueue) throws IOException { - List files = searchService.getRandomSongs(playQueue.getRandomSearchCriteria()); - playQueue.addFiles(false, files); - LOG.info("Recreated random playlist with " + playQueue.size() + " songs."); - } - - @Override - public void close() throws IOException { - try { - if (currentInputStream != null) { - currentInputStream.close(); - } - } finally { - if (player.getClientId() == null) { // Don't scrobble REST players. - audioScrobblerService.register(currentFile, player.getUsername(), true); - } - currentInputStream = null; - currentFile = null; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java deleted file mode 100644 index 25bc03d2..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.io; - -import org.apache.commons.lang.math.Range; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; - - -/** - * Special output stream for grabbing only part of a passed stream. - * - * @author Sindre Mehus (based on code found on http://www.koders.com/ - */ -public class RangeOutputStream extends FilterOutputStream { - - /** - * The starting index. - */ - private long start; - - /** - * The ending index. - */ - private long end; - - /** - * The current position. - */ - protected long pos; - - /** - * Wraps the given output stream in a RangeOutputStream, using the values - * in the given range, unless the range is null in which case - * the original OutputStream is returned. - * - * @param out The output stream to wrap in a RangeOutputStream. - * @param range The range, may be null. - * @return The possibly wrapped output stream. - */ - public static OutputStream wrap(OutputStream out, Range range) { - if (range == null) { - return out; - } - return new RangeOutputStream(out, range.getMinimumLong(), range.getMaximumLong()); - } - - /** - * Creates the stream with the passed start and end. - * - * @param out The stream to write to. - * @param start The starting position. - * @param end The ending position. - */ - public RangeOutputStream(OutputStream out, long start, long end) { - super(out); - this.start = start; - this.end = end; - pos = 0; - } - - /** - * Writes the byte IF it is within the range, otherwise it only - * increments the position. - * - * @param b The byte to write. - * @throws IOException Thrown if there was a problem writing to the stream. - */ - @Override - public void write(int b) throws IOException { - if ((pos >= start) && (pos <= end)) { - super.write(b); - } - pos++; - } - - /** - * Writes the bytes IF it is within the range, otherwise it only - * increments the position. - * - * @param b The bytes to write. - * @param off The offset to start at. - * @param len The length to write. - * @throws IOException Thrown if there was a problem writing to the stream. - */ - @Override - public void write(byte[] b, int off, int len) throws IOException { - boolean allowWrite = false; - long newPos = pos + off, newOff = off, newLen = len; - - // Check to see if we are in the range - if (newPos <= end) { - if (newPos >= start) { - // We are so check to make sure we don't leave it - if (newPos + newLen > end) { - newLen = end - newPos; - } - - // Enable writing - allowWrite = true; - } - - // We aren't yet in the range, but if see if the proposed write - // would place us there - else if (newPos + newLen >= start) { - // It would so, update the offset - newOff += start - newPos; - - // New offset means, a new position, so update that too - newPos = newOff + pos; - newLen = len + (pos - newPos); - - // Make sure we don't go past the range - if (newPos + newLen > end) { - newLen = end - newPos; - } - - // Enable writting - allowWrite = true; - } - } - - // If we have enabled writing, do the write! - if (allowWrite) { - out.write(b, (int) newOff, (int) newLen); - } - - // Move the cursor along - pos += off + len; - } -} - diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/ShoutCastOutputStream.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/io/ShoutCastOutputStream.java deleted file mode 100644 index 9a8618c6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/ShoutCastOutputStream.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.io; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.service.SettingsService; -import org.apache.commons.lang.StringUtils; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; - -/** - * Implements SHOUTcast support by decorating an existing output stream. - *

- * Based on protocol description found on - * http://www.smackfu.com/stuff/programming/shoutcast.html - * - * @author Sindre Mehus - */ -public class ShoutCastOutputStream extends OutputStream { - - private static final Logger LOG = Logger.getLogger(ShoutCastOutputStream.class); - - /** - * Number of bytes between each SHOUTcast metadata block. - */ - public static final int META_DATA_INTERVAL = 20480; - - /** - * The underlying output stream to decorate. - */ - private OutputStream out; - - /** - * What to write in the SHOUTcast metadata is fetched from the playlist. - */ - private PlayQueue playQueue; - - /** - * Keeps track of the number of bytes written (excluding meta-data). Between 0 and {@link #META_DATA_INTERVAL}. - */ - private int byteCount; - - /** - * The last stream title sent. - */ - private String previousStreamTitle; - - private SettingsService settingsService; - - /** - * Creates a new SHOUTcast-decorated stream for the given output stream. - * - * @param out The output stream to decorate. - * @param playQueue Meta-data is fetched from this playlist. - */ - public ShoutCastOutputStream(OutputStream out, PlayQueue playQueue, SettingsService settingsService) { - this.out = out; - this.playQueue = playQueue; - this.settingsService = settingsService; - } - - /** - * Writes the given byte array to the underlying stream, adding SHOUTcast meta-data as necessary. - */ - public void write(byte[] b, int off, int len) throws IOException { - - int bytesWritten = 0; - while (bytesWritten < len) { - - // 'n' is the number of bytes to write before the next potential meta-data block. - int n = Math.min(len - bytesWritten, ShoutCastOutputStream.META_DATA_INTERVAL - byteCount); - - out.write(b, off + bytesWritten, n); - bytesWritten += n; - byteCount += n; - - // Reached meta-data block? - if (byteCount % ShoutCastOutputStream.META_DATA_INTERVAL == 0) { - writeMetaData(); - byteCount = 0; - } - } - } - - /** - * Writes the given byte array to the underlying stream, adding SHOUTcast meta-data as necessary. - */ - public void write(byte[] b) throws IOException { - write(b, 0, b.length); - } - - /** - * Writes the given byte to the underlying stream, adding SHOUTcast meta-data as necessary. - */ - public void write(int b) throws IOException { - byte[] buf = new byte[]{(byte) b}; - write(buf); - } - - /** - * Flushes the underlying stream. - */ - public void flush() throws IOException { - out.flush(); - } - - /** - * Closes the underlying stream. - */ - public void close() throws IOException { - out.close(); - } - - private void writeMetaData() throws IOException { - String streamTitle = StringUtils.trimToEmpty(settingsService.getWelcomeTitle()); - - MediaFile result; - synchronized (playQueue) { - result = playQueue.getCurrentFile(); - } - MediaFile mediaFile = result; - if (mediaFile != null) { - streamTitle = mediaFile.getArtist() + " - " + mediaFile.getTitle(); - } - - byte[] bytes; - - if (streamTitle.equals(previousStreamTitle)) { - bytes = new byte[0]; - } else { - try { - previousStreamTitle = streamTitle; - bytes = createStreamTitle(streamTitle); - } catch (UnsupportedEncodingException x) { - LOG.warn("Failed to create SHOUTcast meta-data. Ignoring.", x); - bytes = new byte[0]; - } - } - - // Length in groups of 16 bytes. - int length = bytes.length / 16; - if (bytes.length % 16 > 0) { - length++; - } - - // Write the length as a single byte. - out.write(length); - - // Write the message. - out.write(bytes); - - // Write padding zero bytes. - int padding = length * 16 - bytes.length; - for (int i = 0; i < padding; i++) { - out.write(0); - } - } - - private byte[] createStreamTitle(String title) throws UnsupportedEncodingException { - // Remove any quotes from the title. - title = title.replaceAll("'", ""); - - // Convert non-ascii characters to similar ascii characters. - for (char[] chars : ShoutCastOutputStream.CHAR_MAP) { - title = title.replace(chars[0], chars[1]); - } - - title = "StreamTitle='" + title + "';"; - return title.getBytes("US-ASCII"); - } - - /** - * Maps from miscellaneous accented characters to similar-looking ASCII characters. - */ - private static final char[][] CHAR_MAP = { - {'\u00C0', 'A'}, {'\u00C1', 'A'}, {'\u00C2', 'A'}, {'\u00C3', 'A'}, {'\u00C4', 'A'}, {'\u00C5', 'A'}, {'\u00C6', 'A'}, - {'\u00C8', 'E'}, {'\u00C9', 'E'}, {'\u00CA', 'E'}, {'\u00CB', 'E'}, {'\u00CC', 'I'}, {'\u00CD', 'I'}, {'\u00CE', 'I'}, - {'\u00CF', 'I'}, {'\u00D2', 'O'}, {'\u00D3', 'O'}, {'\u00D4', 'O'}, {'\u00D5', 'O'}, {'\u00D6', 'O'}, {'\u00D9', 'U'}, - {'\u00DA', 'U'}, {'\u00DB', 'U'}, {'\u00DC', 'U'}, {'\u00DF', 'B'}, {'\u00E0', 'a'}, {'\u00E1', 'a'}, {'\u00E2', 'a'}, - {'\u00E3', 'a'}, {'\u00E4', 'a'}, {'\u00E5', 'a'}, {'\u00E6', 'a'}, {'\u00E7', 'c'}, {'\u00E8', 'e'}, {'\u00E9', 'e'}, - {'\u00EA', 'e'}, {'\u00EB', 'e'}, {'\u00EC', 'i'}, {'\u00ED', 'i'}, {'\u00EE', 'i'}, {'\u00EF', 'i'}, {'\u00F1', 'n'}, - {'\u00F2', 'o'}, {'\u00F3', 'o'}, {'\u00F4', 'o'}, {'\u00F5', 'o'}, {'\u00F6', 'o'}, {'\u00F8', 'o'}, {'\u00F9', 'u'}, - {'\u00FA', 'u'}, {'\u00FB', 'u'}, {'\u00FC', 'u'}, {'\u2013', '-'} - }; -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/TranscodeInputStream.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/io/TranscodeInputStream.java deleted file mode 100644 index b7a5e31e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/io/TranscodeInputStream.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.io; - -import net.sourceforge.subsonic.*; - -import org.apache.commons.io.*; - -import java.io.*; - -/** - * Subclass of {@link InputStream} which provides on-the-fly transcoding. - * Instances of TranscodeInputStream can be chained together, for instance to convert - * from OGG to WAV to MP3. - * - * @author Sindre Mehus - */ -public class TranscodeInputStream extends InputStream { - - private static final Logger LOG = Logger.getLogger(TranscodeInputStream.class); - - private InputStream processInputStream; - private OutputStream processOutputStream; - private Process process; - private final File tmpFile; - - /** - * Creates a transcoded input stream by executing an external process. If in is not null, - * data from it is copied to the command. - * - * @param processBuilder Used to create the external process. - * @param in Data to feed to the process. May be {@code null}. - * @param tmpFile Temporary file to delete when this stream is closed. May be {@code null}. - * @throws IOException If an I/O error occurs. - */ - public TranscodeInputStream(ProcessBuilder processBuilder, final InputStream in, File tmpFile) throws IOException { - this.tmpFile = tmpFile; - - StringBuffer buf = new StringBuffer("Starting transcoder: "); - for (String s : processBuilder.command()) { - buf.append('[').append(s).append("] "); - } - LOG.debug(buf); - - process = processBuilder.start(); - processOutputStream = process.getOutputStream(); - processInputStream = process.getInputStream(); - - // Must read stderr from the process, otherwise it may block. - final String name = processBuilder.command().get(0); - new InputStreamReaderThread(process.getErrorStream(), name, true).start(); - - // Copy data in a separate thread - if (in != null) { - new Thread(name + " TranscodedInputStream copy thread") { - public void run() { - try { - IOUtils.copy(in, processOutputStream); - } catch (IOException x) { - // Intentionally ignored. Will happen if the remote player closes the stream. - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(processOutputStream); - } - } - }.start(); - } - } - - /** - * @see InputStream#read() - */ - public int read() throws IOException { - return processInputStream.read(); - } - - /** - * @see InputStream#read(byte[]) - */ - public int read(byte[] b) throws IOException { - return processInputStream.read(b); - } - - /** - * @see InputStream#read(byte[], int, int) - */ - public int read(byte[] b, int off, int len) throws IOException { - return processInputStream.read(b, off, len); - } - - /** - * @see InputStream#close() - */ - public void close() throws IOException { - IOUtils.closeQuietly(processInputStream); - IOUtils.closeQuietly(processOutputStream); - - if (process != null) { - process.destroy(); - } - - if (tmpFile != null) { - if (!tmpFile.delete()) { - LOG.warn("Failed to delete tmp file: " + tmpFile); - } - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ldap/SubsonicLdapBindAuthenticator.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ldap/SubsonicLdapBindAuthenticator.java deleted file mode 100644 index fee4ff2c..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ldap/SubsonicLdapBindAuthenticator.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ldap; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import org.acegisecurity.BadCredentialsException; -import org.acegisecurity.ldap.DefaultInitialDirContextFactory; -import org.acegisecurity.ldap.search.FilterBasedLdapUserSearch; -import org.acegisecurity.providers.ldap.LdapAuthenticator; -import org.acegisecurity.providers.ldap.authenticator.BindAuthenticator; -import org.acegisecurity.userdetails.ldap.LdapUserDetails; -import org.apache.commons.lang.StringUtils; - -import java.util.HashMap; -import java.util.Map; - -/** - * LDAP authenticator which uses a delegate {@link BindAuthenticator}, and which - * supports dynamically changing LDAP provider URL and search filter. - * - * @author Sindre Mehus - */ -public class SubsonicLdapBindAuthenticator implements LdapAuthenticator { - - private static final Logger LOG = Logger.getLogger(SubsonicLdapBindAuthenticator.class); - - private SecurityService securityService; - private SettingsService settingsService; - - private long authenticatorTimestamp; - private BindAuthenticator delegateAuthenticator; - - public LdapUserDetails authenticate(String username, String password) { - - // LDAP authentication must be enabled on the system. - if (!settingsService.isLdapEnabled()) { - throw new BadCredentialsException("LDAP authentication disabled."); - } - - // User must be defined in Subsonic, unless auto-shadowing is enabled. - User user = securityService.getUserByName(username); - if (user == null && !settingsService.isLdapAutoShadowing()) { - throw new BadCredentialsException("User does not exist."); - } - - // LDAP authentication must be enabled for the given user. - if (user != null && !user.isLdapAuthenticated()) { - throw new BadCredentialsException("LDAP authentication disabled for user."); - } - - try { - createDelegate(); - LdapUserDetails details = delegateAuthenticator.authenticate(username, password); - if (details != null) { - LOG.info("User '" + username + "' successfully authenticated in LDAP. DN: " + details.getDn()); - - if (user == null) { - User newUser = new User(username, "", null, true, 0L, 0L, 0L); - newUser.setStreamRole(true); - newUser.setSettingsRole(true); - securityService.createUser(newUser); - LOG.info("Created local user '" + username + "' for DN " + details.getDn()); - } - } - - return details; - } catch (RuntimeException x) { - LOG.info("Failed to authenticate user '" + username + "' in LDAP.", x); - throw x; - } - } - - /** - * Creates the delegate {@link BindAuthenticator}. - */ - private synchronized void createDelegate() { - - // Only create it if necessary. - if (delegateAuthenticator == null || authenticatorTimestamp < settingsService.getSettingsChanged()) { - - DefaultInitialDirContextFactory contextFactory = new DefaultInitialDirContextFactory(settingsService.getLdapUrl()); - - String managerDn = settingsService.getLdapManagerDn(); - String managerPassword = settingsService.getLdapManagerPassword(); - if (StringUtils.isNotEmpty(managerDn) && StringUtils.isNotEmpty(managerPassword)) { - contextFactory.setManagerDn(managerDn); - contextFactory.setManagerPassword(managerPassword); - } - - Map extraEnvVars = new HashMap(); - extraEnvVars.put("java.naming.referral", "follow"); - contextFactory.setExtraEnvVars(extraEnvVars); - - FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch("", settingsService.getLdapSearchFilter(), contextFactory); - userSearch.setSearchSubtree(true); - userSearch.setDerefLinkFlag(true); - - delegateAuthenticator = new BindAuthenticator(contextFactory); - delegateAuthenticator.setUserSearch(userSearch); - - authenticatorTimestamp = settingsService.getSettingsChanged(); - } - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/ldap/UserDetailsServiceBasedAuthoritiesPopulator.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/ldap/UserDetailsServiceBasedAuthoritiesPopulator.java deleted file mode 100644 index a3b9359e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/ldap/UserDetailsServiceBasedAuthoritiesPopulator.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.ldap; - -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.ldap.LdapDataAccessException; -import org.acegisecurity.providers.ldap.LdapAuthoritiesPopulator; -import org.acegisecurity.userdetails.UserDetailsService; -import org.acegisecurity.userdetails.UserDetails; -import org.acegisecurity.userdetails.ldap.LdapUserDetails; - -/** - * An {@link LdapAuthoritiesPopulator} that retrieves the roles from the - * database using the {@link UserDetailsService} instead of retrieving the roles - * from LDAP. An instance of this class can be configured for the - * {@link org.acegisecurity.providers.ldap.LdapAuthenticationProvider} when - * authentication should be done using LDAP and authorization using the - * information stored in the database. - * - * @author Thomas M. Hofmann - */ -public class UserDetailsServiceBasedAuthoritiesPopulator implements LdapAuthoritiesPopulator { - - private UserDetailsService userDetailsService; - - public GrantedAuthority[] getGrantedAuthorities(LdapUserDetails userDetails) throws LdapDataAccessException { - UserDetails details = userDetailsService.loadUserByUsername(userDetails.getUsername()); - return details.getAuthorities(); - } - - public void setUserDetailsService(UserDetailsService userDetailsService) { - this.userDetailsService = userDetailsService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/security/RESTRequestParameterProcessingFilter.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/security/RESTRequestParameterProcessingFilter.java deleted file mode 100644 index add44643..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/security/RESTRequestParameterProcessingFilter.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.security; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.domain.Version; -import net.sourceforge.subsonic.controller.RESTController; -import net.sourceforge.subsonic.util.StringUtil; -import net.sourceforge.subsonic.util.XMLBuilder; -import org.acegisecurity.Authentication; -import org.acegisecurity.AuthenticationException; -import org.acegisecurity.context.SecurityContextHolder; -import org.acegisecurity.providers.ProviderManager; -import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.bind.ServletRequestUtils; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -/** - * Performs authentication based on credentials being present in the HTTP request parameters. Also checks - * API versions and license information. - *

- * The username should be set in parameter "u", and the password should be set in parameter "p". - * The REST protocol version should be set in parameter "v". - * - * The password can either be in plain text or be UTF-8 hexencoded preceded by "enc:". - * - * @author Sindre Mehus - */ -public class RESTRequestParameterProcessingFilter implements Filter { - - private static final Logger LOG = Logger.getLogger(RESTRequestParameterProcessingFilter.class); - private static final long TRIAL_DAYS = 35L; - - private ProviderManager authenticationManager; - private SettingsService settingsService; - - /** - * {@inheritDoc} - */ - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - if (!(request instanceof HttpServletRequest)) { - throw new ServletException("Can only process HttpServletRequest"); - } - if (!(response instanceof HttpServletResponse)) { - throw new ServletException("Can only process HttpServletResponse"); - } - - HttpServletRequest httpRequest = (HttpServletRequest) request; - HttpServletResponse httpResponse = (HttpServletResponse) response; - - String username = StringUtils.trimToNull(httpRequest.getParameter("u")); - String password = decrypt(StringUtils.trimToNull(httpRequest.getParameter("p"))); - String version = StringUtils.trimToNull(httpRequest.getParameter("v")); - String client = StringUtils.trimToNull(httpRequest.getParameter("c")); - - RESTController.ErrorCode errorCode = null; - - // The username and password parameters are not required if the user - // was previously authenticated, for example using Basic Auth. - Authentication previousAuth = SecurityContextHolder.getContext().getAuthentication(); - boolean missingCredentials = previousAuth == null && (username == null || password == null); - if (missingCredentials || version == null || client == null) { - errorCode = RESTController.ErrorCode.MISSING_PARAMETER; - } - - if (errorCode == null) { - errorCode = checkAPIVersion(version); - } - - if (errorCode == null) { - errorCode = authenticate(username, password, previousAuth); - } - - if (errorCode == null) { - String restMethod = StringUtils.substringAfterLast(httpRequest.getRequestURI(), "/"); - errorCode = checkLicense(client, restMethod); - } - - if (errorCode == null) { - chain.doFilter(request, response); - } else { - SecurityContextHolder.getContext().setAuthentication(null); - sendErrorXml(httpRequest, httpResponse, errorCode); - } - } - - private RESTController.ErrorCode checkAPIVersion(String version) { - Version serverVersion = new Version(StringUtil.getRESTProtocolVersion()); - Version clientVersion = new Version(version); - - if (serverVersion.getMajor() > clientVersion.getMajor()) { - return RESTController.ErrorCode.PROTOCOL_MISMATCH_CLIENT_TOO_OLD; - } else if (serverVersion.getMajor() < clientVersion.getMajor()) { - return RESTController.ErrorCode.PROTOCOL_MISMATCH_SERVER_TOO_OLD; - } else if (serverVersion.getMinor() < clientVersion.getMinor()) { - return RESTController.ErrorCode.PROTOCOL_MISMATCH_SERVER_TOO_OLD; - } - return null; - } - - private RESTController.ErrorCode authenticate(String username, String password, Authentication previousAuth) { - - // Previously authenticated and username not overridden? - if (username == null && previousAuth != null) { - return null; - } - - // Ensure password is given. - if (password == null) { - return RESTController.ErrorCode.MISSING_PARAMETER; - } - - try { - UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); - Authentication authResult = authenticationManager.authenticate(authRequest); - SecurityContextHolder.getContext().setAuthentication(authResult); -// LOG.info("Authentication succeeded for user " + username); - } catch (AuthenticationException x) { - LOG.info("Authentication failed for user " + username); - return RESTController.ErrorCode.NOT_AUTHENTICATED; - } - return null; - } - - private RESTController.ErrorCode checkLicense(String client, String restMethod) { - if (settingsService.isLicenseValid()) { - return null; - } - - if (settingsService.getRESTTrialExpires(client) == null) { - Date expiryDate = new Date(System.currentTimeMillis() + TRIAL_DAYS * 24L * 3600L * 1000L); - settingsService.setRESTTrialExpires(client, expiryDate); - settingsService.save(); - LOG.info("REST access for client '" + client + "' will expire " + expiryDate); - } else if (settingsService.getRESTTrialExpires(client).before(new Date())) { - - // Exception: iPhone clients are allowed to call any method except stream.view and download.view. - List iPhoneClients = Arrays.asList("iSub", "zsubsonic"); - List restrictedMethods = Arrays.asList("stream.view", "download.view"); - if (iPhoneClients.contains(client) && !restrictedMethods.contains(restMethod)) { - return null; - } - - LOG.info("REST access for client '" + client + "' has expired."); - return RESTController.ErrorCode.NOT_LICENSED; - } - - return null; - } - - public static String decrypt(String s) { - if (s == null) { - return null; - } - if (!s.startsWith("enc:")) { - return s; - } - try { - return StringUtil.utf8HexDecode(s.substring(4)); - } catch (Exception e) { - return s; - } - } - - private void sendErrorXml(HttpServletRequest request, HttpServletResponse response, RESTController.ErrorCode errorCode) throws IOException { - String format = ServletRequestUtils.getStringParameter(request, "f", "xml"); - boolean json = "json".equals(format); - boolean jsonp = "jsonp".equals(format); - XMLBuilder builder; - - response.setCharacterEncoding(StringUtil.ENCODING_UTF8); - - if (json) { - builder = XMLBuilder.createJSONBuilder(); - response.setContentType("application/json"); - } else if (jsonp) { - builder = XMLBuilder.createJSONPBuilder(request.getParameter("callback")); - response.setContentType("text/javascript"); - } else { - builder = XMLBuilder.createXMLBuilder(); - response.setContentType("text/xml"); - } - - builder.preamble(StringUtil.ENCODING_UTF8); - builder.add("subsonic-response", false, - new XMLBuilder.Attribute("xmlns", "http://subsonic.org/restapi"), - new XMLBuilder.Attribute("status", "failed"), - new XMLBuilder.Attribute("version", StringUtil.getRESTProtocolVersion())); - - builder.add("error", true, - new XMLBuilder.Attribute("code", errorCode.getCode()), - new XMLBuilder.Attribute("message", errorCode.getMessage())); - builder.end(); - response.getWriter().print(builder); - } - - /** - * {@inheritDoc} - */ - public void init(FilterConfig filterConfig) throws ServletException { - } - - /** - * {@inheritDoc} - */ - public void destroy() { - } - - public void setAuthenticationManager(ProviderManager authenticationManager) { - this.authenticationManager = authenticationManager; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/AdService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/AdService.java deleted file mode 100644 index 9ae4d765..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/AdService.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -/** - * Provides services for generating ads. - * - * @author Sindre Mehus - */ -public class AdService { - - private final String[] ads = { - - "", - "", - "", - "", - "", - "", - "", - " ", - "", - "", - "", - " ", - "", - " ", - "", - "", - "" - }; - private int adInterval; - private int pageCount; - private int adIndex; - - /** - * Returns an ad or null if no ad should be displayed. - */ - public String getAd() { - if (pageCount++ % adInterval == 0) { - - adIndex = (adIndex + 1) % ads.length; - return ads[adIndex]; - } - - return null; - } - - /** - * Set by Spring. - */ - public void setAdInterval(int adInterval) { - this.adInterval = adInterval; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/AudioScrobblerService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/AudioScrobblerService.java deleted file mode 100644 index 9ca402b8..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/AudioScrobblerService.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; - -import net.sourceforge.subsonic.domain.MediaFile; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.params.HttpConnectionParams; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.util.StringUtil; - -/** - * Provides services for "audioscrobbling", which is the process of - * registering what songs are played at www.last.fm. - *

- * See http://www.last.fm/api/submissions - * - * @author Sindre Mehus - */ -public class AudioScrobblerService { - - private static final Logger LOG = Logger.getLogger(AudioScrobblerService.class); - private static final int MAX_PENDING_REGISTRATION = 2000; - private static final long MIN_REGISTRATION_INTERVAL = 30000L; - - private RegistrationThread thread; - private final Map lastRegistrationTimes = new HashMap(); - private final LinkedBlockingQueue queue = new LinkedBlockingQueue(); - - private SettingsService settingsService; - - /** - * Registers the given media file at www.last.fm. This method returns immediately, the actual registration is done - * by a separate thread. - * - * @param mediaFile The media file to register. - * @param username The user which played the music file. - * @param submission Whether this is a submission or a now playing notification. - */ - public synchronized void register(MediaFile mediaFile, String username, boolean submission) { - - if (thread == null) { - thread = new RegistrationThread(); - thread.start(); - } - - if (queue.size() >= MAX_PENDING_REGISTRATION) { - LOG.warn("Last.fm scrobbler queue is full. Ignoring " + mediaFile); - return; - } - - RegistrationData registrationData = createRegistrationData(mediaFile, username, submission); - if (registrationData == null) { - return; - } - - try { - queue.put(registrationData); - } catch (InterruptedException x) { - LOG.warn("Interrupted while queuing Last.fm scrobble.", x); - } - } - - /** - * Returns registration details, or null if not eligible for registration. - */ - private RegistrationData createRegistrationData(MediaFile mediaFile, String username, boolean submission) { - - if (mediaFile == null || mediaFile.isVideo()) { - return null; - } - - UserSettings userSettings = settingsService.getUserSettings(username); - if (!userSettings.isLastFmEnabled() || userSettings.getLastFmUsername() == null || userSettings.getLastFmPassword() == null) { - return null; - } - - long now = System.currentTimeMillis(); - - // Don't register submissions more often than every 30 seconds. - if (submission) { - Long lastRegistrationTime = lastRegistrationTimes.get(username); - if (lastRegistrationTime != null && now - lastRegistrationTime < MIN_REGISTRATION_INTERVAL) { - return null; - } - lastRegistrationTimes.put(username, now); - } - - RegistrationData reg = new RegistrationData(); - reg.username = userSettings.getLastFmUsername(); - reg.password = userSettings.getLastFmPassword(); - reg.artist = mediaFile.getArtist(); - reg.album = mediaFile.getAlbumName(); - reg.title = mediaFile.getTitle(); - reg.duration = mediaFile.getDurationSeconds() == null ? 0 : mediaFile.getDurationSeconds(); - reg.time = new Date(now); - reg.submission = submission; - - return reg; - } - - /** - * Scrobbles the given song data at last.fm, using the protocol defined at http://www.last.fm/api/submissions. - * - * @param registrationData Registration data for the song. - */ - private void scrobble(RegistrationData registrationData) throws Exception { - if (registrationData == null) { - return; - } - - String[] lines = authenticate(registrationData); - if (lines == null) { - return; - } - - String sessionId = lines[1]; - String nowPlayingUrl = lines[2]; - String submissionUrl = lines[3]; - - if (registrationData.submission) { - lines = registerSubmission(registrationData, sessionId, submissionUrl); - } else { - lines = registerNowPlaying(registrationData, sessionId, nowPlayingUrl); - } - - if (lines[0].startsWith("FAILED")) { - LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm: " + lines[0]); - } else if (lines[0].startsWith("BADSESSION")) { - LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Invalid session."); - } else if (lines[0].startsWith("OK")) { - LOG.debug("Successfully registered " + (registrationData.submission ? "submission" : "now playing") + - " for song '" + registrationData.title + "' for user " + registrationData.username + " at Last.fm."); - } - } - - /** - * Returns the following lines if authentication succeeds: - *

- * Line 0: Always "OK" - * Line 1: Session ID, e.g., "17E61E13454CDD8B68E8D7DEEEDF6170" - * Line 2: URL to use for now playing, e.g., "http://post.audioscrobbler.com:80/np_1.2" - * Line 3: URL to use for submissions, e.g., "http://post2.audioscrobbler.com:80/protocol_1.2" - *

- * If authentication fails, null is returned. - */ - private String[] authenticate(RegistrationData registrationData) throws Exception { - String clientId = "sub"; - String clientVersion = "0.1"; - long timestamp = System.currentTimeMillis() / 1000L; - String authToken = calculateAuthenticationToken(registrationData.password, timestamp); - String[] lines = executeGetRequest("http://post.audioscrobbler.com/?hs=true&p=1.2.1&c=" + clientId + "&v=" + - clientVersion + "&u=" + registrationData.username + "&t=" + timestamp + "&a=" + authToken); - - if (lines[0].startsWith("BANNED")) { - LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Client version is banned."); - return null; - } - - if (lines[0].startsWith("BADAUTH")) { - LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Wrong username or password."); - return null; - } - - if (lines[0].startsWith("BADTIME")) { - LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Bad timestamp, please check local clock."); - return null; - } - - if (lines[0].startsWith("FAILED")) { - LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm: " + lines[0]); - return null; - } - - if (!lines[0].startsWith("OK")) { - LOG.warn("Failed to scrobble song '" + registrationData.title + "' at Last.fm. Unknown response: " + lines[0]); - return null; - } - - return lines; - } - - private String[] registerSubmission(RegistrationData registrationData, String sessionId, String url) throws IOException { - Map params = new HashMap(); - params.put("s", sessionId); - params.put("a[0]", registrationData.artist); - params.put("t[0]", registrationData.title); - params.put("i[0]", String.valueOf(registrationData.time.getTime() / 1000L)); - params.put("o[0]", "P"); - params.put("r[0]", ""); - params.put("l[0]", String.valueOf(registrationData.duration)); - params.put("b[0]", registrationData.album); - params.put("n[0]", ""); - params.put("m[0]", ""); - return executePostRequest(url, params); - } - - private String[] registerNowPlaying(RegistrationData registrationData, String sessionId, String url) throws IOException { - Map params = new HashMap(); - params.put("s", sessionId); - params.put("a", registrationData.artist); - params.put("t", registrationData.title); - params.put("b", registrationData.album); - params.put("l", String.valueOf(registrationData.duration)); - params.put("n", ""); - params.put("m", ""); - return executePostRequest(url, params); - } - - private String calculateAuthenticationToken(String password, long timestamp) { - return DigestUtils.md5Hex(DigestUtils.md5Hex(password) + timestamp); - } - - private String[] executeGetRequest(String url) throws IOException { - return executeRequest(new HttpGet(url)); - } - - private String[] executePostRequest(String url, Map parameters) throws IOException { - List params = new ArrayList(); - for (Map.Entry entry : parameters.entrySet()) { - params.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); - } - - HttpPost request = new HttpPost(url); - request.setEntity(new UrlEncodedFormEntity(params, StringUtil.ENCODING_UTF8)); - - return executeRequest(request); - } - - private String[] executeRequest(HttpUriRequest request) throws IOException { - HttpClient client = new DefaultHttpClient(); - HttpConnectionParams.setConnectionTimeout(client.getParams(), 15000); - HttpConnectionParams.setSoTimeout(client.getParams(), 15000); - - try { - ResponseHandler responseHandler = new BasicResponseHandler(); - String response = client.execute(request, responseHandler); - return response.split("\\n"); - - } finally { - client.getConnectionManager().shutdown(); - } - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - private class RegistrationThread extends Thread { - private RegistrationThread() { - super("AudioScrobbler Registration"); - } - - @Override - public void run() { - while (true) { - RegistrationData registrationData = null; - try { - registrationData = queue.take(); - scrobble(registrationData); - } catch (IOException x) { - handleNetworkError(registrationData, x); - } catch (Exception x) { - LOG.warn("Error in Last.fm registration.", x); - } - } - } - - private void handleNetworkError(RegistrationData registrationData, IOException x) { - try { - queue.put(registrationData); - LOG.info("Last.fm registration for " + registrationData.title + - " encountered network error. Will try again later. In queue: " + queue.size(), x); - } catch (InterruptedException e) { - LOG.error("Failed to reschedule Last.fm registration for " + registrationData.title, e); - } - try { - sleep(15L * 60L * 1000L); // Wait 15 minutes. - } catch (InterruptedException e) { - LOG.error("Failed to sleep after Last.fm registration failure for " + registrationData.title, e); - } - } - } - - private static class RegistrationData { - private String username; - private String password; - private String artist; - private String album; - private String title; - private int duration; - private Date time; - public boolean submission; - } - -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/JukeboxService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/JukeboxService.java deleted file mode 100644 index 9f2eff22..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/JukeboxService.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.PlayQueue; -import net.sourceforge.subsonic.domain.Transcoding; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.domain.VideoTranscodingSettings; -import net.sourceforge.subsonic.service.jukebox.AudioPlayer; -import net.sourceforge.subsonic.util.FileUtil; -import org.apache.commons.io.IOUtils; - -import java.io.InputStream; - -import static net.sourceforge.subsonic.service.jukebox.AudioPlayer.State.EOM; - -/** - * Plays music on the local audio device. - * - * @author Sindre Mehus - */ -public class JukeboxService implements AudioPlayer.Listener { - - private static final Logger LOG = Logger.getLogger(JukeboxService.class); - - private AudioPlayer audioPlayer; - private TranscodingService transcodingService; - private AudioScrobblerService audioScrobblerService; - private StatusService statusService; - private SettingsService settingsService; - private SecurityService securityService; - - private Player player; - private TransferStatus status; - private MediaFile currentPlayingFile; - private float gain = 0.5f; - private int offset; - private MediaFileService mediaFileService; - - /** - * Updates the jukebox by starting or pausing playback on the local audio device. - * - * @param player The player in question. - * @param offset Start playing after this many seconds into the track. - */ - public synchronized void updateJukebox(Player player, int offset) throws Exception { - User user = securityService.getUserByName(player.getUsername()); - if (!user.isJukeboxRole()) { - LOG.warn(user.getUsername() + " is not authorized for jukebox playback."); - return; - } - - if (player.getPlayQueue().getStatus() == PlayQueue.Status.PLAYING) { - this.player = player; - MediaFile result; - synchronized (player.getPlayQueue()) { - result = player.getPlayQueue().getCurrentFile(); - } - play(result, offset); - } else { - if (audioPlayer != null) { - audioPlayer.pause(); - } - } - } - - private synchronized void play(MediaFile file, int offset) { - InputStream in = null; - try { - - // Resume if possible. - boolean sameFile = file != null && file.equals(currentPlayingFile); - boolean paused = audioPlayer != null && audioPlayer.getState() == AudioPlayer.State.PAUSED; - if (sameFile && paused && offset == 0) { - audioPlayer.play(); - } else { - this.offset = offset; - if (audioPlayer != null) { - audioPlayer.close(); - if (currentPlayingFile != null) { - onSongEnd(currentPlayingFile); - } - } - - if (file != null) { - TranscodingService.Parameters parameters = new TranscodingService.Parameters(file, new VideoTranscodingSettings(0, 0, offset)); - String command = settingsService.getJukeboxCommand(); - parameters.setTranscoding(new Transcoding(null, null, null, null, command, null, null, false)); - in = transcodingService.getTranscodedInputStream(parameters); - audioPlayer = new AudioPlayer(in, this); - audioPlayer.setGain(gain); - audioPlayer.play(); - onSongStart(file); - } - } - - currentPlayingFile = file; - - } catch (Exception x) { - LOG.error("Error in jukebox: " + x, x); - IOUtils.closeQuietly(in); - } - } - - public synchronized void stateChanged(AudioPlayer audioPlayer, AudioPlayer.State state) { - if (state == EOM) { - player.getPlayQueue().next(); - MediaFile result; - synchronized (player.getPlayQueue()) { - result = player.getPlayQueue().getCurrentFile(); - } - play(result, 0); - } - } - - public synchronized float getGain() { - return gain; - } - - public synchronized int getPosition() { - return audioPlayer == null ? 0 : offset + audioPlayer.getPosition(); - } - - /** - * Returns the player which currently uses the jukebox. - * - * @return The player, may be {@code null}. - */ - public Player getPlayer() { - return player; - } - - private void onSongStart(MediaFile file) { - LOG.info(player.getUsername() + " starting jukebox for \"" + FileUtil.getShortPath(file.getFile()) + "\""); - status = statusService.createStreamStatus(player); - status.setFile(file.getFile()); - status.addBytesTransfered(file.getFileSize()); - mediaFileService.incrementPlayCount(file); - scrobble(file, false); - } - - private void onSongEnd(MediaFile file) { - LOG.info(player.getUsername() + " stopping jukebox for \"" + FileUtil.getShortPath(file.getFile()) + "\""); - if (status != null) { - statusService.removeStreamStatus(status); - } - scrobble(file, true); - } - - private void scrobble(MediaFile file, boolean submission) { - if (player.getClientId() == null) { // Don't scrobble REST players. - audioScrobblerService.register(file, player.getUsername(), submission); - } - } - - public synchronized void setGain(float gain) { - this.gain = gain; - if (audioPlayer != null) { - audioPlayer.setGain(gain); - } - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } - - public void setAudioScrobblerService(AudioScrobblerService audioScrobblerService) { - this.audioScrobblerService = audioScrobblerService; - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MediaFileService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MediaFileService.java deleted file mode 100644 index bc575714..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MediaFileService.java +++ /dev/null @@ -1,614 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sf.ehcache.Ehcache; -import net.sf.ehcache.Element; -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.AlbumDao; -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.domain.Album; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MediaFileComparator; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.service.metadata.JaudiotaggerParser; -import net.sourceforge.subsonic.service.metadata.MetaData; -import net.sourceforge.subsonic.service.metadata.MetaDataParser; -import net.sourceforge.subsonic.service.metadata.MetaDataParserFactory; -import net.sourceforge.subsonic.util.FileUtil; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.StringUtils; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import static net.sourceforge.subsonic.domain.MediaFile.MediaType.*; - -/** - * Provides services for instantiating and caching media files and cover art. - * - * @author Sindre Mehus - */ -public class MediaFileService { - - private static final Logger LOG = Logger.getLogger(MediaFileService.class); - - private Ehcache mediaFileMemoryCache; - - private SecurityService securityService; - private SettingsService settingsService; - private MediaFileDao mediaFileDao; - private AlbumDao albumDao; - private MetaDataParserFactory metaDataParserFactory; - - /** - * Returns a media file instance for the given file. If possible, a cached value is returned. - * - * @param file A file on the local file system. - * @return A media file instance, or null if not found. - * @throws SecurityException If access is denied to the given file. - */ - public MediaFile getMediaFile(File file) { - return getMediaFile(file, settingsService.isFastCacheEnabled()); - } - - /** - * Returns a media file instance for the given file. If possible, a cached value is returned. - * - * @param file A file on the local file system. - * @return A media file instance, or null if not found. - * @throws SecurityException If access is denied to the given file. - */ - public MediaFile getMediaFile(File file, boolean useFastCache) { - - // Look in fast memory cache first. - Element element = mediaFileMemoryCache.get(file); - MediaFile result = element == null ? null : (MediaFile) element.getObjectValue(); - if (result != null) { - return result; - } - - if (!securityService.isReadAllowed(file)) { - throw new SecurityException("Access denied to file " + file); - } - - // Secondly, look in database. - result = mediaFileDao.getMediaFile(file.getPath()); - if (result != null) { - result = checkLastModified(result, useFastCache); - mediaFileMemoryCache.put(new Element(file, result)); - return result; - } - - if (!FileUtil.exists(file)) { - return null; - } - // Not found in database, must read from disk. - result = createMediaFile(file); - - // Put in cache and database. - mediaFileMemoryCache.put(new Element(file, result)); - mediaFileDao.createOrUpdateMediaFile(result); - - return result; - } - - private MediaFile checkLastModified(MediaFile mediaFile, boolean useFastCache) { - if (useFastCache || mediaFile.getChanged().getTime() >= FileUtil.lastModified(mediaFile.getFile())) { - return mediaFile; - } - mediaFile = createMediaFile(mediaFile.getFile()); - mediaFileDao.createOrUpdateMediaFile(mediaFile); - return mediaFile; - } - - /** - * Returns a media file instance for the given path name. If possible, a cached value is returned. - * - * @param pathName A path name for a file on the local file system. - * @return A media file instance. - * @throws SecurityException If access is denied to the given file. - */ - public MediaFile getMediaFile(String pathName) { - return getMediaFile(new File(pathName)); - } - - // TODO: Optimize with memory caching. - public MediaFile getMediaFile(int id) { - MediaFile mediaFile = mediaFileDao.getMediaFile(id); - if (mediaFile == null) { - return null; - } - - if (!securityService.isReadAllowed(mediaFile.getFile())) { - throw new SecurityException("Access denied to file " + mediaFile); - } - - return checkLastModified(mediaFile, settingsService.isFastCacheEnabled()); - } - - public MediaFile getParentOf(MediaFile mediaFile) { - if (mediaFile.getParentPath() == null) { - return null; - } - return getMediaFile(mediaFile.getParentPath()); - } - - public List getChildrenOf(String parentPath, boolean includeFiles, boolean includeDirectories, boolean sort) { - return getChildrenOf(new File(parentPath), includeFiles, includeDirectories, sort); - } - - public List getChildrenOf(File parent, boolean includeFiles, boolean includeDirectories, boolean sort) { - return getChildrenOf(getMediaFile(parent), includeFiles, includeDirectories, sort); - } - - /** - * Returns all media files that are children of a given media file. - * - * @param includeFiles Whether files should be included in the result. - * @param includeDirectories Whether directories should be included in the result. - * @param sort Whether to sort files in the same directory. - * @return All children media files. - */ - public List getChildrenOf(MediaFile parent, boolean includeFiles, boolean includeDirectories, boolean sort) { - return getChildrenOf(parent, includeFiles, includeDirectories, sort, settingsService.isFastCacheEnabled()); - } - - /** - * Returns all media files that are children of a given media file. - * - * @param includeFiles Whether files should be included in the result. - * @param includeDirectories Whether directories should be included in the result. - * @param sort Whether to sort files in the same directory. - * @return All children media files. - */ - public List getChildrenOf(MediaFile parent, boolean includeFiles, boolean includeDirectories, boolean sort, boolean useFastCache) { - - if (!parent.isDirectory()) { - return Collections.emptyList(); - } - - // Make sure children are stored and up-to-date in the database. - if (!useFastCache) { - updateChildren(parent); - } - - List result = new ArrayList(); - for (MediaFile child : mediaFileDao.getChildrenOf(parent.getPath())) { - child = checkLastModified(child, useFastCache); - if (child.isDirectory() && includeDirectories) { - result.add(child); - } - if (child.isFile() && includeFiles) { - result.add(child); - } - } - - if (sort) { - Comparator comparator = new MediaFileComparator(settingsService.isSortAlbumsByYear()); - // Note: Intentionally not using Collections.sort() since it can be problematic on Java 7. - // http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#jdk7 - Set set = new TreeSet(comparator); - set.addAll(result); - result = new ArrayList(set); - } - - return result; - } - - /** - * Returns whether the given file is the root of a media folder. - * - * @see MusicFolder - */ - public boolean isRoot(MediaFile mediaFile) { - for (MusicFolder musicFolder : settingsService.getAllMusicFolders(false, true)) { - if (mediaFile.getPath().equals(musicFolder.getPath().getPath())) { - return true; - } - } - return false; - } - - /** - * Returns all genres in the music collection. - * - * @return Sorted list of genres. - */ - public List getGenres() { - return mediaFileDao.getGenres(); - } - - /** - * Returns the most frequently played albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most frequently played albums. - */ - public List getMostFrequentlyPlayedAlbums(int offset, int count) { - return mediaFileDao.getMostFrequentlyPlayedAlbums(offset, count); - } - - /** - * Returns the most recently played albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most recently played albums. - */ - public List getMostRecentlyPlayedAlbums(int offset, int count) { - return mediaFileDao.getMostRecentlyPlayedAlbums(offset, count); - } - - /** - * Returns the most recently added albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @return The most recently added albums. - */ - public List getNewestAlbums(int offset, int count) { - return mediaFileDao.getNewestAlbums(offset, count); - } - - /** - * Returns the most recently starred albums. - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @param username Returns albums starred by this user. - * @return The most recently starred albums for this user. - */ - public List getStarredAlbums(int offset, int count, String username) { - return mediaFileDao.getStarredAlbums(offset, count, username); - } - - /** - * Returns albums in alphabetial order. - * - * - * @param offset Number of albums to skip. - * @param count Maximum number of albums to return. - * @param byArtist Whether to sort by artist name - * @return Albums in alphabetical order. - */ - public List getAlphabetialAlbums(int offset, int count, boolean byArtist) { - return mediaFileDao.getAlphabetialAlbums(offset, count, byArtist); - } - - public Date getMediaFileStarredDate(int id, String username) { - return mediaFileDao.getMediaFileStarredDate(id, username); - } - - public void populateStarredDate(List mediaFiles, String username) { - for (MediaFile mediaFile : mediaFiles) { - populateStarredDate(mediaFile, username); - } - } - - public void populateStarredDate(MediaFile mediaFile, String username) { - Date starredDate = mediaFileDao.getMediaFileStarredDate(mediaFile.getId(), username); - mediaFile.setStarredDate(starredDate); - } - - private void updateChildren(MediaFile parent) { - - // Check timestamps. - if (parent.getChildrenLastUpdated().getTime() >= parent.getChanged().getTime()) { - return; - } - - List storedChildren = mediaFileDao.getChildrenOf(parent.getPath()); - Map storedChildrenMap = new HashMap(); - for (MediaFile child : storedChildren) { - storedChildrenMap.put(child.getPath(), child); - } - - List children = filterMediaFiles(FileUtil.listFiles(parent.getFile())); - for (File child : children) { - if (storedChildrenMap.remove(child.getPath()) == null) { - // Add children that are not already stored. - mediaFileDao.createOrUpdateMediaFile(createMediaFile(child)); - } - } - - // Delete children that no longer exist on disk. - for (String path : storedChildrenMap.keySet()) { - mediaFileDao.deleteMediaFile(path); - } - - // Update timestamp in parent. - parent.setChildrenLastUpdated(parent.getChanged()); - parent.setPresent(true); - mediaFileDao.createOrUpdateMediaFile(parent); - } - - private List filterMediaFiles(File[] candidates) { - List result = new ArrayList(); - for (File candidate : candidates) { - String suffix = FilenameUtils.getExtension(candidate.getName()).toLowerCase(); - if (!isExcluded(candidate) && (FileUtil.isDirectory(candidate) || isAudioFile(suffix) || isVideoFile(suffix))) { - result.add(candidate); - } - } - return result; - } - - private boolean isAudioFile(String suffix) { - for (String s : settingsService.getMusicFileTypesAsArray()) { - if (suffix.equals(s.toLowerCase())) { - return true; - } - } - return false; - } - - private boolean isVideoFile(String suffix) { - for (String s : settingsService.getVideoFileTypesAsArray()) { - if (suffix.equals(s.toLowerCase())) { - return true; - } - } - return false; - } - - /** - * Returns whether the given file is excluded. - * - * @param file The child file in question. - * @return Whether the child file is excluded. - */ - private boolean isExcluded(File file) { - - // Exclude all hidden files starting with a "." or "@eaDir" (thumbnail dir created on Synology devices). - String name = file.getName(); - return name.startsWith(".") || name.startsWith("@eaDir") || name.equals("Thumbs.db"); - } - - private MediaFile createMediaFile(File file) { - MediaFile mediaFile = new MediaFile(); - Date lastModified = new Date(FileUtil.lastModified(file)); - mediaFile.setPath(file.getPath()); - mediaFile.setFolder(securityService.getRootFolderForFile(file)); - mediaFile.setParentPath(file.getParent()); - mediaFile.setChanged(lastModified); - mediaFile.setLastScanned(new Date()); - mediaFile.setPlayCount(0); - mediaFile.setChildrenLastUpdated(new Date(0)); - mediaFile.setCreated(lastModified); - mediaFile.setMediaType(DIRECTORY); - mediaFile.setPresent(true); - - if (file.isFile()) { - - MetaDataParser parser = metaDataParserFactory.getParser(file); - if (parser != null) { - MetaData metaData = parser.getMetaData(file); - mediaFile.setArtist(metaData.getArtist()); - mediaFile.setAlbumArtist(metaData.getArtist()); - mediaFile.setAlbumName(metaData.getAlbumName()); - mediaFile.setTitle(metaData.getTitle()); - mediaFile.setDiscNumber(metaData.getDiscNumber()); - mediaFile.setTrackNumber(metaData.getTrackNumber()); - mediaFile.setGenre(metaData.getGenre()); - mediaFile.setYear(metaData.getYear()); - mediaFile.setDurationSeconds(metaData.getDurationSeconds()); - mediaFile.setBitRate(metaData.getBitRate()); - mediaFile.setVariableBitRate(metaData.getVariableBitRate()); - mediaFile.setHeight(metaData.getHeight()); - mediaFile.setWidth(metaData.getWidth()); - } - String format = StringUtils.trimToNull(StringUtils.lowerCase(FilenameUtils.getExtension(mediaFile.getPath()))); - mediaFile.setFormat(format); - mediaFile.setFileSize(FileUtil.length(file)); - mediaFile.setMediaType(getMediaType(mediaFile)); - - } else { - - // Is this an album? - if (!isRoot(mediaFile)) { - File[] children = FileUtil.listFiles(file); - File firstChild = null; - for (File child : filterMediaFiles(children)) { - if (FileUtil.isFile(child)) { - firstChild = child; - break; - } - } - - if (firstChild != null) { - mediaFile.setMediaType(ALBUM); - - // Guess artist/album name and year. - MetaDataParser parser = metaDataParserFactory.getParser(firstChild); - if (parser != null) { - MetaData metaData = parser.getMetaData(firstChild); - mediaFile.setArtist(metaData.getArtist()); - mediaFile.setAlbumName(metaData.getAlbumName()); - mediaFile.setYear(metaData.getYear()); - } - - // Look for cover art. - try { - File coverArt = findCoverArt(children); - if (coverArt != null) { - mediaFile.setCoverArtPath(coverArt.getPath()); - } - } catch (IOException x) { - LOG.error("Failed to find cover art.", x); - } - - } else { - mediaFile.setArtist(file.getName()); - } - } - } - - return mediaFile; - } - - private MediaFile.MediaType getMediaType(MediaFile mediaFile) { - if (isVideoFile(mediaFile.getFormat())) { - return VIDEO; - } - String path = mediaFile.getPath().toLowerCase(); - String genre = StringUtils.trimToEmpty(mediaFile.getGenre()).toLowerCase(); - if (path.contains("podcast") || genre.contains("podcast")) { - return PODCAST; - } - if (path.contains("audiobook") || genre.contains("audiobook") || path.contains("audio book") || genre.contains("audio book")) { - return AUDIOBOOK; - } - return MUSIC; - } - - public void refreshMediaFile(MediaFile mediaFile) { - mediaFile = createMediaFile(mediaFile.getFile()); - mediaFileDao.createOrUpdateMediaFile(mediaFile); - mediaFileMemoryCache.remove(mediaFile.getFile()); - } - - /** - * Returns a cover art image for the given media file. - */ - public File getCoverArt(MediaFile mediaFile) { - if (mediaFile.getCoverArtFile() != null) { - return mediaFile.getCoverArtFile(); - } - MediaFile parent = getParentOf(mediaFile); - return parent == null ? null : parent.getCoverArtFile(); - } - - /** - * Finds a cover art image for the given directory, by looking for it on the disk. - */ - private File findCoverArt(File[] candidates) throws IOException { - for (String mask : settingsService.getCoverArtFileTypesAsArray()) { - for (File candidate : candidates) { - if (candidate.isFile() && candidate.getName().toUpperCase().endsWith(mask.toUpperCase()) && !candidate.getName().startsWith(".")) { - return candidate; - } - } - } - - // Look for embedded images in audiofiles. (Only check first audio file encountered). - JaudiotaggerParser parser = new JaudiotaggerParser(); - for (File candidate : candidates) { - if (parser.isApplicable(candidate)) { - if (parser.isImageAvailable(getMediaFile(candidate))) { - return candidate; - } else { - return null; - } - } - } - return null; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setMediaFileMemoryCache(Ehcache mediaFileMemoryCache) { - this.mediaFileMemoryCache = mediaFileMemoryCache; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } - - /** - * Returns all media files that are children, grand-children etc of a given media file. - * Directories are not included in the result. - * - * @param sort Whether to sort files in the same directory. - * @return All descendant music files. - */ - public List getDescendantsOf(MediaFile ancestor, boolean sort) { - - if (ancestor.isFile()) { - return Arrays.asList(ancestor); - } - - List result = new ArrayList(); - - for (MediaFile child : getChildrenOf(ancestor, true, true, sort)) { - if (child.isDirectory()) { - result.addAll(getDescendantsOf(child, sort)); - } else { - result.add(child); - } - } - return result; - } - - public void setMetaDataParserFactory(MetaDataParserFactory metaDataParserFactory) { - this.metaDataParserFactory = metaDataParserFactory; - } - - public void updateMediaFile(MediaFile mediaFile) { - mediaFileDao.createOrUpdateMediaFile(mediaFile); - } - - /** - * Increments the play count and last played date for the given media file and its - * directory and album. - */ - public void incrementPlayCount(MediaFile file) { - Date now = new Date(); - file.setLastPlayed(now); - file.setPlayCount(file.getPlayCount() + 1); - updateMediaFile(file); - - MediaFile parent = getParentOf(file); - if (!isRoot(parent)) { - parent.setLastPlayed(now); - parent.setPlayCount(parent.getPlayCount() + 1); - updateMediaFile(parent); - } - - Album album = albumDao.getAlbum(file.getAlbumArtist(), file.getAlbumName()); - if (album != null) { - album.setLastPlayed(now); - album.setPlayCount(album.getPlayCount() + 1); - albumDao.createOrUpdateAlbum(album); - } - } - - public void setAlbumDao(AlbumDao albumDao) { - this.albumDao = albumDao; - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MediaScannerService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MediaScannerService.java deleted file mode 100644 index 84f2d31c..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MediaScannerService.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import java.io.File; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.AlbumDao; -import net.sourceforge.subsonic.dao.ArtistDao; -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.domain.Album; -import net.sourceforge.subsonic.domain.Artist; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MediaLibraryStatistics; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.util.FileUtil; -import org.apache.commons.lang.ObjectUtils; - -/** - * Provides services for scanning the music library. - * - * @author Sindre Mehus - */ -public class MediaScannerService { - - private static final int INDEX_VERSION = 15; - private static final Logger LOG = Logger.getLogger(MediaScannerService.class); - - private MediaLibraryStatistics statistics; - - private boolean scanning; - private Timer timer; - private SettingsService settingsService; - private SearchService searchService; - private MediaFileService mediaFileService; - private MediaFileDao mediaFileDao; - private ArtistDao artistDao; - private AlbumDao albumDao; - private int scanCount; - - public void init() { - deleteOldIndexFiles(); - statistics = mediaFileDao.getStatistics(); - schedule(); - } - - /** - * Schedule background execution of media library scanning. - */ - public synchronized void schedule() { - if (timer != null) { - timer.cancel(); - } - timer = new Timer(true); - - TimerTask task = new TimerTask() { - @Override - public void run() { - scanLibrary(); - } - }; - - long daysBetween = settingsService.getIndexCreationInterval(); - int hour = settingsService.getIndexCreationHour(); - - if (daysBetween == -1) { - LOG.info("Automatic media scanning disabled."); - return; - } - - Date now = new Date(); - Calendar cal = Calendar.getInstance(); - cal.setTime(now); - cal.set(Calendar.HOUR_OF_DAY, hour); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - - if (cal.getTime().before(now)) { - cal.add(Calendar.DATE, 1); - } - - Date firstTime = cal.getTime(); - long period = daysBetween * 24L * 3600L * 1000L; - timer.schedule(task, firstTime, period); - - LOG.info("Automatic media library scanning scheduled to run every " + daysBetween + " day(s), starting at " + firstTime); - - // In addition, create index immediately if it doesn't exist on disk. - if (settingsService.getLastScanned() == null) { - LOG.info("Media library never scanned. Doing it now."); - scanLibrary(); - } - } - - /** - * Returns whether the media library is currently being scanned. - */ - public synchronized boolean isScanning() { - return scanning; - } - - /** - * Returns the number of files scanned so far. - */ - public int getScanCount() { - return scanCount; - } - - /** - * Scans the media library. - * The scanning is done asynchronously, i.e., this method returns immediately. - */ - public synchronized void scanLibrary() { - if (isScanning()) { - return; - } - scanning = true; - - Thread thread = new Thread("MediaLibraryScanner") { - @Override - public void run() { - doScanLibrary(); - } - }; - - thread.setPriority(Thread.MIN_PRIORITY); - thread.start(); - } - - private void doScanLibrary() { - LOG.info("Starting to scan media library."); - - try { - Date lastScanned = new Date(); - Map albumCount = new HashMap(); - scanCount = 0; - - searchService.startIndexing(); - - // Recurse through all files on disk. - for (MusicFolder musicFolder : settingsService.getAllMusicFolders()) { - MediaFile root = mediaFileService.getMediaFile(musicFolder.getPath(), false); - scanFile(root, musicFolder, lastScanned, albumCount); - } - mediaFileDao.markNonPresent(lastScanned); - artistDao.markNonPresent(lastScanned); - albumDao.markNonPresent(lastScanned); - - // Update statistics - statistics = mediaFileDao.getStatistics(); - - settingsService.setLastScanned(lastScanned); - settingsService.save(false); - LOG.info("Scanned media library with " + scanCount + " entries."); - - } catch (Throwable x) { - LOG.error("Failed to scan media library.", x); - } finally { - scanning = false; - searchService.stopIndexing(); - } - } - - private void scanFile(MediaFile file, MusicFolder musicFolder, Date lastScanned, Map albumCount) { - scanCount++; - if (scanCount % 250 == 0) { - LOG.info("Scanned media library with " + scanCount + " entries."); - } - - searchService.index(file); - - // Update the root folder if it has changed. - if (!musicFolder.getPath().getPath().equals(file.getFolder())) { - file.setFolder(musicFolder.getPath().getPath()); - mediaFileDao.createOrUpdateMediaFile(file); - } - - if (file.isDirectory()) { - for (MediaFile child : mediaFileService.getChildrenOf(file, true, false, false, false)) { - scanFile(child, musicFolder, lastScanned, albumCount); - } - for (MediaFile child : mediaFileService.getChildrenOf(file, false, true, false, false)) { - scanFile(child, musicFolder, lastScanned, albumCount); - } - } else { - updateAlbum(file, lastScanned, albumCount); - updateArtist(file, lastScanned, albumCount); - } - - mediaFileDao.markPresent(file.getPath(), lastScanned); - artistDao.markPresent(file.getArtist(), lastScanned); - } - - private void updateAlbum(MediaFile file, Date lastScanned, Map albumCount) { - if (file.getAlbumName() == null || file.getArtist() == null || file.getParentPath() == null || !file.isAudio()) { - return; - } - - Album album = albumDao.getAlbumForFile(file); - if (album == null) { - album = new Album(); - album.setPath(file.getParentPath()); - album.setName(file.getAlbumName()); - album.setArtist(file.getArtist()); - album.setCreated(file.getChanged()); - } - if (album.getCoverArtPath() == null) { - MediaFile parent = mediaFileService.getParentOf(file); - if (parent != null) { - album.setCoverArtPath(parent.getCoverArtPath()); - } - } - boolean firstEncounter = !lastScanned.equals(album.getLastScanned()); - if (firstEncounter) { - album.setDurationSeconds(0); - album.setSongCount(0); - Integer n = albumCount.get(file.getArtist()); - albumCount.put(file.getArtist(), n == null ? 1 : n + 1); - } - if (file.getDurationSeconds() != null) { - album.setDurationSeconds(album.getDurationSeconds() + file.getDurationSeconds()); - } - if (file.isAudio()) { - album.setSongCount(album.getSongCount() + 1); - } - - album.setLastScanned(lastScanned); - album.setPresent(true); - albumDao.createOrUpdateAlbum(album); - if (firstEncounter) { - searchService.index(album); - } - - // Update the file's album artist, if necessary. - if (!ObjectUtils.equals(album.getArtist(), file.getAlbumArtist())) { - file.setAlbumArtist(album.getArtist()); - mediaFileDao.createOrUpdateMediaFile(file); - } - } - - private void updateArtist(MediaFile file, Date lastScanned, Map albumCount) { - if (file.getArtist() == null || !file.isAudio()) { - return; - } - - Artist artist = artistDao.getArtist(file.getArtist()); - if (artist == null) { - artist = new Artist(); - artist.setName(file.getArtist()); - } - if (artist.getCoverArtPath() == null) { - MediaFile parent = mediaFileService.getParentOf(file); - if (parent != null) { - artist.setCoverArtPath(parent.getCoverArtPath()); - } - } - boolean firstEncounter = !lastScanned.equals(artist.getLastScanned()); - - Integer n = albumCount.get(artist.getName()); - artist.setAlbumCount(n == null ? 0 : n); - - artist.setLastScanned(lastScanned); - artist.setPresent(true); - artistDao.createOrUpdateArtist(artist); - - if (firstEncounter) { - searchService.index(artist); - } - } - - /** - * Returns media library statistics, including the number of artists, albums and songs. - * - * @return Media library statistics. - */ - public MediaLibraryStatistics getStatistics() { - return statistics; - } - - /** - * Deletes old versions of the index file. - */ - private void deleteOldIndexFiles() { - for (int i = 2; i < INDEX_VERSION; i++) { - File file = getIndexFile(i); - try { - if (FileUtil.exists(file)) { - if (file.delete()) { - LOG.info("Deleted old index file: " + file.getPath()); - } - } - } catch (Exception x) { - LOG.warn("Failed to delete old index file: " + file.getPath(), x); - } - } - } - - /** - * Returns the index file for the given index version. - * - * @param version The index version. - * @return The index file for the given index version. - */ - private File getIndexFile(int version) { - File home = SettingsService.getSubsonicHome(); - return new File(home, "subsonic" + version + ".index"); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSearchService(SearchService searchService) { - this.searchService = searchService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } - - public void setArtistDao(ArtistDao artistDao) { - this.artistDao = artistDao; - } - - public void setAlbumDao(AlbumDao albumDao) { - this.albumDao = albumDao; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MusicIndexService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MusicIndexService.java deleted file mode 100644 index b6ee682e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/MusicIndexService.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.StringTokenizer; -import java.util.TreeMap; -import java.util.TreeSet; - -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.MusicIndex; -import net.sourceforge.subsonic.domain.MusicIndex.Artist; - -/** - * Provides services for grouping artists by index. - * - * @author Sindre Mehus - */ -public class MusicIndexService { - - private SettingsService settingsService; - private MediaFileService mediaFileService; - private MediaFileDao mediaFileDao; - - /** - * Returns a map from music indexes to sets of artists that are direct children of the given music folders. - * - * @param folders The music folders. - * @return A map from music indexes to sets of artists that are direct children of this music file. - * @throws IOException If an I/O error occurs. - */ - public SortedMap> getIndexedArtists(List folders) throws IOException { - - String[] ignoredArticles = settingsService.getIgnoredArticlesAsArray(); - String[] shortcuts = settingsService.getShortcutsAsArray(); - final List indexes = createIndexesFromExpression(settingsService.getIndexString()); - - Comparator indexComparator = new MusicIndexComparator(indexes); - SortedSet artists = createArtists(folders, ignoredArticles, shortcuts); - SortedMap> result = new TreeMap>(indexComparator); - - for (Artist artist : artists) { - MusicIndex index = getIndex(artist, indexes); - SortedSet artistSet = result.get(index); - if (artistSet == null) { - artistSet = new TreeSet(); - result.put(index, artistSet); - } - artistSet.add(artist); - } - - return result; - } - - /** - * Creates a new instance by parsing the given expression. The expression consists of an index name, followed by - * an optional list of one-character prefixes. For example:

- *

- * The expression "A" will create the index "A" -> ["A"]
- * The expression "The" will create the index "The" -> ["The"]
- * The expression "A(AÅÆ)" will create the index "A" -> ["A", "Å", "Æ"]
- * The expression "X-Z(XYZ)" will create the index "X-Z" -> ["X", "Y", "Z"] - * - * @param expr The expression to parse. - * @return A new instance. - */ - protected MusicIndex createIndexFromExpression(String expr) { - int separatorIndex = expr.indexOf('('); - if (separatorIndex == -1) { - - MusicIndex index = new MusicIndex(expr); - index.addPrefix(expr); - return index; - } - - MusicIndex index = new MusicIndex(expr.substring(0, separatorIndex)); - String prefixString = expr.substring(separatorIndex + 1, expr.length() - 1); - for (int i = 0; i < prefixString.length(); i++) { - index.addPrefix(prefixString.substring(i, i + 1)); - } - return index; - } - - /** - * Creates a list of music indexes by parsing the given expression. The expression is a space-separated list of - * sub-expressions, for which the rules described in {@link #createIndexFromExpression} apply. - * - * @param expr The expression to parse. - * @return A list of music indexes. - */ - protected List createIndexesFromExpression(String expr) { - List result = new ArrayList(); - - StringTokenizer tokenizer = new StringTokenizer(expr, " "); - while (tokenizer.hasMoreTokens()) { - MusicIndex index = createIndexFromExpression(tokenizer.nextToken()); - result.add(index); - } - - return result; - } - - private SortedSet createArtists(List folders, String[] ignoredArticles, String[] shortcuts) throws IOException { - return settingsService.isOrganizeByFolderStructure() ? - createArtistsByFolderStructure(folders, ignoredArticles, shortcuts) : - createArtistsByTagStructure(folders, ignoredArticles, shortcuts); - } - - private SortedSet createArtistsByFolderStructure(List folders, String[] ignoredArticles, String[] shortcuts) { - SortedMap artistMap = new TreeMap(); - Set shortcutSet = new HashSet(Arrays.asList(shortcuts)); - - for (MusicFolder folder : folders) { - - MediaFile root = mediaFileService.getMediaFile(folder.getPath(), true); - List children = mediaFileService.getChildrenOf(root, false, true, true, true); - for (MediaFile child : children) { - if (shortcutSet.contains(child.getName())) { - continue; - } - - String sortableName = createSortableName(child.getName(), ignoredArticles); - Artist artist = artistMap.get(sortableName); - if (artist == null) { - artist = new Artist(child.getName(), sortableName); - artistMap.put(sortableName, artist); - } - artist.addMediaFile(child); - } - } - - return new TreeSet(artistMap.values()); - } - - private SortedSet createArtistsByTagStructure(List folders, String[] ignoredArticles, String[] shortcuts) { - Set shortcutSet = new HashSet(Arrays.asList(shortcuts)); - SortedSet artists = new TreeSet(); - - // TODO: Filter by folder - for (String artistName : mediaFileDao.getArtists()) { - - if (shortcutSet.contains(artistName)) { - continue; - } - - String sortableName = createSortableName(artistName, ignoredArticles); - Artist artist = new Artist(artistName, sortableName); - artists.add(artist); - } - - return artists; - } - - private String createSortableName(String name, String[] ignoredArticles) { - String uppercaseName = name.toUpperCase(); - for (String article : ignoredArticles) { - if (uppercaseName.startsWith(article.toUpperCase() + " ")) { - return name.substring(article.length() + 1) + ", " + article; - } - } - return name; - } - - /** - * Returns the music index to which the given artist belongs. - * - * @param artist The artist in question. - * @param indexes List of available indexes. - * @return The music index to which this music file belongs, or {@link MusicIndex#OTHER} if no index applies. - */ - private MusicIndex getIndex(Artist artist, List indexes) { - String sortableName = artist.getSortableName().toUpperCase(); - for (MusicIndex index : indexes) { - for (String prefix : index.getPrefixes()) { - if (sortableName.startsWith(prefix.toUpperCase())) { - return index; - } - } - } - return MusicIndex.OTHER; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } - - private static class MusicIndexComparator implements Comparator, Serializable { - - private List indexes; - - public MusicIndexComparator(List indexes) { - this.indexes = indexes; - } - - public int compare(MusicIndex a, MusicIndex b) { - int indexA = indexes.indexOf(a); - int indexB = indexes.indexOf(b); - - if (indexA == -1) { - indexA = Integer.MAX_VALUE; - } - if (indexB == -1) { - indexB = Integer.MAX_VALUE; - } - - if (indexA < indexB) { - return -1; - } - if (indexA > indexB) { - return 1; - } - return 0; - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/NetworkService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/NetworkService.java deleted file mode 100644 index b54026a0..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/NetworkService.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.NameValuePair; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.util.EntityUtils; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.NATPMPRouter; -import net.sourceforge.subsonic.domain.Router; -import net.sourceforge.subsonic.domain.SBBIRouter; -import net.sourceforge.subsonic.domain.WeUPnPRouter; -import net.sourceforge.subsonic.util.StringUtil; -import net.sourceforge.subsonic.util.Util; - -/** - * Provides network-related services, including port forwarding on UPnP routers and - * URL redirection from http://xxxx.subsonic.org. - * - * @author Sindre Mehus - */ -public class NetworkService { - - private static final Logger LOG = Logger.getLogger(NetworkService.class); - private static final long PORT_FORWARDING_DELAY = 3600L; - private static final long URL_REDIRECTION_DELAY = 2 * 3600L; - - private static final String URL_REDIRECTION_REGISTER_URL = getBackendUrl() + "/backend/redirect/register.view"; - private static final String URL_REDIRECTION_UNREGISTER_URL = getBackendUrl() + "/backend/redirect/unregister.view"; - private static final String URL_REDIRECTION_TEST_URL = getBackendUrl() + "/backend/redirect/test.view"; - - private SettingsService settingsService; - private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(4); - private final PortForwardingTask portForwardingTask = new PortForwardingTask(); - private final URLRedirectionTask urlRedirectionTask = new URLRedirectionTask(); - private Future portForwardingFuture; - private Future urlRedirectionFuture; - - private final Status portForwardingStatus = new Status(); - private final Status urlRedirectionStatus = new Status(); - private boolean testUrlRedirection; - - public void init() { - initPortForwarding(); - initUrlRedirection(false); - } - - /** - * Configures UPnP port forwarding. - */ - public synchronized void initPortForwarding() { - portForwardingStatus.setText("Idle"); - if (portForwardingFuture != null) { - portForwardingFuture.cancel(true); - } - portForwardingFuture = executor.scheduleWithFixedDelay(portForwardingTask, 0L, PORT_FORWARDING_DELAY, TimeUnit.SECONDS); - } - - /** - * Configures URL redirection. - * - * @param test Whether to test that the redirection works. - */ - public synchronized void initUrlRedirection(boolean test) { - urlRedirectionStatus.setText("Idle"); - if (urlRedirectionFuture != null) { - urlRedirectionFuture.cancel(true); - } - testUrlRedirection = test; - urlRedirectionFuture = executor.scheduleWithFixedDelay(urlRedirectionTask, 0L, URL_REDIRECTION_DELAY, TimeUnit.SECONDS); - } - - public Status getPortForwardingStatus() { - return portForwardingStatus; - } - - public Status getURLRedirecionStatus() { - return urlRedirectionStatus; - } - - public static String getBackendUrl() { - return "true".equals(System.getProperty("subsonic.test")) ? "http://localhost:8181" : "http://subsonic.org"; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - private class PortForwardingTask extends Task { - - @Override - protected void execute() { - - boolean enabled = settingsService.isPortForwardingEnabled(); - portForwardingStatus.setText("Looking for router..."); - Router router = findRouter(); - if (router == null) { - LOG.warn("No UPnP router found."); - portForwardingStatus.setText("No router found."); - } else { - - portForwardingStatus.setText("Router found."); - - int port = settingsService.getPort(); - int httpsPort = settingsService.getHttpsPort(); - - // Create new NAT entry. - if (enabled) { - try { - router.addPortMapping(port, port, 0); - String message = "Successfully forwarding port " + port; - - if (httpsPort != 0 && httpsPort != port) { - router.addPortMapping(httpsPort, httpsPort, 0); - message += " and port " + httpsPort; - } - message += "."; - - LOG.info(message); - portForwardingStatus.setText(message); - } catch (Throwable x) { - String message = "Failed to create port forwarding."; - LOG.warn(message, x); - portForwardingStatus.setText(message + " See log for details."); - } - } - - // Delete NAT entry. - else { - try { - router.deletePortMapping(port, port); - LOG.info("Deleted port mapping for port " + port); - if (httpsPort != 0 && httpsPort != port) { - router.deletePortMapping(httpsPort, httpsPort); - LOG.info("Deleted port mapping for port " + httpsPort); - } - } catch (Throwable x) { - LOG.warn("Failed to delete port mapping.", x); - } - portForwardingStatus.setText("Port forwarding disabled."); - } - } - - // Don't do it again if disabled. - if (!enabled && portForwardingFuture != null) { - portForwardingFuture.cancel(false); - } - } - - private Router findRouter() { - try { - Router router = SBBIRouter.findRouter(); - if (router != null) { - return router; - } - } catch (Throwable x) { - LOG.warn("Failed to find UPnP router using SBBI library.", x); - } - - try { - Router router = WeUPnPRouter.findRouter(); - if (router != null) { - return router; - } - } catch (Throwable x) { - LOG.warn("Failed to find UPnP router using WeUPnP library.", x); - } - - try { - Router router = NATPMPRouter.findRouter(); - if (router != null) { - return router; - } - } catch (Throwable x) { - LOG.warn("Failed to find NAT-PMP router.", x); - } - - return null; - } - } - - private class URLRedirectionTask extends Task { - - @Override - protected void execute() { - - boolean enable = settingsService.isUrlRedirectionEnabled(); - HttpPost request = new HttpPost(enable ? URL_REDIRECTION_REGISTER_URL : URL_REDIRECTION_UNREGISTER_URL); - - int port = settingsService.getPort(); - boolean trial = !settingsService.isLicenseValid(); - Date trialExpires = settingsService.getUrlRedirectTrialExpires(); - - List params = new ArrayList(); - params.add(new BasicNameValuePair("serverId", settingsService.getServerId())); - params.add(new BasicNameValuePair("redirectFrom", settingsService.getUrlRedirectFrom())); - params.add(new BasicNameValuePair("port", String.valueOf(port))); - params.add(new BasicNameValuePair("localIp", Util.getLocalIpAddress())); - params.add(new BasicNameValuePair("localPort", String.valueOf(port))); - params.add(new BasicNameValuePair("contextPath", settingsService.getUrlRedirectContextPath())); - params.add(new BasicNameValuePair("trial", String.valueOf(trial))); - if (trial && trialExpires != null) { - params.add(new BasicNameValuePair("trialExpires", String.valueOf(trialExpires.getTime()))); - } else { - params.add(new BasicNameValuePair("licenseHolder", settingsService.getLicenseEmail())); - } - - HttpClient client = new DefaultHttpClient(); - - try { - urlRedirectionStatus.setText(enable ? "Registering web address..." : "Unregistering web address..."); - request.setEntity(new UrlEncodedFormEntity(params, StringUtil.ENCODING_UTF8)); - - HttpResponse response = client.execute(request); - StatusLine status = response.getStatusLine(); - - switch (status.getStatusCode()) { - case HttpStatus.SC_BAD_REQUEST: - urlRedirectionStatus.setText(EntityUtils.toString(response.getEntity())); - break; - case HttpStatus.SC_OK: - urlRedirectionStatus.setText(enable ? "Successfully registered web address." : "Web address disabled."); - break; - default: - throw new IOException(status.getStatusCode() + " " + status.getReasonPhrase()); - } - - } catch (Throwable x) { - LOG.warn(enable ? "Failed to register web address." : "Failed to unregister web address.", x); - urlRedirectionStatus.setText(enable ? ("Failed to register web address. " + x.getMessage() + - " (" + x.getClass().getSimpleName() + ")") : "Web address disabled."); - } finally { - client.getConnectionManager().shutdown(); - } - - // Test redirection, but only once. - if (testUrlRedirection) { - testUrlRedirection = false; - testUrlRedirection(); - } - - // Don't do it again if disabled. - if (!enable && urlRedirectionFuture != null) { - urlRedirectionFuture.cancel(false); - } - } - - private void testUrlRedirection() { - - HttpGet request = new HttpGet(URL_REDIRECTION_TEST_URL + "?redirectFrom=" + settingsService.getUrlRedirectFrom()); - HttpClient client = new DefaultHttpClient(); - HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000); - HttpConnectionParams.setSoTimeout(client.getParams(), 30000); - - try { - urlRedirectionStatus.setText("Testing web address " + settingsService.getUrlRedirectFrom() + ".subsonic.org. Please wait..."); - String response = client.execute(request, new BasicResponseHandler()); - urlRedirectionStatus.setText(response); - - } catch (Throwable x) { - LOG.warn("Failed to test web address.", x); - urlRedirectionStatus.setText("Failed to test web address. " + x.getMessage() + " (" + x.getClass().getSimpleName() + ")"); - } finally { - client.getConnectionManager().shutdown(); - } - } - } - - private abstract class Task implements Runnable { - public void run() { - String name = getClass().getSimpleName(); - try { - execute(); - } catch (Throwable x) { - LOG.error("Error executing " + name + ": " + x.getMessage(), x); - } - } - - protected abstract void execute(); - } - - public static class Status { - - private String text; - private Date date; - - public void setText(String text) { - this.text = text; - date = new Date(); - } - - public String getText() { - return text; - } - - public Date getDate() { - return date; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PlayerService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PlayerService.java deleted file mode 100644 index 0f24b2b8..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PlayerService.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sourceforge.subsonic.dao.PlayerDao; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.Transcoding; -import net.sourceforge.subsonic.domain.TransferStatus; -import net.sourceforge.subsonic.util.StringUtil; -import org.apache.commons.lang.StringUtils; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * Provides services for maintaining the set of players. - * - * @author Sindre Mehus - * @see Player - */ -public class PlayerService { - - private static final String COOKIE_NAME = "player"; - private static final int COOKIE_EXPIRY = 365 * 24 * 3600; // One year - - private PlayerDao playerDao; - private StatusService statusService; - private SecurityService securityService; - private TranscodingService transcodingService; - - public void init() { - playerDao.deleteOldPlayers(60); - } - - /** - * Equivalent to getPlayer(request, response, true) . - */ - public Player getPlayer(HttpServletRequest request, HttpServletResponse response) { - return getPlayer(request, response, true, false); - } - - /** - * Returns the player associated with the given HTTP request. If no such player exists, a new - * one is created. - * - * @param request The HTTP request. - * @param response The HTTP response. - * @param remoteControlEnabled Whether this method should return a remote-controlled player. - * @param isStreamRequest Whether the HTTP request is a request for streaming data. - * @return The player associated with the given HTTP request. - */ - public synchronized Player getPlayer(HttpServletRequest request, HttpServletResponse response, - boolean remoteControlEnabled, boolean isStreamRequest) { - - // Find by 'player' request parameter. - Player player = getPlayerById(request.getParameter("player")); - - // Find in session context. - if (player == null && remoteControlEnabled) { - String playerId = (String) request.getSession().getAttribute("player"); - if (playerId != null) { - player = getPlayerById(playerId); - } - } - - // Find by cookie. - String username = securityService.getCurrentUsername(request); - if (player == null && remoteControlEnabled) { - player = getPlayerById(getPlayerIdFromCookie(request, username)); - } - - // Make sure we're not hijacking the player of another user. - if (player != null && player.getUsername() != null && username != null && !player.getUsername().equals(username)) { - player = null; - } - - // Look for player with same IP address and user name. - if (player == null) { - player = getPlayerByIpAddressAndUsername(request.getRemoteAddr(), username); - - // Don't use this player if it's used by REST API. - if (player != null && player.getClientId() != null) { - player = null; - } - } - - // If no player was found, create it. - if (player == null) { - player = new Player(); - createPlayer(player); -// LOG.debug("Created player " + player.getId() + " (remoteControlEnabled: " + remoteControlEnabled + -// ", isStreamRequest: " + isStreamRequest + ", username: " + username + -// ", ip: " + request.getRemoteAddr() + ")."); - } - - // Update player data. - boolean isUpdate = false; - if (username != null && player.getUsername() == null) { - player.setUsername(username); - isUpdate = true; - } - if (player.getIpAddress() == null || isStreamRequest || - (!isPlayerConnected(player) && player.isDynamicIp() && !request.getRemoteAddr().equals(player.getIpAddress()))) { - player.setIpAddress(request.getRemoteAddr()); - isUpdate = true; - } - String userAgent = request.getHeader("user-agent"); - if (isStreamRequest) { - player.setType(userAgent); - player.setLastSeen(new Date()); - isUpdate = true; - } - - if (isUpdate) { - updatePlayer(player); - } - - // Set cookie in response. - if (response != null) { - String cookieName = COOKIE_NAME + "-" + StringUtil.utf8HexEncode(username); - Cookie cookie = new Cookie(cookieName, player.getId()); - cookie.setMaxAge(COOKIE_EXPIRY); - String path = request.getContextPath(); - if (StringUtils.isEmpty(path)) { - path = "/"; - } - cookie.setPath(path); - response.addCookie(cookie); - } - - // Save player in session context. - if (remoteControlEnabled) { - request.getSession().setAttribute("player", player.getId()); - } - - return player; - } - - /** - * Updates the given player. - * - * @param player The player to update. - */ - public void updatePlayer(Player player) { - playerDao.updatePlayer(player); - } - - /** - * Returns the player with the given ID. - * - * @param id The unique player ID. - * @return The player with the given ID, or null if no such player exists. - */ - public Player getPlayerById(String id) { - return playerDao.getPlayerById(id); - } - - /** - * Returns whether the given player is connected. - * - * @param player The player in question. - * @return Whether the player is connected. - */ - private boolean isPlayerConnected(Player player) { - for (TransferStatus status : statusService.getStreamStatusesForPlayer(player)) { - if (status.isActive()) { - return true; - } - } - return false; - } - - /** - * Returns the player with the given IP address and username. If no username is given, only IP address is - * used as search criteria. - * - * @param ipAddress The IP address. - * @param username The remote user. - * @return The player with the given IP address, or null if no such player exists. - */ - private Player getPlayerByIpAddressAndUsername(final String ipAddress, final String username) { - if (ipAddress == null) { - return null; - } - for (Player player : getAllPlayers()) { - boolean ipMatches = ipAddress.equals(player.getIpAddress()); - boolean userMatches = username == null || username.equals(player.getUsername()); - if (ipMatches && userMatches) { - return player; - } - } - return null; - } - - /** - * Reads the player ID from the cookie in the HTTP request. - * - * @param request The HTTP request. - * @param username The name of the current user. - * @return The player ID embedded in the cookie, or null if cookie is not present. - */ - private String getPlayerIdFromCookie(HttpServletRequest request, String username) { - Cookie[] cookies = request.getCookies(); - if (cookies == null) { - return null; - } - String cookieName = COOKIE_NAME + "-" + StringUtil.utf8HexEncode(username); - for (Cookie cookie : cookies) { - if (cookieName.equals(cookie.getName())) { - return cookie.getValue(); - } - } - return null; - } - - /** - * Returns all players owned by the given username and client ID. - * - * @param username The name of the user. - * @param clientId The third-party client ID (used if this player is managed over the - * Subsonic REST API). May be null. - * @return All relevant players. - */ - public List getPlayersForUserAndClientId(String username, String clientId) { - return playerDao.getPlayersForUserAndClientId(username, clientId); - } - - /** - * Returns all currently registered players. - * - * @return All currently registered players. - */ - public List getAllPlayers() { - return playerDao.getAllPlayers(); - } - - /** - * Removes the player with the given ID. - * - * @param id The unique player ID. - */ - public synchronized void removePlayerById(String id) { - playerDao.deletePlayer(id); - } - - /** - * Creates and returns a clone of the given player. - * - * @param playerId The ID of the player to clone. - * @return The cloned player. - */ - public Player clonePlayer(String playerId) { - Player player = getPlayerById(playerId); - if (player.getName() != null) { - player.setName(player.getName() + " (copy)"); - } - - createPlayer(player); - return player; - } - - /** - * Creates the given player, and activates all transcodings. - * - * @param player The player to create. - */ - public void createPlayer(Player player) { - playerDao.createPlayer(player); - - List transcodings = transcodingService.getAllTranscodings(); - List defaultActiveTranscodings = new ArrayList(); - for (Transcoding transcoding : transcodings) { - if (transcoding.isDefaultActive()) { - defaultActiveTranscodings.add(transcoding); - } - } - - transcodingService.setTranscodingsForPlayer(player, defaultActiveTranscodings); - } - - public void setStatusService(StatusService statusService) { - this.statusService = statusService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setPlayerDao(PlayerDao playerDao) { - this.playerDao = playerDao; - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PlaylistService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PlaylistService.java deleted file mode 100644 index 6208c3dc..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PlaylistService.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.util.Pair; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringEscapeUtils; -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.JDOMException; -import org.jdom.Namespace; -import org.jdom.input.SAXBuilder; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.MediaFileDao; -import net.sourceforge.subsonic.dao.PlaylistDao; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Playlist; -import net.sourceforge.subsonic.util.StringUtil; - -/** - * Provides services for loading and saving playlists to and from persistent storage. - * - * @author Sindre Mehus - * @see net.sourceforge.subsonic.domain.PlayQueue - */ -public class PlaylistService { - - private static final Logger LOG = Logger.getLogger(PlaylistService.class); - private MediaFileService mediaFileService; - private MediaFileDao mediaFileDao; - private PlaylistDao playlistDao; - private SecurityService securityService; - private SettingsService settingsService; - - public void init() { - try { - importPlaylists(); - } catch (Throwable x) { - LOG.warn("Failed to import playlists: " + x, x); - } - } - - public List getReadablePlaylistsForUser(String username) { - return playlistDao.getReadablePlaylistsForUser(username); - } - - public List getWritablePlaylistsForUser(String username) { - - // Admin users are allowed to modify all playlists that are visible to them. - if (securityService.isAdmin(username)) { - return getReadablePlaylistsForUser(username); - } - - return playlistDao.getWritablePlaylistsForUser(username); - } - - public Playlist getPlaylist(int id) { - return playlistDao.getPlaylist(id); - } - - public List getPlaylistUsers(int playlistId) { - return playlistDao.getPlaylistUsers(playlistId); - } - - public List getFilesInPlaylist(int id) { - return mediaFileDao.getFilesInPlaylist(id); - } - - public void setFilesInPlaylist(int id, List files) { - playlistDao.setFilesInPlaylist(id, files); - } - - public void createPlaylist(Playlist playlist) { - playlistDao.createPlaylist(playlist); - } - - public void addPlaylistUser(int playlistId, String username) { - playlistDao.addPlaylistUser(playlistId, username); - } - - public void deletePlaylistUser(int playlistId, String username) { - playlistDao.deletePlaylistUser(playlistId, username); - } - - public boolean isReadAllowed(Playlist playlist, String username) { - if (username == null) { - return false; - } - if (username.equals(playlist.getUsername()) || playlist.isPublic()) { - return true; - } - return playlistDao.getPlaylistUsers(playlist.getId()).contains(username); - } - - public boolean isWriteAllowed(Playlist playlist, String username) { - return username != null && username.equals(playlist.getUsername()); - } - - public void deletePlaylist(int id) { - playlistDao.deletePlaylist(id); - } - - public void updatePlaylist(Playlist playlist) { - playlistDao.updatePlaylist(playlist); - } - - public Playlist importPlaylist(String username, String playlistName, String fileName, String format, InputStream inputStream) throws Exception { - PlaylistFormat playlistFormat = PlaylistFormat.getPlaylistFormat(format); - if (playlistFormat == null) { - throw new Exception("Unsupported playlist format: " + format); - } - - Pair, List> result = parseFiles(IOUtils.toByteArray(inputStream), playlistFormat); - if (result.getFirst().isEmpty() && !result.getSecond().isEmpty()) { - throw new Exception("No songs in the playlist were found."); - } - - for (String error : result.getSecond()) { - LOG.warn("File in playlist '" + fileName + "' not found: " + error); - } - - Date now = new Date(); - Playlist playlist = new Playlist(); - playlist.setUsername(username); - playlist.setCreated(now); - playlist.setChanged(now); - playlist.setPublic(true); - playlist.setName(playlistName); - playlist.setImportedFrom(fileName); - - createPlaylist(playlist); - setFilesInPlaylist(playlist.getId(), result.getFirst()); - - return playlist; - } - - private Pair, List> parseFiles(byte[] playlist, PlaylistFormat playlistFormat) throws IOException { - Pair, List> result = null; - - // Try with multiple encodings; use the one that finds the most files. - String[] encodings = {StringUtil.ENCODING_LATIN, StringUtil.ENCODING_UTF8, Charset.defaultCharset().name()}; - for (String encoding : encodings) { - Pair, List> files = parseFilesWithEncoding(playlist, playlistFormat, encoding); - if (result == null || result.getFirst().size() < files.getFirst().size()) { - result = files; - } - } - return result; - } - - private Pair, List> parseFilesWithEncoding(byte[] playlist, PlaylistFormat playlistFormat, String encoding) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(playlist), encoding)); - return playlistFormat.parse(reader, mediaFileService); - } - - public void exportPlaylist(int id, OutputStream out) throws Exception { - PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, StringUtil.ENCODING_UTF8)); - new M3UFormat().format(getFilesInPlaylist(id), writer); - } - - /** - * Implementation of M3U playlist format. - */ - private void importPlaylists() throws Exception { - String playlistFolderPath = settingsService.getPlaylistFolder(); - if (playlistFolderPath == null) { - return; - } - File playlistFolder = new File(playlistFolderPath); - if (!playlistFolder.exists()) { - return; - } - - List allPlaylists = playlistDao.getAllPlaylists(); - for (File file : playlistFolder.listFiles()) { - try { - importPlaylistIfNotExisting(file, allPlaylists); - } catch (Exception x) { - LOG.warn("Failed to auto-import playlist " + file + ". " + x.getMessage()); - } - } - } - - private void importPlaylistIfNotExisting(File file, List allPlaylists) throws Exception { - String format = FilenameUtils.getExtension(file.getPath()); - if (PlaylistFormat.getPlaylistFormat(format) == null) { - return; - } - - String fileName = file.getName(); - for (Playlist playlist : allPlaylists) { - if (fileName.equals(playlist.getImportedFrom())) { - return; // Already imported. - } - } - InputStream in = new FileInputStream(file); - try { - importPlaylist(User.USERNAME_ADMIN, FilenameUtils.getBaseName(fileName), fileName, format, in); - LOG.info("Auto-imported playlist " + file); - } finally { - IOUtils.closeQuietly(in); - } - } - - public void setPlaylistDao(PlaylistDao playlistDao) { - this.playlistDao = playlistDao; - } - - public void setMediaFileDao(MediaFileDao mediaFileDao) { - this.mediaFileDao = mediaFileDao; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - /** - * Abstract superclass for playlist formats. - */ - - private abstract static class PlaylistFormat { - public abstract Pair, List> parse(BufferedReader reader, MediaFileService mediaFileService) throws IOException; - - public abstract void format(List files, PrintWriter writer) throws IOException; - - public static PlaylistFormat getPlaylistFormat(String format) { - if (format == null) { - return null; - } - if (format.equalsIgnoreCase("m3u") || format.equalsIgnoreCase("m3u8")) { - return new M3UFormat(); - } - if (format.equalsIgnoreCase("pls")) { - return new PLSFormat(); - } - if (format.equalsIgnoreCase("xspf")) { - return new XSPFFormat(); - } - return null; - } - - protected MediaFile getMediaFile(MediaFileService mediaFileService, String path) { - try { - MediaFile file = mediaFileService.getMediaFile(path); - if (file != null && file.exists()) { - return file; - } - } catch (SecurityException x) { - // Ignored - } - return null; - } - } - - private static class M3UFormat extends PlaylistFormat { - public Pair, List> parse(BufferedReader reader, MediaFileService mediaFileService) throws IOException { - List ok = new ArrayList(); - List error = new ArrayList(); - String line = reader.readLine(); - while (line != null) { - if (!line.startsWith("#")) { - MediaFile file = getMediaFile(mediaFileService, line); - if (file != null) { - ok.add(file); - } else { - error.add(line); - } - } - line = reader.readLine(); - } - return new Pair, List>(ok, error); - } - - public void format(List files, PrintWriter writer) throws IOException { - writer.println("#EXTM3U"); - for (MediaFile file : files) { - writer.println(file.getPath()); - } - if (writer.checkError()) { - throw new IOException("Error when writing playlist"); - } - } - } - - /** - * Implementation of PLS playlist format. - */ - private static class PLSFormat extends PlaylistFormat { - public Pair, List> parse(BufferedReader reader, MediaFileService mediaFileService) throws IOException { - List ok = new ArrayList(); - List error = new ArrayList(); - - Pattern pattern = Pattern.compile("^File\\d+=(.*)$"); - String line = reader.readLine(); - while (line != null) { - - Matcher matcher = pattern.matcher(line); - if (matcher.find()) { - String path = matcher.group(1); - MediaFile file = getMediaFile(mediaFileService, path); - if (file != null) { - ok.add(file); - } else { - error.add(path); - } - } - line = reader.readLine(); - } - return new Pair, List>(ok, error); - } - - public void format(List files, PrintWriter writer) throws IOException { - writer.println("[playlist]"); - int counter = 0; - - for (MediaFile file : files) { - counter++; - writer.println("File" + counter + '=' + file.getPath()); - } - writer.println("NumberOfEntries=" + counter); - writer.println("Version=2"); - - if (writer.checkError()) { - throw new IOException("Error when writing playlist."); - } - } - } - - /** - * Implementation of XSPF (http://www.xspf.org/) playlist format. - */ - private static class XSPFFormat extends PlaylistFormat { - public Pair, List> parse(BufferedReader reader, MediaFileService mediaFileService) throws IOException { - List ok = new ArrayList(); - List error = new ArrayList(); - - SAXBuilder builder = new SAXBuilder(); - Document document; - try { - document = builder.build(reader); - } catch (JDOMException x) { - LOG.warn("Failed to parse XSPF playlist.", x); - throw new IOException("Failed to parse XSPF playlist."); - } - - Element root = document.getRootElement(); - Namespace ns = root.getNamespace(); - Element trackList = root.getChild("trackList", ns); - List tracks = trackList.getChildren("track", ns); - - for (Object obj : tracks) { - Element track = (Element) obj; - String location = track.getChildText("location", ns); - if (location != null && location.startsWith("file://")) { - location = location.replaceFirst("file://", ""); - MediaFile file = getMediaFile(mediaFileService, location); - if (file != null) { - ok.add(file); - } else { - error.add(location); - } - } - } - return new Pair, List>(ok, error); - } - - public void format(List files, PrintWriter writer) throws IOException { - writer.println(""); - writer.println(""); - writer.println(" "); - - for (MediaFile file : files) { - writer.println(" file://" + StringEscapeUtils.escapeXml(file.getPath()) + ""); - } - writer.println(" "); - writer.println(""); - - if (writer.checkError()) { - throw new IOException("Error when writing playlist."); - } - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PodcastService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PodcastService.java deleted file mode 100644 index 09184df6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/PodcastService.java +++ /dev/null @@ -1,599 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.PodcastDao; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.PodcastChannel; -import net.sourceforge.subsonic.domain.PodcastEpisode; -import net.sourceforge.subsonic.domain.PodcastStatus; -import net.sourceforge.subsonic.util.StringUtil; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.Namespace; -import org.jdom.input.SAXBuilder; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - -/** - * Provides services for Podcast reception. - * - * @author Sindre Mehus - */ -public class PodcastService { - - private static final Logger LOG = Logger.getLogger(PodcastService.class); - private static final DateFormat[] RSS_DATE_FORMATS = {new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US), - new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z", Locale.US)}; - - private static final Namespace[] ITUNES_NAMESPACES = {Namespace.getNamespace("http://www.itunes.com/DTDs/Podcast-1.0.dtd"), - Namespace.getNamespace("http://www.itunes.com/dtds/podcast-1.0.dtd")}; - - private final ExecutorService refreshExecutor; - private final ExecutorService downloadExecutor; - private final ScheduledExecutorService scheduledExecutor; - private ScheduledFuture scheduledRefresh; - private PodcastDao podcastDao; - private SettingsService settingsService; - private SecurityService securityService; - private MediaFileService mediaFileService; - - public PodcastService() { - ThreadFactory threadFactory = new ThreadFactory() { - public Thread newThread(Runnable r) { - Thread t = Executors.defaultThreadFactory().newThread(r); - t.setDaemon(true); - return t; - } - }; - refreshExecutor = Executors.newFixedThreadPool(5, threadFactory); - downloadExecutor = Executors.newFixedThreadPool(3, threadFactory); - scheduledExecutor = Executors.newSingleThreadScheduledExecutor(threadFactory); - } - - public synchronized void init() { - // Clean up partial downloads. - for (PodcastChannel channel : getAllChannels()) { - for (PodcastEpisode episode : getEpisodes(channel.getId(), false)) { - if (episode.getStatus() == PodcastStatus.DOWNLOADING) { - deleteEpisode(episode.getId(), false); - LOG.info("Deleted Podcast episode '" + episode.getTitle() + "' since download was interrupted."); - } - } - } - - schedule(); - } - - public synchronized void schedule() { - Runnable task = new Runnable() { - public void run() { - LOG.info("Starting scheduled Podcast refresh."); - refreshAllChannels(true); - LOG.info("Completed scheduled Podcast refresh."); - } - }; - - if (scheduledRefresh != null) { - scheduledRefresh.cancel(true); - } - - int hoursBetween = settingsService.getPodcastUpdateInterval(); - - if (hoursBetween == -1) { - LOG.info("Automatic Podcast update disabled."); - return; - } - - long periodMillis = hoursBetween * 60L * 60L * 1000L; - long initialDelayMillis = 5L * 60L * 1000L; - - scheduledRefresh = scheduledExecutor.scheduleAtFixedRate(task, initialDelayMillis, periodMillis, TimeUnit.MILLISECONDS); - Date firstTime = new Date(System.currentTimeMillis() + initialDelayMillis); - LOG.info("Automatic Podcast update scheduled to run every " + hoursBetween + " hour(s), starting at " + firstTime); - } - - /** - * Creates a new Podcast channel. - * - * @param url The URL of the Podcast channel. - */ - public void createChannel(String url) { - url = sanitizeUrl(url); - PodcastChannel channel = new PodcastChannel(url); - int channelId = podcastDao.createChannel(channel); - - refreshChannels(Arrays.asList(getChannel(channelId)), true); - } - - private String sanitizeUrl(String url) { - return url.replace(" ", "%20"); - } - - private PodcastChannel getChannel(int channelId) { - for (PodcastChannel channel : getAllChannels()) { - if (channelId == channel.getId()) { - return channel; - } - } - return null; - } - - /** - * Returns all Podcast channels. - * - * @return Possibly empty list of all Podcast channels. - */ - public List getAllChannels() { - return podcastDao.getAllChannels(); - } - - /** - * Returns all Podcast episodes for a given channel. - * - * @param channelId The Podcast channel ID. - * @param includeDeleted Whether to include logically deleted episodes in the result. - * @return Possibly empty list of all Podcast episodes for the given channel, sorted in - * reverse chronological order (newest episode first). - */ - public List getEpisodes(int channelId, boolean includeDeleted) { - List all = podcastDao.getEpisodes(channelId); - addMediaFileIdToEpisodes(all); - if (includeDeleted) { - return all; - } - - List filtered = new ArrayList(); - for (PodcastEpisode episode : all) { - if (episode.getStatus() != PodcastStatus.DELETED) { - filtered.add(episode); - } - } - return filtered; - } - - public PodcastEpisode getEpisode(int episodeId, boolean includeDeleted) { - PodcastEpisode episode = podcastDao.getEpisode(episodeId); - if (episode == null) { - return null; - } - if (episode.getStatus() == PodcastStatus.DELETED && !includeDeleted) { - return null; - } - addMediaFileIdToEpisodes(Arrays.asList(episode)); - return episode; - } - - private void addMediaFileIdToEpisodes(List episodes) { - for (PodcastEpisode episode : episodes) { - if (episode.getPath() != null) { - MediaFile mediaFile = mediaFileService.getMediaFile(episode.getPath()); - if (mediaFile != null) { - episode.setMediaFileId(mediaFile.getId()); - } - } - } - } - - private PodcastEpisode getEpisode(int channelId, String url) { - if (url == null) { - return null; - } - - for (PodcastEpisode episode : getEpisodes(channelId, true)) { - if (url.equals(episode.getUrl())) { - return episode; - } - } - return null; - } - - public void refreshAllChannels(boolean downloadEpisodes) { - refreshChannels(getAllChannels(), downloadEpisodes); - } - - private void refreshChannels(final List channels, final boolean downloadEpisodes) { - for (final PodcastChannel channel : channels) { - Runnable task = new Runnable() { - public void run() { - doRefreshChannel(channel, downloadEpisodes); - } - }; - refreshExecutor.submit(task); - } - } - - @SuppressWarnings({"unchecked"}) - private void doRefreshChannel(PodcastChannel channel, boolean downloadEpisodes) { - InputStream in = null; - HttpClient client = new DefaultHttpClient(); - - try { - channel.setStatus(PodcastStatus.DOWNLOADING); - channel.setErrorMessage(null); - podcastDao.updateChannel(channel); - - HttpConnectionParams.setConnectionTimeout(client.getParams(), 2 * 60 * 1000); // 2 minutes - HttpConnectionParams.setSoTimeout(client.getParams(), 10 * 60 * 1000); // 10 minutes - HttpGet method = new HttpGet(channel.getUrl()); - - HttpResponse response = client.execute(method); - in = response.getEntity().getContent(); - - Document document = new SAXBuilder().build(in); - Element channelElement = document.getRootElement().getChild("channel"); - - channel.setTitle(channelElement.getChildTextTrim("title")); - channel.setDescription(channelElement.getChildTextTrim("description")); - channel.setStatus(PodcastStatus.COMPLETED); - channel.setErrorMessage(null); - podcastDao.updateChannel(channel); - - refreshEpisodes(channel, channelElement.getChildren("item")); - - } catch (Exception x) { - LOG.warn("Failed to get/parse RSS file for Podcast channel " + channel.getUrl(), x); - channel.setStatus(PodcastStatus.ERROR); - channel.setErrorMessage(x.toString()); - podcastDao.updateChannel(channel); - } finally { - IOUtils.closeQuietly(in); - client.getConnectionManager().shutdown(); - } - - if (downloadEpisodes) { - for (final PodcastEpisode episode : getEpisodes(channel.getId(), false)) { - if (episode.getStatus() == PodcastStatus.NEW && episode.getUrl() != null) { - downloadEpisode(episode); - } - } - } - } - - public void downloadEpisode(final PodcastEpisode episode) { - Runnable task = new Runnable() { - public void run() { - doDownloadEpisode(episode); - } - }; - downloadExecutor.submit(task); - } - - private void refreshEpisodes(PodcastChannel channel, List episodeElements) { - - List episodes = new ArrayList(); - - for (Element episodeElement : episodeElements) { - - String title = episodeElement.getChildTextTrim("title"); - String duration = getITunesElement(episodeElement, "duration"); - String description = episodeElement.getChildTextTrim("description"); - if (StringUtils.isBlank(description)) { - description = getITunesElement(episodeElement, "summary"); - } - - Element enclosure = episodeElement.getChild("enclosure"); - if (enclosure == null) { - LOG.debug("No enclosure found for episode " + title); - continue; - } - - String url = enclosure.getAttributeValue("url"); - url = sanitizeUrl(url); - if (url == null) { - LOG.debug("No enclosure URL found for episode " + title); - continue; - } - - if (getEpisode(channel.getId(), url) == null) { - Long length = null; - try { - length = new Long(enclosure.getAttributeValue("length")); - } catch (Exception x) { - LOG.warn("Failed to parse enclosure length.", x); - } - - Date date = parseDate(episodeElement.getChildTextTrim("pubDate")); - PodcastEpisode episode = new PodcastEpisode(null, channel.getId(), url, null, title, description, date, - duration, length, 0L, PodcastStatus.NEW, null); - episodes.add(episode); - LOG.info("Created Podcast episode " + title); - } - } - - // Sort episode in reverse chronological order (newest first) - Collections.sort(episodes, new Comparator() { - public int compare(PodcastEpisode a, PodcastEpisode b) { - long timeA = a.getPublishDate() == null ? 0L : a.getPublishDate().getTime(); - long timeB = b.getPublishDate() == null ? 0L : b.getPublishDate().getTime(); - - if (timeA < timeB) { - return 1; - } - if (timeA > timeB) { - return -1; - } - return 0; - } - }); - - // Create episodes in database, skipping the proper number of episodes. - int downloadCount = settingsService.getPodcastEpisodeDownloadCount(); - if (downloadCount == -1) { - downloadCount = Integer.MAX_VALUE; - } - - for (int i = 0; i < episodes.size(); i++) { - PodcastEpisode episode = episodes.get(i); - if (i >= downloadCount) { - episode.setStatus(PodcastStatus.SKIPPED); - } - podcastDao.createEpisode(episode); - } - } - - private Date parseDate(String s) { - for (DateFormat dateFormat : RSS_DATE_FORMATS) { - try { - return dateFormat.parse(s); - } catch (Exception x) { - // Ignored. - } - } - LOG.warn("Failed to parse publish date: '" + s + "'."); - return null; - } - - private String getITunesElement(Element element, String childName) { - for (Namespace ns : ITUNES_NAMESPACES) { - String value = element.getChildTextTrim(childName, ns); - if (value != null) { - return value; - } - } - return null; - } - - private void doDownloadEpisode(PodcastEpisode episode) { - InputStream in = null; - OutputStream out = null; - - if (getEpisode(episode.getId(), false) == null) { - LOG.info("Podcast " + episode.getUrl() + " was deleted. Aborting download."); - return; - } - - LOG.info("Starting to download Podcast from " + episode.getUrl()); - - HttpClient client = new DefaultHttpClient(); - try { - PodcastChannel channel = getChannel(episode.getChannelId()); - - HttpConnectionParams.setConnectionTimeout(client.getParams(), 2 * 60 * 1000); // 2 minutes - HttpConnectionParams.setSoTimeout(client.getParams(), 10 * 60 * 1000); // 10 minutes - HttpGet method = new HttpGet(episode.getUrl()); - - HttpResponse response = client.execute(method); - in = response.getEntity().getContent(); - - File file = getFile(channel, episode); - out = new FileOutputStream(file); - - episode.setStatus(PodcastStatus.DOWNLOADING); - episode.setBytesDownloaded(0L); - episode.setErrorMessage(null); - episode.setPath(file.getPath()); - podcastDao.updateEpisode(episode); - - byte[] buffer = new byte[4096]; - long bytesDownloaded = 0; - int n; - long nextLogCount = 30000L; - - while ((n = in.read(buffer)) != -1) { - out.write(buffer, 0, n); - bytesDownloaded += n; - - if (bytesDownloaded > nextLogCount) { - episode.setBytesDownloaded(bytesDownloaded); - nextLogCount += 30000L; - if (getEpisode(episode.getId(), false) == null) { - break; - } - podcastDao.updateEpisode(episode); - } - } - - if (getEpisode(episode.getId(), false) == null) { - LOG.info("Podcast " + episode.getUrl() + " was deleted. Aborting download."); - IOUtils.closeQuietly(out); - file.delete(); - } else { - episode.setBytesDownloaded(bytesDownloaded); - podcastDao.updateEpisode(episode); - LOG.info("Downloaded " + bytesDownloaded + " bytes from Podcast " + episode.getUrl()); - IOUtils.closeQuietly(out); - episode.setStatus(PodcastStatus.COMPLETED); - podcastDao.updateEpisode(episode); - deleteObsoleteEpisodes(channel); - } - - } catch (Exception x) { - LOG.warn("Failed to download Podcast from " + episode.getUrl(), x); - episode.setStatus(PodcastStatus.ERROR); - episode.setErrorMessage(x.toString()); - podcastDao.updateEpisode(episode); - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - client.getConnectionManager().shutdown(); - } - } - - private synchronized void deleteObsoleteEpisodes(PodcastChannel channel) { - int episodeCount = settingsService.getPodcastEpisodeRetentionCount(); - if (episodeCount == -1) { - return; - } - - List episodes = getEpisodes(channel.getId(), false); - - // Don't do anything if other episodes of the same channel is currently downloading. - for (PodcastEpisode episode : episodes) { - if (episode.getStatus() == PodcastStatus.DOWNLOADING) { - return; - } - } - - // Reverse array to get chronological order (oldest episodes first). - Collections.reverse(episodes); - - int episodesToDelete = Math.max(0, episodes.size() - episodeCount); - for (int i = 0; i < episodesToDelete; i++) { - deleteEpisode(episodes.get(i).getId(), true); - LOG.info("Deleted old Podcast episode " + episodes.get(i).getUrl()); - } - } - - private synchronized File getFile(PodcastChannel channel, PodcastEpisode episode) { - - File podcastDir = new File(settingsService.getPodcastFolder()); - File channelDir = new File(podcastDir, StringUtil.fileSystemSafe(channel.getTitle())); - - if (!channelDir.exists()) { - boolean ok = channelDir.mkdirs(); - if (!ok) { - throw new RuntimeException("Failed to create directory " + channelDir); - } - - MediaFile mediaFile = mediaFileService.getMediaFile(channelDir); - mediaFile.setComment(channel.getDescription()); - mediaFileService.updateMediaFile(mediaFile); - } - - String filename = StringUtil.getUrlFile(episode.getUrl()); - if (filename == null) { - filename = episode.getTitle(); - } - filename = StringUtil.fileSystemSafe(filename); - String extension = FilenameUtils.getExtension(filename); - filename = FilenameUtils.removeExtension(filename); - if (StringUtils.isBlank(extension)) { - extension = "mp3"; - } - - File file = new File(channelDir, filename + "." + extension); - for (int i = 0; file.exists(); i++) { - file = new File(channelDir, filename + i + "." + extension); - } - - if (!securityService.isWriteAllowed(file)) { - throw new SecurityException("Access denied to file " + file); - } - return file; - } - - /** - * Deletes the Podcast channel with the given ID. - * - * @param channelId The Podcast channel ID. - */ - public void deleteChannel(int channelId) { - // Delete all associated episodes (in case they have files that need to be deleted). - List episodes = getEpisodes(channelId, false); - for (PodcastEpisode episode : episodes) { - deleteEpisode(episode.getId(), false); - } - podcastDao.deleteChannel(channelId); - } - - /** - * Deletes the Podcast episode with the given ID. - * - * @param episodeId The Podcast episode ID. - * @param logicalDelete Whether to perform a logical delete by setting the - * episode status to {@link PodcastStatus#DELETED}. - */ - public void deleteEpisode(int episodeId, boolean logicalDelete) { - PodcastEpisode episode = podcastDao.getEpisode(episodeId); - if (episode == null) { - return; - } - - // Delete file. - if (episode.getPath() != null) { - File file = new File(episode.getPath()); - if (file.exists()) { - file.delete(); - // TODO: Delete directory if empty? - } - } - - if (logicalDelete) { - episode.setStatus(PodcastStatus.DELETED); - episode.setErrorMessage(null); - podcastDao.updateEpisode(episode); - } else { - podcastDao.deleteEpisode(episodeId); - } - } - - public void setPodcastDao(PodcastDao podcastDao) { - this.podcastDao = podcastDao; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/RatingService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/RatingService.java deleted file mode 100644 index 6208faf2..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/RatingService.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sourceforge.subsonic.dao.*; -import net.sourceforge.subsonic.domain.*; -import net.sourceforge.subsonic.util.FileUtil; - -import java.util.*; -import java.io.File; - -/** - * Provides services for user ratings. - * - * @author Sindre Mehus - */ -public class RatingService { - - private RatingDao ratingDao; - private SecurityService securityService; - private MediaFileService mediaFileService; - - /** - * Returns the highest rated music files. - * - * @param offset Number of files to skip. - * @param count Maximum number of files to return. - * @return The highest rated music files. - */ - public List getHighestRated(int offset, int count) { - List highestRated = ratingDao.getHighestRated(offset, count); - List result = new ArrayList(); - for (String path : highestRated) { - File file = new File(path); - if (FileUtil.exists(file) && securityService.isReadAllowed(file)) { - result.add(mediaFileService.getMediaFile(path)); - } - } - return result; - } - - /** - * Sets the rating for a music file and a given user. - * - * @param username The user name. - * @param mediaFile The music file. - * @param rating The rating between 1 and 5, or null to remove the rating. - */ - public void setRatingForUser(String username, MediaFile mediaFile, Integer rating) { - ratingDao.setRatingForUser(username, mediaFile, rating); - } - - /** - * Returns the average rating for the given music file. - * - * @param mediaFile The music file. - * @return The average rating, or null if no ratings are set. - */ - public Double getAverageRating(MediaFile mediaFile) { - return ratingDao.getAverageRating(mediaFile); - } - - /** - * Returns the rating for the given user and music file. - * - * @param username The user name. - * @param mediaFile The music file. - * @return The rating, or null if no rating is set. - */ - public Integer getRatingForUser(String username, MediaFile mediaFile) { - return ratingDao.getRatingForUser(username, mediaFile); - } - - public void setRatingDao(RatingDao ratingDao) { - this.ratingDao = ratingDao; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SearchService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SearchService.java deleted file mode 100644 index 2698bbd6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SearchService.java +++ /dev/null @@ -1,567 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.AlbumDao; -import net.sourceforge.subsonic.dao.ArtistDao; -import net.sourceforge.subsonic.domain.Album; -import net.sourceforge.subsonic.domain.Artist; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.RandomSearchCriteria; -import net.sourceforge.subsonic.domain.SearchCriteria; -import net.sourceforge.subsonic.domain.SearchResult; -import net.sourceforge.subsonic.util.FileUtil; -import org.apache.lucene.analysis.ASCIIFoldingFilter; -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.analysis.LowerCaseFilter; -import org.apache.lucene.analysis.StopFilter; -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.analysis.standard.StandardAnalyzer; -import org.apache.lucene.analysis.standard.StandardFilter; -import org.apache.lucene.analysis.standard.StandardTokenizer; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.document.NumericField; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.Term; -import org.apache.lucene.queryParser.MultiFieldQueryParser; -import org.apache.lucene.search.BooleanClause; -import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.NumericRangeQuery; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.Searcher; -import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.TopDocs; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.FSDirectory; -import org.apache.lucene.util.Version; - -import java.io.File; -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import static net.sourceforge.subsonic.service.SearchService.IndexType.*; -import static net.sourceforge.subsonic.service.SearchService.IndexType.SONG; - -/** - * Performs Lucene-based searching and indexing. - * - * @author Sindre Mehus - * @version $Id$ - * @see MediaScannerService - */ -public class SearchService { - - private static final Logger LOG = Logger.getLogger(SearchService.class); - - private static final String FIELD_ID = "id"; - private static final String FIELD_TITLE = "title"; - private static final String FIELD_ALBUM = "album"; - private static final String FIELD_ARTIST = "artist"; - private static final String FIELD_GENRE = "genre"; - private static final String FIELD_YEAR = "year"; - private static final String FIELD_MEDIA_TYPE = "mediaType"; - private static final String FIELD_FOLDER = "folder"; - - private static final Version LUCENE_VERSION = Version.LUCENE_30; - - private MediaFileService mediaFileService; - private SettingsService settingsService; - private ArtistDao artistDao; - private AlbumDao albumDao; - - private IndexWriter artistWriter; - private IndexWriter artistId3Writer; - private IndexWriter albumWriter; - private IndexWriter albumId3Writer; - private IndexWriter songWriter; - - public SearchService() { - removeLocks(); - } - - - public void startIndexing() { - try { - artistWriter = createIndexWriter(ARTIST); - artistId3Writer = createIndexWriter(ARTIST_ID3); - albumWriter = createIndexWriter(ALBUM); - albumId3Writer = createIndexWriter(ALBUM_ID3); - songWriter = createIndexWriter(SONG); - } catch (Exception x) { - LOG.error("Failed to create search index.", x); - } - } - - public void index(MediaFile mediaFile) { - try { - if (mediaFile.isFile()) { - songWriter.addDocument(SONG.createDocument(mediaFile)); - } else if (mediaFile.isAlbum()) { - albumWriter.addDocument(ALBUM.createDocument(mediaFile)); - } else { - artistWriter.addDocument(ARTIST.createDocument(mediaFile)); - } - } catch (Exception x) { - LOG.error("Failed to create search index for " + mediaFile, x); - } - } - - public void index(Artist artist) { - try { - artistId3Writer.addDocument(ARTIST_ID3.createDocument(artist)); - } catch (Exception x) { - LOG.error("Failed to create search index for " + artist, x); - } - } - - public void index(Album album) { - try { - albumId3Writer.addDocument(ALBUM_ID3.createDocument(album)); - } catch (Exception x) { - LOG.error("Failed to create search index for " + album, x); - } - } - - public void stopIndexing() { - try { - artistWriter.optimize(); - artistId3Writer.optimize(); - albumWriter.optimize(); - albumId3Writer.optimize(); - songWriter.optimize(); - } catch (Exception x) { - LOG.error("Failed to create search index.", x); - } finally { - FileUtil.closeQuietly(artistId3Writer); - FileUtil.closeQuietly(artistWriter); - FileUtil.closeQuietly(albumWriter); - FileUtil.closeQuietly(albumId3Writer); - FileUtil.closeQuietly(songWriter); - } - } - - public SearchResult search(SearchCriteria criteria, IndexType indexType) { - SearchResult result = new SearchResult(); - int offset = criteria.getOffset(); - int count = criteria.getCount(); - result.setOffset(offset); - - IndexReader reader = null; - try { - reader = createIndexReader(indexType); - Searcher searcher = new IndexSearcher(reader); - Analyzer analyzer = new SubsonicAnalyzer(); - - MultiFieldQueryParser queryParser = new MultiFieldQueryParser(LUCENE_VERSION, indexType.getFields(), analyzer, indexType.getBoosts()); - Query query = queryParser.parse(criteria.getQuery()); - - TopDocs topDocs = searcher.search(query, null, offset + count); - result.setTotalHits(topDocs.totalHits); - - int start = Math.min(offset, topDocs.totalHits); - int end = Math.min(start + count, topDocs.totalHits); - for (int i = start; i < end; i++) { - Document doc = searcher.doc(topDocs.scoreDocs[i].doc); - switch (indexType) { - case SONG: - case ARTIST: - case ALBUM: - MediaFile mediaFile = mediaFileService.getMediaFile(Integer.valueOf(doc.get(FIELD_ID))); - addIfNotNull(mediaFile, result.getMediaFiles()); - break; - case ARTIST_ID3: - Artist artist = artistDao.getArtist(Integer.valueOf(doc.get(FIELD_ID))); - addIfNotNull(artist, result.getArtists()); - break; - case ALBUM_ID3: - Album album = albumDao.getAlbum(Integer.valueOf(doc.get(FIELD_ID))); - addIfNotNull(album, result.getAlbums()); - break; - default: - break; - } - } - - } catch (Throwable x) { - LOG.error("Failed to execute Lucene search.", x); - } finally { - FileUtil.closeQuietly(reader); - } - return result; - } - - /** - * Returns a number of random songs. - * - * @param criteria Search criteria. - * @return List of random songs. - */ - public List getRandomSongs(RandomSearchCriteria criteria) { - List result = new ArrayList(); - - String musicFolderPath = null; - if (criteria.getMusicFolderId() != null) { - MusicFolder musicFolder = settingsService.getMusicFolderById(criteria.getMusicFolderId()); - musicFolderPath = musicFolder.getPath().getPath(); - } - - IndexReader reader = null; - try { - reader = createIndexReader(SONG); - Searcher searcher = new IndexSearcher(reader); - - BooleanQuery query = new BooleanQuery(); - query.add(new TermQuery(new Term(FIELD_MEDIA_TYPE, MediaFile.MediaType.MUSIC.name().toLowerCase())), BooleanClause.Occur.MUST); - if (criteria.getGenre() != null) { - String genre = normalizeGenre(criteria.getGenre()); - query.add(new TermQuery(new Term(FIELD_GENRE, genre)), BooleanClause.Occur.MUST); - } - if (criteria.getFromYear() != null || criteria.getToYear() != null) { - NumericRangeQuery rangeQuery = NumericRangeQuery.newIntRange(FIELD_YEAR, criteria.getFromYear(), criteria.getToYear(), true, true); - query.add(rangeQuery, BooleanClause.Occur.MUST); - } - if (musicFolderPath != null) { - query.add(new TermQuery(new Term(FIELD_FOLDER, musicFolderPath)), BooleanClause.Occur.MUST); - } - - TopDocs topDocs = searcher.search(query, null, Integer.MAX_VALUE); - Random random = new Random(System.currentTimeMillis()); - - for (int i = 0; i < Math.min(criteria.getCount(), topDocs.totalHits); i++) { - int index = random.nextInt(topDocs.totalHits); - Document doc = searcher.doc(topDocs.scoreDocs[index].doc); - int id = Integer.valueOf(doc.get(FIELD_ID)); - try { - result.add(mediaFileService.getMediaFile(id)); - } catch (Exception x) { - LOG.warn("Failed to get media file " + id); - } - } - - } catch (Throwable x) { - LOG.error("Failed to search or random songs.", x); - } finally { - FileUtil.closeQuietly(reader); - } - return result; - } - - private static String normalizeGenre(String genre) { - return genre.toLowerCase().replace(" ", ""); - } - - /** - * Returns a number of random albums. - * - * @param count Number of albums to return. - * @return List of random albums. - */ - public List getRandomAlbums(int count) { - List result = new ArrayList(); - - IndexReader reader = null; - try { - reader = createIndexReader(ALBUM); - Searcher searcher = new IndexSearcher(reader); - - Query query = new MatchAllDocsQuery(); - TopDocs topDocs = searcher.search(query, null, Integer.MAX_VALUE); - Random random = new Random(System.currentTimeMillis()); - - for (int i = 0; i < Math.min(count, topDocs.totalHits); i++) { - int index = random.nextInt(topDocs.totalHits); - Document doc = searcher.doc(topDocs.scoreDocs[index].doc); - int id = Integer.valueOf(doc.get(FIELD_ID)); - try { - addIfNotNull(mediaFileService.getMediaFile(id), result); - } catch (Exception x) { - LOG.warn("Failed to get media file " + id, x); - } - } - - } catch (Throwable x) { - LOG.error("Failed to search for random albums.", x); - } finally { - FileUtil.closeQuietly(reader); - } - return result; - } - - /** - * Returns a number of random albums, using ID3 tag. - * - * @param count Number of albums to return. - * @return List of random albums. - */ - public List getRandomAlbumsId3(int count) { - List result = new ArrayList(); - - IndexReader reader = null; - try { - reader = createIndexReader(ALBUM_ID3); - Searcher searcher = new IndexSearcher(reader); - - Query query = new MatchAllDocsQuery(); - TopDocs topDocs = searcher.search(query, null, Integer.MAX_VALUE); - Random random = new Random(System.currentTimeMillis()); - - for (int i = 0; i < Math.min(count, topDocs.totalHits); i++) { - int index = random.nextInt(topDocs.totalHits); - Document doc = searcher.doc(topDocs.scoreDocs[index].doc); - int id = Integer.valueOf(doc.get(FIELD_ID)); - try { - addIfNotNull(albumDao.getAlbum(id), result); - } catch (Exception x) { - LOG.warn("Failed to get album file " + id, x); - } - } - - } catch (Throwable x) { - LOG.error("Failed to search for random albums.", x); - } finally { - FileUtil.closeQuietly(reader); - } - return result; - } - - private void addIfNotNull(T value, List list) { - if (value != null) { - list.add(value); - } - } - private IndexWriter createIndexWriter(IndexType indexType) throws IOException { - File dir = getIndexDirectory(indexType); - return new IndexWriter(FSDirectory.open(dir), new SubsonicAnalyzer(), true, new IndexWriter.MaxFieldLength(10)); - } - - private IndexReader createIndexReader(IndexType indexType) throws IOException { - File dir = getIndexDirectory(indexType); - return IndexReader.open(FSDirectory.open(dir), true); - } - - private File getIndexRootDirectory() { - return new File(SettingsService.getSubsonicHome(), "lucene2"); - } - - private File getIndexDirectory(IndexType indexType) { - return new File(getIndexRootDirectory(), indexType.toString().toLowerCase()); - } - - private void removeLocks() { - for (IndexType indexType : IndexType.values()) { - Directory dir = null; - try { - dir = FSDirectory.open(getIndexDirectory(indexType)); - if (IndexWriter.isLocked(dir)) { - IndexWriter.unlock(dir); - LOG.info("Removed Lucene lock file in " + dir); - } - } catch (Exception x) { - LOG.warn("Failed to remove Lucene lock file in " + dir, x); - } finally { - FileUtil.closeQuietly(dir); - } - } - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setArtistDao(ArtistDao artistDao) { - this.artistDao = artistDao; - } - - public void setAlbumDao(AlbumDao albumDao) { - this.albumDao = albumDao; - } - - public static enum IndexType { - - SONG(new String[]{FIELD_TITLE, FIELD_ARTIST}, FIELD_TITLE) { - @Override - public Document createDocument(MediaFile mediaFile) { - Document doc = new Document(); - doc.add(new NumericField(FIELD_ID, Field.Store.YES, false).setIntValue(mediaFile.getId())); - doc.add(new Field(FIELD_MEDIA_TYPE, mediaFile.getMediaType().name(), Field.Store.NO, Field.Index.ANALYZED_NO_NORMS)); - - if (mediaFile.getTitle() != null) { - doc.add(new Field(FIELD_TITLE, mediaFile.getTitle(), Field.Store.YES, Field.Index.ANALYZED)); - } - if (mediaFile.getArtist() != null) { - doc.add(new Field(FIELD_ARTIST, mediaFile.getArtist(), Field.Store.YES, Field.Index.ANALYZED)); - } - if (mediaFile.getGenre() != null) { - doc.add(new Field(FIELD_GENRE, normalizeGenre(mediaFile.getGenre()), Field.Store.NO, Field.Index.ANALYZED)); - } - if (mediaFile.getYear() != null) { - doc.add(new NumericField(FIELD_YEAR, Field.Store.NO, true).setIntValue(mediaFile.getYear())); - } - if (mediaFile.getFolder() != null) { - doc.add(new Field(FIELD_FOLDER, mediaFile.getFolder(), Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS)); - } - - return doc; - } - }, - - ALBUM(new String[]{FIELD_ALBUM, FIELD_ARTIST}, FIELD_ALBUM) { - @Override - public Document createDocument(MediaFile mediaFile) { - Document doc = new Document(); - doc.add(new NumericField(FIELD_ID, Field.Store.YES, false).setIntValue(mediaFile.getId())); - - if (mediaFile.getArtist() != null) { - doc.add(new Field(FIELD_ARTIST, mediaFile.getArtist(), Field.Store.YES, Field.Index.ANALYZED)); - } - if (mediaFile.getAlbumName() != null) { - doc.add(new Field(FIELD_ALBUM, mediaFile.getAlbumName(), Field.Store.YES, Field.Index.ANALYZED)); - } - - return doc; - } - }, - - ALBUM_ID3(new String[]{FIELD_ALBUM, FIELD_ARTIST}, FIELD_ALBUM) { - @Override - public Document createDocument(Album album) { - Document doc = new Document(); - doc.add(new NumericField(FIELD_ID, Field.Store.YES, false).setIntValue(album.getId())); - - if (album.getArtist() != null) { - doc.add(new Field(FIELD_ARTIST, album.getArtist(), Field.Store.YES, Field.Index.ANALYZED)); - } - if (album.getName() != null) { - doc.add(new Field(FIELD_ALBUM, album.getName(), Field.Store.YES, Field.Index.ANALYZED)); - } - - return doc; - } - }, - - ARTIST(new String[]{FIELD_ARTIST}, null) { - @Override - public Document createDocument(MediaFile mediaFile) { - Document doc = new Document(); - doc.add(new NumericField(FIELD_ID, Field.Store.YES, false).setIntValue(mediaFile.getId())); - - if (mediaFile.getArtist() != null) { - doc.add(new Field(FIELD_ARTIST, mediaFile.getArtist(), Field.Store.YES, Field.Index.ANALYZED)); - } - - return doc; - } - }, - - ARTIST_ID3(new String[]{FIELD_ARTIST}, null) { - @Override - public Document createDocument(Artist artist) { - Document doc = new Document(); - doc.add(new NumericField(FIELD_ID, Field.Store.YES, false).setIntValue(artist.getId())); - doc.add(new Field(FIELD_ARTIST, artist.getName(), Field.Store.YES, Field.Index.ANALYZED)); - - return doc; - } - }; - - private final String[] fields; - private final Map boosts; - - private IndexType(String[] fields, String boostedField) { - this.fields = fields; - boosts = new HashMap(); - if (boostedField != null) { - boosts.put(boostedField, 2.0F); - } - } - - public String[] getFields() { - return fields; - } - - protected Document createDocument(MediaFile mediaFile) { - throw new UnsupportedOperationException(); - } - - protected Document createDocument(Artist artist) { - throw new UnsupportedOperationException(); - } - - protected Document createDocument(Album album) { - throw new UnsupportedOperationException(); - } - - public Map getBoosts() { - return boosts; - } - } - - private class SubsonicAnalyzer extends StandardAnalyzer { - private SubsonicAnalyzer() { - super(LUCENE_VERSION); - } - - @Override - public TokenStream tokenStream(String fieldName, Reader reader) { - TokenStream result = super.tokenStream(fieldName, reader); - return new ASCIIFoldingFilter(result); - } - - @Override - public TokenStream reusableTokenStream(String fieldName, Reader reader) throws IOException { - class SavedStreams { - StandardTokenizer tokenStream; - TokenStream filteredTokenStream; - } - - SavedStreams streams = (SavedStreams) getPreviousTokenStream(); - if (streams == null) { - streams = new SavedStreams(); - setPreviousTokenStream(streams); - streams.tokenStream = new StandardTokenizer(LUCENE_VERSION, reader); - streams.filteredTokenStream = new StandardFilter(streams.tokenStream); - streams.filteredTokenStream = new LowerCaseFilter(streams.filteredTokenStream); - streams.filteredTokenStream = new StopFilter(true, streams.filteredTokenStream, STOP_WORDS_SET); - streams.filteredTokenStream = new ASCIIFoldingFilter(streams.filteredTokenStream); - } else { - streams.tokenStream.reset(reader); - } - streams.tokenStream.setMaxTokenLength(DEFAULT_MAX_TOKEN_LENGTH); - - return streams.filteredTokenStream; - } - } -} - - diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SecurityService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SecurityService.java deleted file mode 100644 index d6ca871d..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SecurityService.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import java.io.File; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -import org.acegisecurity.GrantedAuthority; -import org.acegisecurity.GrantedAuthorityImpl; -import org.acegisecurity.providers.dao.DaoAuthenticationProvider; -import org.acegisecurity.userdetails.UserDetails; -import org.acegisecurity.userdetails.UserDetailsService; -import org.acegisecurity.userdetails.UsernameNotFoundException; -import org.acegisecurity.wrapper.SecurityContextHolderAwareRequestWrapper; -import org.springframework.dao.DataAccessException; - -import net.sf.ehcache.Ehcache; -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.UserDao; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.User; -import net.sourceforge.subsonic.util.FileUtil; - -/** - * Provides security-related services for authentication and authorization. - * - * @author Sindre Mehus - */ -public class SecurityService implements UserDetailsService { - - private static final Logger LOG = Logger.getLogger(SecurityService.class); - - private UserDao userDao; - private SettingsService settingsService; - private Ehcache userCache; - - /** - * Locates the user based on the username. - * - * @param username The username presented to the {@link DaoAuthenticationProvider} - * @return A fully populated user record (never null) - * @throws UsernameNotFoundException if the user could not be found or the user has no GrantedAuthority. - * @throws DataAccessException If user could not be found for a repository-specific reason. - */ - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { - User user = getUserByName(username); - if (user == null) { - throw new UsernameNotFoundException("User \"" + username + "\" was not found."); - } - - String[] roles = userDao.getRolesForUser(username); - GrantedAuthority[] authorities = new GrantedAuthority[roles.length]; - for (int i = 0; i < roles.length; i++) { - authorities[i] = new GrantedAuthorityImpl("ROLE_" + roles[i].toUpperCase()); - } - - // If user is LDAP authenticated, disable user. The proper authentication should in that case - // be done by SubsonicLdapBindAuthenticator. - boolean enabled = !user.isLdapAuthenticated(); - - return new org.acegisecurity.userdetails.User(username, user.getPassword(), enabled, true, true, true, authorities); - } - - /** - * Returns the currently logged-in user for the given HTTP request. - * - * @param request The HTTP request. - * @return The logged-in user, or null. - */ - public User getCurrentUser(HttpServletRequest request) { - String username = getCurrentUsername(request); - return username == null ? null : userDao.getUserByName(username); - } - - /** - * Returns the name of the currently logged-in user. - * - * @param request The HTTP request. - * @return The name of the logged-in user, or null. - */ - public String getCurrentUsername(HttpServletRequest request) { - return new SecurityContextHolderAwareRequestWrapper(request, null).getRemoteUser(); - } - - /** - * Returns the user with the given username. - * - * @param username The username used when logging in. - * @return The user, or null if not found. - */ - public User getUserByName(String username) { - return userDao.getUserByName(username); - } - - /** - * Returns the user with the given email address. - * - * @param email The email address. - * @return The user, or null if not found. - */ - public User getUserByEmail(String email) { - return userDao.getUserByEmail(email); - } - - /** - * Returns all users. - * - * @return Possibly empty array of all users. - */ - public List getAllUsers() { - return userDao.getAllUsers(); - } - - /** - * Returns whether the given user has administrative rights. - */ - public boolean isAdmin(String username) { - if (User.USERNAME_ADMIN.equals(username)) { - return true; - } - User user = getUserByName(username); - return user != null && user.isAdminRole(); - } - - /** - * Creates a new user. - * - * @param user The user to create. - */ - public void createUser(User user) { - userDao.createUser(user); - LOG.info("Created user " + user.getUsername()); - } - - /** - * Deletes the user with the given username. - * - * @param username The username. - */ - public void deleteUser(String username) { - userDao.deleteUser(username); - LOG.info("Deleted user " + username); - userCache.remove(username); - } - - /** - * Updates the given user. - * - * @param user The user to update. - */ - public void updateUser(User user) { - userDao.updateUser(user); - userCache.remove(user.getUsername()); - } - - /** - * Updates the byte counts for given user. - * - * @param user The user to update, may be null. - * @param bytesStreamedDelta Increment bytes streamed count with this value. - * @param bytesDownloadedDelta Increment bytes downloaded count with this value. - * @param bytesUploadedDelta Increment bytes uploaded count with this value. - */ - public void updateUserByteCounts(User user, long bytesStreamedDelta, long bytesDownloadedDelta, long bytesUploadedDelta) { - if (user == null) { - return; - } - - user.setBytesStreamed(user.getBytesStreamed() + bytesStreamedDelta); - user.setBytesDownloaded(user.getBytesDownloaded() + bytesDownloadedDelta); - user.setBytesUploaded(user.getBytesUploaded() + bytesUploadedDelta); - - userDao.updateUser(user); - } - - /** - * Returns whether the given file may be read. - * - * @return Whether the given file may be read. - */ - public boolean isReadAllowed(File file) { - // Allowed to read from both music folder and podcast folder. - return isInMusicFolder(file) || isInPodcastFolder(file); - } - - /** - * Returns whether the given file may be written, created or deleted. - * - * @return Whether the given file may be written, created or deleted. - */ - public boolean isWriteAllowed(File file) { - // Only allowed to write podcasts or cover art. - boolean isPodcast = isInPodcastFolder(file); - boolean isCoverArt = isInMusicFolder(file) && file.getName().startsWith("cover."); - - return isPodcast || isCoverArt; - } - - /** - * Returns whether the given file may be uploaded. - * - * @return Whether the given file may be uploaded. - */ - public boolean isUploadAllowed(File file) { - return isInMusicFolder(file) && !FileUtil.exists(file); - } - - /** - * Returns whether the given file is located in one of the music folders (or any of their sub-folders). - * - * @param file The file in question. - * @return Whether the given file is located in one of the music folders. - */ - private boolean isInMusicFolder(File file) { - return getMusicFolderForFile(file) != null; - } - - private MusicFolder getMusicFolderForFile(File file) { - List folders = settingsService.getAllMusicFolders(false, true); - String path = file.getPath(); - for (MusicFolder folder : folders) { - if (isFileInFolder(path, folder.getPath().getPath())) { - return folder; - } - } - return null; - } - - /** - * Returns whether the given file is located in the Podcast folder (or any of its sub-folders). - * - * @param file The file in question. - * @return Whether the given file is located in the Podcast folder. - */ - private boolean isInPodcastFolder(File file) { - String podcastFolder = settingsService.getPodcastFolder(); - return isFileInFolder(file.getPath(), podcastFolder); - } - - public String getRootFolderForFile(File file) { - MusicFolder folder = getMusicFolderForFile(file); - if (folder != null) { - return folder.getPath().getPath(); - } - - if (isInPodcastFolder(file)) { - return settingsService.getPodcastFolder(); - } - return null; - } - - /** - * Returns whether the given file is located in the given folder (or any of its sub-folders). - * If the given file contains the expression ".." (indicating a reference to the parent directory), - * this method will return false. - * - * @param file The file in question. - * @param folder The folder in question. - * @return Whether the given file is located in the given folder. - */ - protected boolean isFileInFolder(String file, String folder) { - // Deny access if file contains ".." surrounded by slashes (or end of line). - if (file.matches(".*(/|\\\\)\\.\\.(/|\\\\|$).*")) { - return false; - } - - // Convert slashes. - file = file.replace('\\', '/'); - folder = folder.replace('\\', '/'); - - return file.toUpperCase().startsWith(folder.toUpperCase()); - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setUserDao(UserDao userDao) { - this.userDao = userDao; - } - - public void setUserCache(Ehcache userCache) { - this.userCache = userCache; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/ServiceLocator.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/ServiceLocator.java deleted file mode 100644 index 4a7f95b4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/ServiceLocator.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import javax.xml.parsers.SAXParser; - -import net.sourceforge.subsonic.service.metadata.MetaDataParserFactory; - -/** - * Locates services for objects that are not part of the Spring context. - * - * @author Sindre Mehus - */ -@Deprecated -public class ServiceLocator { - - private static SettingsService settingsService; - - private ServiceLocator() { - } - - public static SettingsService getSettingsService() { - return settingsService; - } - - public static void setSettingsService(SettingsService settingsService) { - ServiceLocator.settingsService = settingsService; - } -} - diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SettingsService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SettingsService.java deleted file mode 100644 index a0b3e8d5..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/SettingsService.java +++ /dev/null @@ -1,1225 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Properties; -import java.util.StringTokenizer; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.AvatarDao; -import net.sourceforge.subsonic.dao.InternetRadioDao; -import net.sourceforge.subsonic.dao.MusicFolderDao; -import net.sourceforge.subsonic.dao.UserDao; -import net.sourceforge.subsonic.domain.Avatar; -import net.sourceforge.subsonic.domain.InternetRadio; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.domain.Theme; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.util.FileUtil; -import net.sourceforge.subsonic.util.StringUtil; -import net.sourceforge.subsonic.util.Util; - -/** - * Provides persistent storage of application settings and preferences. - * - * @author Sindre Mehus - */ -public class SettingsService { - - // Subsonic home directory. - private static final File SUBSONIC_HOME_WINDOWS = new File("c:/subsonic"); - private static final File SUBSONIC_HOME_OTHER = new File("/var/subsonic"); - - // Global settings. - private static final String KEY_INDEX_STRING = "IndexString"; - private static final String KEY_IGNORED_ARTICLES = "IgnoredArticles"; - private static final String KEY_SHORTCUTS = "Shortcuts"; - private static final String KEY_PLAYLIST_FOLDER = "PlaylistFolder"; - private static final String KEY_MUSIC_FILE_TYPES = "MusicFileTypes"; - private static final String KEY_VIDEO_FILE_TYPES = "VideoFileTypes"; - private static final String KEY_COVER_ART_FILE_TYPES = "CoverArtFileTypes"; - private static final String KEY_COVER_ART_LIMIT = "CoverArtLimit"; - private static final String KEY_WELCOME_TITLE = "WelcomeTitle"; - private static final String KEY_WELCOME_SUBTITLE = "WelcomeSubtitle"; - private static final String KEY_WELCOME_MESSAGE = "WelcomeMessage2"; - private static final String KEY_LOGIN_MESSAGE = "LoginMessage"; - private static final String KEY_LOCALE_LANGUAGE = "LocaleLanguage"; - private static final String KEY_LOCALE_COUNTRY = "LocaleCountry"; - private static final String KEY_LOCALE_VARIANT = "LocaleVariant"; - private static final String KEY_THEME_ID = "Theme"; - private static final String KEY_INDEX_CREATION_INTERVAL = "IndexCreationInterval"; - private static final String KEY_INDEX_CREATION_HOUR = "IndexCreationHour"; - private static final String KEY_FAST_CACHE_ENABLED = "FastCacheEnabled"; - private static final String KEY_PODCAST_UPDATE_INTERVAL = "PodcastUpdateInterval"; - private static final String KEY_PODCAST_FOLDER = "PodcastFolder"; - private static final String KEY_PODCAST_EPISODE_RETENTION_COUNT = "PodcastEpisodeRetentionCount"; - private static final String KEY_PODCAST_EPISODE_DOWNLOAD_COUNT = "PodcastEpisodeDownloadCount"; - private static final String KEY_DOWNLOAD_BITRATE_LIMIT = "DownloadBitrateLimit"; - private static final String KEY_UPLOAD_BITRATE_LIMIT = "UploadBitrateLimit"; - private static final String KEY_STREAM_PORT = "StreamPort"; - private static final String KEY_LICENSE_EMAIL = "LicenseEmail"; - private static final String KEY_LICENSE_CODE = "LicenseCode"; - private static final String KEY_LICENSE_DATE = "LicenseDate"; - private static final String KEY_DOWNSAMPLING_COMMAND = "DownsamplingCommand3"; - private static final String KEY_JUKEBOX_COMMAND = "JukeboxCommand"; - private static final String KEY_REWRITE_URL = "RewriteUrl"; - private static final String KEY_LDAP_ENABLED = "LdapEnabled"; - private static final String KEY_LDAP_URL = "LdapUrl"; - private static final String KEY_LDAP_MANAGER_DN = "LdapManagerDn"; - private static final String KEY_LDAP_MANAGER_PASSWORD = "LdapManagerPassword"; - private static final String KEY_LDAP_SEARCH_FILTER = "LdapSearchFilter"; - private static final String KEY_LDAP_AUTO_SHADOWING = "LdapAutoShadowing"; - private static final String KEY_GETTING_STARTED_ENABLED = "GettingStartedEnabled"; - private static final String KEY_PORT_FORWARDING_ENABLED = "PortForwardingEnabled"; - private static final String KEY_PORT = "Port"; - private static final String KEY_HTTPS_PORT = "HttpsPort"; - private static final String KEY_URL_REDIRECTION_ENABLED = "UrlRedirectionEnabled"; - private static final String KEY_URL_REDIRECT_FROM = "UrlRedirectFrom"; - private static final String KEY_URL_REDIRECT_TRIAL_EXPIRES = "UrlRedirectTrialExpires"; - private static final String KEY_URL_REDIRECT_CONTEXT_PATH = "UrlRedirectContextPath"; - private static final String KEY_REST_TRIAL_EXPIRES = "RestTrialExpires-"; - private static final String KEY_VIDEO_TRIAL_EXPIRES = "VideoTrialExpires"; - private static final String KEY_SERVER_ID = "ServerId"; - private static final String KEY_SETTINGS_CHANGED = "SettingsChanged"; - private static final String KEY_LAST_SCANNED = "LastScanned"; - private static final String KEY_ORGANIZE_BY_FOLDER_STRUCTURE = "OrganizeByFolderStructure"; - private static final String KEY_SORT_ALBUMS_BY_YEAR = "SortAlbumsByYear"; - - // Default values. - private static final String DEFAULT_INDEX_STRING = "A B C D E F G H I J K L M N O P Q R S T U V W X-Z(XYZ)"; - private static final String DEFAULT_IGNORED_ARTICLES = "The El La Los Las Le Les"; - private static final String DEFAULT_SHORTCUTS = "New Incoming Podcast"; - private static final String DEFAULT_PLAYLIST_FOLDER = Util.getDefaultPlaylistFolder(); - private static final String DEFAULT_MUSIC_FILE_TYPES = "mp3 ogg oga aac m4a flac wav wma aif aiff ape mpc shn"; - private static final String DEFAULT_VIDEO_FILE_TYPES = "flv avi mpg mpeg mp4 m4v mkv mov wmv ogv divx m2ts"; - private static final String DEFAULT_COVER_ART_FILE_TYPES = "cover.jpg folder.jpg jpg jpeg gif png"; - private static final int DEFAULT_COVER_ART_LIMIT = 30; - private static final String DEFAULT_WELCOME_TITLE = "Welcome to Subsonic!"; - private static final String DEFAULT_WELCOME_SUBTITLE = null; - private static final String DEFAULT_WELCOME_MESSAGE = "__Welcome to Subsonic!__\n" + - "\\\\ \\\\\n" + - "Subsonic is a free, web-based media streamer, providing ubiquitous access to your music. \n" + - "\\\\ \\\\\n" + - "Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple " + - "players simultaneously, for instance to one player in your kitchen and another in your living room.\n" + - "\\\\ \\\\\n" + - "To change or remove this message, log in with administrator rights and go to {link:Settings > General|generalSettings.view}."; - private static final String DEFAULT_LOGIN_MESSAGE = null; - private static final String DEFAULT_LOCALE_LANGUAGE = "en"; - private static final String DEFAULT_LOCALE_COUNTRY = ""; - private static final String DEFAULT_LOCALE_VARIANT = ""; - private static final String DEFAULT_THEME_ID = "default"; - private static final int DEFAULT_INDEX_CREATION_INTERVAL = 1; - private static final int DEFAULT_INDEX_CREATION_HOUR = 3; - private static final boolean DEFAULT_FAST_CACHE_ENABLED = false; - private static final int DEFAULT_PODCAST_UPDATE_INTERVAL = 24; - private static final String DEFAULT_PODCAST_FOLDER = Util.getDefaultPodcastFolder(); - private static final int DEFAULT_PODCAST_EPISODE_RETENTION_COUNT = 10; - private static final int DEFAULT_PODCAST_EPISODE_DOWNLOAD_COUNT = 1; - private static final long DEFAULT_DOWNLOAD_BITRATE_LIMIT = 0; - private static final long DEFAULT_UPLOAD_BITRATE_LIMIT = 0; - private static final long DEFAULT_STREAM_PORT = 0; - private static final String DEFAULT_LICENSE_EMAIL = null; - private static final String DEFAULT_LICENSE_CODE = null; - private static final String DEFAULT_LICENSE_DATE = null; - private static final String DEFAULT_DOWNSAMPLING_COMMAND = "ffmpeg -i %s -ab %bk -v 0 -f mp3 -"; - private static final String DEFAULT_JUKEBOX_COMMAND = "ffmpeg -ss %o -i %s -v 0 -f au -"; - private static final boolean DEFAULT_REWRITE_URL = true; - private static final boolean DEFAULT_LDAP_ENABLED = false; - private static final String DEFAULT_LDAP_URL = "ldap://host.domain.com:389/cn=Users,dc=domain,dc=com"; - private static final String DEFAULT_LDAP_MANAGER_DN = null; - private static final String DEFAULT_LDAP_MANAGER_PASSWORD = null; - private static final String DEFAULT_LDAP_SEARCH_FILTER = "(sAMAccountName={0})"; - private static final boolean DEFAULT_LDAP_AUTO_SHADOWING = false; - private static final boolean DEFAULT_PORT_FORWARDING_ENABLED = false; - private static final boolean DEFAULT_GETTING_STARTED_ENABLED = true; - private static final int DEFAULT_PORT = 80; - private static final int DEFAULT_HTTPS_PORT = 0; - private static final boolean DEFAULT_URL_REDIRECTION_ENABLED = false; - private static final String DEFAULT_URL_REDIRECT_FROM = "yourname"; - private static final String DEFAULT_URL_REDIRECT_TRIAL_EXPIRES = null; - private static final String DEFAULT_URL_REDIRECT_CONTEXT_PATH = null; - private static final String DEFAULT_REST_TRIAL_EXPIRES = null; - private static final String DEFAULT_VIDEO_TRIAL_EXPIRES = null; - private static final String DEFAULT_SERVER_ID = null; - private static final long DEFAULT_SETTINGS_CHANGED = 0L; - private static final boolean DEFAULT_ORGANIZE_BY_FOLDER_STRUCTURE = true; - private static final boolean DEFAULT_SORT_ALBUMS_BY_YEAR = true; - - // Array of obsolete keys. Used to clean property file. - private static final List OBSOLETE_KEYS = Arrays.asList("PortForwardingPublicPort", "PortForwardingLocalPort", - "DownsamplingCommand", "DownsamplingCommand2", "AutoCoverBatch", "MusicMask", "VideoMask", "CoverArtMask"); - - private static final String LOCALES_FILE = "/net/sourceforge/subsonic/i18n/locales.txt"; - private static final String THEMES_FILE = "/net/sourceforge/subsonic/theme/themes.txt"; - - private static final Logger LOG = Logger.getLogger(SettingsService.class); - - private Properties properties = new Properties(); - private List themes; - private List locales; - private InternetRadioDao internetRadioDao; - private MusicFolderDao musicFolderDao; - private UserDao userDao; - private AvatarDao avatarDao; - private VersionService versionService; - - private String[] cachedCoverArtFileTypesArray; - private String[] cachedMusicFileTypesArray; - private String[] cachedVideoFileTypesArray; - private List cachedMusicFolders; - - private static File subsonicHome; - - private boolean licenseValidated = true; - - public SettingsService() { - File propertyFile = getPropertyFile(); - - if (propertyFile.exists()) { - FileInputStream in = null; - try { - in = new FileInputStream(propertyFile); - properties.load(in); - } catch (Exception x) { - LOG.error("Unable to read from property file.", x); - } finally { - IOUtils.closeQuietly(in); - } - - // Remove obsolete properties. - for (Iterator iterator = properties.keySet().iterator(); iterator.hasNext();) { - String key = (String) iterator.next(); - if (OBSOLETE_KEYS.contains(key)) { - LOG.debug("Removing obsolete property [" + key + ']'); - iterator.remove(); - } - } - } - - save(false); - } - - /** - * Register in service locator so that non-Spring objects can access me. - * This method is invoked automatically by Spring. - */ - public void init() { - ServiceLocator.setSettingsService(this); - validateLicenseAsync(); - } - - public void save() { - save(true); - } - - public void save(boolean updateChangedDate) { - if (updateChangedDate) { - setProperty(KEY_SETTINGS_CHANGED, String.valueOf(System.currentTimeMillis())); - } - - OutputStream out = null; - try { - out = new FileOutputStream(getPropertyFile()); - properties.store(out, "Subsonic preferences. NOTE: This file is automatically generated."); - } catch (Exception x) { - LOG.error("Unable to write to property file.", x); - } finally { - IOUtils.closeQuietly(out); - } - } - - private File getPropertyFile() { - return new File(getSubsonicHome(), "subsonic.properties"); - } - - /** - * Returns the Subsonic home directory. - * - * @return The Subsonic home directory, if it exists. - * @throws RuntimeException If directory doesn't exist. - */ - public static synchronized File getSubsonicHome() { - - if (subsonicHome != null) { - return subsonicHome; - } - - File home; - - String overrideHome = System.getProperty("subsonic.home"); - if (overrideHome != null) { - home = new File(overrideHome); - } else { - boolean isWindows = System.getProperty("os.name", "Windows").toLowerCase().startsWith("windows"); - home = isWindows ? SUBSONIC_HOME_WINDOWS : SUBSONIC_HOME_OTHER; - } - - // Attempt to create home directory if it doesn't exist. - if (!home.exists() || !home.isDirectory()) { - boolean success = home.mkdirs(); - if (success) { - subsonicHome = home; - } else { - String message = "The directory " + home + " does not exist. Please create it and make it writable. " + - "(You can override the directory location by specifying -Dsubsonic.home=... when " + - "starting the servlet container.)"; - System.err.println("ERROR: " + message); - } - } else { - subsonicHome = home; - } - - return home; - } - - private boolean getBoolean(String key, boolean defaultValue) { - return Boolean.valueOf(properties.getProperty(key, String.valueOf(defaultValue))); - } - - private void setBoolean(String key, boolean value) { - setProperty(key, String.valueOf(value)); - } - - public String getIndexString() { - return properties.getProperty(KEY_INDEX_STRING, DEFAULT_INDEX_STRING); - } - - public void setIndexString(String indexString) { - setProperty(KEY_INDEX_STRING, indexString); - } - - public String getIgnoredArticles() { - return properties.getProperty(KEY_IGNORED_ARTICLES, DEFAULT_IGNORED_ARTICLES); - } - - public String[] getIgnoredArticlesAsArray() { - return getIgnoredArticles().split("\\s+"); - } - - public void setIgnoredArticles(String ignoredArticles) { - setProperty(KEY_IGNORED_ARTICLES, ignoredArticles); - } - - public String getShortcuts() { - return properties.getProperty(KEY_SHORTCUTS, DEFAULT_SHORTCUTS); - } - - public String[] getShortcutsAsArray() { - return StringUtil.split(getShortcuts()); - } - - public void setShortcuts(String shortcuts) { - setProperty(KEY_SHORTCUTS, shortcuts); - } - - public String getPlaylistFolder() { - return properties.getProperty(KEY_PLAYLIST_FOLDER, DEFAULT_PLAYLIST_FOLDER); - } - - public String getMusicFileTypes() { - return properties.getProperty(KEY_MUSIC_FILE_TYPES, DEFAULT_MUSIC_FILE_TYPES); - } - - public synchronized void setMusicFileTypes(String fileTypes) { - setProperty(KEY_MUSIC_FILE_TYPES, fileTypes); - cachedMusicFileTypesArray = null; - } - - public synchronized String[] getMusicFileTypesAsArray() { - if (cachedMusicFileTypesArray == null) { - cachedMusicFileTypesArray = toStringArray(getMusicFileTypes()); - } - return cachedMusicFileTypesArray; - } - - public String getVideoFileTypes() { - return properties.getProperty(KEY_VIDEO_FILE_TYPES, DEFAULT_VIDEO_FILE_TYPES); - } - - public synchronized void setVideoFileTypes(String fileTypes) { - setProperty(KEY_VIDEO_FILE_TYPES, fileTypes); - cachedVideoFileTypesArray = null; - } - - public synchronized String[] getVideoFileTypesAsArray() { - if (cachedVideoFileTypesArray == null) { - cachedVideoFileTypesArray = toStringArray(getVideoFileTypes()); - } - return cachedVideoFileTypesArray; - } - - public String getCoverArtFileTypes() { - return properties.getProperty(KEY_COVER_ART_FILE_TYPES, DEFAULT_COVER_ART_FILE_TYPES); - } - - public synchronized void setCoverArtFileTypes(String fileTypes) { - setProperty(KEY_COVER_ART_FILE_TYPES, fileTypes); - cachedCoverArtFileTypesArray = null; - } - - public synchronized String[] getCoverArtFileTypesAsArray() { - if (cachedCoverArtFileTypesArray == null) { - cachedCoverArtFileTypesArray = toStringArray(getCoverArtFileTypes()); - } - return cachedCoverArtFileTypesArray; - } - - public int getCoverArtLimit() { - return Integer.parseInt(properties.getProperty(KEY_COVER_ART_LIMIT, "" + DEFAULT_COVER_ART_LIMIT)); - } - - public void setCoverArtLimit(int limit) { - setProperty(KEY_COVER_ART_LIMIT, "" + limit); - } - - public String getWelcomeTitle() { - return StringUtils.trimToNull(properties.getProperty(KEY_WELCOME_TITLE, DEFAULT_WELCOME_TITLE)); - } - - public void setWelcomeTitle(String title) { - setProperty(KEY_WELCOME_TITLE, title); - } - - public String getWelcomeSubtitle() { - return StringUtils.trimToNull(properties.getProperty(KEY_WELCOME_SUBTITLE, DEFAULT_WELCOME_SUBTITLE)); - } - - public void setWelcomeSubtitle(String subtitle) { - setProperty(KEY_WELCOME_SUBTITLE, subtitle); - } - - public String getWelcomeMessage() { - return StringUtils.trimToNull(properties.getProperty(KEY_WELCOME_MESSAGE, DEFAULT_WELCOME_MESSAGE)); - } - - public void setWelcomeMessage(String message) { - setProperty(KEY_WELCOME_MESSAGE, message); - } - - public String getLoginMessage() { - return StringUtils.trimToNull(properties.getProperty(KEY_LOGIN_MESSAGE, DEFAULT_LOGIN_MESSAGE)); - } - - public void setLoginMessage(String message) { - setProperty(KEY_LOGIN_MESSAGE, message); - } - - /** - * Returns the number of days between automatic index creation, of -1 if automatic index - * creation is disabled. - */ - public int getIndexCreationInterval() { - return Integer.parseInt(properties.getProperty(KEY_INDEX_CREATION_INTERVAL, "" + DEFAULT_INDEX_CREATION_INTERVAL)); - } - - /** - * Sets the number of days between automatic index creation, of -1 if automatic index - * creation is disabled. - */ - public void setIndexCreationInterval(int days) { - setProperty(KEY_INDEX_CREATION_INTERVAL, String.valueOf(days)); - } - - /** - * Returns the hour of day (0 - 23) when automatic index creation should run. - */ - public int getIndexCreationHour() { - return Integer.parseInt(properties.getProperty(KEY_INDEX_CREATION_HOUR, String.valueOf(DEFAULT_INDEX_CREATION_HOUR))); - } - - /** - * Sets the hour of day (0 - 23) when automatic index creation should run. - */ - public void setIndexCreationHour(int hour) { - setProperty(KEY_INDEX_CREATION_HOUR, String.valueOf(hour)); - } - - public boolean isFastCacheEnabled() { - return getBoolean(KEY_FAST_CACHE_ENABLED, DEFAULT_FAST_CACHE_ENABLED); - } - - public void setFastCacheEnabled(boolean enabled) { - setBoolean(KEY_FAST_CACHE_ENABLED, enabled); - } - - /** - * Returns the number of hours between Podcast updates, of -1 if automatic updates - * are disabled. - */ - public int getPodcastUpdateInterval() { - return Integer.parseInt(properties.getProperty(KEY_PODCAST_UPDATE_INTERVAL, String.valueOf(DEFAULT_PODCAST_UPDATE_INTERVAL))); - } - - /** - * Sets the number of hours between Podcast updates, of -1 if automatic updates - * are disabled. - */ - public void setPodcastUpdateInterval(int hours) { - setProperty(KEY_PODCAST_UPDATE_INTERVAL, String.valueOf(hours)); - } - - /** - * Returns the number of Podcast episodes to keep (-1 to keep all). - */ - public int getPodcastEpisodeRetentionCount() { - return Integer.parseInt(properties.getProperty(KEY_PODCAST_EPISODE_RETENTION_COUNT, String.valueOf(DEFAULT_PODCAST_EPISODE_RETENTION_COUNT))); - } - - /** - * Sets the number of Podcast episodes to keep (-1 to keep all). - */ - public void setPodcastEpisodeRetentionCount(int count) { - setProperty(KEY_PODCAST_EPISODE_RETENTION_COUNT, String.valueOf(count)); - } - - /** - * Returns the number of Podcast episodes to download (-1 to download all). - */ - public int getPodcastEpisodeDownloadCount() { - return Integer.parseInt(properties.getProperty(KEY_PODCAST_EPISODE_DOWNLOAD_COUNT, String.valueOf(DEFAULT_PODCAST_EPISODE_DOWNLOAD_COUNT))); - } - - /** - * Sets the number of Podcast episodes to download (-1 to download all). - */ - public void setPodcastEpisodeDownloadCount(int count) { - setProperty(KEY_PODCAST_EPISODE_DOWNLOAD_COUNT, String.valueOf(count)); - } - - /** - * Returns the Podcast download folder. - */ - public String getPodcastFolder() { - return properties.getProperty(KEY_PODCAST_FOLDER, DEFAULT_PODCAST_FOLDER); - } - - /** - * Sets the Podcast download folder. - */ - public void setPodcastFolder(String folder) { - setProperty(KEY_PODCAST_FOLDER, folder); - } - - /** - * @return The download bitrate limit in Kbit/s. Zero if unlimited. - */ - public long getDownloadBitrateLimit() { - return Long.parseLong(properties.getProperty(KEY_DOWNLOAD_BITRATE_LIMIT, "" + DEFAULT_DOWNLOAD_BITRATE_LIMIT)); - } - - /** - * @param limit The download bitrate limit in Kbit/s. Zero if unlimited. - */ - public void setDownloadBitrateLimit(long limit) { - setProperty(KEY_DOWNLOAD_BITRATE_LIMIT, "" + limit); - } - - /** - * @return The upload bitrate limit in Kbit/s. Zero if unlimited. - */ - public long getUploadBitrateLimit() { - return Long.parseLong(properties.getProperty(KEY_UPLOAD_BITRATE_LIMIT, "" + DEFAULT_UPLOAD_BITRATE_LIMIT)); - } - - /** - * @param limit The upload bitrate limit in Kbit/s. Zero if unlimited. - */ - public void setUploadBitrateLimit(long limit) { - setProperty(KEY_UPLOAD_BITRATE_LIMIT, "" + limit); - } - - /** - * @return The non-SSL stream port. Zero if disabled. - */ - public int getStreamPort() { - return Integer.parseInt(properties.getProperty(KEY_STREAM_PORT, "" + DEFAULT_STREAM_PORT)); - } - - /** - * @param port The non-SSL stream port. Zero if disabled. - */ - public void setStreamPort(int port) { - setProperty(KEY_STREAM_PORT, "" + port); - } - - public String getLicenseEmail() { - return properties.getProperty(KEY_LICENSE_EMAIL, DEFAULT_LICENSE_EMAIL); - } - - public void setLicenseEmail(String email) { - setProperty(KEY_LICENSE_EMAIL, email); - } - - public String getLicenseCode() { - return properties.getProperty(KEY_LICENSE_CODE, DEFAULT_LICENSE_CODE); - } - - public void setLicenseCode(String code) { - setProperty(KEY_LICENSE_CODE, code); - } - - public Date getLicenseDate() { - String value = properties.getProperty(KEY_LICENSE_DATE, DEFAULT_LICENSE_DATE); - return value == null ? null : new Date(Long.parseLong(value)); - } - - public void setLicenseDate(Date date) { - String value = (date == null ? null : String.valueOf(date.getTime())); - setProperty(KEY_LICENSE_DATE, value); - } - - public boolean isLicenseValid() { - return true; - } - - public boolean isLicenseValid(String email, String license) { - return true; - } - - public String getDownsamplingCommand() { - return properties.getProperty(KEY_DOWNSAMPLING_COMMAND, DEFAULT_DOWNSAMPLING_COMMAND); - } - - public void setDownsamplingCommand(String command) { - setProperty(KEY_DOWNSAMPLING_COMMAND, command); - } - - public String getJukeboxCommand() { - return properties.getProperty(KEY_JUKEBOX_COMMAND, DEFAULT_JUKEBOX_COMMAND); - } - - public boolean isRewriteUrlEnabled() { - return getBoolean(KEY_REWRITE_URL, DEFAULT_REWRITE_URL); - } - - public void setRewriteUrlEnabled(boolean rewriteUrl) { - setBoolean(KEY_REWRITE_URL, rewriteUrl); - } - - public boolean isLdapEnabled() { - return getBoolean(KEY_LDAP_ENABLED, DEFAULT_LDAP_ENABLED); - } - - public void setLdapEnabled(boolean ldapEnabled) { - setBoolean(KEY_LDAP_ENABLED, ldapEnabled); - } - - public String getLdapUrl() { - return properties.getProperty(KEY_LDAP_URL, DEFAULT_LDAP_URL); - } - - public void setLdapUrl(String ldapUrl) { - properties.setProperty(KEY_LDAP_URL, ldapUrl); - } - - public String getLdapSearchFilter() { - return properties.getProperty(KEY_LDAP_SEARCH_FILTER, DEFAULT_LDAP_SEARCH_FILTER); - } - - public void setLdapSearchFilter(String ldapSearchFilter) { - properties.setProperty(KEY_LDAP_SEARCH_FILTER, ldapSearchFilter); - } - - public String getLdapManagerDn() { - return properties.getProperty(KEY_LDAP_MANAGER_DN, DEFAULT_LDAP_MANAGER_DN); - } - - public void setLdapManagerDn(String ldapManagerDn) { - properties.setProperty(KEY_LDAP_MANAGER_DN, ldapManagerDn); - } - - public String getLdapManagerPassword() { - String s = properties.getProperty(KEY_LDAP_MANAGER_PASSWORD, DEFAULT_LDAP_MANAGER_PASSWORD); - try { - return StringUtil.utf8HexDecode(s); - } catch (Exception x) { - LOG.warn("Failed to decode LDAP manager password.", x); - return s; - } - } - - public void setLdapManagerPassword(String ldapManagerPassword) { - try { - ldapManagerPassword = StringUtil.utf8HexEncode(ldapManagerPassword); - } catch (Exception x) { - LOG.warn("Failed to encode LDAP manager password.", x); - } - properties.setProperty(KEY_LDAP_MANAGER_PASSWORD, ldapManagerPassword); - } - - public boolean isLdapAutoShadowing() { - return getBoolean(KEY_LDAP_AUTO_SHADOWING, DEFAULT_LDAP_AUTO_SHADOWING); - } - - public void setLdapAutoShadowing(boolean ldapAutoShadowing) { - setBoolean(KEY_LDAP_AUTO_SHADOWING, ldapAutoShadowing); - } - - public boolean isGettingStartedEnabled() { - return getBoolean(KEY_GETTING_STARTED_ENABLED, DEFAULT_GETTING_STARTED_ENABLED); - } - - public void setGettingStartedEnabled(boolean isGettingStartedEnabled) { - setBoolean(KEY_GETTING_STARTED_ENABLED, isGettingStartedEnabled); - } - - public boolean isPortForwardingEnabled() { - return getBoolean(KEY_PORT_FORWARDING_ENABLED, DEFAULT_PORT_FORWARDING_ENABLED); - } - - public void setPortForwardingEnabled(boolean isPortForwardingEnabled) { - setBoolean(KEY_PORT_FORWARDING_ENABLED, isPortForwardingEnabled); - } - - public int getPort() { - return Integer.valueOf(properties.getProperty(KEY_PORT, String.valueOf(DEFAULT_PORT))); - } - - public void setPort(int port) { - setProperty(KEY_PORT, String.valueOf(port)); - } - - public int getHttpsPort() { - return Integer.valueOf(properties.getProperty(KEY_HTTPS_PORT, String.valueOf(DEFAULT_HTTPS_PORT))); - } - - public void setHttpsPort(int httpsPort) { - setProperty(KEY_HTTPS_PORT, String.valueOf(httpsPort)); - } - - public boolean isUrlRedirectionEnabled() { - return getBoolean(KEY_URL_REDIRECTION_ENABLED, DEFAULT_URL_REDIRECTION_ENABLED); - } - - public void setUrlRedirectionEnabled(boolean isUrlRedirectionEnabled) { - setBoolean(KEY_URL_REDIRECTION_ENABLED, isUrlRedirectionEnabled); - } - - public String getUrlRedirectFrom() { - return properties.getProperty(KEY_URL_REDIRECT_FROM, DEFAULT_URL_REDIRECT_FROM); - } - - public void setUrlRedirectFrom(String urlRedirectFrom) { - properties.setProperty(KEY_URL_REDIRECT_FROM, urlRedirectFrom); - } - - public Date getUrlRedirectTrialExpires() { - String value = properties.getProperty(KEY_URL_REDIRECT_TRIAL_EXPIRES, DEFAULT_URL_REDIRECT_TRIAL_EXPIRES); - return value == null ? null : new Date(Long.parseLong(value)); - } - - public void setUrlRedirectTrialExpires(Date date) { - String value = (date == null ? null : String.valueOf(date.getTime())); - setProperty(KEY_URL_REDIRECT_TRIAL_EXPIRES, value); - } - - public Date getVideoTrialExpires() { - String value = properties.getProperty(KEY_VIDEO_TRIAL_EXPIRES, DEFAULT_VIDEO_TRIAL_EXPIRES); - return value == null ? null : new Date(Long.parseLong(value)); - } - - public void setVideoTrialExpires(Date date) { - String value = (date == null ? null : String.valueOf(date.getTime())); - setProperty(KEY_VIDEO_TRIAL_EXPIRES, value); - } - - public String getUrlRedirectContextPath() { - return properties.getProperty(KEY_URL_REDIRECT_CONTEXT_PATH, DEFAULT_URL_REDIRECT_CONTEXT_PATH); - } - - public void setUrlRedirectContextPath(String contextPath) { - properties.setProperty(KEY_URL_REDIRECT_CONTEXT_PATH, contextPath); - } - - public Date getRESTTrialExpires(String client) { - String value = properties.getProperty(KEY_REST_TRIAL_EXPIRES + client, DEFAULT_REST_TRIAL_EXPIRES); - return value == null ? null : new Date(Long.parseLong(value)); - } - - public void setRESTTrialExpires(String client, Date date) { - String value = (date == null ? null : String.valueOf(date.getTime())); - setProperty(KEY_REST_TRIAL_EXPIRES + client, value); - } - - public String getServerId() { - return properties.getProperty(KEY_SERVER_ID, DEFAULT_SERVER_ID); - } - - public void setServerId(String serverId) { - properties.setProperty(KEY_SERVER_ID, serverId); - } - - public long getSettingsChanged() { - return Long.parseLong(properties.getProperty(KEY_SETTINGS_CHANGED, String.valueOf(DEFAULT_SETTINGS_CHANGED))); - } - - public Date getLastScanned() { - String lastScanned = properties.getProperty(KEY_LAST_SCANNED); - return lastScanned == null ? null : new Date(Long.parseLong(lastScanned)); - } - - public void setLastScanned(Date date) { - if (date == null) { - properties.remove(KEY_LAST_SCANNED); - } else { - properties.setProperty(KEY_LAST_SCANNED, String.valueOf(date.getTime())); - } - } - - public boolean isOrganizeByFolderStructure() { - return getBoolean(KEY_ORGANIZE_BY_FOLDER_STRUCTURE, DEFAULT_ORGANIZE_BY_FOLDER_STRUCTURE); - } - - public void setOrganizeByFolderStructure(boolean b) { - setBoolean(KEY_ORGANIZE_BY_FOLDER_STRUCTURE, b); - } - - public boolean isSortAlbumsByYear() { - return getBoolean(KEY_SORT_ALBUMS_BY_YEAR, DEFAULT_SORT_ALBUMS_BY_YEAR); - } - - public void setSortAlbumsByYear(boolean b) { - setBoolean(KEY_SORT_ALBUMS_BY_YEAR, b); - } - - /** - * Returns the locale (for language, date format etc). - * - * @return The locale. - */ - public Locale getLocale() { - String language = properties.getProperty(KEY_LOCALE_LANGUAGE, DEFAULT_LOCALE_LANGUAGE); - String country = properties.getProperty(KEY_LOCALE_COUNTRY, DEFAULT_LOCALE_COUNTRY); - String variant = properties.getProperty(KEY_LOCALE_VARIANT, DEFAULT_LOCALE_VARIANT); - - return new Locale(language, country, variant); - } - - /** - * Sets the locale (for language, date format etc.) - * - * @param locale The locale. - */ - public void setLocale(Locale locale) { - setProperty(KEY_LOCALE_LANGUAGE, locale.getLanguage()); - setProperty(KEY_LOCALE_COUNTRY, locale.getCountry()); - setProperty(KEY_LOCALE_VARIANT, locale.getVariant()); - } - - /** - * Returns the ID of the theme to use. - * - * @return The theme ID. - */ - public String getThemeId() { - return properties.getProperty(KEY_THEME_ID, DEFAULT_THEME_ID); - } - - /** - * Sets the ID of the theme to use. - * - * @param themeId The theme ID - */ - public void setThemeId(String themeId) { - setProperty(KEY_THEME_ID, themeId); - } - - /** - * Returns a list of available themes. - * - * @return A list of available themes. - */ - public synchronized Theme[] getAvailableThemes() { - if (themes == null) { - themes = new ArrayList(); - try { - InputStream in = SettingsService.class.getResourceAsStream(THEMES_FILE); - String[] lines = StringUtil.readLines(in); - for (String line : lines) { - String[] elements = StringUtil.split(line); - if (elements.length == 2) { - themes.add(new Theme(elements[0], elements[1])); - } else { - LOG.warn("Failed to parse theme from line: [" + line + "]."); - } - } - } catch (IOException x) { - LOG.error("Failed to resolve list of themes.", x); - themes.add(new Theme("default", "Subsonic default")); - } - } - return themes.toArray(new Theme[themes.size()]); - } - - /** - * Returns a list of available locales. - * - * @return A list of available locales. - */ - public synchronized Locale[] getAvailableLocales() { - if (locales == null) { - locales = new ArrayList(); - try { - InputStream in = SettingsService.class.getResourceAsStream(LOCALES_FILE); - String[] lines = StringUtil.readLines(in); - - for (String line : lines) { - locales.add(parseLocale(line)); - } - - } catch (IOException x) { - LOG.error("Failed to resolve list of locales.", x); - locales.add(Locale.ENGLISH); - } - } - return locales.toArray(new Locale[locales.size()]); - } - - private Locale parseLocale(String line) { - String[] s = line.split("_"); - String language = s[0]; - String country = ""; - String variant = ""; - - if (s.length > 1) { - country = s[1]; - } - if (s.length > 2) { - variant = s[2]; - } - return new Locale(language, country, variant); - } - - /** - * Returns the "brand" name. Normally, this is just "Subsonic". - * - * @return The brand name. - */ - public String getBrand() { - return "Subsonic"; - } - - /** - * Returns all music folders. Non-existing and disabled folders are not included. - * - * @return Possibly empty list of all music folders. - */ - public List getAllMusicFolders() { - return getAllMusicFolders(false, false); - } - - /** - * Returns all music folders. - * - * @param includeDisabled Whether to include disabled folders. - * @param includeNonExisting Whether to include non-existing folders. - * @return Possibly empty list of all music folders. - */ - public List getAllMusicFolders(boolean includeDisabled, boolean includeNonExisting) { - if (cachedMusicFolders == null) { - cachedMusicFolders = musicFolderDao.getAllMusicFolders(); - } - - List result = new ArrayList(cachedMusicFolders.size()); - for (MusicFolder folder : cachedMusicFolders) { - if ((includeDisabled || folder.isEnabled()) && (includeNonExisting || FileUtil.exists(folder.getPath()))) { - result.add(folder); - } - } - return result; - } - - /** - * Returns the music folder with the given ID. - * - * @param id The ID. - * @return The music folder with the given ID, or null if not found. - */ - public MusicFolder getMusicFolderById(Integer id) { - List all = getAllMusicFolders(); - for (MusicFolder folder : all) { - if (id.equals(folder.getId())) { - return folder; - } - } - return null; - } - - /** - * Creates a new music folder. - * - * @param musicFolder The music folder to create. - */ - public void createMusicFolder(MusicFolder musicFolder) { - musicFolderDao.createMusicFolder(musicFolder); - cachedMusicFolders = null; - } - - /** - * Deletes the music folder with the given ID. - * - * @param id The ID of the music folder to delete. - */ - public void deleteMusicFolder(Integer id) { - musicFolderDao.deleteMusicFolder(id); - cachedMusicFolders = null; - } - - /** - * Updates the given music folder. - * - * @param musicFolder The music folder to update. - */ - public void updateMusicFolder(MusicFolder musicFolder) { - musicFolderDao.updateMusicFolder(musicFolder); - cachedMusicFolders = null; - } - - /** - * Returns all internet radio stations. Disabled stations are not returned. - * - * @return Possibly empty list of all internet radio stations. - */ - public List getAllInternetRadios() { - return getAllInternetRadios(false); - } - - /** - * Returns the internet radio station with the given ID. - * - * @param id The ID. - * @return The internet radio station with the given ID, or null if not found. - */ - public InternetRadio getInternetRadioById(Integer id) { - for (InternetRadio radio : getAllInternetRadios()) { - if (id.equals(radio.getId())) { - return radio; - } - } - return null; - } - - /** - * Returns all internet radio stations. - * - * @param includeAll Whether disabled stations should be included. - * @return Possibly empty list of all internet radio stations. - */ - public List getAllInternetRadios(boolean includeAll) { - List all = internetRadioDao.getAllInternetRadios(); - List result = new ArrayList(all.size()); - for (InternetRadio folder : all) { - if (includeAll || folder.isEnabled()) { - result.add(folder); - } - } - return result; - } - - /** - * Creates a new internet radio station. - * - * @param radio The internet radio station to create. - */ - public void createInternetRadio(InternetRadio radio) { - internetRadioDao.createInternetRadio(radio); - } - - /** - * Deletes the internet radio station with the given ID. - * - * @param id The internet radio station ID. - */ - public void deleteInternetRadio(Integer id) { - internetRadioDao.deleteInternetRadio(id); - } - - /** - * Updates the given internet radio station. - * - * @param radio The internet radio station to update. - */ - public void updateInternetRadio(InternetRadio radio) { - internetRadioDao.updateInternetRadio(radio); - } - - /** - * Returns settings for the given user. - * - * @param username The username. - * @return User-specific settings. Never null. - */ - public UserSettings getUserSettings(String username) { - UserSettings settings = userDao.getUserSettings(username); - return settings == null ? createDefaultUserSettings(username) : settings; - } - - private UserSettings createDefaultUserSettings(String username) { - UserSettings settings = new UserSettings(username); - settings.setFinalVersionNotificationEnabled(true); - settings.setBetaVersionNotificationEnabled(false); - settings.setShowNowPlayingEnabled(true); - settings.setShowChatEnabled(true); - settings.setPartyModeEnabled(false); - settings.setNowPlayingAllowed(true); - settings.setLastFmEnabled(false); - settings.setLastFmUsername(null); - settings.setLastFmPassword(null); - settings.setChanged(new Date()); - - UserSettings.Visibility playlist = settings.getPlaylistVisibility(); - playlist.setCaptionCutoff(35); - playlist.setArtistVisible(true); - playlist.setAlbumVisible(true); - playlist.setYearVisible(true); - playlist.setDurationVisible(true); - playlist.setBitRateVisible(true); - playlist.setFormatVisible(true); - playlist.setFileSizeVisible(true); - - UserSettings.Visibility main = settings.getMainVisibility(); - main.setCaptionCutoff(35); - main.setTrackNumberVisible(true); - main.setArtistVisible(true); - main.setDurationVisible(true); - - return settings; - } - - /** - * Updates settings for the given username. - * - * @param settings The user-specific settings. - */ - public void updateUserSettings(UserSettings settings) { - userDao.updateUserSettings(settings); - } - - /** - * Returns all system avatars. - * - * @return All system avatars. - */ - public List getAllSystemAvatars() { - return avatarDao.getAllSystemAvatars(); - } - - /** - * Returns the system avatar with the given ID. - * - * @param id The system avatar ID. - * @return The avatar or null if not found. - */ - public Avatar getSystemAvatar(int id) { - return avatarDao.getSystemAvatar(id); - } - - /** - * Returns the custom avatar for the given user. - * - * @param username The username. - * @return The avatar or null if not found. - */ - public Avatar getCustomAvatar(String username) { - return avatarDao.getCustomAvatar(username); - } - - /** - * Sets the custom avatar for the given user. - * - * @param avatar The avatar, or null to remove the avatar. - * @param username The username. - */ - public void setCustomAvatar(Avatar avatar, String username) { - avatarDao.setCustomAvatar(avatar, username); - } - - private void setProperty(String key, String value) { - if (value == null) { - properties.remove(key); - } else { - properties.setProperty(key, value); - } - } - - private String[] toStringArray(String s) { - List result = new ArrayList(); - StringTokenizer tokenizer = new StringTokenizer(s, " "); - while (tokenizer.hasMoreTokens()) { - result.add(tokenizer.nextToken()); - } - - return result.toArray(new String[result.size()]); - } - - private void validateLicense() { - licenseValidated = true; - } - - public void validateLicenseAsync() { - new Thread() { - @Override - public void run() { - validateLicense(); - } - }.start(); - } - - public void setInternetRadioDao(InternetRadioDao internetRadioDao) { - this.internetRadioDao = internetRadioDao; - } - - public void setMusicFolderDao(MusicFolderDao musicFolderDao) { - this.musicFolderDao = musicFolderDao; - } - - public void setUserDao(UserDao userDao) { - this.userDao = userDao; - } - - public void setAvatarDao(AvatarDao avatarDao) { - this.avatarDao = avatarDao; - } - - public void setVersionService(VersionService versionService) { - this.versionService = versionService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/ShareService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/ShareService.java deleted file mode 100644 index cf5860e6..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/ShareService.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -import net.sourceforge.subsonic.domain.MediaFile; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.RandomStringUtils; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.ShareDao; -import net.sourceforge.subsonic.domain.Share; -import net.sourceforge.subsonic.domain.User; - -/** - * Provides services for sharing media. - * - * @author Sindre Mehus - * @see Share - */ -public class ShareService { - - private static final Logger LOG = Logger.getLogger(ShareService.class); - - private ShareDao shareDao; - private SecurityService securityService; - private SettingsService settingsService; - private MediaFileService mediaFileService; - - public List getAllShares() { - return shareDao.getAllShares(); - } - - public List getSharesForUser(User user) { - List result = new ArrayList(); - for (Share share : getAllShares()) { - if (user.isAdminRole() || ObjectUtils.equals(user.getUsername(), share.getUsername())) { - result.add(share); - } - } - return result; - } - - public Share getShareById(int id) { - return shareDao.getShareById(id); - } - - public List getSharedFiles(int id) { - List result = new ArrayList(); - for (String path : shareDao.getSharedFiles(id)) { - try { - result.add(mediaFileService.getMediaFile(path)); - } catch (Exception x) { - // Ignored - } - } - return result; - } - - public Share createShare(HttpServletRequest request, List files) throws Exception { - - Share share = new Share(); - share.setName(RandomStringUtils.random(5, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")); - share.setCreated(new Date()); - share.setUsername(securityService.getCurrentUsername(request)); - - Calendar expires = Calendar.getInstance(); - expires.add(Calendar.YEAR, 1); - share.setExpires(expires.getTime()); - - shareDao.createShare(share); - for (MediaFile file : files) { - shareDao.createSharedFiles(share.getId(), file.getPath()); - } - LOG.info("Created share '" + share.getName() + "' with " + files.size() + " file(s)."); - - return share; - } - - public void updateShare(Share share) { - shareDao.updateShare(share); - } - - public void deleteShare(int id) { - shareDao.deleteShare(id); - } - - public String getShareBaseUrl() { - return "http://" + settingsService.getUrlRedirectFrom() + ".subsonic.org/share/"; - } - - public String getShareUrl(Share share) { - return getShareBaseUrl() + share.getName(); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setShareDao(ShareDao shareDao) { - this.shareDao = shareDao; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/StatusService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/StatusService.java deleted file mode 100644 index a893166a..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/StatusService.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.TransferStatus; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Provides services for maintaining the list of stream, download and upload statuses. - *

- * Note that for stream statuses, the last inactive status is also stored. - * - * @author Sindre Mehus - * @see TransferStatus - */ -public class StatusService { - - private final List streamStatuses = new ArrayList(); - private final List downloadStatuses = new ArrayList(); - private final List uploadStatuses = new ArrayList(); - - // Maps from player ID to latest inactive stream status. - private final Map inactiveStreamStatuses = new LinkedHashMap(); - - public synchronized TransferStatus createStreamStatus(Player player) { - // Reuse existing status, if possible. - TransferStatus status = inactiveStreamStatuses.get(player.getId()); - if (status != null) { - status.setActive(true); - } else { - status = createStatus(player, streamStatuses); - } - return status; - } - - public synchronized void removeStreamStatus(TransferStatus status) { - // Move it to the map of inactive statuses. - status.setActive(false); - inactiveStreamStatuses.put(status.getPlayer().getId(), status); - streamStatuses.remove(status); - } - - public synchronized List getAllStreamStatuses() { - - List result = new ArrayList(streamStatuses); - - // Add inactive status for those players that have no active status. - Set activePlayers = new HashSet(); - for (TransferStatus status : streamStatuses) { - activePlayers.add(status.getPlayer().getId()); - } - - for (Map.Entry entry : inactiveStreamStatuses.entrySet()) { - if (!activePlayers.contains(entry.getKey())) { - result.add(entry.getValue()); - } - } - return result; - } - - public synchronized List getStreamStatusesForPlayer(Player player) { - List result = new ArrayList(); - for (TransferStatus status : streamStatuses) { - if (status.getPlayer().getId().equals(player.getId())) { - result.add(status); - } - } - - // If no active statuses exists, add the inactive one. - if (result.isEmpty()) { - TransferStatus inactiveStatus = inactiveStreamStatuses.get(player.getId()); - if (inactiveStatus != null) { - result.add(inactiveStatus); - } - } - - return result; - } - - public synchronized TransferStatus createDownloadStatus(Player player) { - return createStatus(player, downloadStatuses); - } - - public synchronized void removeDownloadStatus(TransferStatus status) { - downloadStatuses.remove(status); - } - - public synchronized List getAllDownloadStatuses() { - return new ArrayList(downloadStatuses); - } - - public synchronized TransferStatus createUploadStatus(Player player) { - return createStatus(player, uploadStatuses); - } - - public synchronized void removeUploadStatus(TransferStatus status) { - uploadStatuses.remove(status); - } - - public synchronized List getAllUploadStatuses() { - return new ArrayList(uploadStatuses); - } - - private synchronized TransferStatus createStatus(Player player, List statusList) { - TransferStatus status = new TransferStatus(); - status.setPlayer(player); - statusList.add(status); - return status; - } - -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/TranscodingService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/TranscodingService.java deleted file mode 100644 index 2c8b9c5e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/TranscodingService.java +++ /dev/null @@ -1,530 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.controller.VideoPlayerController; -import net.sourceforge.subsonic.dao.TranscodingDao; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.Player; -import net.sourceforge.subsonic.domain.TranscodeScheme; -import net.sourceforge.subsonic.domain.Transcoding; -import net.sourceforge.subsonic.domain.UserSettings; -import net.sourceforge.subsonic.domain.VideoTranscodingSettings; -import net.sourceforge.subsonic.io.TranscodeInputStream; -import net.sourceforge.subsonic.util.StringUtil; -import net.sourceforge.subsonic.util.Util; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.filefilter.PrefixFileFilter; -import org.apache.commons.lang.StringUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - -/** - * Provides services for transcoding media. Transcoding is the process of - * converting an audio stream to a different format and/or bit rate. The latter is - * also called downsampling. - * - * @author Sindre Mehus - * @see TranscodeInputStream - */ -public class TranscodingService { - - private static final Logger LOG = Logger.getLogger(TranscodingService.class); - - private TranscodingDao transcodingDao; - private SettingsService settingsService; - private PlayerService playerService; - - /** - * Returns all transcodings. - * - * @return Possibly empty list of all transcodings. - */ - public List getAllTranscodings() { - return transcodingDao.getAllTranscodings(); - } - - /** - * Returns all active transcodings for the given player. Only enabled transcodings are returned. - * - * @param player The player. - * @return All active transcodings for the player. - */ - public List getTranscodingsForPlayer(Player player) { - return transcodingDao.getTranscodingsForPlayer(player.getId()); - } - - /** - * Sets the list of active transcodings for the given player. - * - * @param player The player. - * @param transcodingIds ID's of the active transcodings. - */ - public void setTranscodingsForPlayer(Player player, int[] transcodingIds) { - transcodingDao.setTranscodingsForPlayer(player.getId(), transcodingIds); - } - - /** - * Sets the list of active transcodings for the given player. - * - * @param player The player. - * @param transcodings The active transcodings. - */ - public void setTranscodingsForPlayer(Player player, List transcodings) { - int[] transcodingIds = new int[transcodings.size()]; - for (int i = 0; i < transcodingIds.length; i++) { - transcodingIds[i] = transcodings.get(i).getId(); - } - setTranscodingsForPlayer(player, transcodingIds); - } - - - /** - * Creates a new transcoding. - * - * @param transcoding The transcoding to create. - */ - public void createTranscoding(Transcoding transcoding) { - transcodingDao.createTranscoding(transcoding); - - // Activate this transcoding for all players? - if (transcoding.isDefaultActive()) { - for (Player player : playerService.getAllPlayers()) { - List transcodings = getTranscodingsForPlayer(player); - transcodings.add(transcoding); - setTranscodingsForPlayer(player, transcodings); - } - } - } - - /** - * Deletes the transcoding with the given ID. - * - * @param id The transcoding ID. - */ - public void deleteTranscoding(Integer id) { - transcodingDao.deleteTranscoding(id); - } - - /** - * Updates the given transcoding. - * - * @param transcoding The transcoding to update. - */ - public void updateTranscoding(Transcoding transcoding) { - transcodingDao.updateTranscoding(transcoding); - } - - /** - * Returns whether transcoding is required for the given media file and player combination. - * - * @param mediaFile The media file. - * @param player The player. - * @return Whether transcoding will be performed if invoking the - * {@link #getTranscodedInputStream} method with the same arguments. - */ - public boolean isTranscodingRequired(MediaFile mediaFile, Player player) { - return getTranscoding(mediaFile, player, null) != null; - } - - /** - * Returns the suffix for the given player and media file, taking transcodings into account. - * - * @param player The player in question. - * @param file The media file. - * @param preferredTargetFormat Used to select among multiple applicable transcodings. May be {@code null}. - * @return The file suffix, e.g., "mp3". - */ - public String getSuffix(Player player, MediaFile file, String preferredTargetFormat) { - Transcoding transcoding = getTranscoding(file, player, preferredTargetFormat); - return transcoding != null ? transcoding.getTargetFormat() : file.getFormat(); - } - - /** - * Creates parameters for a possibly transcoded or downsampled input stream for the given media file and player combination. - *

- * A transcoding is applied if it is applicable for the format of the given file, and is activated for the - * given player. - *

- * If no transcoding is applicable, the file may still be downsampled, given that the player is configured - * with a bit rate limit which is higher than the actual bit rate of the file. - *

- * Otherwise, a normal input stream to the original file is returned. - * - * @param mediaFile The media file. - * @param player The player. - * @param maxBitRate Overrides the per-player and per-user bitrate limit. May be {@code null}. - * @param preferredTargetFormat Used to select among multiple applicable transcodings. May be {@code null}. - * @param videoTranscodingSettings Parameters used when transcoding video. May be {@code null}. - * @return Parameters to be used in the {@link #getTranscodedInputStream} method. - */ - public Parameters getParameters(MediaFile mediaFile, Player player, Integer maxBitRate, String preferredTargetFormat, - VideoTranscodingSettings videoTranscodingSettings) { - - Parameters parameters = new Parameters(mediaFile, videoTranscodingSettings); - - TranscodeScheme transcodeScheme = getTranscodeScheme(player); - if (maxBitRate == null && transcodeScheme != TranscodeScheme.OFF) { - maxBitRate = transcodeScheme.getMaxBitRate(); - } - - Transcoding transcoding = getTranscoding(mediaFile, player, preferredTargetFormat); - if (transcoding != null) { - parameters.setTranscoding(transcoding); - if (maxBitRate == null) { - maxBitRate = mediaFile.isVideo() ? VideoPlayerController.DEFAULT_BIT_RATE : 128; - } - } else if (maxBitRate != null) { - boolean supported = isDownsamplingSupported(mediaFile); - Integer bitRate = mediaFile.getBitRate(); - if (supported && bitRate != null && bitRate > maxBitRate) { - parameters.setDownsample(true); - } - } - - parameters.setMaxBitRate(maxBitRate); - return parameters; - } - - /** - * Returns a possibly transcoded or downsampled input stream for the given music file and player combination. - *

- * A transcoding is applied if it is applicable for the format of the given file, and is activated for the - * given player. - *

- * If no transcoding is applicable, the file may still be downsampled, given that the player is configured - * with a bit rate limit which is higher than the actual bit rate of the file. - *

- * Otherwise, a normal input stream to the original file is returned. - * - * @param parameters As returned by {@link #getParameters}. - * @return A possible transcoded or downsampled input stream. - * @throws IOException If an I/O error occurs. - */ - public InputStream getTranscodedInputStream(Parameters parameters) throws IOException { - try { - - if (parameters.getTranscoding() != null) { - return createTranscodedInputStream(parameters); - } - - if (parameters.downsample) { - return createDownsampledInputStream(parameters); - } - - } catch (Exception x) { - LOG.warn("Failed to transcode " + parameters.getMediaFile() + ". Using original.", x); - } - - return new FileInputStream(parameters.getMediaFile().getFile()); - } - - - /** - * Returns the strictest transcoding scheme defined for the player and the user. - */ - private TranscodeScheme getTranscodeScheme(Player player) { - String username = player.getUsername(); - if (username != null) { - UserSettings userSettings = settingsService.getUserSettings(username); - return player.getTranscodeScheme().strictest(userSettings.getTranscodeScheme()); - } - - return player.getTranscodeScheme(); - } - - /** - * Returns an input stream by applying the given transcoding to the given music file. - * - * @param parameters Transcoding parameters. - * @return The transcoded input stream. - * @throws IOException If an I/O error occurs. - */ - private InputStream createTranscodedInputStream(Parameters parameters) - throws IOException { - - Transcoding transcoding = parameters.getTranscoding(); - Integer maxBitRate = parameters.getMaxBitRate(); - VideoTranscodingSettings videoTranscodingSettings = parameters.getVideoTranscodingSettings(); - MediaFile mediaFile = parameters.getMediaFile(); - - TranscodeInputStream in = createTranscodeInputStream(transcoding.getStep1(), maxBitRate, videoTranscodingSettings, mediaFile, null); - - if (transcoding.getStep2() != null) { - in = createTranscodeInputStream(transcoding.getStep2(), maxBitRate, videoTranscodingSettings, mediaFile, in); - } - - if (transcoding.getStep3() != null) { - in = createTranscodeInputStream(transcoding.getStep3(), maxBitRate, videoTranscodingSettings, mediaFile, in); - } - - return in; - } - - /** - * Creates a transcoded input stream by interpreting the given command line string. - * This includes the following: - *

    - *
  • Splitting the command line string to an array.
  • - *
  • Replacing occurrences of "%s" with the path of the given music file.
  • - *
  • Replacing occurrences of "%t" with the title of the given music file.
  • - *
  • Replacing occurrences of "%l" with the album name of the given music file.
  • - *
  • Replacing occurrences of "%a" with the artist name of the given music file.
  • - *
  • Replacing occurrcences of "%b" with the max bitrate.
  • - *
  • Replacing occurrcences of "%o" with the video time offset (used for scrubbing).
  • - *
  • Replacing occurrcences of "%w" with the video image width.
  • - *
  • Replacing occurrcences of "%h" with the video image height.
  • - *
  • Prepending the path of the transcoder directory if the transcoder is found there.
  • - *
- * - * @param command The command line string. - * @param maxBitRate The maximum bitrate to use. May not be {@code null}. - * @param videoTranscodingSettings Parameters used when transcoding video. May be {@code null}. - * @param mediaFile The media file. - * @param in Data to feed to the process. May be {@code null}. @return The newly created input stream. - */ - private TranscodeInputStream createTranscodeInputStream(String command, Integer maxBitRate, - VideoTranscodingSettings videoTranscodingSettings, MediaFile mediaFile, InputStream in) throws IOException { - - String title = mediaFile.getTitle(); - String album = mediaFile.getAlbumName(); - String artist = mediaFile.getArtist(); - - if (title == null) { - title = "Unknown Song"; - } - if (album == null) { - title = "Unknown Album"; - } - if (artist == null) { - title = "Unknown Artist"; - } - - List result = new LinkedList(Arrays.asList(StringUtil.split(command))); - result.set(0, getTranscodeDirectory().getPath() + File.separatorChar + result.get(0)); - - File tmpFile = null; - - for (int i = 1; i < result.size(); i++) { - String cmd = result.get(i); - if (cmd.contains("%b")) { - cmd = cmd.replace("%b", String.valueOf(maxBitRate)); - } - if (cmd.contains("%t")) { - cmd = cmd.replace("%t", title); - } - if (cmd.contains("%l")) { - cmd = cmd.replace("%l", album); - } - if (cmd.contains("%a")) { - cmd = cmd.replace("%a", artist); - } - if (cmd.contains("%o") && videoTranscodingSettings != null) { - cmd = cmd.replace("%o", String.valueOf(videoTranscodingSettings.getTimeOffset())); - } - if (cmd.contains("%w") && videoTranscodingSettings != null) { - cmd = cmd.replace("%w", String.valueOf(videoTranscodingSettings.getWidth())); - } - if (cmd.contains("%h") && videoTranscodingSettings != null) { - cmd = cmd.replace("%h", String.valueOf(videoTranscodingSettings.getHeight())); - } - if (cmd.contains("%s")) { - - // Work-around for filename character encoding problem on Windows. - // Create temporary file, and feed this to the transcoder. - String path = mediaFile.getFile().getAbsolutePath(); - if (Util.isWindows() && !mediaFile.isVideo() && !StringUtils.isAsciiPrintable(path)) { - tmpFile = File.createTempFile("subsonic", "." + FilenameUtils.getExtension(path)); - tmpFile.deleteOnExit(); - FileUtils.copyFile(new File(path), tmpFile); - LOG.debug("Created tmp file: " + tmpFile); - cmd = cmd.replace("%s", tmpFile.getPath()); - } else { - cmd = cmd.replace("%s", path); - } - } - - result.set(i, cmd); - } - return new TranscodeInputStream(new ProcessBuilder(result), in, tmpFile); - } - - /** - * Returns an applicable transcoding for the given file and player, or null if no - * transcoding should be done. - */ - private Transcoding getTranscoding(MediaFile mediaFile, Player player, String preferredTargetFormat) { - - List applicableTranscodings = new LinkedList(); - String suffix = mediaFile.getFormat(); - - for (Transcoding transcoding : getTranscodingsForPlayer(player)) { - for (String sourceFormat : transcoding.getSourceFormatsAsArray()) { - if (sourceFormat.equalsIgnoreCase(suffix)) { - if (isTranscodingInstalled(transcoding)) { - applicableTranscodings.add(transcoding); - } - } - } - } - - if (applicableTranscodings.isEmpty()) { - return null; - } - - for (Transcoding transcoding : applicableTranscodings) { - if (transcoding.getTargetFormat().equalsIgnoreCase(preferredTargetFormat)) { - return transcoding; - } - } - - return applicableTranscodings.get(0); - } - - /** - * Returns a downsampled input stream to the music file. - * - * @param parameters Downsample parameters. - * @throws IOException If an I/O error occurs. - */ - private InputStream createDownsampledInputStream(Parameters parameters) throws IOException { - String command = settingsService.getDownsamplingCommand(); - return createTranscodeInputStream(command, parameters.getMaxBitRate(), parameters.getVideoTranscodingSettings(), - parameters.getMediaFile(), null); - } - - /** - * Returns whether downsampling is supported (i.e., whether LAME is installed or not.) - * - * @param mediaFile If not null, returns whether downsampling is supported for this file. - * @return Whether downsampling is supported. - */ - public boolean isDownsamplingSupported(MediaFile mediaFile) { - if (mediaFile != null) { - boolean isMp3 = "mp3".equalsIgnoreCase(mediaFile.getFormat()); - if (!isMp3) { - return false; - } - } - - String commandLine = settingsService.getDownsamplingCommand(); - return isTranscodingStepInstalled(commandLine); - } - - private boolean isTranscodingInstalled(Transcoding transcoding) { - return isTranscodingStepInstalled(transcoding.getStep1()) && - isTranscodingStepInstalled(transcoding.getStep2()) && - isTranscodingStepInstalled(transcoding.getStep3()); - } - - private boolean isTranscodingStepInstalled(String step) { - if (StringUtils.isEmpty(step)) { - return true; - } - String executable = StringUtil.split(step)[0]; - PrefixFileFilter filter = new PrefixFileFilter(executable); - String[] matches = getTranscodeDirectory().list(filter); - return matches != null && matches.length > 0; - } - - /** - * Returns the directory in which all transcoders are installed. - */ - public File getTranscodeDirectory() { - File dir = new File(SettingsService.getSubsonicHome(), "transcode"); - if (!dir.exists()) { - boolean ok = dir.mkdir(); - if (ok) { - LOG.info("Created directory " + dir); - } else { - LOG.warn("Failed to create directory " + dir); - } - } - return dir; - } - - public void setTranscodingDao(TranscodingDao transcodingDao) { - this.transcodingDao = transcodingDao; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } - - public void setPlayerService(PlayerService playerService) { - this.playerService = playerService; - } - - public static class Parameters { - private boolean downsample; - private final MediaFile mediaFile; - private final VideoTranscodingSettings videoTranscodingSettings; - private Integer maxBitRate; - private Transcoding transcoding; - - public Parameters(MediaFile mediaFile, VideoTranscodingSettings videoTranscodingSettings) { - this.mediaFile = mediaFile; - this.videoTranscodingSettings = videoTranscodingSettings; - } - - public void setMaxBitRate(Integer maxBitRate) { - this.maxBitRate = maxBitRate; - } - - public boolean isDownsample() { - return downsample; - } - - public void setDownsample(boolean downsample) { - this.downsample = downsample; - } - - public boolean isTranscode() { - return transcoding != null; - } - - public void setTranscoding(Transcoding transcoding) { - this.transcoding = transcoding; - } - - public Transcoding getTranscoding() { - return transcoding; - } - - public MediaFile getMediaFile() { - return mediaFile; - } - - public Integer getMaxBitRate() { - return maxBitRate; - } - - public VideoTranscodingSettings getVideoTranscodingSettings() { - return videoTranscodingSettings; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java deleted file mode 100644 index e24e6409..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.Version; -import org.apache.commons.io.IOUtils; -import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Provides version-related services, including functionality for determining whether a newer - * version of Subsonic is available. - * - * @author Sindre Mehus - */ -public class VersionService { - - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd"); - private static final Logger LOG = Logger.getLogger(VersionService.class); - - private Version localVersion; - private Version latestFinalVersion; - private Version latestBetaVersion; - private Date localBuildDate; - private String localBuildNumber; - - /** - * Time when latest version was fetched (in milliseconds). - */ - private long lastVersionFetched; - - /** - * Only fetch last version this often (in milliseconds.). - */ - private static final long LAST_VERSION_FETCH_INTERVAL = 7L * 24L * 3600L * 1000L; // One week - - /** - * URL from which to fetch latest versions. - */ - private static final String VERSION_URL = "http://subsonic.org/backend/version.view"; - - /** - * Returns the version number for the locally installed Subsonic version. - * - * @return The version number for the locally installed Subsonic version. - */ - public synchronized Version getLocalVersion() { - if (localVersion == null) { - try { - localVersion = new Version(readLineFromResource("/version.txt")); - LOG.info("Resolved local Subsonic version to: " + localVersion); - } catch (Exception x) { - LOG.warn("Failed to resolve local Subsonic version.", x); - } - } - return localVersion; - } - - /** - * Returns the version number for the latest available Subsonic final version. - * - * @return The version number for the latest available Subsonic final version, or null - * if the version number can't be resolved. - */ - public synchronized Version getLatestFinalVersion() { - refreshLatestVersion(); - return latestFinalVersion; - } - - /** - * Returns the version number for the latest available Subsonic beta version. - * - * @return The version number for the latest available Subsonic beta version, or null - * if the version number can't be resolved. - */ - public synchronized Version getLatestBetaVersion() { - refreshLatestVersion(); - return latestBetaVersion; - } - - /** - * Returns the build date for the locally installed Subsonic version. - * - * @return The build date for the locally installed Subsonic version, or null - * if the build date can't be resolved. - */ - public synchronized Date getLocalBuildDate() { - if (localBuildDate == null) { - try { - String date = readLineFromResource("/build_date.txt"); - localBuildDate = DATE_FORMAT.parse(date); - } catch (Exception x) { - LOG.warn("Failed to resolve local Subsonic build date.", x); - } - } - return localBuildDate; - } - - /** - * Returns the build number for the locally installed Subsonic version. - * - * @return The build number for the locally installed Subsonic version, or null - * if the build number can't be resolved. - */ - public synchronized String getLocalBuildNumber() { - if (localBuildNumber == null) { - try { - localBuildNumber = readLineFromResource("/build_number.txt"); - } catch (Exception x) { - LOG.warn("Failed to resolve local Subsonic build number.", x); - } - } - return localBuildNumber; - } - - /** - * Returns whether a new final version of Subsonic is available. - * - * @return Whether a new final version of Subsonic is available. - */ - public boolean isNewFinalVersionAvailable() { - Version latest = getLatestFinalVersion(); - Version local = getLocalVersion(); - - if (latest == null || local == null) { - return false; - } - - return local.compareTo(latest) < 0; - } - - /** - * Returns whether a new beta version of Subsonic is available. - * - * @return Whether a new beta version of Subsonic is available. - */ - public boolean isNewBetaVersionAvailable() { - Version latest = getLatestBetaVersion(); - Version local = getLocalVersion(); - - if (latest == null || local == null) { - return false; - } - - return local.compareTo(latest) < 0; - } - - /** - * Reads the first line from the resource with the given name. - * - * @param resourceName The resource name. - * @return The first line of the resource. - */ - private String readLineFromResource(String resourceName) { - InputStream in = VersionService.class.getResourceAsStream(resourceName); - if (in == null) { - return null; - } - BufferedReader reader = null; - try { - - reader = new BufferedReader(new InputStreamReader(in)); - return reader.readLine(); - - } catch (IOException x) { - return null; - } finally { - IOUtils.closeQuietly(reader); - IOUtils.closeQuietly(in); - } - } - - /** - * Refreshes the latest final and beta versions. - */ - private void refreshLatestVersion() { - long now = System.currentTimeMillis(); - boolean isOutdated = now - lastVersionFetched > LAST_VERSION_FETCH_INTERVAL; - - if (isOutdated) { - try { - lastVersionFetched = now; - readLatestVersion(); - } catch (Exception x) { - LOG.warn("Failed to resolve latest Subsonic version.", x); - } - } - } - - /** - * Resolves the latest available Subsonic version by screen-scraping a web page. - * - * @throws IOException If an I/O error occurs. - */ - private void readLatestVersion() throws IOException { - - HttpClient client = new DefaultHttpClient(); - HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000); - HttpConnectionParams.setSoTimeout(client.getParams(), 10000); - HttpGet method = new HttpGet(VERSION_URL + "?v=" + getLocalVersion()); - String content; - try { - - ResponseHandler responseHandler = new BasicResponseHandler(); - content = client.execute(method, responseHandler); - - } finally { - client.getConnectionManager().shutdown(); - } - - BufferedReader reader = new BufferedReader(new StringReader(content)); - Pattern finalPattern = Pattern.compile("SUBSONIC_FULL_VERSION_BEGIN(.*)SUBSONIC_FULL_VERSION_END"); - Pattern betaPattern = Pattern.compile("SUBSONIC_BETA_VERSION_BEGIN(.*)SUBSONIC_BETA_VERSION_END"); - - try { - String line = reader.readLine(); - while (line != null) { - Matcher finalMatcher = finalPattern.matcher(line); - if (finalMatcher.find()) { - latestFinalVersion = new Version(finalMatcher.group(1)); - LOG.info("Resolved latest Subsonic final version to: " + latestFinalVersion); - } - Matcher betaMatcher = betaPattern.matcher(line); - if (betaMatcher.find()) { - latestBetaVersion = new Version(betaMatcher.group(1)); - LOG.info("Resolved latest Subsonic beta version to: " + latestBetaVersion); - } - line = reader.readLine(); - } - - } finally { - reader.close(); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java deleted file mode 100644 index 902387be..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/AudioPlayer.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service.jukebox; - -import java.io.BufferedInputStream; -import java.io.InputStream; -import java.util.concurrent.atomic.AtomicReference; - -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.FloatControl; -import javax.sound.sampled.SourceDataLine; - -import org.apache.commons.io.IOUtils; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.service.JukeboxService; - -import static net.sourceforge.subsonic.service.jukebox.AudioPlayer.State.*; - -/** - * A simple wrapper for playing sound from an input stream. - *

- * Supports pause and resume, but not restarting. - * - * @author Sindre Mehus - * @version $Id$ - */ -public class AudioPlayer { - - private static final Logger LOG = Logger.getLogger(JukeboxService.class); - - private final InputStream in; - private final Listener listener; - private final SourceDataLine line; - private final AtomicReference state = new AtomicReference(PAUSED); - private FloatControl gainControl; - - public AudioPlayer(InputStream in, Listener listener) throws Exception { - this.in = new BufferedInputStream(in); - this.listener = listener; - - AudioFormat format = AudioSystem.getAudioFileFormat(this.in).getFormat(); - line = AudioSystem.getSourceDataLine(format); - line.open(format); - LOG.debug("Opened line " + line); - - if (line.isControlSupported(FloatControl.Type.MASTER_GAIN)) { - gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); - setGain(0.5f); - } - new AudioDataWriter(); - } - - /** - * Starts (or resumes) the player. This only has effect if the current state is - * {@link State#PAUSED}. - */ - public synchronized void play() { - if (state.get() == PAUSED) { - line.start(); - setState(PLAYING); - } - } - - /** - * Pauses the player. This only has effect if the current state is - * {@link State#PLAYING}. - */ - public synchronized void pause() { - if (state.get() == PLAYING) { - setState(PAUSED); - line.stop(); - line.flush(); - } - } - - /** - * Closes the player, releasing all resources. After this the player state is - * {@link State#CLOSED} (unless the current state is {@link State#EOM}). - */ - public synchronized void close() { - if (state.get() != CLOSED && state.get() != EOM) { - setState(CLOSED); - } - - try { - line.stop(); - } catch (Throwable x) { - LOG.warn("Failed to stop player: " + x, x); - } - try { - if (line.isOpen()) { - line.close(); - LOG.debug("Closed line " + line); - } - } catch (Throwable x) { - LOG.warn("Failed to close player: " + x, x); - } - IOUtils.closeQuietly(in); - } - - /** - * Returns the player state. - */ - public State getState() { - return state.get(); - } - - /** - * Sets the gain. - * - * @param gain The gain between 0.0 and 1.0. - */ - public void setGain(float gain) { - if (gainControl != null) { - - double minGainDB = gainControl.getMinimum(); - double maxGainDB = gainControl.getMaximum(); - double ampGainDB = 0.5f * maxGainDB - minGainDB; - double cste = Math.log(10.0) / 20; - double valueDB = minGainDB + (1 / cste) * Math.log(1 + (Math.exp(cste * ampGainDB) - 1) * gain); - - valueDB = Math.min(valueDB, maxGainDB); - valueDB = Math.max(valueDB, minGainDB); - - gainControl.setValue((float) valueDB); - } - } - - /** - * Returns the position in seconds. - */ - public int getPosition() { - return (int) (line.getMicrosecondPosition() / 1000000L); - } - - private void setState(State state) { - if (this.state.getAndSet(state) != state && listener != null) { - listener.stateChanged(this, state); - } - } - - private class AudioDataWriter implements Runnable { - - public AudioDataWriter() { - new Thread(this).start(); - } - - public void run() { - try { - byte[] buffer = new byte[8192]; - - while (true) { - - switch (state.get()) { - case CLOSED: - case EOM: - return; - case PAUSED: - Thread.sleep(250); - break; - case PLAYING: - int n = in.read(buffer); - if (n == -1) { - setState(EOM); - return; - } - line.write(buffer, 0, n); - break; - } - } - } catch (Throwable x) { - LOG.warn("Error when copying audio data: " + x, x); - } finally { - close(); - } - } - } - - public interface Listener { - void stateChanged(AudioPlayer player, State state); - } - - public static enum State { - PAUSED, - PLAYING, - CLOSED, - EOM - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/PlayerTest.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/PlayerTest.java deleted file mode 100644 index 30ed2847..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/jukebox/PlayerTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package net.sourceforge.subsonic.service.jukebox; - -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.FileInputStream; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JSlider; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -/** - * @author Sindre Mehus - * @version $Id$ - */ -public class PlayerTest implements AudioPlayer.Listener { - - private AudioPlayer player; - - public PlayerTest() throws Exception { - player = new AudioPlayer(new FileInputStream("i:\\tmp\\foo.au"), this); - createGUI(); - } - - private void createGUI() { - JFrame frame = new JFrame(); - - JButton startButton = new JButton("Start"); - JButton stopButton = new JButton("Stop"); - JButton resetButton = new JButton("Reset"); - final JSlider gainSlider = new JSlider(0, 1000); - - startButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - player.play(); - } - }); - stopButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - player.pause(); - } - }); - resetButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - player.close(); - } - }); - gainSlider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - float gain = (float) gainSlider.getValue() / 1000.0F; - player.setGain(gain); - } - }); - - frame.setLayout(new FlowLayout()); - frame.add(startButton); - frame.add(stopButton); - frame.add(resetButton); - frame.add(gainSlider); - - frame.pack(); - frame.setVisible(true); - } - - public static void main(String[] args) throws Exception { - new PlayerTest(); - } - - public void stateChanged(AudioPlayer player, AudioPlayer.State state) { - System.out.println(state); - } -} - diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/DefaultMetaDataParser.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/DefaultMetaDataParser.java deleted file mode 100644 index 897f39d4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/DefaultMetaDataParser.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service.metadata; - -import java.io.File; - -import net.sourceforge.subsonic.domain.MediaFile; - -/** - * Parses meta data by guessing artist, album and song title based on the path of the file. - * - * @author Sindre Mehus - */ -public class DefaultMetaDataParser extends MetaDataParser { - - /** - * Parses meta data for the given file. No guessing or reformatting is done. - * - * @param file The file to parse. - * @return Meta data for the file. - */ - public MetaData getRawMetaData(File file) { - MetaData metaData = new MetaData(); - metaData.setArtist(guessArtist(file)); - metaData.setAlbumName(guessAlbum(file, metaData.getArtist())); - metaData.setTitle(guessTitle(file)); - return metaData; - } - - /** - * Updates the given file with the given meta data. - * This method has no effect. - * - * @param file The file to update. - * @param metaData The new meta data. - */ - public void setMetaData(MediaFile file, MetaData metaData) { - } - - /** - * Returns whether this parser supports tag editing (using the {@link #setMetaData} method). - * - * @return Always false. - */ - public boolean isEditingSupported() { - return false; - } - - /** - * Returns whether this parser is applicable to the given file. - * - * @param file The file in question. - * @return Whether this parser is applicable to the given file. - */ - public boolean isApplicable(File file) { - return file.isFile(); - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/FFmpegParser.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/FFmpegParser.java deleted file mode 100644 index 60ae1750..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/FFmpegParser.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service.metadata; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.io.InputStreamReaderThread; -import net.sourceforge.subsonic.service.ServiceLocator; -import net.sourceforge.subsonic.service.TranscodingService; -import net.sourceforge.subsonic.util.StringUtil; -import org.apache.commons.io.FilenameUtils; - -import java.io.File; -import java.io.InputStream; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Parses meta data from video files using FFmpeg (http://ffmpeg.org/). - *

- * Currently duration, bitrate and dimension are supported. - * - * @author Sindre Mehus - */ -public class FFmpegParser extends MetaDataParser { - - private static final Logger LOG = Logger.getLogger(FFmpegParser.class); - private static final Pattern DURATION_PATTERN = Pattern.compile("Duration: (\\d+):(\\d+):(\\d+).(\\d+)"); - private static final Pattern BITRATE_PATTERN = Pattern.compile("bitrate: (\\d+) kb/s"); - private static final Pattern DIMENSION_PATTERN = Pattern.compile("Video.*?, (\\d+)x(\\d+)"); - private static final Pattern PAR_PATTERN = Pattern.compile("PAR (\\d+):(\\d+)"); - - private TranscodingService transcodingService; - - /** - * Parses meta data for the given music file. No guessing or reformatting is done. - * - * - * @param file The music file to parse. - * @return Meta data for the file. - */ - @Override - public MetaData getRawMetaData(File file) { - - MetaData metaData = new MetaData(); - - try { - - File ffmpeg = new File(transcodingService.getTranscodeDirectory(), "ffmpeg"); - - String[] command = new String[]{ffmpeg.getAbsolutePath(), "-i", file.getAbsolutePath()}; - Process process = Runtime.getRuntime().exec(command); - InputStream stdout = process.getInputStream(); - InputStream stderr = process.getErrorStream(); - - // Consume stdout, we're not interested in that. - new InputStreamReaderThread(stdout, "ffmpeg", true).start(); - - // Read everything from stderr. It will contain text similar to: - // Input #0, avi, from 'foo.avi': - // Duration: 00:00:33.90, start: 0.000000, bitrate: 2225 kb/s - // Stream #0.0: Video: mpeg4, yuv420p, 352x240 [PAR 1:1 DAR 22:15], 29.97 fps, 29.97 tbr, 29.97 tbn, 30k tbc - // Stream #0.1: Audio: pcm_s16le, 44100 Hz, 2 channels, s16, 1411 kb/s - String[] lines = StringUtil.readLines(stderr); - - Integer width = null; - Integer height = null; - Double par = 1.0; - for (String line : lines) { - - Matcher matcher = DURATION_PATTERN.matcher(line); - if (matcher.find()) { - int hours = Integer.parseInt(matcher.group(1)); - int minutes = Integer.parseInt(matcher.group(2)); - int seconds = Integer.parseInt(matcher.group(3)); - metaData.setDurationSeconds(hours * 3600 + minutes * 60 + seconds); - } - - matcher = BITRATE_PATTERN.matcher(line); - if (matcher.find()) { - metaData.setBitRate(Integer.valueOf(matcher.group(1))); - } - - matcher = DIMENSION_PATTERN.matcher(line); - if (matcher.find()) { - width = Integer.valueOf(matcher.group(1)); - height = Integer.valueOf(matcher.group(2)); - } - - // PAR = Pixel Aspect Rate - matcher = PAR_PATTERN.matcher(line); - if (matcher.find()) { - int a = Integer.parseInt(matcher.group(1)); - int b = Integer.parseInt(matcher.group(2)); - if (a > 0 && b > 0) { - par = (double) a / (double) b; - } - } - } - - if (width != null && height != null) { - width = (int) Math.round(width.doubleValue() * par); - metaData.setWidth(width); - metaData.setHeight(height); - } - - - } catch (Throwable x) { - LOG.warn("Error when parsing metadata in " + file, x); - } - - return metaData; - } - - /** - * Not supported. - */ - @Override - public void setMetaData(MediaFile file, MetaData metaData) { - throw new RuntimeException("setMetaData() not supported in " + getClass().getSimpleName()); - } - - /** - * Returns whether this parser supports tag editing (using the {@link #setMetaData} method). - * - * @return Always false. - */ - @Override - public boolean isEditingSupported() { - return false; - } - - /** - * Returns whether this parser is applicable to the given file. - * - * @param file The file in question. - * @return Whether this parser is applicable to the given file. - */ - @Override - public boolean isApplicable(File file) { - String format = FilenameUtils.getExtension(file.getName()).toLowerCase(); - - for (String s : ServiceLocator.getSettingsService().getVideoFileTypesAsArray()) { - if (format.equals(s)) { - return true; - } - } - return false; - } - - public void setTranscodingService(TranscodingService transcodingService) { - this.transcodingService = transcodingService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/JaudiotaggerParser.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/JaudiotaggerParser.java deleted file mode 100644 index 8fa7659a..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/JaudiotaggerParser.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service.metadata; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.domain.MediaFile; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.StringUtils; -import org.jaudiotagger.audio.AudioFile; -import org.jaudiotagger.audio.AudioFileIO; -import org.jaudiotagger.audio.AudioHeader; -import org.jaudiotagger.tag.FieldKey; -import org.jaudiotagger.tag.Tag; -import org.jaudiotagger.tag.datatype.Artwork; -import org.jaudiotagger.tag.reference.GenreTypes; - -import java.io.File; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.logging.LogManager; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Parses meta data from audio files using the Jaudiotagger library - * (http://www.jthink.net/jaudiotagger/) - * - * @author Sindre Mehus - */ -public class JaudiotaggerParser extends MetaDataParser { - - private static final Logger LOG = Logger.getLogger(JaudiotaggerParser.class); - private static final Pattern GENRE_PATTERN = Pattern.compile("\\((\\d+)\\).*"); - private static final Pattern TRACK_NUMBER_PATTERN = Pattern.compile("(\\d+)/\\d+"); - - static { - try { - LogManager.getLogManager().reset(); - } catch (Throwable x) { - LOG.warn("Failed to turn off logging from Jaudiotagger.", x); - } - } - - /** - * Parses meta data for the given music file. No guessing or reformatting is done. - * - * - * @param file The music file to parse. - * @return Meta data for the file. - */ - @Override - public MetaData getRawMetaData(File file) { - - MetaData metaData = new MetaData(); - - try { - AudioFile audioFile = AudioFileIO.read(file); - Tag tag = audioFile.getTag(); - if (tag != null) { - metaData.setAlbumName(getTagField(tag, FieldKey.ALBUM)); - metaData.setTitle(getTagField(tag, FieldKey.TITLE)); - metaData.setYear(parseInteger(getTagField(tag, FieldKey.YEAR))); - metaData.setGenre(mapGenre(getTagField(tag, FieldKey.GENRE))); - metaData.setDiscNumber(parseInteger(getTagField(tag, FieldKey.DISC_NO))); - metaData.setTrackNumber(parseTrackNumber(getTagField(tag, FieldKey.TRACK))); - - String songArtist = getTagField(tag, FieldKey.ARTIST); - String albumArtist = getTagField(tag, FieldKey.ALBUM_ARTIST); - metaData.setArtist(StringUtils.isBlank(albumArtist) ? songArtist : albumArtist); - } - - AudioHeader audioHeader = audioFile.getAudioHeader(); - if (audioHeader != null) { - metaData.setVariableBitRate(audioHeader.isVariableBitRate()); - metaData.setBitRate((int) audioHeader.getBitRateAsNumber()); - metaData.setDurationSeconds(audioHeader.getTrackLength()); - } - - - } catch (Throwable x) { - LOG.warn("Error when parsing tags in " + file, x); - } - - return metaData; - } - - private String getTagField(Tag tag, FieldKey fieldKey) { - try { - return StringUtils.trimToNull(tag.getFirst(fieldKey)); - } catch (Exception x) { - // Ignored. - return null; - } - } - - /** - * Returns all tags supported by id3v1. - */ - public static SortedSet getID3V1Genres() { - return new TreeSet(GenreTypes.getInstanceOf().getAlphabeticalValueList()); - } - - /** - * Sometimes the genre is returned as "(17)" or "(17)Rock", instead of "Rock". This method - * maps the genre ID to the corresponding text. - */ - private String mapGenre(String genre) { - if (genre == null) { - return null; - } - Matcher matcher = GENRE_PATTERN.matcher(genre); - if (matcher.matches()) { - int genreId = Integer.parseInt(matcher.group(1)); - if (genreId >= 0 && genreId < GenreTypes.getInstanceOf().getSize()) { - return GenreTypes.getInstanceOf().getValueForId(genreId); - } - } - return genre; - } - - /** - * Parses the track number from the given string. Also supports - * track numbers on the form "4/12". - */ - private Integer parseTrackNumber(String trackNumber) { - if (trackNumber == null) { - return null; - } - - Integer result = null; - - try { - result = new Integer(trackNumber); - } catch (NumberFormatException x) { - Matcher matcher = TRACK_NUMBER_PATTERN.matcher(trackNumber); - if (matcher.matches()) { - try { - result = Integer.valueOf(matcher.group(1)); - } catch (NumberFormatException e) { - return null; - } - } - } - - if (Integer.valueOf(0).equals(result)) { - return null; - } - return result; - } - - private Integer parseInteger(String s) { - s = StringUtils.trimToNull(s); - if (s == null) { - return null; - } - try { - Integer result = Integer.valueOf(s); - if (Integer.valueOf(0).equals(result)) { - return null; - } - return result; - } catch (NumberFormatException x) { - return null; - } - } - - /** - * Updates the given file with the given meta data. - * - * @param file The music file to update. - * @param metaData The new meta data. - */ - @Override - public void setMetaData(MediaFile file, MetaData metaData) { - - try { - AudioFile audioFile = AudioFileIO.read(file.getFile()); - Tag tag = audioFile.getTagOrCreateAndSetDefault(); - - tag.setField(FieldKey.ARTIST, StringUtils.trimToEmpty(metaData.getArtist())); - tag.setField(FieldKey.ALBUM_ARTIST, StringUtils.trimToEmpty(metaData.getArtist())); - tag.setField(FieldKey.ALBUM, StringUtils.trimToEmpty(metaData.getAlbumName())); - tag.setField(FieldKey.TITLE, StringUtils.trimToEmpty(metaData.getTitle())); - tag.setField(FieldKey.GENRE, StringUtils.trimToEmpty(metaData.getGenre())); - - Integer track = metaData.getTrackNumber(); - if (track == null) { - tag.deleteField(FieldKey.TRACK); - } else { - tag.setField(FieldKey.TRACK, String.valueOf(track)); - } - - Integer year = metaData.getYear(); - if (year == null) { - tag.deleteField(FieldKey.YEAR); - } else { - tag.setField(FieldKey.YEAR, String.valueOf(year)); - } - - audioFile.commit(); - - } catch (Throwable x) { - LOG.warn("Failed to update tags for file " + file, x); - throw new RuntimeException("Failed to update tags for file " + file + ". " + x.getMessage(), x); - } - } - - /** - * Returns whether this parser supports tag editing (using the {@link #setMetaData} method). - * - * @return Always true. - */ - @Override - public boolean isEditingSupported() { - return true; - } - - /** - * Returns whether this parser is applicable to the given file. - * - * @param file The music file in question. - * @return Whether this parser is applicable to the given file. - */ - @Override - public boolean isApplicable(File file) { - if (!file.isFile()) { - return false; - } - - String format = FilenameUtils.getExtension(file.getName()).toLowerCase(); - - return format.equals("mp3") || - format.equals("m4a") || - format.equals("aac") || - format.equals("ogg") || - format.equals("flac") || - format.equals("wav") || - format.equals("mpc") || - format.equals("mp+") || - format.equals("ape") || - format.equals("wma"); - } - - /** - * Returns whether cover art image data is available in the given file. - * - * @param file The music file. - * @return Whether cover art image data is available. - */ - public boolean isImageAvailable(MediaFile file) { - try { - return getArtwork(file) != null; - } catch (Throwable x) { - LOG.warn("Failed to find cover art tag in " + file, x); - return false; - } - } - - /** - * Returns the cover art image data embedded in the given file. - * - * @param file The music file. - * @return The embedded cover art image data, or null if not available. - */ - public byte[] getImageData(MediaFile file) { - try { - return getArtwork(file).getBinaryData(); - } catch (Throwable x) { - LOG.warn("Failed to find cover art tag in " + file, x); - return null; - } - } - - private Artwork getArtwork(MediaFile file) throws Exception { - AudioFile audioFile = AudioFileIO.read(file.getFile()); - Tag tag = audioFile.getTag(); - return tag == null ? null : tag.getFirstArtwork(); - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaData.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaData.java deleted file mode 100644 index d3fa08a0..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaData.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service.metadata; - -/** - * Contains meta-data (song title, artist, album etc) for a music file. - * @author Sindre Mehus - */ -public class MetaData { - - private Integer discNumber; - private Integer trackNumber; - private String title; - private String artist; - private String albumName; - private String genre; - private Integer year; - private Integer bitRate; - private boolean variableBitRate; - private Integer durationSeconds; - private Integer width; - private Integer height; - - public Integer getDiscNumber() { - return discNumber; - } - - public void setDiscNumber(Integer discNumber) { - this.discNumber = discNumber; - } - - public Integer getTrackNumber() { - return trackNumber; - } - - public void setTrackNumber(Integer trackNumber) { - this.trackNumber = trackNumber; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getArtist() { - return artist; - } - - public void setArtist(String artist) { - this.artist = artist; - } - - public String getAlbumName() { - return albumName; - } - - public void setAlbumName(String albumName) { - this.albumName = albumName; - } - - public String getGenre() { - return genre; - } - - public void setGenre(String genre) { - this.genre = genre; - } - - public Integer getYear() { - return year; - } - - public void setYear(Integer year) { - this.year = year; - } - - public Integer getBitRate() { - return bitRate; - } - - public void setBitRate(Integer bitRate) { - this.bitRate = bitRate; - } - - public boolean getVariableBitRate() { - return variableBitRate; - } - - public void setVariableBitRate(boolean variableBitRate) { - this.variableBitRate = variableBitRate; - } - - public Integer getDurationSeconds() { - return durationSeconds; - } - - public void setDurationSeconds(Integer durationSeconds) { - this.durationSeconds = durationSeconds; - } - - public Integer getWidth() { - return width; - } - - public void setWidth(Integer width) { - this.width = width; - } - - public Integer getHeight() { - return height; - } - - public void setHeight(Integer height) { - this.height = height; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaDataParser.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaDataParser.java deleted file mode 100644 index 2ed70acc..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaDataParser.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service.metadata; - -import java.io.File; -import java.util.List; - -import org.apache.commons.io.FilenameUtils; - -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.domain.MusicFolder; -import net.sourceforge.subsonic.service.ServiceLocator; -import net.sourceforge.subsonic.service.SettingsService; - - -/** - * Parses meta data from media files. - * - * @author Sindre Mehus - */ -public abstract class MetaDataParser { - - /** - * Parses meta data for the given file. - * - * @param file The file to parse. - * @return Meta data for the file, never null. - */ - public MetaData getMetaData(File file) { - - MetaData metaData = getRawMetaData(file); - String artist = metaData.getArtist(); - String album = metaData.getAlbumName(); - String title = metaData.getTitle(); - - if (artist == null) { - artist = guessArtist(file); - } - if (album == null) { - album = guessAlbum(file, artist); - } - if (title == null) { - title = guessTitle(file); - } - - title = removeTrackNumberFromTitle(title, metaData.getTrackNumber()); - metaData.setArtist(artist); - metaData.setAlbumName(album); - metaData.setTitle(title); - - return metaData; - } - - /** - * Parses meta data for the given file. No guessing or reformatting is done. - * - * - * @param file The file to parse. - * @return Meta data for the file. - */ - public abstract MetaData getRawMetaData(File file); - - /** - * Updates the given file with the given meta data. - * - * @param file The file to update. - * @param metaData The new meta data. - */ - public abstract void setMetaData(MediaFile file, MetaData metaData); - - /** - * Returns whether this parser is applicable to the given file. - * - * @param file The file in question. - * @return Whether this parser is applicable to the given file. - */ - public abstract boolean isApplicable(File file); - - /** - * Returns whether this parser supports tag editing (using the {@link #setMetaData} method). - * - * @return Whether tag editing is supported. - */ - public abstract boolean isEditingSupported(); - - /** - * Guesses the artist for the given file. - */ - public String guessArtist(File file) { - File parent = file.getParentFile(); - if (isRoot(parent)) { - return null; - } - File grandParent = parent.getParentFile(); - return isRoot(grandParent) ? null : grandParent.getName(); - } - - /** - * Guesses the album for the given file. - */ - public String guessAlbum(File file, String artist) { - File parent = file.getParentFile(); - String album = isRoot(parent) ? null : parent.getName(); - if (artist != null && album != null) { - album = album.replace(artist + " - ", ""); - } - return album; - } - - /** - * Guesses the title for the given file. - */ - public String guessTitle(File file) { - return removeTrackNumberFromTitle(FilenameUtils.getBaseName(file.getPath()), null); - } - - private boolean isRoot(File file) { - SettingsService settings = ServiceLocator.getSettingsService(); - List folders = settings.getAllMusicFolders(false, true); - for (MusicFolder folder : folders) { - if (file.equals(folder.getPath())) { - return true; - } - } - return false; - } - - /** - * Removes any prefixed track number from the given title string. - * - * @param title The title with or without a prefixed track number, e.g., "02 - Back In Black". - * @param trackNumber If specified, this is the "true" track number. - * @return The title with the track number removed, e.g., "Back In Black". - */ - protected String removeTrackNumberFromTitle(String title, Integer trackNumber) { - title = title.trim(); - - // Don't remove numbers if true track number is given, and title does not start with it. - if (trackNumber != null && !title.matches("0?" + trackNumber + "[\\.\\- ].*")) { - return title; - } - - String result = title.replaceFirst("^\\d{2}[\\.\\- ]+", ""); - return result.length() == 0 ? title : result; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaDataParserFactory.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaDataParserFactory.java deleted file mode 100644 index 31b56be4..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/metadata/MetaDataParserFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.service.metadata; - -import java.io.File; -import java.util.List; - -/** - * Factory for creating meta-data parsers. - * - * @author Sindre Mehus - */ -public class MetaDataParserFactory { - - private List parsers; - - public void setParsers(List parsers) { - this.parsers = parsers; - } - - /** - * Returns a meta-data parser for the given file. - * - * @param file The file in question. - * @return An applicable parser, or null if no parser is found. - */ - public MetaDataParser getParser(File file) { - for (MetaDataParser parser : parsers) { - if (parser.isApplicable(file)) { - return parser; - } - } - return null; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/EscapeJavaScriptTag.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/EscapeJavaScriptTag.java deleted file mode 100644 index c7c09677..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/EscapeJavaScriptTag.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.taglib; - -import org.apache.commons.lang.StringEscapeUtils; - -import javax.servlet.jsp.JspException; -import javax.servlet.jsp.JspTagException; -import javax.servlet.jsp.tagext.BodyTagSupport; -import java.io.IOException; - -/** - * Escapes the characters in a String using JavaScript String rules. - *

- * Escapes any values it finds into their JavaScript String form. - * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) - *

- * So a tab becomes the characters '\\' and - * 't'. - *

- * The only difference between Java strings and JavaScript strings - * is that in JavaScript, a single quote must be escaped. - *

- * Example: - *

- * input string: He didn't say, "Stop!"
- * output string: He didn\'t say, \"Stop!\"
- * 
- * - * @author Sindre Mehus - */ -public class EscapeJavaScriptTag extends BodyTagSupport { - - private String string; - - public int doStartTag() throws JspException { - return EVAL_BODY_BUFFERED; - } - - public int doEndTag() throws JspException { - try { - pageContext.getOut().print(StringEscapeUtils.escapeJavaScript(string)); - } catch (IOException x) { - throw new JspTagException(x); - } - return EVAL_PAGE; - } - - public void release() { - string = null; - super.release(); - } - - public String getString() { - return string; - } - - public void setString(String string) { - this.string = string; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/FormatBytesTag.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/FormatBytesTag.java deleted file mode 100644 index 0279316b..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/FormatBytesTag.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.taglib; - -import net.sourceforge.subsonic.util.*; -import org.springframework.web.servlet.support.*; - -import javax.servlet.http.*; -import javax.servlet.jsp.*; -import javax.servlet.jsp.tagext.*; -import java.io.*; -import java.util.*; - -/** - * Converts a byte-count to a formatted string suitable for display to the user, with respect - * to the current locale. - *

- * For instance: - *

    - *
  • format(918) returns "918 B".
  • - *
  • format(98765) returns "96 KB".
  • - *
  • format(1238476) returns "1.2 MB".
  • - *
- * This class assumes that 1 KB is 1024 bytes. - * - * @author Sindre Mehus - */ -public class FormatBytesTag extends BodyTagSupport { - - private long bytes; - - public int doStartTag() throws JspException { - return EVAL_BODY_BUFFERED; - } - - public int doEndTag() throws JspException { - Locale locale = RequestContextUtils.getLocale((HttpServletRequest) pageContext.getRequest()); - String result = StringUtil.formatBytes(bytes, locale); - - try { - pageContext.getOut().print(result); - } catch (IOException x) { - throw new JspTagException(x); - } - return EVAL_PAGE; - } - - public void release() { - bytes = 0L; - super.release(); - } - - public long getBytes() { - return bytes; - } - - public void setBytes(long bytes) { - this.bytes = bytes; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/ParamTag.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/ParamTag.java deleted file mode 100644 index 1043902e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/ParamTag.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.taglib; - -import javax.servlet.jsp.tagext.*; -import javax.servlet.jsp.*; - -/** - * A tag representing an URL query parameter. - * - * @see ParamTag - * @author Sindre Mehus - */ -public class ParamTag extends TagSupport { - - private String name; - private String value; - - public int doEndTag() throws JspTagException { - - // Add parameter name and value to surrounding 'url' tag. - UrlTag tag = (UrlTag) findAncestorWithClass(this, UrlTag.class); - if (tag == null) { - throw new JspTagException("'sub:param' tag used outside 'sub:url'"); - } - tag.addParameter(name, value); - return EVAL_PAGE; - } - - public void release() { - name = null; - value = null; - super.release(); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/UrlTag.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/UrlTag.java deleted file mode 100644 index 141ba847..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/UrlTag.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.taglib; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.filter.ParameterDecodingFilter; -import net.sourceforge.subsonic.util.StringUtil; -import org.apache.taglibs.standard.tag.common.core.UrlSupport; -import org.apache.commons.lang.CharUtils; - -import javax.servlet.jsp.JspException; -import javax.servlet.jsp.JspTagException; -import javax.servlet.jsp.PageContext; -import javax.servlet.jsp.tagext.BodyTagSupport; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; - -/** - * Creates a URL with optional query parameters. Similar to 'c:url', but - * you may specify which character encoding to use for the URL query - * parameters. If no encoding is specified, the following steps are performed: - *
    - *
  • Parameter values are encoded as the hexadecimal representation of the UTF-8 bytes of the original string.
  • - *
  • Parameter names are prepended with the suffix "Utf8Hex"
  • - *
  • Note: Nothing is done with the parameter name or value if the value only contains ASCII alphanumeric characters.
  • - *
- *

- * (The problem with c:url is that is uses the same encoding as the http response, - * but most(?) servlet container assumes that ISO-8859-1 is used.) - * - * @author Sindre Mehus - */ -public class UrlTag extends BodyTagSupport { - - private String DEFAULT_ENCODING = "Utf8Hex"; - private static final Logger LOG = Logger.getLogger(UrlTag.class); - - private String var; - private String value; - private String encoding = DEFAULT_ENCODING; - private List parameters = new ArrayList(); - - public int doStartTag() throws JspException { - parameters.clear(); - return EVAL_BODY_BUFFERED; - } - - public int doEndTag() throws JspException { - - // Rewrite and encode the url. - String result = formatUrl(); - - // Store or print the output - if (var != null) - pageContext.setAttribute(var, result, PageContext.PAGE_SCOPE); - else { - try { - pageContext.getOut().print(result); - } catch (IOException x) { - throw new JspTagException(x); - } - } - return EVAL_PAGE; - } - - private String formatUrl() throws JspException { - String baseUrl = UrlSupport.resolveUrl(value, null, pageContext); - - StringBuffer result = new StringBuffer(); - result.append(baseUrl); - if (!parameters.isEmpty()) { - result.append('?'); - - for (int i = 0; i < parameters.size(); i++) { - Parameter parameter = parameters.get(i); - try { - result.append(parameter.getName()); - if (isUtf8Hex() && !isAsciiAlphaNumeric(parameter.getValue())) { - result.append(ParameterDecodingFilter.PARAM_SUFFIX); - } - - result.append('='); - if (parameter.getValue() != null) { - result.append(encode(parameter.getValue())); - } - if (i < parameters.size() - 1) { - result.append("&"); - } - - } catch (UnsupportedEncodingException x) { - throw new JspTagException(x); - } - } - } - return result.toString(); - } - - private String encode(String s) throws UnsupportedEncodingException { - if (isUtf8Hex()) { - if (isAsciiAlphaNumeric(s)) { - return s; - } - - try { - return StringUtil.utf8HexEncode(s); - } catch (Exception x) { - LOG.error("Failed to utf8hex-encode the string '" + s + "'.", x); - return s; - } - } - - return URLEncoder.encode(s, encoding); - } - - private boolean isUtf8Hex() { - return DEFAULT_ENCODING.equals(encoding); - } - - private boolean isAsciiAlphaNumeric(String s) { - if (s == null) { - return true; - } - - for (int i = 0; i < s.length(); i++) { - if (!CharUtils.isAsciiAlphanumeric(s.charAt(i))) { - return false; - } - } - return true; - } - - public void release() { - var = null; - value = null; - encoding = DEFAULT_ENCODING; - parameters.clear(); - super.release(); - } - - public void addParameter(String name, String value) { - parameters.add(new Parameter(name, value)); - } - - public String getVar() { - return var; - } - - public void setVar(String var) { - this.var = var; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - /** - * A URL query parameter. - */ - private static class Parameter { - private String name; - private String value; - - private Parameter(String name, String value) { - this.name = name; - this.value = value; - } - - private String getName() { - return name; - } - - private String getValue() { - return value; - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/WikiTag.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/WikiTag.java deleted file mode 100644 index e099bd1e..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/taglib/WikiTag.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.taglib; - -import org.radeox.api.engine.*; -import org.radeox.api.engine.context.*; -import org.radeox.engine.*; -import org.radeox.engine.context.*; -import org.apache.commons.lang.*; - -import javax.servlet.jsp.*; -import javax.servlet.jsp.tagext.*; -import java.io.*; - -/** - * Renders a Wiki text with markup to HTML, using the Radeox render engine. - * - * @author Sindre Mehus - */ -public class WikiTag extends BodyTagSupport { - - private static final RenderContext RENDER_CONTEXT = new BaseRenderContext(); - private static final RenderEngine RENDER_ENGINE = new BaseRenderEngine(); - - private String text; - - public int doStartTag() throws JspException { - return EVAL_BODY_BUFFERED; - } - - public int doEndTag() throws JspException { - String result; - synchronized (RENDER_ENGINE) { - result = RENDER_ENGINE.render(StringEscapeUtils.unescapeXml(text), RENDER_CONTEXT); - } - try { - pageContext.getOut().print(result); - } catch (IOException x) { - throw new JspTagException(x); - } - return EVAL_PAGE; - } - - public void release() { - text = null; - super.release(); - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/theme/SubsonicThemeResolver.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/theme/SubsonicThemeResolver.java deleted file mode 100644 index 874c2e9c..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/theme/SubsonicThemeResolver.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.theme; - -import net.sourceforge.subsonic.service.*; -import net.sourceforge.subsonic.domain.*; -import org.springframework.web.servlet.*; - -import javax.servlet.http.*; -import java.util.*; - -/** - * Theme resolver implementation which returns the theme selected in the settings. - * - * @author Sindre Mehus - */ -public class SubsonicThemeResolver implements ThemeResolver { - - private SecurityService securityService; - private SettingsService settingsService; - private Set themeIds; - - /** - * Resolve the current theme name via the given request. - * - * @param request Request to be used for resolution - * @return The current theme name - */ - public String resolveThemeName(HttpServletRequest request) { - String themeId = (String) request.getAttribute("subsonic.theme"); - if (themeId != null) { - return themeId; - } - - // Optimization: Cache theme in the request. - themeId = doResolveThemeName(request); - request.setAttribute("subsonic.theme", themeId); - - return themeId; - } - - private String doResolveThemeName(HttpServletRequest request) { - String themeId = null; - - // Look for user-specific theme. - String username = securityService.getCurrentUsername(request); - if (username != null) { - UserSettings userSettings = settingsService.getUserSettings(username); - if (userSettings != null) { - themeId = userSettings.getThemeId(); - } - } - - if (themeId != null && themeExists(themeId)) { - return themeId; - } - - // Return system theme. - themeId = settingsService.getThemeId(); - return themeExists(themeId) ? themeId : "default"; - } - - /** - * Returns whether the theme with the given ID exists. - * @param themeId The theme ID. - * @return Whether the theme with the given ID exists. - */ - private synchronized boolean themeExists(String themeId) { - // Lazily create set of theme IDs. - if (themeIds == null) { - themeIds = new HashSet(); - Theme[] themes = settingsService.getAvailableThemes(); - for (Theme theme : themes) { - themeIds.add(theme.getId()); - } - } - - return themeIds.contains(themeId); - } - - /** - * Set the current theme name to the given one. This method is not supported. - * - * @param request Request to be used for theme name modification - * @param response Response to be used for theme name modification - * @param themeName The new theme name - * @throws UnsupportedOperationException If the ThemeResolver implementation - * does not support dynamic changing of the theme - */ - public void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName) { - throw new UnsupportedOperationException("Cannot change theme - use a different theme resolution strategy"); - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/theme/SubsonicThemeSource.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/theme/SubsonicThemeSource.java deleted file mode 100644 index 61db6516..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/theme/SubsonicThemeSource.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.theme; - -import org.springframework.ui.context.support.ResourceBundleThemeSource; -import org.springframework.context.MessageSource; -import org.springframework.context.support.ResourceBundleMessageSource; - -/** - * Theme source implementation which uses two resource bundles: the - * theme specific (e.g., barents.properties), and the default (default.properties). - * - * @author Sindre Mehus - */ -public class SubsonicThemeSource extends ResourceBundleThemeSource { - - private String defaultResourceBundle; - - @Override - protected MessageSource createMessageSource(String basename) { - ResourceBundleMessageSource messageSource = (ResourceBundleMessageSource) super.createMessageSource(basename); - - ResourceBundleMessageSource parentMessageSource = new ResourceBundleMessageSource(); - parentMessageSource.setBasename(defaultResourceBundle); - messageSource.setParentMessageSource(parentMessageSource); - - return messageSource; - } - - public void setDefaultResourceBundle(String defaultResourceBundle) { - this.defaultResourceBundle = defaultResourceBundle; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredDiskFileItem.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredDiskFileItem.java deleted file mode 100644 index f9b89bb7..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredDiskFileItem.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.upload; - -import org.apache.commons.fileupload.disk.DiskFileItem; - -import java.io.File; -import java.io.OutputStream; -import java.io.IOException; - -/** - * Extension of Commons FileUpload for monitoring the upload progress. - * - * @author Pierre-Alexandre Losson -- http://www.telio.be/blog -- plosson@users.sourceforge.net - */ -public class MonitoredDiskFileItem extends DiskFileItem { - private MonitoredOutputStream mos; - private UploadListener listener; - - public MonitoredDiskFileItem(String fieldName, String contentType, boolean isFormField, String fileName, int sizeThreshold, - File repository, UploadListener listener) { - super(fieldName, contentType, isFormField, fileName, sizeThreshold, repository); - this.listener = listener; - if (fileName != null) { - listener.start(fileName); - } - } - - public OutputStream getOutputStream() throws IOException { - if (mos == null) { - mos = new MonitoredOutputStream(super.getOutputStream(), listener); - } - return mos; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredDiskFileItemFactory.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredDiskFileItemFactory.java deleted file mode 100644 index b5d6125d..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredDiskFileItemFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.upload; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; - -import java.io.File; - -/** - * Extension of Commons FileUpload for monitoring the upload progress. - * - * @author Pierre-Alexandre Losson -- http://www.telio.be/blog -- plosson@users.sourceforge.net - */ -public class MonitoredDiskFileItemFactory extends DiskFileItemFactory { - private UploadListener listener; - - public MonitoredDiskFileItemFactory(UploadListener listener) { - super(); - this.listener = listener; - } - - public MonitoredDiskFileItemFactory(int sizeThreshold, File repository, UploadListener listener) { - super(sizeThreshold, repository); - this.listener = listener; - } - - public FileItem createItem(String fieldName, String contentType, boolean isFormField, String fileName) { - return new MonitoredDiskFileItem(fieldName, contentType, isFormField, fileName, getSizeThreshold(), getRepository(), listener); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredOutputStream.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredOutputStream.java deleted file mode 100644 index c7f0d525..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/MonitoredOutputStream.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.upload; - -import java.io.OutputStream; -import java.io.IOException; - -/** - * Extension of Commons FileUpload for monitoring the upload progress. - * - * @author Pierre-Alexandre Losson -- http://www.telio.be/blog -- plosson@users.sourceforge.net - */ -public class MonitoredOutputStream extends OutputStream { - private OutputStream target; - private UploadListener listener; - - public MonitoredOutputStream(OutputStream target, UploadListener listener) { - this.target = target; - this.listener = listener; - } - - public void write(byte[] b, int off, int len) throws IOException { - target.write(b, off, len); - listener.bytesRead(len); - } - - public void write(byte[] b) throws IOException { - target.write(b); - listener.bytesRead(b.length); - } - - public void write(int b) throws IOException { - target.write(b); - listener.bytesRead(1); - } - - public void close() throws IOException { - target.close(); - } - - public void flush() throws IOException { - target.flush(); - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/UploadListener.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/UploadListener.java deleted file mode 100644 index 7eac415a..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/upload/UploadListener.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.upload; - -/** - * Extension of Commons FileUpload for monitoring the upload progress. - * - * @author Pierre-Alexandre Losson -- http://www.telio.be/blog -- plosson@users.sourceforge.net - */ -public interface UploadListener { - void start(String fileName); - void bytesRead(long bytesRead); -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/BoundedList.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/util/BoundedList.java deleted file mode 100644 index fb240d5f..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/BoundedList.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.util; - -import java.util.*; - -/** - * Simple implementation of a bounded list. If the maximum size is reached, adding a new element will - * remove the first element in the list. - * - * @author Sindre Mehus - * @version $Revision: 1.1 $ $Date: 2005/05/09 20:01:25 $ - */ -public class BoundedList extends LinkedList { - private int maxSize; - - /** - * Creates a new bounded list with the given maximum size. - * @param maxSize The maximum number of elements the list may hold. - */ - public BoundedList(int maxSize) { - this.maxSize = maxSize; - } - - /** - * Adds an element to the tail of the list. If the list is full, the first element is removed. - * @param e The element to add. - * @return Always true. - */ - public boolean add(E e) { - if (isFull()) { - removeFirst(); - } - return super.add(e); - } - - /** - * Adds an element to the head of list. If the list is full, the last element is removed. - * @param e The element to add. - */ - public void addFirst(E e) { - if (isFull()) { - removeLast(); - } - super.addFirst(e); - } - - /** - * Returns whether the list if full. - * @return Whether the list is full. - */ - private boolean isFull() { - return size() == maxSize; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/FileUtil.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/util/FileUtil.java deleted file mode 100644 index e91758ef..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/FileUtil.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.util; - -import java.io.Closeable; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.util.Arrays; - -import net.sourceforge.subsonic.Logger; - -/** - * Miscellaneous file utility methods. - * - * @author Sindre Mehus - */ -public final class FileUtil { - - private static final Logger LOG = Logger.getLogger(FileUtil.class); - - /** - * Disallow external instantiation. - */ - private FileUtil() { - } - - public static boolean isFile(final File file) { - return timed(new FileTask("isFile", file) { - @Override - public Boolean execute() { - return file.isFile(); - } - }); - } - - public static boolean isDirectory(final File file) { - return timed(new FileTask("isDirectory", file) { - @Override - public Boolean execute() { - return file.isDirectory(); - } - }); - } - - public static boolean exists(final File file) { - return timed(new FileTask("exists", file) { - @Override - public Boolean execute() { - return file.exists(); - } - }); - } - - public static long lastModified(final File file) { - return timed(new FileTask("lastModified", file) { - @Override - public Long execute() { - return file.lastModified(); - } - }); - } - - public static long length(final File file) { - return timed(new FileTask("length", file) { - @Override - public Long execute() { - return file.length(); - } - }); - } - - /** - * Similar to {@link File#listFiles()}, but never returns null. - * Instead a warning is logged, and an empty array is returned. - */ - public static File[] listFiles(final File dir) { - File[] files = timed(new FileTask("listFiles", dir) { - @Override - public File[] execute() { - return dir.listFiles(); - } - }); - - if (files == null) { - LOG.warn("Failed to list children for " + dir.getPath()); - return new File[0]; - } - return files; - } - - /** - * Similar to {@link File#listFiles(FilenameFilter)}, but never returns null. - * Instead a warning is logged, and an empty array is returned. - */ - public static File[] listFiles(final File dir, final FilenameFilter filter, boolean sort) { - File[] files = timed(new FileTask("listFiles2", dir) { - @Override - public File[] execute() { - return dir.listFiles(filter); - } - }); - if (files == null) { - LOG.warn("Failed to list children for " + dir.getPath()); - return new File[0]; - } - if (sort) { - Arrays.sort(files); - } - return files; - } - - /** - * Returns a short path for the given file. The path consists of the name - * of the parent directory and the given file. - */ - public static String getShortPath(File file) { - if (file == null) { - return null; - } - File parent = file.getParentFile(); - if (parent == null) { - return file.getName(); - } - return parent.getName() + File.separator + file.getName(); - } - - /** - * Closes the "closable", ignoring any excepetions. - * - * @param closeable The Closable to close, may be {@code null}. - */ - public static void closeQuietly(Closeable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (IOException e) { - // Ignored - } - } - } - - private static T timed(FileTask task) { -// long t0 = System.nanoTime(); -// try { - return task.execute(); -// } finally { -// long t1 = System.nanoTime(); -// LOG.debug((t1 - t0) / 1000L + " microsec, " + task); -// } - } - - private abstract static class FileTask { - - private final String name; - private final File file; - - public FileTask(String name, File file) { - this.name = name; - this.file = file; - } - - public abstract T execute(); - - @Override - public String toString() { - return name + ", " + file; - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/Pair.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/util/Pair.java deleted file mode 100644 index 7edecaa2..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/Pair.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.util; - -import java.io.Serializable; - -/** - * @author Sindre Mehus - */ -public class Pair implements Serializable { - - private S first; - private T second; - - public Pair() { - } - - public Pair(S first, T second) { - this.first = first; - this.second = second; - } - - public S getFirst() { - return first; - } - - public void setFirst(S first) { - this.first = first; - } - - public T getSecond() { - return second; - } - - public void setSecond(T second) { - this.second = second; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/StringUtil.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/util/StringUtil.java deleted file mode 100644 index ebad9fbf..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/StringUtil.java +++ /dev/null @@ -1,537 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.util; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLEncoder; -import java.security.MessageDigest; -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.math.LongRange; - -/** - * Miscellaneous string utility methods. - * - * @author Sindre Mehus - */ -public final class StringUtil { - - public static final String ENCODING_LATIN = "ISO-8859-1"; - public static final String ENCODING_UTF8 = "UTF-8"; - private static final DateFormat ISO_8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - - private static final String[][] HTML_SUBSTITUTIONS = { - {"&", "&"}, - {"<", "<"}, - {">", ">"}, - {"'", "'"}, - {"\"", """}, - }; - - private static final String[][] MIME_TYPES = { - {"mp3", "audio/mpeg"}, - {"ogg", "audio/ogg"}, - {"oga", "audio/ogg"}, - {"ogx", "application/ogg"}, - {"aac", "audio/mp4"}, - {"m4a", "audio/mp4"}, - {"flac", "audio/flac"}, - {"wav", "audio/x-wav"}, - {"wma", "audio/x-ms-wma"}, - {"ape", "audio/x-monkeys-audio"}, - {"mpc", "audio/x-musepack"}, - {"shn", "audio/x-shn"}, - - {"flv", "video/x-flv"}, - {"avi", "video/avi"}, - {"mpg", "video/mpeg"}, - {"mpeg", "video/mpeg"}, - {"mp4", "video/mp4"}, - {"m4v", "video/x-m4v"}, - {"mkv", "video/x-matroska"}, - {"mov", "video/quicktime"}, - {"wmv", "video/x-ms-wmv"}, - {"ogv", "video/ogg"}, - {"divx", "video/divx"}, - {"m2ts", "video/MP2T"}, - - {"gif", "image/gif"}, - {"jpg", "image/jpeg"}, - {"jpeg", "image/jpeg"}, - {"png", "image/png"}, - {"bmp", "image/bmp"}, - }; - - private static final String[] FILE_SYSTEM_UNSAFE = {"/", "\\", "..", ":", "\"", "?", "*", "|"}; - - /** - * Disallow external instantiation. - */ - private StringUtil() { - } - - /** - * Returns the specified string converted to a format suitable for - * HTML. All single-quote, double-quote, greater-than, less-than and - * ampersand characters are replaces with their corresponding HTML - * Character Entity code. - * - * @param s the string to convert - * @return the converted string - */ - public static String toHtml(String s) { - if (s == null) { - return null; - } - for (String[] substitution : HTML_SUBSTITUTIONS) { - if (s.contains(substitution[0])) { - s = s.replaceAll(substitution[0], substitution[1]); - } - } - return s; - } - - - /** - * Formats the given date to a ISO-8601 date/time format, and UTC timezone. - *

- * The returned date uses the following format: 2007-12-17T14:57:17 - * - * @param date The date to format - * @return The corresponding ISO-8601 formatted string. - */ - public static String toISO8601(Date date) { - if (date == null) { - return null; - } - - synchronized (ISO_8601_DATE_FORMAT) { - return ISO_8601_DATE_FORMAT.format(date); - } - } - - /** - * Removes the suffix (the substring after the last dot) of the given string. The dot is - * also removed. - * - * @param s The string in question, e.g., "foo.mp3". - * @return The string without the suffix, e.g., "foo". - */ - public static String removeSuffix(String s) { - int index = s.lastIndexOf('.'); - return index == -1 ? s : s.substring(0, index); - } - - /** - * Returns the proper MIME type for the given suffix. - * - * @param suffix The suffix, e.g., "mp3" or ".mp3". - * @return The corresponding MIME type, e.g., "audio/mpeg". If no MIME type is found, - * application/octet-stream is returned. - */ - public static String getMimeType(String suffix) { - for (String[] map : MIME_TYPES) { - if (map[0].equalsIgnoreCase(suffix) || ('.' + map[0]).equalsIgnoreCase(suffix)) { - return map[1]; - } - } - return "application/octet-stream"; - } - - /** - * Converts a byte-count to a formatted string suitable for display to the user. - * For instance: - *

    - *
  • format(918) returns "918 B".
  • - *
  • format(98765) returns "96 KB".
  • - *
  • format(1238476) returns "1.2 MB".
  • - *
- * This method assumes that 1 KB is 1024 bytes. - * - * @param byteCount The number of bytes. - * @param locale The locale used for formatting. - * @return The formatted string. - */ - public static synchronized String formatBytes(long byteCount, Locale locale) { - - // More than 1 GB? - if (byteCount >= 1024 * 1024 * 1024) { - NumberFormat gigaByteFormat = new DecimalFormat("0.00 GB", new DecimalFormatSymbols(locale)); - return gigaByteFormat.format((double) byteCount / (1024 * 1024 * 1024)); - } - - // More than 1 MB? - if (byteCount >= 1024 * 1024) { - NumberFormat megaByteFormat = new DecimalFormat("0.0 MB", new DecimalFormatSymbols(locale)); - return megaByteFormat.format((double) byteCount / (1024 * 1024)); - } - - // More than 1 KB? - if (byteCount >= 1024) { - NumberFormat kiloByteFormat = new DecimalFormat("0 KB", new DecimalFormatSymbols(locale)); - return kiloByteFormat.format((double) byteCount / 1024); - } - - return byteCount + " B"; - } - - /** - * Formats a duration with minutes and seconds, e.g., "93:45" - */ - public static String formatDuration(int seconds) { - int minutes = seconds / 60; - int secs = seconds % 60; - - StringBuilder builder = new StringBuilder(6); - builder.append(minutes).append(":"); - if (secs < 10) { - builder.append("0"); - } - builder.append(secs); - return builder.toString(); - } - - /** - * Splits the input string. White space is interpreted as separator token. Double quotes - * are interpreted as grouping operator.
- * For instance, the input "u2 rem "greatest hits"" will return an array with - * three elements: {"u2", "rem", "greatest hits"} - * - * @param input The input string. - * @return Array of elements. - */ - public static String[] split(String input) { - if (input == null) { - return new String[0]; - } - - Pattern pattern = Pattern.compile("\".*?\"|\\S+"); - Matcher matcher = pattern.matcher(input); - - List result = new ArrayList(); - while (matcher.find()) { - String element = matcher.group(); - if (element.startsWith("\"") && element.endsWith("\"") && element.length() > 1) { - element = element.substring(1, element.length() - 1); - } - result.add(element); - } - - return result.toArray(new String[result.size()]); - } - - /** - * Reads lines from the given input stream. All lines are trimmed. Empty lines and lines starting - * with "#" are skipped. The input stream is always closed by this method. - * - * @param in The input stream to read from. - * @return Array of lines. - * @throws IOException If an I/O error occurs. - */ - public static String[] readLines(InputStream in) throws IOException { - BufferedReader reader = null; - - try { - reader = new BufferedReader(new InputStreamReader(in)); - List result = new ArrayList(); - for (String line = reader.readLine(); line != null; line = reader.readLine()) { - line = line.trim(); - if (!line.startsWith("#") && line.length() > 0) { - result.add(line); - } - } - return result.toArray(new String[result.size()]); - - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(reader); - } - } - - /** - * Converts the given string of whitespace-separated integers to an int array. - * - * @param s String consisting of integers separated by whitespace. - * @return The corresponding array of ints. - * @throws NumberFormatException If string contains non-parseable text. - */ - public static int[] parseInts(String s) { - if (s == null) { - return new int[0]; - } - - String[] strings = StringUtils.split(s); - int[] ints = new int[strings.length]; - for (int i = 0; i < strings.length; i++) { - ints[i] = Integer.parseInt(strings[i]); - } - return ints; - } - - /** - * Change protocol from "https" to "http" for the given URL. The port number is also changed, - * but not if the given URL is already "http". - * - * @param url The original URL. - * @param port The port number to use, for instance 443. - * @return The transformed URL. - * @throws MalformedURLException If the original URL is invalid. - */ - public static String toHttpUrl(String url, int port) throws MalformedURLException { - URL u = new URL(url); - if ("https".equals(u.getProtocol())) { - return new URL("http", u.getHost(), port, u.getFile()).toString(); - } - return url; - } - - /** - * Determines whether a is equal to b, taking null into account. - * - * @return Whether a and b are equal, or both null. - */ - public static boolean isEqual(Object a, Object b) { - return a == null ? b == null : a.equals(b); - } - - /** - * Parses a locale from the given string. - * - * @param s The locale string. Should be formatted as per the documentation in {@link Locale#toString()}. - * @return The locale. - */ - public static Locale parseLocale(String s) { - if (s == null) { - return null; - } - - String[] elements = s.split("_"); - - if (elements.length == 0) { - return new Locale(s, "", ""); - } - if (elements.length == 1) { - return new Locale(elements[0], "", ""); - } - if (elements.length == 2) { - return new Locale(elements[0], elements[1], ""); - } - return new Locale(elements[0], elements[1], elements[2]); - } - - /** - * URL-encodes the input value using UTF-8. - */ - public static String urlEncode(String s) { - try { - return URLEncoder.encode(s, StringUtil.ENCODING_UTF8); - } catch (UnsupportedEncodingException x) { - throw new RuntimeException(x); - } - } - - /** - * Encodes the given string by using the hexadecimal representation of its UTF-8 bytes. - * - * @param s The string to encode. - * @return The encoded string. - */ - public static String utf8HexEncode(String s) { - if (s == null) { - return null; - } - byte[] utf8; - try { - utf8 = s.getBytes(ENCODING_UTF8); - } catch (UnsupportedEncodingException x) { - throw new RuntimeException(x); - } - return String.valueOf(Hex.encodeHex(utf8)); - } - - /** - * Decodes the given string by using the hexadecimal representation of its UTF-8 bytes. - * - * @param s The string to decode. - * @return The decoded string. - * @throws Exception If an error occurs. - */ - public static String utf8HexDecode(String s) throws Exception { - if (s == null) { - return null; - } - return new String(Hex.decodeHex(s.toCharArray()), ENCODING_UTF8); - } - - /** - * Calculates the MD5 digest and returns the value as a 32 character hex string. - * - * @param s Data to digest. - * @return MD5 digest as a hex string. - */ - public static String md5Hex(String s) { - if (s == null) { - return null; - } - - try { - MessageDigest md5 = MessageDigest.getInstance("MD5"); - return new String(Hex.encodeHex(md5.digest(s.getBytes(ENCODING_UTF8)))); - } catch (Exception x) { - throw new RuntimeException(x.getMessage(), x); - } - } - - /** - * Returns the file part of an URL. For instance: - *

- * - * getUrlFile("http://archive.ncsa.uiuc.edu:80/SDG/Software/Mosaic/Demo/url-primer.html") - * - *

- * will return "url-primer.html". - * - * @param url The URL in question. - * @return The file part, or null if no file can be resolved. - */ - public static String getUrlFile(String url) { - try { - String path = new URL(url).getPath(); - if (StringUtils.isBlank(path) || path.endsWith("/")) { - return null; - } - - File file = new File(path); - String filename = file.getName(); - if (StringUtils.isBlank(filename)) { - return null; - } - return filename; - - } catch (MalformedURLException x) { - return null; - } - } - - /** - * Rewrites the URL by changing the protocol, host and port. - * - * @param urlToRewrite The URL to rewrite. - * @param urlWithProtocolHostAndPort Use protocol, host and port from this URL. - * @return The rewritten URL, or an unchanged URL if either argument is not a proper URL. - */ - public static String rewriteUrl(String urlToRewrite, String urlWithProtocolHostAndPort) { - if (urlToRewrite == null) { - return null; - } - - try { - URL urlA = new URL(urlToRewrite); - URL urlB = new URL(urlWithProtocolHostAndPort); - - URL result = new URL(urlB.getProtocol(), urlB.getHost(), urlB.getPort(), urlA.getFile()); - return result.toExternalForm(); - } catch (MalformedURLException x) { - return urlToRewrite; - } - } - - /** - * Makes a given filename safe by replacing special characters like slashes ("/" and "\") - * with dashes ("-"). - * - * @param filename The filename in question. - * @return The filename with special characters replaced by underscores. - */ - public static String fileSystemSafe(String filename) { - for (String s : FILE_SYSTEM_UNSAFE) { - filename = filename.replace(s, "-"); - } - return filename; - } - - /** - * Parses the given string as a HTTP header byte range. See chapter 14.36.1 in RFC 2068 - * for details. - *

- * Only a subset of the allowed syntaxes are supported. Only ranges which specify first-byte-pos - * are supported. The last-byte-pos is optional. - * - * @param range The range from the HTTP header, for instance "bytes=0-499" or "bytes=500-" - * @return A range object (using inclusive values). If the last-byte-pos is not given, the end of - * the returned range is {@link Long#MAX_VALUE}. The method returns null if the syntax - * of the given range is not supported. - */ - public static LongRange parseRange(String range) { - if (range == null) { - return null; - } - - Pattern pattern = Pattern.compile("bytes=(\\d+)-(\\d*)"); - Matcher matcher = pattern.matcher(range); - - if (matcher.matches()) { - String firstString = matcher.group(1); - String lastString = StringUtils.trimToNull(matcher.group(2)); - - long first = Long.parseLong(firstString); - long last = lastString == null ? Long.MAX_VALUE : Long.parseLong(lastString); - - if (first > last) { - return null; - } - - return new LongRange(first, last); - } - return null; - } - - public static String removeMarkup(String s) { - if (s == null) { - return null; - } - return s.replaceAll("<.*?>", ""); - } - - public static String getRESTProtocolVersion() { - // TODO: Read from xsd. - return "1.8.0"; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/Util.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/util/Util.java deleted file mode 100644 index ec7175a2..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/Util.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.util; - -import net.sourceforge.subsonic.Logger; - -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletResponse; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.Inet4Address; -import java.util.Enumeration; -import java.util.Random; - -/** - * Miscellaneous general utility methods. - * - * @author Sindre Mehus - */ -public final class Util { - - private static final Logger LOG = Logger.getLogger(Util.class); - private static final Random RANDOM = new Random(System.currentTimeMillis()); - - /** - * Disallow external instantiation. - */ - private Util() { - } - - public static String getDefaultMusicFolder() { - String def = isWindows() ? "c:\\music" : "/var/music"; - return System.getProperty("subsonic.defaultMusicFolder", def); - } - - public static String getDefaultPodcastFolder() { - String def = isWindows() ? "c:\\music\\Podcast" : "/var/music/Podcast"; - return System.getProperty("subsonic.defaultPodcastFolder", def); - } - - public static String getDefaultPlaylistFolder() { - String def = isWindows() ? "c:\\playlists" : "/var/playlists"; - return System.getProperty("subsonic.defaultPlaylistFolder", def); - } - - public static boolean isWindows() { - return System.getProperty("os.name", "Windows").toLowerCase().startsWith("windows"); - } - - public static boolean isWindowsInstall() { - return "true".equals(System.getProperty("subsonic.windowsInstall")); - } - - /** - * Similar to {@link ServletResponse#setContentLength(int)}, but this - * method supports lengths bigger than 2GB. - *

- * See http://blogger.ziesemer.com/2008/03/suns-version-of-640k-2gb.html - * - * @param response The HTTP response. - * @param length The content length. - */ - public static void setContentLength(HttpServletResponse response, long length) { - if (length <= Integer.MAX_VALUE) { - response.setContentLength((int) length); - } else { - response.setHeader("Content-Length", String.valueOf(length)); - } - } - - /** - * Returns the local IP address. - * @return The local IP, or the loopback address (127.0.0.1) if not found. - */ - public static String getLocalIpAddress() { - try { - - // Try the simple way first. - InetAddress address = InetAddress.getLocalHost(); - if (!address.isLoopbackAddress()) { - return address.getHostAddress(); - } - - // Iterate through all network interfaces, looking for a suitable IP. - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - while (interfaces.hasMoreElements()) { - NetworkInterface iface = interfaces.nextElement(); - Enumeration addresses = iface.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress addr = addresses.nextElement(); - if (addr instanceof Inet4Address && !addr.isLoopbackAddress()) { - return addr.getHostAddress(); - } - } - } - - } catch (Throwable x) { - LOG.warn("Failed to resolve local IP address.", x); - } - - return "127.0.0.1"; - } - - public static int randomInt(int min, int max) { - if (min >= max) { - return 0; - } - return min + RANDOM.nextInt(max - min); - - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/XMLBuilder.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/util/XMLBuilder.java deleted file mode 100644 index a572ac0f..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/util/XMLBuilder.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.util; - -import org.apache.commons.lang.StringEscapeUtils; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.XML; - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Stack; - - -/** - * Simplifies building of XML documents. - *

- * Example:
- * The following code: - *

- * XMLBuilder builder = XMLBuilder.createXMLBuilder();
- * builder.add("foo").add("bar");
- * builder.add("zonk", 42);
- * builder.end().end();
- * System.out.println(builder.toString());
- * 
- * produces the following XML: - *
- * <foo>
- *   <bar>
- *     <zonk>42</zonk>
- *   </bar>
- * </foo>
- * 
- * This class is not thread safe. - *

- * Also supports JSON and JSONP formats. - * - * @author Sindre Mehus - */ -public class XMLBuilder { - - private static final String INDENTATION = " "; - private static final String NEWLINE = "\n"; - - private final Writer writer = new StringWriter(); - private final Stack elementStack = new Stack(); - private final boolean json; - private final String jsonpCallback; - - public static XMLBuilder createXMLBuilder() { - return new XMLBuilder(false, null); - } - - public static XMLBuilder createJSONBuilder() { - return new XMLBuilder(true, null); - } - - public static XMLBuilder createJSONPBuilder(String callback) { - return new XMLBuilder(true, callback); - } - - /** - * Creates a new instance. - * - * @param json Whether to produce JSON rather than XML. - * @param jsonpCallback Name of javascript callback for JSONP. - */ - private XMLBuilder(boolean json, String jsonpCallback) { - this.json = json; - this.jsonpCallback = jsonpCallback; - } - - /** - * Adds an XML preamble, with the given encoding. The preamble will typically - * look like this: - *

- * <?xml version="1.0" encoding="UTF-8"?> - * - * @param encoding The encoding to put in the preamble. - * @return A reference to this object. - */ - public XMLBuilder preamble(String encoding) throws IOException { - writer.write(""); - newline(); - return this; - } - - /** - * Adds an element with the given name and a single attribute. - * - * @param element The element name. - * @param attributeKey The attributes key. - * @param attributeValue The attributes value. - * @param close Whether to close the element. - * @return A reference to this object. - */ - public XMLBuilder add(String element, String attributeKey, Object attributeValue, boolean close) throws IOException { - return add(element, close, new Attribute(attributeKey, attributeValue)); - } - - /** - * Adds an element with the given name and attributes. - * - * @param element The element name. - * @param close Whether to close the element. - * @param attributes The element attributes. - * @return A reference to this object. - */ - public XMLBuilder add(String element, boolean close, Attribute... attributes) throws IOException { - return add(element, Arrays.asList(attributes), close); - } - - /** - * Adds an element with the given name and attributes. - * - * @param element The element name. - * @param attributes The element attributes. - * @param close Whether to close the element. - * @return A reference to this object. - */ - public XMLBuilder add(String element, Iterable attributes, boolean close) throws IOException { - return add(element, attributes, null, close); - } - - /** - * Adds an element with the given name, attributes and character data. - * - * @param element The element name. - * @param attributes The element attributes. - * @param text The character data. - * @param close Whether to close the element. - * @return A reference to this object. - */ - public XMLBuilder add(String element, Iterable attributes, String text, boolean close) throws IOException { - indent(); - elementStack.push(element); - writer.write('<'); - writer.write(element); - - if (attributes == null) { - attributes = Collections.emptyList(); - } - - Iterator iterator = attributes.iterator(); - - if (iterator.hasNext()) { - writer.write(' '); - } - while (iterator.hasNext()) { - Attribute attribute = iterator.next(); - attribute.append(writer); - if (iterator.hasNext()) { - writer.write(' '); - } - } - - if (close && text == null) { - elementStack.pop(); - writer.write("/>"); - } else { - writer.write('>'); - } - - if (text != null) { - writer.write(text); - - if (close) { - elementStack.pop(); - writer.write("'); - } - } - - newline(); - return this; - } - - /** - * Closes the current element. - * - * @return A reference to this object. - * @throws IllegalStateException If there are no unclosed elements. - */ - public XMLBuilder end() throws IllegalStateException, IOException { - if (elementStack.isEmpty()) { - throw new IllegalStateException("There are no unclosed elements."); - } - - String element = elementStack.pop(); - indent(); - writer.write("'); - newline(); - return this; - } - - /** - * Closes all unclosed elements. - * - * @return A reference to this object. - */ - public XMLBuilder endAll() throws IOException { - while (!elementStack.isEmpty()) { - end(); - } - return this; - } - - /** - * Returns the XML document as a string. - */ - @Override - public String toString() { - String xml = writer.toString(); - if (!json) { - return xml; - } - try { - JSONObject jsonObject = XML.toJSONObject(xml); - - if (jsonpCallback != null) { - return jsonpCallback + "(" + jsonObject.toString(1) + ");"; - } - - return jsonObject.toString(1); - } catch (JSONException x) { - throw new RuntimeException("Failed to convert from XML to JSON.", x); - } - } - - private void indent() throws IOException { - int depth = elementStack.size(); - for (int i = 0; i < depth; i++) { - writer.write(INDENTATION); - } - } - - private void newline() throws IOException { - writer.write(NEWLINE); - } - - /** - * An XML element attribute. - */ - public static class Attribute { - - private final String key; - private final Object value; - - public Attribute(String key, Object value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public Object getValue() { - return value; - } - - private void append(Writer writer) throws IOException { - if (key != null && value != null) { - writer.write(key); - writer.write("=\""); - writer.write(StringEscapeUtils.escapeXml(value.toString())); - writer.write("\""); - } - } - } - - /** - * A set of attributes. - */ - public static class AttributeSet implements Iterable { - - private final Map attributes = new LinkedHashMap(); - - public void add(Attribute attribute) { - attributes.put(attribute.getKey(), attribute); - } - - public void add(String key, Object value) { - if (key != null && value != null) { - add(new Attribute(key, value)); - } - } - - public void addAll(Iterable attributes) { - for (Attribute attribute : attributes) { - add(attribute); - } - } - - public Iterator iterator() { - return attributes.values().iterator(); - } - } - -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/DonateValidator.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/DonateValidator.java deleted file mode 100644 index 276eacb0..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/DonateValidator.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.validator; - -import org.springframework.validation.Validator; -import org.springframework.validation.Errors; -import net.sourceforge.subsonic.command.PasswordSettingsCommand; -import net.sourceforge.subsonic.command.DonateCommand; -import net.sourceforge.subsonic.controller.DonateController; -import net.sourceforge.subsonic.service.SettingsService; - -/** - * Validator for {@link DonateController}. - * - * @author Sindre Mehus - */ -public class DonateValidator implements Validator { - private SettingsService settingsService; - - public boolean supports(Class clazz) { - return clazz.equals(DonateCommand.class); - } - - public void validate(Object obj, Errors errors) { - DonateCommand command = (DonateCommand) obj; - - if (!settingsService.isLicenseValid(command.getEmailAddress(), command.getLicense())) { - errors.rejectValue("license", "donate.invalidlicense"); - } - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/PasswordSettingsValidator.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/PasswordSettingsValidator.java deleted file mode 100644 index 12fb06ce..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/PasswordSettingsValidator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.validator; - -import org.springframework.validation.*; -import net.sourceforge.subsonic.command.*; -import net.sourceforge.subsonic.controller.*; - -/** - * Validator for {@link PasswordSettingsController}. - * - * @author Sindre Mehus - */ -public class PasswordSettingsValidator implements Validator { - - public boolean supports(Class clazz) { - return clazz.equals(PasswordSettingsCommand.class); - } - - public void validate(Object obj, Errors errors) { - PasswordSettingsCommand command = (PasswordSettingsCommand) obj; - - if (command.getPassword() == null || command.getPassword().length() == 0) { - errors.rejectValue("password", "usersettings.nopassword"); - } else if (!command.getPassword().equals(command.getConfirmPassword())) { - errors.rejectValue("password", "usersettings.wrongpassword"); - } - } -} diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/UserSettingsValidator.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/UserSettingsValidator.java deleted file mode 100644 index 3445b7d8..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/validator/UserSettingsValidator.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic 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. - - Subsonic 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 Subsonic. If not, see . - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.validator; - -import net.sourceforge.subsonic.command.UserSettingsCommand; -import net.sourceforge.subsonic.controller.UserSettingsController; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import org.apache.commons.lang.StringUtils; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; - -/** - * Validator for {@link UserSettingsController}. - * - * @author Sindre Mehus - */ -public class UserSettingsValidator implements Validator { - - private SecurityService securityService; - private SettingsService settingsService; - - /** - * {@inheritDoc} - */ - public boolean supports(Class clazz) { - return clazz.equals(UserSettingsCommand.class); - } - - /** - * {@inheritDoc} - */ - public void validate(Object obj, Errors errors) { - UserSettingsCommand command = (UserSettingsCommand) obj; - String username = command.getUsername(); - String email = StringUtils.trimToNull(command.getEmail()); - String password = StringUtils.trimToNull(command.getPassword()); - String confirmPassword = command.getConfirmPassword(); - - if (command.isNew()) { - if (username == null || username.length() == 0) { - errors.rejectValue("username", "usersettings.nousername"); - } else if (securityService.getUserByName(username) != null) { - errors.rejectValue("username", "usersettings.useralreadyexists"); - } else if (email == null) { - errors.rejectValue("email", "usersettings.noemail"); - } else if (command.isLdapAuthenticated() && !settingsService.isLdapEnabled()) { - errors.rejectValue("password", "usersettings.ldapdisabled"); - } else if (command.isLdapAuthenticated() && password != null) { - errors.rejectValue("password", "usersettings.passwordnotsupportedforldap"); - } - } - - if ((command.isNew() || command.isPasswordChange()) && !command.isLdapAuthenticated()) { - if (password == null) { - errors.rejectValue("password", "usersettings.nopassword"); - } else if (!password.equals(confirmPassword)) { - errors.rejectValue("password", "usersettings.wrongpassword"); - } - } - - if (command.isPasswordChange() && command.isLdapAuthenticated()) { - errors.rejectValue("password", "usersettings.passwordnotsupportedforldap"); - } - - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setSettingsService(SettingsService settingsService) { - this.settingsService = settingsService; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/org/json/CDL.java b/subsonic-main/src/main/java/org/json/CDL.java deleted file mode 100644 index a1885aad..00000000 --- a/subsonic-main/src/main/java/org/json/CDL.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * This provides static methods to convert comma delimited text into a - * JSONArray, and to covert a JSONArray into comma delimited text. Comma - * delimited text is a very popular format for data interchange. It is - * understood by most database, spreadsheet, and organizer programs. - *

- * Each row of text represents a row in a table or a data record. Each row - * ends with a NEWLINE character. Each row contains one or more values. - * Values are separated by commas. A value can contain any character except - * for comma, unless is is wrapped in single quotes or double quotes. - *

- * The first row usually contains the names of the columns. - *

- * A comma delimited list can be converted into a JSONArray of JSONObjects. - * The names for the elements in the JSONObjects can be taken from the names - * in the first row. - * @author JSON.org - * @version 2010-12-24 - */ -public class CDL { - - /** - * Get the next value. The value can be wrapped in quotes. The value can - * be empty. - * @param x A JSONTokener of the source text. - * @return The value string, or null if empty. - * @throws JSONException if the quoted string is badly formed. - */ - private static String getValue(JSONTokener x) throws JSONException { - char c; - char q; - StringBuffer sb; - do { - c = x.next(); - } while (c == ' ' || c == '\t'); - switch (c) { - case 0: - return null; - case '"': - case '\'': - q = c; - sb = new StringBuffer(); - for (;;) { - c = x.next(); - if (c == q) { - break; - } - if (c == 0 || c == '\n' || c == '\r') { - throw x.syntaxError("Missing close quote '" + q + "'."); - } - sb.append(c); - } - return sb.toString(); - case ',': - x.back(); - return ""; - default: - x.back(); - return x.nextTo(','); - } - } - - /** - * Produce a JSONArray of strings from a row of comma delimited values. - * @param x A JSONTokener of the source text. - * @return A JSONArray of strings. - * @throws JSONException - */ - public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { - JSONArray ja = new JSONArray(); - for (;;) { - String value = getValue(x); - char c = x.next(); - if (value == null || - (ja.length() == 0 && value.length() == 0 && c != ',')) { - return null; - } - ja.put(value); - for (;;) { - if (c == ',') { - break; - } - if (c != ' ') { - if (c == '\n' || c == '\r' || c == 0) { - return ja; - } - throw x.syntaxError("Bad character '" + c + "' (" + - (int)c + ")."); - } - c = x.next(); - } - } - } - - /** - * Produce a JSONObject from a row of comma delimited text, using a - * parallel JSONArray of strings to provides the names of the elements. - * @param names A JSONArray of names. This is commonly obtained from the - * first row of a comma delimited text file using the rowToJSONArray - * method. - * @param x A JSONTokener of the source text. - * @return A JSONObject combining the names and values. - * @throws JSONException - */ - public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) - throws JSONException { - JSONArray ja = rowToJSONArray(x); - return ja != null ? ja.toJSONObject(names) : null; - } - - /** - * Produce a comma delimited text row from a JSONArray. Values containing - * the comma character will be quoted. Troublesome characters may be - * removed. - * @param ja A JSONArray of strings. - * @return A string ending in NEWLINE. - */ - public static String rowToString(JSONArray ja) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < ja.length(); i += 1) { - if (i > 0) { - sb.append(','); - } - Object object = ja.opt(i); - if (object != null) { - String string = object.toString(); - if (string.length() > 0 && (string.indexOf(',') >= 0 || - string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 || - string.indexOf(0) >= 0 || string.charAt(0) == '"')) { - sb.append('"'); - int length = string.length(); - for (int j = 0; j < length; j += 1) { - char c = string.charAt(j); - if (c >= ' ' && c != '"') { - sb.append(c); - } - } - sb.append('"'); - } else { - sb.append(string); - } - } - } - sb.append('\n'); - return sb.toString(); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string, - * using the first row as a source of names. - * @param string The comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(String string) throws JSONException { - return toJSONArray(new JSONTokener(string)); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string, - * using the first row as a source of names. - * @param x The JSONTokener containing the comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONTokener x) throws JSONException { - return toJSONArray(rowToJSONArray(x), x); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string - * using a supplied JSONArray as the source of element names. - * @param names A JSONArray of strings. - * @param string The comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONArray names, String string) - throws JSONException { - return toJSONArray(names, new JSONTokener(string)); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string - * using a supplied JSONArray as the source of element names. - * @param names A JSONArray of strings. - * @param x A JSONTokener of the source text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONArray names, JSONTokener x) - throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - JSONArray ja = new JSONArray(); - for (;;) { - JSONObject jo = rowToJSONObject(names, x); - if (jo == null) { - break; - } - ja.put(jo); - } - if (ja.length() == 0) { - return null; - } - return ja; - } - - - /** - * Produce a comma delimited text from a JSONArray of JSONObjects. The - * first row will be a list of names obtained by inspecting the first - * JSONObject. - * @param ja A JSONArray of JSONObjects. - * @return A comma delimited text. - * @throws JSONException - */ - public static String toString(JSONArray ja) throws JSONException { - JSONObject jo = ja.optJSONObject(0); - if (jo != null) { - JSONArray names = jo.names(); - if (names != null) { - return rowToString(names) + toString(names, ja); - } - } - return null; - } - - /** - * Produce a comma delimited text from a JSONArray of JSONObjects using - * a provided list of names. The list of names is not included in the - * output. - * @param names A JSONArray of strings. - * @param ja A JSONArray of JSONObjects. - * @return A comma delimited text. - * @throws JSONException - */ - public static String toString(JSONArray names, JSONArray ja) - throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < ja.length(); i += 1) { - JSONObject jo = ja.optJSONObject(i); - if (jo != null) { - sb.append(rowToString(jo.toJSONArray(names))); - } - } - return sb.toString(); - } -} diff --git a/subsonic-main/src/main/java/org/json/Cookie.java b/subsonic-main/src/main/java/org/json/Cookie.java deleted file mode 100644 index a2d9c4ed..00000000 --- a/subsonic-main/src/main/java/org/json/Cookie.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * Convert a web browser cookie specification to a JSONObject and back. - * JSON and Cookies are both notations for name/value pairs. - * @author JSON.org - * @version 2010-12-24 - */ -public class Cookie { - - /** - * Produce a copy of a string in which the characters '+', '%', '=', ';' - * and control characters are replaced with "%hh". This is a gentle form - * of URL encoding, attempting to cause as little distortion to the - * string as possible. The characters '=' and ';' are meta characters in - * cookies. By convention, they are escaped using the URL-encoding. This is - * only a convention, not a standard. Often, cookies are expected to have - * encoded values. We encode '=' and ';' because we must. We encode '%' and - * '+' because they are meta characters in URL encoding. - * @param string The source string. - * @return The escaped result. - */ - public static String escape(String string) { - char c; - String s = string.trim(); - StringBuffer sb = new StringBuffer(); - int length = s.length(); - for (int i = 0; i < length; i += 1) { - c = s.charAt(i); - if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { - sb.append('%'); - sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); - sb.append(Character.forDigit((char)(c & 0x0f), 16)); - } else { - sb.append(c); - } - } - return sb.toString(); - } - - - /** - * Convert a cookie specification string into a JSONObject. The string - * will contain a name value pair separated by '='. The name and the value - * will be unescaped, possibly converting '+' and '%' sequences. The - * cookie properties may follow, separated by ';', also represented as - * name=value (except the secure property, which does not have a value). - * The name will be stored under the key "name", and the value will be - * stored under the key "value". This method does not do checking or - * validation of the parameters. It only converts the cookie string into - * a JSONObject. - * @param string The cookie specification string. - * @return A JSONObject containing "name", "value", and possibly other - * members. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - String name; - JSONObject jo = new JSONObject(); - Object value; - JSONTokener x = new JSONTokener(string); - jo.put("name", x.nextTo('=')); - x.next('='); - jo.put("value", x.nextTo(';')); - x.next(); - while (x.more()) { - name = unescape(x.nextTo("=;")); - if (x.next() != '=') { - if (name.equals("secure")) { - value = Boolean.TRUE; - } else { - throw x.syntaxError("Missing '=' in cookie parameter."); - } - } else { - value = unescape(x.nextTo(';')); - x.next(); - } - jo.put(name, value); - } - return jo; - } - - - /** - * Convert a JSONObject into a cookie specification string. The JSONObject - * must contain "name" and "value" members. - * If the JSONObject contains "expires", "domain", "path", or "secure" - * members, they will be appended to the cookie specification string. - * All other members are ignored. - * @param jo A JSONObject - * @return A cookie specification string - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - StringBuffer sb = new StringBuffer(); - - sb.append(escape(jo.getString("name"))); - sb.append("="); - sb.append(escape(jo.getString("value"))); - if (jo.has("expires")) { - sb.append(";expires="); - sb.append(jo.getString("expires")); - } - if (jo.has("domain")) { - sb.append(";domain="); - sb.append(escape(jo.getString("domain"))); - } - if (jo.has("path")) { - sb.append(";path="); - sb.append(escape(jo.getString("path"))); - } - if (jo.optBoolean("secure")) { - sb.append(";secure"); - } - return sb.toString(); - } - - /** - * Convert %hh sequences to single characters, and - * convert plus to space. - * @param string A string that may contain - * + (plus) and - * %hh sequences. - * @return The unescaped string. - */ - public static String unescape(String string) { - int length = string.length(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < length; ++i) { - char c = string.charAt(i); - if (c == '+') { - c = ' '; - } else if (c == '%' && i + 2 < length) { - int d = JSONTokener.dehexchar(string.charAt(i + 1)); - int e = JSONTokener.dehexchar(string.charAt(i + 2)); - if (d >= 0 && e >= 0) { - c = (char)(d * 16 + e); - i += 2; - } - } - sb.append(c); - } - return sb.toString(); - } -} diff --git a/subsonic-main/src/main/java/org/json/CookieList.java b/subsonic-main/src/main/java/org/json/CookieList.java deleted file mode 100644 index 1111135f..00000000 --- a/subsonic-main/src/main/java/org/json/CookieList.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - -/** - * Convert a web browser cookie list string to a JSONObject and back. - * @author JSON.org - * @version 2010-12-24 - */ -public class CookieList { - - /** - * Convert a cookie list into a JSONObject. A cookie list is a sequence - * of name/value pairs. The names are separated from the values by '='. - * The pairs are separated by ';'. The names and the values - * will be unescaped, possibly converting '+' and '%' sequences. - * - * To add a cookie to a cooklist, - * cookielistJSONObject.put(cookieJSONObject.getString("name"), - * cookieJSONObject.getString("value")); - * @param string A cookie list string - * @return A JSONObject - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - JSONTokener x = new JSONTokener(string); - while (x.more()) { - String name = Cookie.unescape(x.nextTo('=')); - x.next('='); - jo.put(name, Cookie.unescape(x.nextTo(';'))); - x.next(); - } - return jo; - } - - - /** - * Convert a JSONObject into a cookie list. A cookie list is a sequence - * of name/value pairs. The names are separated from the values by '='. - * The pairs are separated by ';'. The characters '%', '+', '=', and ';' - * in the names and values are replaced by "%hh". - * @param jo A JSONObject - * @return A cookie list string - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - boolean b = false; - Iterator keys = jo.keys(); - String string; - StringBuffer sb = new StringBuffer(); - while (keys.hasNext()) { - string = keys.next().toString(); - if (!jo.isNull(string)) { - if (b) { - sb.append(';'); - } - sb.append(Cookie.escape(string)); - sb.append("="); - sb.append(Cookie.escape(jo.getString(string))); - b = true; - } - } - return sb.toString(); - } -} diff --git a/subsonic-main/src/main/java/org/json/HTTP.java b/subsonic-main/src/main/java/org/json/HTTP.java deleted file mode 100644 index cc8203d1..00000000 --- a/subsonic-main/src/main/java/org/json/HTTP.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - -/** - * Convert an HTTP header to a JSONObject and back. - * @author JSON.org - * @version 2010-12-24 - */ -public class HTTP { - - /** Carriage return/line feed. */ - public static final String CRLF = "\r\n"; - - /** - * Convert an HTTP header string into a JSONObject. It can be a request - * header or a response header. A request header will contain - *

{
-     *    Method: "POST" (for example),
-     *    "Request-URI": "/" (for example),
-     *    "HTTP-Version": "HTTP/1.1" (for example)
-     * }
- * A response header will contain - *
{
-     *    "HTTP-Version": "HTTP/1.1" (for example),
-     *    "Status-Code": "200" (for example),
-     *    "Reason-Phrase": "OK" (for example)
-     * }
- * In addition, the other parameters in the header will be captured, using - * the HTTP field names as JSON names, so that
-     *    Date: Sun, 26 May 2002 18:06:04 GMT
-     *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
-     *    Cache-Control: no-cache
- * become - *
{...
-     *    Date: "Sun, 26 May 2002 18:06:04 GMT",
-     *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
-     *    "Cache-Control": "no-cache",
-     * ...}
- * It does no further checking or conversion. It does not parse dates. - * It does not do '%' transforms on URLs. - * @param string An HTTP header string. - * @return A JSONObject containing the elements and attributes - * of the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - HTTPTokener x = new HTTPTokener(string); - String token; - - token = x.nextToken(); - if (token.toUpperCase().startsWith("HTTP")) { - -// Response - - jo.put("HTTP-Version", token); - jo.put("Status-Code", x.nextToken()); - jo.put("Reason-Phrase", x.nextTo('\0')); - x.next(); - - } else { - -// Request - - jo.put("Method", token); - jo.put("Request-URI", x.nextToken()); - jo.put("HTTP-Version", x.nextToken()); - } - -// Fields - - while (x.more()) { - String name = x.nextTo(':'); - x.next(':'); - jo.put(name, x.nextTo('\0')); - x.next(); - } - return jo; - } - - - /** - * Convert a JSONObject into an HTTP header. A request header must contain - *
{
-     *    Method: "POST" (for example),
-     *    "Request-URI": "/" (for example),
-     *    "HTTP-Version": "HTTP/1.1" (for example)
-     * }
- * A response header must contain - *
{
-     *    "HTTP-Version": "HTTP/1.1" (for example),
-     *    "Status-Code": "200" (for example),
-     *    "Reason-Phrase": "OK" (for example)
-     * }
- * Any other members of the JSONObject will be output as HTTP fields. - * The result will end with two CRLF pairs. - * @param jo A JSONObject - * @return An HTTP header string. - * @throws JSONException if the object does not contain enough - * information. - */ - public static String toString(JSONObject jo) throws JSONException { - Iterator keys = jo.keys(); - String string; - StringBuffer sb = new StringBuffer(); - if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { - sb.append(jo.getString("HTTP-Version")); - sb.append(' '); - sb.append(jo.getString("Status-Code")); - sb.append(' '); - sb.append(jo.getString("Reason-Phrase")); - } else if (jo.has("Method") && jo.has("Request-URI")) { - sb.append(jo.getString("Method")); - sb.append(' '); - sb.append('"'); - sb.append(jo.getString("Request-URI")); - sb.append('"'); - sb.append(' '); - sb.append(jo.getString("HTTP-Version")); - } else { - throw new JSONException("Not enough material for an HTTP header."); - } - sb.append(CRLF); - while (keys.hasNext()) { - string = keys.next().toString(); - if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && - !"Reason-Phrase".equals(string) && !"Method".equals(string) && - !"Request-URI".equals(string) && !jo.isNull(string)) { - sb.append(string); - sb.append(": "); - sb.append(jo.getString(string)); - sb.append(CRLF); - } - } - sb.append(CRLF); - return sb.toString(); - } -} diff --git a/subsonic-main/src/main/java/org/json/HTTPTokener.java b/subsonic-main/src/main/java/org/json/HTTPTokener.java deleted file mode 100644 index 86fed61d..00000000 --- a/subsonic-main/src/main/java/org/json/HTTPTokener.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * The HTTPTokener extends the JSONTokener to provide additional methods - * for the parsing of HTTP headers. - * @author JSON.org - * @version 2010-12-24 - */ -public class HTTPTokener extends JSONTokener { - - /** - * Construct an HTTPTokener from a string. - * @param string A source string. - */ - public HTTPTokener(String string) { - super(string); - } - - - /** - * Get the next token or string. This is used in parsing HTTP headers. - * @throws JSONException - * @return A String. - */ - public String nextToken() throws JSONException { - char c; - char q; - StringBuffer sb = new StringBuffer(); - do { - c = next(); - } while (Character.isWhitespace(c)); - if (c == '"' || c == '\'') { - q = c; - for (;;) { - c = next(); - if (c < ' ') { - throw syntaxError("Unterminated string."); - } - if (c == q) { - return sb.toString(); - } - sb.append(c); - } - } - for (;;) { - if (c == 0 || Character.isWhitespace(c)) { - return sb.toString(); - } - sb.append(c); - c = next(); - } - } -} diff --git a/subsonic-main/src/main/java/org/json/JSONArray.java b/subsonic-main/src/main/java/org/json/JSONArray.java deleted file mode 100644 index 4ae610f0..00000000 --- a/subsonic-main/src/main/java/org/json/JSONArray.java +++ /dev/null @@ -1,920 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.IOException; -import java.io.Writer; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; - -/** - * A JSONArray is an ordered sequence of values. Its external text form is a - * string wrapped in square brackets with commas separating the values. The - * internal form is an object having get and opt - * methods for accessing the values by index, and put methods for - * adding or replacing values. The values can be any of these types: - * Boolean, JSONArray, JSONObject, - * Number, String, or the - * JSONObject.NULL object. - *

- * The constructor can convert a JSON text into a Java object. The - * toString method converts to JSON text. - *

- * A get method returns a value if one can be found, and throws an - * exception if one cannot be found. An opt method returns a - * default value instead of throwing an exception, and so is useful for - * obtaining optional values. - *

- * The generic get() and opt() methods return an - * object which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. - *

- * The texts produced by the toString methods strictly conform to - * JSON syntax rules. The constructors are more forgiving in the texts they will - * accept: - *

    - *
  • An extra , (comma) may appear just - * before the closing bracket.
  • - *
  • The null value will be inserted when there - * is , (comma) elision.
  • - *
  • Strings may be quoted with ' (single - * quote).
  • - *
  • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, - * and if they do not contain any of these characters: - * { } [ ] / \ : , = ; # and if they do not look like numbers - * and if they are not the reserved words true, - * false, or null.
  • - *
  • Values can be separated by ; (semicolon) as - * well as by , (comma).
  • - *
- - * @author JSON.org - * @version 2011-12-19 - */ -public class JSONArray { - - - /** - * The arrayList where the JSONArray's properties are kept. - */ - private final ArrayList myArrayList; - - - /** - * Construct an empty JSONArray. - */ - public JSONArray() { - this.myArrayList = new ArrayList(); - } - - /** - * Construct a JSONArray from a JSONTokener. - * @param x A JSONTokener - * @throws JSONException If there is a syntax error. - */ - public JSONArray(JSONTokener x) throws JSONException { - this(); - if (x.nextClean() != '[') { - throw x.syntaxError("A JSONArray text must start with '['"); - } - if (x.nextClean() != ']') { - x.back(); - for (;;) { - if (x.nextClean() == ',') { - x.back(); - this.myArrayList.add(JSONObject.NULL); - } else { - x.back(); - this.myArrayList.add(x.nextValue()); - } - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == ']') { - return; - } - x.back(); - break; - case ']': - return; - default: - throw x.syntaxError("Expected a ',' or ']'"); - } - } - } - } - - - /** - * Construct a JSONArray from a source JSON text. - * @param source A string that begins with - * [ (left bracket) - * and ends with ] (right bracket). - * @throws JSONException If there is a syntax error. - */ - public JSONArray(String source) throws JSONException { - this(new JSONTokener(source)); - } - - - /** - * Construct a JSONArray from a Collection. - * @param collection A Collection. - */ - public JSONArray(Collection collection) { - this.myArrayList = new ArrayList(); - if (collection != null) { - Iterator iter = collection.iterator(); - while (iter.hasNext()) { - this.myArrayList.add(JSONObject.wrap(iter.next())); - } - } - } - - - /** - * Construct a JSONArray from an array - * @throws JSONException If not an array. - */ - public JSONArray(Object array) throws JSONException { - this(); - if (array.getClass().isArray()) { - int length = Array.getLength(array); - for (int i = 0; i < length; i += 1) { - this.put(JSONObject.wrap(Array.get(array, i))); - } - } else { - throw new JSONException( -"JSONArray initial value should be a string or collection or array."); - } - } - - - /** - * Get the object value associated with an index. - * @param index - * The index must be between 0 and length() - 1. - * @return An object value. - * @throws JSONException If there is no value for the index. - */ - public Object get(int index) throws JSONException { - Object object = this.opt(index); - if (object == null) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - return object; - } - - - /** - * Get the boolean value associated with an index. - * The string values "true" and "false" are converted to boolean. - * - * @param index The index must be between 0 and length() - 1. - * @return The truth. - * @throws JSONException If there is no value for the index or if the - * value is not convertible to boolean. - */ - public boolean getBoolean(int index) throws JSONException { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONArray[" + index + "] is not a boolean."); - } - - - /** - * Get the double value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value cannot - * be converted to a number. - */ - public double getDouble(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).doubleValue() - : Double.parseDouble((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the int value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value is not a number. - */ - public int getInt(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).intValue() - : Integer.parseInt((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the JSONArray associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return A JSONArray value. - * @throws JSONException If there is no value for the index. or if the - * value is not a JSONArray - */ - public JSONArray getJSONArray(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray)object; - } - throw new JSONException("JSONArray[" + index + - "] is not a JSONArray."); - } - - - /** - * Get the JSONObject associated with an index. - * @param index subscript - * @return A JSONObject value. - * @throws JSONException If there is no value for the index or if the - * value is not a JSONObject - */ - public JSONObject getJSONObject(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject)object; - } - throw new JSONException("JSONArray[" + index + - "] is not a JSONObject."); - } - - - /** - * Get the long value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value cannot - * be converted to a number. - */ - public long getLong(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).longValue() - : Long.parseLong((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the string associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return A string value. - * @throws JSONException If there is no string value for the index. - */ - public String getString(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof String) { - return (String)object; - } - throw new JSONException("JSONArray[" + index + "] not a string."); - } - - - /** - * Determine if the value is null. - * @param index The index must be between 0 and length() - 1. - * @return true if the value at the index is null, or if there is no value. - */ - public boolean isNull(int index) { - return JSONObject.NULL.equals(this.opt(index)); - } - - - /** - * Make a string from the contents of this JSONArray. The - * separator string is inserted between each element. - * Warning: This method assumes that the data structure is acyclical. - * @param separator A string that will be inserted between the elements. - * @return a string. - * @throws JSONException If the array contains an invalid number. - */ - public String join(String separator) throws JSONException { - int len = this.length(); - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < len; i += 1) { - if (i > 0) { - sb.append(separator); - } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); - } - return sb.toString(); - } - - - /** - * Get the number of elements in the JSONArray, included nulls. - * - * @return The length (or size). - */ - public int length() { - return this.myArrayList.size(); - } - - - /** - * Get the optional object value associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return An object value, or null if there is no - * object at that index. - */ - public Object opt(int index) { - return (index < 0 || index >= this.length()) - ? null - : this.myArrayList.get(index); - } - - - /** - * Get the optional boolean value associated with an index. - * It returns false if there is no value at that index, - * or if the value is not Boolean.TRUE or the String "true". - * - * @param index The index must be between 0 and length() - 1. - * @return The truth. - */ - public boolean optBoolean(int index) { - return this.optBoolean(index, false); - } - - - /** - * Get the optional boolean value associated with an index. - * It returns the defaultValue if there is no value at that index or if - * it is not a Boolean or the String "true" or "false" (case insensitive). - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue A boolean default. - * @return The truth. - */ - public boolean optBoolean(int index, boolean defaultValue) { - try { - return this.getBoolean(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional double value associated with an index. - * NaN is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public double optDouble(int index) { - return this.optDouble(index, Double.NaN); - } - - - /** - * Get the optional double value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index subscript - * @param defaultValue The default value. - * @return The value. - */ - public double optDouble(int index, double defaultValue) { - try { - return this.getDouble(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional int value associated with an index. - * Zero is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public int optInt(int index) { - return this.optInt(index, 0); - } - - - /** - * Get the optional int value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public int optInt(int index, int defaultValue) { - try { - return this.getInt(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional JSONArray associated with an index. - * @param index subscript - * @return A JSONArray value, or null if the index has no value, - * or if the value is not a JSONArray. - */ - public JSONArray optJSONArray(int index) { - Object o = this.opt(index); - return o instanceof JSONArray ? (JSONArray)o : null; - } - - - /** - * Get the optional JSONObject associated with an index. - * Null is returned if the key is not found, or null if the index has - * no value, or if the value is not a JSONObject. - * - * @param index The index must be between 0 and length() - 1. - * @return A JSONObject value. - */ - public JSONObject optJSONObject(int index) { - Object o = this.opt(index); - return o instanceof JSONObject ? (JSONObject)o : null; - } - - - /** - * Get the optional long value associated with an index. - * Zero is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public long optLong(int index) { - return this.optLong(index, 0); - } - - - /** - * Get the optional long value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public long optLong(int index, long defaultValue) { - try { - return this.getLong(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional string value associated with an index. It returns an - * empty string if there is no value at that index. If the value - * is not a string and is not null, then it is coverted to a string. - * - * @param index The index must be between 0 and length() - 1. - * @return A String value. - */ - public String optString(int index) { - return this.optString(index, ""); - } - - - /** - * Get the optional string associated with an index. - * The defaultValue is returned if the key is not found. - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return A String value. - */ - public String optString(int index, String defaultValue) { - Object object = this.opt(index); - return JSONObject.NULL.equals(object) - ? defaultValue - : object.toString(); - } - - - /** - * Append a boolean value. This increases the array's length by one. - * - * @param value A boolean value. - * @return this. - */ - public JSONArray put(boolean value) { - this.put(value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONArray which is produced from a Collection. - * @param value A Collection value. - * @return this. - */ - public JSONArray put(Collection value) { - this.put(new JSONArray(value)); - return this; - } - - - /** - * Append a double value. This increases the array's length by one. - * - * @param value A double value. - * @throws JSONException if the value is not finite. - * @return this. - */ - public JSONArray put(double value) throws JSONException { - Double d = new Double(value); - JSONObject.testValidity(d); - this.put(d); - return this; - } - - - /** - * Append an int value. This increases the array's length by one. - * - * @param value An int value. - * @return this. - */ - public JSONArray put(int value) { - this.put(new Integer(value)); - return this; - } - - - /** - * Append an long value. This increases the array's length by one. - * - * @param value A long value. - * @return this. - */ - public JSONArray put(long value) { - this.put(new Long(value)); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONObject which is produced from a Map. - * @param value A Map value. - * @return this. - */ - public JSONArray put(Map value) { - this.put(new JSONObject(value)); - return this; - } - - - /** - * Append an object value. This increases the array's length by one. - * @param value An object value. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - */ - public JSONArray put(Object value) { - this.myArrayList.add(value); - return this; - } - - - /** - * Put or replace a boolean value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * @param index The subscript. - * @param value A boolean value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, boolean value) throws JSONException { - this.put(index, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONArray which is produced from a Collection. - * @param index The subscript. - * @param value A Collection value. - * @return this. - * @throws JSONException If the index is negative or if the value is - * not finite. - */ - public JSONArray put(int index, Collection value) throws JSONException { - this.put(index, new JSONArray(value)); - return this; - } - - - /** - * Put or replace a double value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value A double value. - * @return this. - * @throws JSONException If the index is negative or if the value is - * not finite. - */ - public JSONArray put(int index, double value) throws JSONException { - this.put(index, new Double(value)); - return this; - } - - - /** - * Put or replace an int value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value An int value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, int value) throws JSONException { - this.put(index, new Integer(value)); - return this; - } - - - /** - * Put or replace a long value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value A long value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, long value) throws JSONException { - this.put(index, new Long(value)); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONObject that is produced from a Map. - * @param index The subscript. - * @param value The Map value. - * @return this. - * @throws JSONException If the index is negative or if the the value is - * an invalid number. - */ - public JSONArray put(int index, Map value) throws JSONException { - this.put(index, new JSONObject(value)); - return this; - } - - - /** - * Put or replace an object value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * @param index The subscript. - * @param value The value to put into the array. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - * @throws JSONException If the index is negative or if the the value is - * an invalid number. - */ - public JSONArray put(int index, Object value) throws JSONException { - JSONObject.testValidity(value); - if (index < 0) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - if (index < this.length()) { - this.myArrayList.set(index, value); - } else { - while (index != this.length()) { - this.put(JSONObject.NULL); - } - this.put(value); - } - return this; - } - - - /** - * Remove an index and close the hole. - * @param index The index of the element to be removed. - * @return The value that was associated with the index, - * or null if there was no value. - */ - public Object remove(int index) { - Object o = this.opt(index); - this.myArrayList.remove(index); - return o; - } - - - /** - * Produce a JSONObject by combining a JSONArray of names with the values - * of this JSONArray. - * @param names A JSONArray containing a list of key strings. These will be - * paired with the values. - * @return A JSONObject, or null if there are no names or if this JSONArray - * has no values. - * @throws JSONException If any of the names are null. - */ - public JSONObject toJSONObject(JSONArray names) throws JSONException { - if (names == null || names.length() == 0 || this.length() == 0) { - return null; - } - JSONObject jo = new JSONObject(); - for (int i = 0; i < names.length(); i += 1) { - jo.put(names.getString(i), this.opt(i)); - } - return jo; - } - - - /** - * Make a JSON text of this JSONArray. For compactness, no - * unnecessary whitespace is added. If it is not possible to produce a - * syntactically correct JSON text then null will be returned instead. This - * could occur if the array contains an invalid number. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, transmittable - * representation of the array. - */ - public String toString() { - try { - return '[' + this.join(",") + ']'; - } catch (Exception e) { - return null; - } - } - - - /** - * Make a prettyprinted JSON text of this JSONArray. - * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with [ (left bracket) and ending - * with ] (right bracket). - * @throws JSONException - */ - public String toString(int indentFactor) throws JSONException { - return this.toString(indentFactor, 0); - } - - - /** - * Make a prettyprinted JSON text of this JSONArray. - * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @param indent The indention of the top level. - * @return a printable, displayable, transmittable - * representation of the array. - * @throws JSONException - */ - String toString(int indentFactor, int indent) throws JSONException { - int len = this.length(); - if (len == 0) { - return "[]"; - } - int i; - StringBuffer sb = new StringBuffer("["); - if (len == 1) { - sb.append(JSONObject.valueToString(this.myArrayList.get(0), - indentFactor, indent)); - } else { - int newindent = indent + indentFactor; - sb.append('\n'); - for (i = 0; i < len; i += 1) { - if (i > 0) { - sb.append(",\n"); - } - for (int j = 0; j < newindent; j += 1) { - sb.append(' '); - } - sb.append(JSONObject.valueToString(this.myArrayList.get(i), - indentFactor, newindent)); - } - sb.append('\n'); - for (i = 0; i < indent; i += 1) { - sb.append(' '); - } - } - sb.append(']'); - return sb.toString(); - } - - - /** - * Write the contents of the JSONArray as JSON text to a writer. - * For compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - try { - boolean b = false; - int len = this.length(); - - writer.write('['); - - for (int i = 0; i < len; i += 1) { - if (b) { - writer.write(','); - } - Object v = this.myArrayList.get(i); - if (v instanceof JSONObject) { - ((JSONObject)v).write(writer); - } else if (v instanceof JSONArray) { - ((JSONArray)v).write(writer); - } else { - writer.write(JSONObject.valueToString(v)); - } - b = true; - } - writer.write(']'); - return writer; - } catch (IOException e) { - throw new JSONException(e); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/org/json/JSONException.java b/subsonic-main/src/main/java/org/json/JSONException.java deleted file mode 100644 index 3ec8fb99..00000000 --- a/subsonic-main/src/main/java/org/json/JSONException.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.json; - -/** - * The JSONException is thrown by the JSON.org classes when things are amiss. - * @author JSON.org - * @version 2010-12-24 - */ -public class JSONException extends Exception { - private static final long serialVersionUID = 0; - private Throwable cause; - - /** - * Constructs a JSONException with an explanatory message. - * @param message Detail about the reason for the exception. - */ - public JSONException(String message) { - super(message); - } - - public JSONException(Throwable cause) { - super(cause.getMessage()); - this.cause = cause; - } - - public Throwable getCause() { - return this.cause; - } -} diff --git a/subsonic-main/src/main/java/org/json/JSONML.java b/subsonic-main/src/main/java/org/json/JSONML.java deleted file mode 100644 index d20a9c3c..00000000 --- a/subsonic-main/src/main/java/org/json/JSONML.java +++ /dev/null @@ -1,465 +0,0 @@ -package org.json; - -/* -Copyright (c) 2008 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - - -/** - * This provides static methods to convert an XML text into a JSONArray or - * JSONObject, and to covert a JSONArray or JSONObject into an XML text using - * the JsonML transform. - * @author JSON.org - * @version 2011-11-24 - */ -public class JSONML { - - /** - * Parse XML values and store them in a JSONArray. - * @param x The XMLTokener containing the source string. - * @param arrayForm true if array form, false if object form. - * @param ja The JSONArray that is containing the current tag or null - * if we are at the outermost level. - * @return A JSONArray if the value is the outermost tag, otherwise null. - * @throws JSONException - */ - private static Object parse( - XMLTokener x, - boolean arrayForm, - JSONArray ja - ) throws JSONException { - String attribute; - char c; - String closeTag = null; - int i; - JSONArray newja = null; - JSONObject newjo = null; - Object token; - String tagName = null; - -// Test for and skip past these forms: -// -// -// -// - - while (true) { - if (!x.more()) { - throw x.syntaxError("Bad XML"); - } - token = x.nextContent(); - if (token == XML.LT) { - token = x.nextToken(); - if (token instanceof Character) { - if (token == XML.SLASH) { - -// Close tag "); - } - x.back(); - } else if (c == '[') { - token = x.nextToken(); - if (token.equals("CDATA") && x.next() == '[') { - if (ja != null) { - ja.put(x.nextCDATA()); - } - } else { - throw x.syntaxError("Expected 'CDATA['"); - } - } else { - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after ' 0); - } - } else if (token == XML.QUEST) { - -// "); - } else { - throw x.syntaxError("Misshaped tag"); - } - -// Open tag < - - } else { - if (!(token instanceof String)) { - throw x.syntaxError("Bad tagName '" + token + "'."); - } - tagName = (String)token; - newja = new JSONArray(); - newjo = new JSONObject(); - if (arrayForm) { - newja.put(tagName); - if (ja != null) { - ja.put(newja); - } - } else { - newjo.put("tagName", tagName); - if (ja != null) { - ja.put(newjo); - } - } - token = null; - for (;;) { - if (token == null) { - token = x.nextToken(); - } - if (token == null) { - throw x.syntaxError("Misshaped tag"); - } - if (!(token instanceof String)) { - break; - } - -// attribute = value - - attribute = (String)token; - if (!arrayForm && (attribute == "tagName" || attribute == "childNode")) { - throw x.syntaxError("Reserved attribute."); - } - token = x.nextToken(); - if (token == XML.EQ) { - token = x.nextToken(); - if (!(token instanceof String)) { - throw x.syntaxError("Missing value"); - } - newjo.accumulate(attribute, XML.stringToValue((String)token)); - token = null; - } else { - newjo.accumulate(attribute, ""); - } - } - if (arrayForm && newjo.length() > 0) { - newja.put(newjo); - } - -// Empty tag <.../> - - if (token == XML.SLASH) { - if (x.nextToken() != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - -// Content, between <...> and - - } else { - if (token != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - closeTag = (String)parse(x, arrayForm, newja); - if (closeTag != null) { - if (!closeTag.equals(tagName)) { - throw x.syntaxError("Mismatched '" + tagName + - "' and '" + closeTag + "'"); - } - tagName = null; - if (!arrayForm && newja.length() > 0) { - newjo.put("childNodes", newja); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - } - } - } - } else { - if (ja != null) { - ja.put(token instanceof String - ? XML.stringToValue((String)token) - : token); - } - } - } - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONArray using the JsonML transform. Each XML tag is represented as - * a JSONArray in which the first element is the tag name. If the tag has - * attributes, then the second element will be JSONObject containing the - * name/value pairs. If the tag contains children, then strings and - * JSONArrays will represent the child tags. - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param string The source string. - * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONArray toJSONArray(String string) throws JSONException { - return toJSONArray(new XMLTokener(string)); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONArray using the JsonML transform. Each XML tag is represented as - * a JSONArray in which the first element is the tag name. If the tag has - * attributes, then the second element will be JSONObject containing the - * name/value pairs. If the tag contains children, then strings and - * JSONArrays will represent the child content and tags. - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param x An XMLTokener. - * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONArray toJSONArray(XMLTokener x) throws JSONException { - return (JSONArray)parse(x, true, null); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject using the JsonML transform. Each XML tag is represented as - * a JSONObject with a "tagName" property. If the tag has attributes, then - * the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which - * will be an array of strings and JsonML JSONObjects. - - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param x An XMLTokener of the XML source text. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(XMLTokener x) throws JSONException { - return (JSONObject)parse(x, false, null); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject using the JsonML transform. Each XML tag is represented as - * a JSONObject with a "tagName" property. If the tag has attributes, then - * the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which - * will be an array of strings and JsonML JSONObjects. - - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param string The XML source text. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - return toJSONObject(new XMLTokener(string)); - } - - - /** - * Reverse the JSONML transformation, making an XML text from a JSONArray. - * @param ja A JSONArray. - * @return An XML string. - * @throws JSONException - */ - public static String toString(JSONArray ja) throws JSONException { - int i; - JSONObject jo; - String key; - Iterator keys; - int length; - Object object; - StringBuffer sb = new StringBuffer(); - String tagName; - String value; - -// Emit = length) { - sb.append('/'); - sb.append('>'); - } else { - sb.append('>'); - do { - object = ja.get(i); - i += 1; - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray)object)); - } - } - } while (i < length); - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } - return sb.toString(); - } - - /** - * Reverse the JSONML transformation, making an XML text from a JSONObject. - * The JSONObject must contain a "tagName" property. If it has children, - * then it must have a "childNodes" property containing an array of objects. - * The other properties are attributes with string values. - * @param jo A JSONObject. - * @return An XML string. - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - StringBuffer sb = new StringBuffer(); - int i; - JSONArray ja; - String key; - Iterator keys; - int length; - Object object; - String tagName; - String value; - -//Emit '); - } else { - sb.append('>'); - length = ja.length(); - for (i = 0; i < length; i += 1) { - object = ja.get(i); - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray)object)); - } else { - sb.append(object.toString()); - } - } - } - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } - return sb.toString(); - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/org/json/JSONObject.java b/subsonic-main/src/main/java/org/json/JSONObject.java deleted file mode 100644 index f8ee3590..00000000 --- a/subsonic-main/src/main/java/org/json/JSONObject.java +++ /dev/null @@ -1,1630 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.IOException; -import java.io.Writer; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; - -/** - * A JSONObject is an unordered collection of name/value pairs. Its - * external form is a string wrapped in curly braces with colons between the - * names and values, and commas between the values and names. The internal form - * is an object having get and opt methods for - * accessing the values by name, and put methods for adding or - * replacing values by name. The values can be any of these types: - * Boolean, JSONArray, JSONObject, - * Number, String, or the JSONObject.NULL - * object. A JSONObject constructor can be used to convert an external form - * JSON text into an internal form whose values can be retrieved with the - * get and opt methods, or to convert values into a - * JSON text using the put and toString methods. - * A get method returns a value if one can be found, and throws an - * exception if one cannot be found. An opt method returns a - * default value instead of throwing an exception, and so is useful for - * obtaining optional values. - *

- * The generic get() and opt() methods return an - * object, which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. The opt methods differ from the get methods in that they - * do not throw. Instead, they return a specified value, such as null. - *

- * The put methods add or replace values in an object. For example, - *

myString = new JSONObject().put("JSON", "Hello, World!").toString();
- * produces the string {"JSON": "Hello, World"}. - *

- * The texts produced by the toString methods strictly conform to - * the JSON syntax rules. - * The constructors are more forgiving in the texts they will accept: - *

    - *
  • An extra , (comma) may appear just - * before the closing brace.
  • - *
  • Strings may be quoted with ' (single - * quote).
  • - *
  • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, - * and if they do not contain any of these characters: - * { } [ ] / \ : , = ; # and if they do not look like numbers - * and if they are not the reserved words true, - * false, or null.
  • - *
  • Keys can be followed by = or => as well as - * by :.
  • - *
  • Values can be followed by ; (semicolon) as - * well as by , (comma).
  • - *
- * @author JSON.org - * @version 2011-11-24 - */ -public class JSONObject { - - /** - * JSONObject.NULL is equivalent to the value that JavaScript calls null, - * whilst Java's null is equivalent to the value that JavaScript calls - * undefined. - */ - private static final class Null { - - /** - * There is only intended to be a single instance of the NULL object, - * so the clone method returns itself. - * @return NULL. - */ - protected final Object clone() { - return this; - } - - /** - * A Null object is equal to the null value and to itself. - * @param object An object to test for nullness. - * @return true if the object parameter is the JSONObject.NULL object - * or null. - */ - public boolean equals(Object object) { - return object == null || object == this; - } - - /** - * Get the "null" string value. - * @return The string "null". - */ - public String toString() { - return "null"; - } - } - - - /** - * The map where the JSONObject's properties are kept. - */ - private final Map map; - - - /** - * It is sometimes more convenient and less ambiguous to have a - * NULL object than to use Java's null value. - * JSONObject.NULL.equals(null) returns true. - * JSONObject.NULL.toString() returns "null". - */ - public static final Object NULL = new Null(); - - - /** - * Construct an empty JSONObject. - */ - public JSONObject() { - this.map = new HashMap(); - } - - - /** - * Construct a JSONObject from a subset of another JSONObject. - * An array of strings is used to identify the keys that should be copied. - * Missing keys are ignored. - * @param jo A JSONObject. - * @param names An array of strings. - * @throws JSONException - * @exception JSONException If a value is a non-finite number or if a name is duplicated. - */ - public JSONObject(JSONObject jo, String[] names) { - this(); - for (int i = 0; i < names.length; i += 1) { - try { - this.putOnce(names[i], jo.opt(names[i])); - } catch (Exception ignore) { - } - } - } - - - /** - * Construct a JSONObject from a JSONTokener. - * @param x A JSONTokener object containing the source string. - * @throws JSONException If there is a syntax error in the source string - * or a duplicated key. - */ - public JSONObject(JSONTokener x) throws JSONException { - this(); - char c; - String key; - - if (x.nextClean() != '{') { - throw x.syntaxError("A JSONObject text must begin with '{'"); - } - for (;;) { - c = x.nextClean(); - switch (c) { - case 0: - throw x.syntaxError("A JSONObject text must end with '}'"); - case '}': - return; - default: - x.back(); - key = x.nextValue().toString(); - } - -// The key is followed by ':'. We will also tolerate '=' or '=>'. - - c = x.nextClean(); - if (c == '=') { - if (x.next() != '>') { - x.back(); - } - } else if (c != ':') { - throw x.syntaxError("Expected a ':' after a key"); - } - this.putOnce(key, x.nextValue()); - -// Pairs are separated by ','. We will also tolerate ';'. - - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == '}') { - return; - } - x.back(); - break; - case '}': - return; - default: - throw x.syntaxError("Expected a ',' or '}'"); - } - } - } - - - /** - * Construct a JSONObject from a Map. - * - * @param map A map object that can be used to initialize the contents of - * the JSONObject. - * @throws JSONException - */ - public JSONObject(Map map) { - this.map = new HashMap(); - if (map != null) { - Iterator i = map.entrySet().iterator(); - while (i.hasNext()) { - Map.Entry e = (Map.Entry)i.next(); - Object value = e.getValue(); - if (value != null) { - this.map.put(e.getKey(), wrap(value)); - } - } - } - } - - - /** - * Construct a JSONObject from an Object using bean getters. - * It reflects on all of the public methods of the object. - * For each of the methods with no parameters and a name starting - * with "get" or "is" followed by an uppercase letter, - * the method is invoked, and a key and the value returned from the getter method - * are put into the new JSONObject. - * - * The key is formed by removing the "get" or "is" prefix. - * If the second remaining character is not upper case, then the first - * character is converted to lower case. - * - * For example, if an object has a method named "getName", and - * if the result of calling object.getName() is "Larry Fine", - * then the JSONObject will contain "name": "Larry Fine". - * - * @param bean An object that has getter methods that should be used - * to make a JSONObject. - */ - public JSONObject(Object bean) { - this(); - this.populateMap(bean); - } - - - /** - * Construct a JSONObject from an Object, using reflection to find the - * public members. The resulting JSONObject's keys will be the strings - * from the names array, and the values will be the field values associated - * with those keys in the object. If a key is not found or not visible, - * then it will not be copied into the new JSONObject. - * @param object An object that has fields that should be used to make a - * JSONObject. - * @param names An array of strings, the names of the fields to be obtained - * from the object. - */ - public JSONObject(Object object, String names[]) { - this(); - Class c = object.getClass(); - for (int i = 0; i < names.length; i += 1) { - String name = names[i]; - try { - this.putOpt(name, c.getField(name).get(object)); - } catch (Exception ignore) { - } - } - } - - - /** - * Construct a JSONObject from a source JSON text string. - * This is the most commonly used JSONObject constructor. - * @param source A string beginning - * with { (left brace) and ending - * with } (right brace). - * @exception JSONException If there is a syntax error in the source - * string or a duplicated key. - */ - public JSONObject(String source) throws JSONException { - this(new JSONTokener(source)); - } - - - /** - * Construct a JSONObject from a ResourceBundle. - * @param baseName The ResourceBundle base name. - * @param locale The Locale to load the ResourceBundle for. - * @throws JSONException If any JSONExceptions are detected. - */ - public JSONObject(String baseName, Locale locale) throws JSONException { - this(); - ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, - Thread.currentThread().getContextClassLoader()); - -// Iterate through the keys in the bundle. - - Enumeration keys = bundle.getKeys(); - while (keys.hasMoreElements()) { - Object key = keys.nextElement(); - if (key instanceof String) { - -// Go through the path, ensuring that there is a nested JSONObject for each -// segment except the last. Add the value using the last segment's name into -// the deepest nested JSONObject. - - String[] path = ((String)key).split("\\."); - int last = path.length - 1; - JSONObject target = this; - for (int i = 0; i < last; i += 1) { - String segment = path[i]; - JSONObject nextTarget = target.optJSONObject(segment); - if (nextTarget == null) { - nextTarget = new JSONObject(); - target.put(segment, nextTarget); - } - target = nextTarget; - } - target.put(path[last], bundle.getString((String)key)); - } - } - } - - - /** - * Accumulate values under a key. It is similar to the put method except - * that if there is already an object stored under the key then a - * JSONArray is stored under the key to hold all of the accumulated values. - * If there is already a JSONArray, then the new value is appended to it. - * In contrast, the put method replaces the previous value. - * - * If only one value is accumulated that is not a JSONArray, then the - * result will be the same as using put. But if multiple values are - * accumulated, then the result will be like append. - * @param key A key string. - * @param value An object to be accumulated under the key. - * @return this. - * @throws JSONException If the value is an invalid number - * or if the key is null. - */ - public JSONObject accumulate( - String key, - Object value - ) throws JSONException { - testValidity(value); - Object object = this.opt(key); - if (object == null) { - this.put(key, value instanceof JSONArray - ? new JSONArray().put(value) - : value); - } else if (object instanceof JSONArray) { - ((JSONArray)object).put(value); - } else { - this.put(key, new JSONArray().put(object).put(value)); - } - return this; - } - - - /** - * Append values to the array under a key. If the key does not exist in the - * JSONObject, then the key is put in the JSONObject with its value being a - * JSONArray containing the value parameter. If the key was already - * associated with a JSONArray, then the value parameter is appended to it. - * @param key A key string. - * @param value An object to be accumulated under the key. - * @return this. - * @throws JSONException If the key is null or if the current value - * associated with the key is not a JSONArray. - */ - public JSONObject append(String key, Object value) throws JSONException { - testValidity(value); - Object object = this.opt(key); - if (object == null) { - this.put(key, new JSONArray().put(value)); - } else if (object instanceof JSONArray) { - this.put(key, ((JSONArray)object).put(value)); - } else { - throw new JSONException("JSONObject[" + key + - "] is not a JSONArray."); - } - return this; - } - - - /** - * Produce a string from a double. The string "null" will be returned if - * the number is not finite. - * @param d A double. - * @return A String. - */ - public static String doubleToString(double d) { - if (Double.isInfinite(d) || Double.isNaN(d)) { - return "null"; - } - -// Shave off trailing zeros and decimal point, if possible. - - String string = Double.toString(d); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && - string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - - /** - * Get the value object associated with a key. - * - * @param key A key string. - * @return The object associated with the key. - * @throws JSONException if the key is not found. - */ - public Object get(String key) throws JSONException { - if (key == null) { - throw new JSONException("Null key."); - } - Object object = this.opt(key); - if (object == null) { - throw new JSONException("JSONObject[" + quote(key) + - "] not found."); - } - return object; - } - - - /** - * Get the boolean value associated with a key. - * - * @param key A key string. - * @return The truth. - * @throws JSONException - * if the value is not a Boolean or the String "true" or "false". - */ - public boolean getBoolean(String key) throws JSONException { - Object object = this.get(key); - if (object.equals(Boolean.FALSE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a Boolean."); - } - - - /** - * Get the double value associated with a key. - * @param key A key string. - * @return The numeric value. - * @throws JSONException if the key is not found or - * if the value is not a Number object and cannot be converted to a number. - */ - public double getDouble(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).doubleValue() - : Double.parseDouble((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not a number."); - } - } - - - /** - * Get the int value associated with a key. - * - * @param key A key string. - * @return The integer value. - * @throws JSONException if the key is not found or if the value cannot - * be converted to an integer. - */ - public int getInt(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).intValue() - : Integer.parseInt((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not an int."); - } - } - - - /** - * Get the JSONArray value associated with a key. - * - * @param key A key string. - * @return A JSONArray which is the value. - * @throws JSONException if the key is not found or - * if the value is not a JSONArray. - */ - public JSONArray getJSONArray(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONArray) { - return (JSONArray)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a JSONArray."); - } - - - /** - * Get the JSONObject value associated with a key. - * - * @param key A key string. - * @return A JSONObject which is the value. - * @throws JSONException if the key is not found or - * if the value is not a JSONObject. - */ - public JSONObject getJSONObject(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONObject) { - return (JSONObject)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a JSONObject."); - } - - - /** - * Get the long value associated with a key. - * - * @param key A key string. - * @return The long value. - * @throws JSONException if the key is not found or if the value cannot - * be converted to a long. - */ - public long getLong(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).longValue() - : Long.parseLong((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not a long."); - } - } - - - /** - * Get an array of field names from a JSONObject. - * - * @return An array of field names, or null if there are no names. - */ - public static String[] getNames(JSONObject jo) { - int length = jo.length(); - if (length == 0) { - return null; - } - Iterator iterator = jo.keys(); - String[] names = new String[length]; - int i = 0; - while (iterator.hasNext()) { - names[i] = (String)iterator.next(); - i += 1; - } - return names; - } - - - /** - * Get an array of field names from an Object. - * - * @return An array of field names, or null if there are no names. - */ - public static String[] getNames(Object object) { - if (object == null) { - return null; - } - Class klass = object.getClass(); - Field[] fields = klass.getFields(); - int length = fields.length; - if (length == 0) { - return null; - } - String[] names = new String[length]; - for (int i = 0; i < length; i += 1) { - names[i] = fields[i].getName(); - } - return names; - } - - - /** - * Get the string associated with a key. - * - * @param key A key string. - * @return A string which is the value. - * @throws JSONException if there is no string value for the key. - */ - public String getString(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof String) { - return (String)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] not a string."); - } - - - /** - * Determine if the JSONObject contains a specific key. - * @param key A key string. - * @return true if the key exists in the JSONObject. - */ - public boolean has(String key) { - return this.map.containsKey(key); - } - - - /** - * Increment a property of a JSONObject. If there is no such property, - * create one with a value of 1. If there is such a property, and if - * it is an Integer, Long, Double, or Float, then add one to it. - * @param key A key string. - * @return this. - * @throws JSONException If there is already a property with this name - * that is not an Integer, Long, Double, or Float. - */ - public JSONObject increment(String key) throws JSONException { - Object value = this.opt(key); - if (value == null) { - this.put(key, 1); - } else if (value instanceof Integer) { - this.put(key, ((Integer)value).intValue() + 1); - } else if (value instanceof Long) { - this.put(key, ((Long)value).longValue() + 1); - } else if (value instanceof Double) { - this.put(key, ((Double)value).doubleValue() + 1); - } else if (value instanceof Float) { - this.put(key, ((Float)value).floatValue() + 1); - } else { - throw new JSONException("Unable to increment [" + quote(key) + "]."); - } - return this; - } - - - /** - * Determine if the value associated with the key is null or if there is - * no value. - * @param key A key string. - * @return true if there is no value associated with the key or if - * the value is the JSONObject.NULL object. - */ - public boolean isNull(String key) { - return JSONObject.NULL.equals(this.opt(key)); - } - - - /** - * Get an enumeration of the keys of the JSONObject. - * - * @return An iterator of the keys. - */ - public Iterator keys() { - return this.map.keySet().iterator(); - } - - - /** - * Get the number of keys stored in the JSONObject. - * - * @return The number of keys in the JSONObject. - */ - public int length() { - return this.map.size(); - } - - - /** - * Produce a JSONArray containing the names of the elements of this - * JSONObject. - * @return A JSONArray containing the key strings, or null if the JSONObject - * is empty. - */ - public JSONArray names() { - JSONArray ja = new JSONArray(); - Iterator keys = this.keys(); - while (keys.hasNext()) { - ja.put(keys.next()); - } - return ja.length() == 0 ? null : ja; - } - - /** - * Produce a string from a Number. - * @param number A Number - * @return A String. - * @throws JSONException If n is a non-finite number. - */ - public static String numberToString(Number number) - throws JSONException { - if (number == null) { - throw new JSONException("Null pointer"); - } - testValidity(number); - -// Shave off trailing zeros and decimal point, if possible. - - String string = number.toString(); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && - string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - - /** - * Get an optional value associated with a key. - * @param key A key string. - * @return An object which is the value, or null if there is no value. - */ - public Object opt(String key) { - return key == null ? null : this.map.get(key); - } - - - /** - * Get an optional boolean associated with a key. - * It returns false if there is no such key, or if the value is not - * Boolean.TRUE or the String "true". - * - * @param key A key string. - * @return The truth. - */ - public boolean optBoolean(String key) { - return this.optBoolean(key, false); - } - - - /** - * Get an optional boolean associated with a key. - * It returns the defaultValue if there is no such key, or if it is not - * a Boolean or the String "true" or "false" (case insensitive). - * - * @param key A key string. - * @param defaultValue The default. - * @return The truth. - */ - public boolean optBoolean(String key, boolean defaultValue) { - try { - return this.getBoolean(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional double associated with a key, - * or NaN if there is no such key or if its value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A string which is the key. - * @return An object which is the value. - */ - public double optDouble(String key) { - return this.optDouble(key, Double.NaN); - } - - - /** - * Get an optional double associated with a key, or the - * defaultValue if there is no such key or if its value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public double optDouble(String key, double defaultValue) { - try { - return this.getDouble(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional int value associated with a key, - * or zero if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @return An object which is the value. - */ - public int optInt(String key) { - return this.optInt(key, 0); - } - - - /** - * Get an optional int value associated with a key, - * or the default if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public int optInt(String key, int defaultValue) { - try { - return this.getInt(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional JSONArray associated with a key. - * It returns null if there is no such key, or if its value is not a - * JSONArray. - * - * @param key A key string. - * @return A JSONArray which is the value. - */ - public JSONArray optJSONArray(String key) { - Object o = this.opt(key); - return o instanceof JSONArray ? (JSONArray)o : null; - } - - - /** - * Get an optional JSONObject associated with a key. - * It returns null if there is no such key, or if its value is not a - * JSONObject. - * - * @param key A key string. - * @return A JSONObject which is the value. - */ - public JSONObject optJSONObject(String key) { - Object object = this.opt(key); - return object instanceof JSONObject ? (JSONObject)object : null; - } - - - /** - * Get an optional long value associated with a key, - * or zero if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @return An object which is the value. - */ - public long optLong(String key) { - return this.optLong(key, 0); - } - - - /** - * Get an optional long value associated with a key, - * or the default if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public long optLong(String key, long defaultValue) { - try { - return this.getLong(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional string associated with a key. - * It returns an empty string if there is no such key. If the value is not - * a string and is not null, then it is converted to a string. - * - * @param key A key string. - * @return A string which is the value. - */ - public String optString(String key) { - return this.optString(key, ""); - } - - - /** - * Get an optional string associated with a key. - * It returns the defaultValue if there is no such key. - * - * @param key A key string. - * @param defaultValue The default. - * @return A string which is the value. - */ - public String optString(String key, String defaultValue) { - Object object = this.opt(key); - return NULL.equals(object) ? defaultValue : object.toString(); - } - - - private void populateMap(Object bean) { - Class klass = bean.getClass(); - -// If klass is a System class then set includeSuperClass to false. - - boolean includeSuperClass = klass.getClassLoader() != null; - - Method[] methods = includeSuperClass - ? klass.getMethods() - : klass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) || - "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); - } - if (key.length() > 0 && - Character.isUpperCase(key.charAt(0)) && - method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase() + - key.substring(1); - } - - Object result = method.invoke(bean, (Object[])null); - if (result != null) { - this.map.put(key, wrap(result)); - } - } - } - } catch (Exception ignore) { - } - } - } - - - /** - * Put a key/boolean pair in the JSONObject. - * - * @param key A key string. - * @param value A boolean which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, boolean value) throws JSONException { - this.put(key, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a key/value pair in the JSONObject, where the value will be a - * JSONArray which is produced from a Collection. - * @param key A key string. - * @param value A Collection value. - * @return this. - * @throws JSONException - */ - public JSONObject put(String key, Collection value) throws JSONException { - this.put(key, new JSONArray(value)); - return this; - } - - - /** - * Put a key/double pair in the JSONObject. - * - * @param key A key string. - * @param value A double which is the value. - * @return this. - * @throws JSONException If the key is null or if the number is invalid. - */ - public JSONObject put(String key, double value) throws JSONException { - this.put(key, new Double(value)); - return this; - } - - - /** - * Put a key/int pair in the JSONObject. - * - * @param key A key string. - * @param value An int which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, int value) throws JSONException { - this.put(key, new Integer(value)); - return this; - } - - - /** - * Put a key/long pair in the JSONObject. - * - * @param key A key string. - * @param value A long which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, long value) throws JSONException { - this.put(key, new Long(value)); - return this; - } - - - /** - * Put a key/value pair in the JSONObject, where the value will be a - * JSONObject which is produced from a Map. - * @param key A key string. - * @param value A Map value. - * @return this. - * @throws JSONException - */ - public JSONObject put(String key, Map value) throws JSONException { - this.put(key, new JSONObject(value)); - return this; - } - - - /** - * Put a key/value pair in the JSONObject. If the value is null, - * then the key will be removed from the JSONObject if it is present. - * @param key A key string. - * @param value An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, - * or the JSONObject.NULL object. - * @return this. - * @throws JSONException If the value is non-finite number - * or if the key is null. - */ - public JSONObject put(String key, Object value) throws JSONException { - if (key == null) { - throw new JSONException("Null key."); - } - if (value != null) { - testValidity(value); - this.map.put(key, value); - } else { - this.remove(key); - } - return this; - } - - - /** - * Put a key/value pair in the JSONObject, but only if the key and the - * value are both non-null, and only if there is not already a member - * with that name. - * @param key - * @param value - * @return his. - * @throws JSONException if the key is a duplicate - */ - public JSONObject putOnce(String key, Object value) throws JSONException { - if (key != null && value != null) { - if (this.opt(key) != null) { - throw new JSONException("Duplicate key \"" + key + "\""); - } - this.put(key, value); - } - return this; - } - - - /** - * Put a key/value pair in the JSONObject, but only if the - * key and the value are both non-null. - * @param key A key string. - * @param value An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, - * or the JSONObject.NULL object. - * @return this. - * @throws JSONException If the value is a non-finite number. - */ - public JSONObject putOpt(String key, Object value) throws JSONException { - if (key != null && value != null) { - this.put(key, value); - } - return this; - } - - - /** - * Produce a string in double quotes with backslash sequences in all the - * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') || - (c >= '\u2000' && c < '\u2100')) { - hhhh = "000" + Integer.toHexString(c); - sb.append("\\u" + hhhh.substring(hhhh.length() - 4)); - } else { - sb.append(c); - } - } - } - sb.append('"'); - return sb.toString(); - } - - /** - * Remove a name and its value, if present. - * @param key The name to be removed. - * @return The value that was associated with the name, - * or null if there was no value. - */ - public Object remove(String key) { - return this.map.remove(key); - } - - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. - * @param string A String. - * @return A simple JSON value. - */ - public static Object stringToValue(String string) { - Double d; - if (string.equals("")) { - return string; - } - if (string.equalsIgnoreCase("true")) { - return Boolean.TRUE; - } - if (string.equalsIgnoreCase("false")) { - return Boolean.FALSE; - } - if (string.equalsIgnoreCase("null")) { - return JSONObject.NULL; - } - - /* - * If it might be a number, try converting it. - * If a number cannot be produced, then the value will just - * be a string. Note that the plus and implied string - * conventions are non-standard. A JSON parser may accept - * non-JSON forms as long as it accepts all correct JSON forms. - */ - - char b = string.charAt(0); - if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { - try { - if (string.indexOf('.') > -1 || - string.indexOf('e') > -1 || string.indexOf('E') > -1) { - d = Double.valueOf(string); - if (!d.isInfinite() && !d.isNaN()) { - return d; - } - } else { - Long myLong = new Long(string); - if (myLong.longValue() == myLong.intValue()) { - return new Integer(myLong.intValue()); - } else { - return myLong; - } - } - } catch (Exception ignore) { - } - } - return string; - } - - - /** - * Throw an exception if the object is a NaN or infinite number. - * @param o The object to test. - * @throws JSONException If o is a non-finite number. - */ - public static void testValidity(Object o) throws JSONException { - if (o != null) { - if (o instanceof Double) { - if (((Double)o).isInfinite() || ((Double)o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } else if (o instanceof Float) { - if (((Float)o).isInfinite() || ((Float)o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } - } - } - - - /** - * Produce a JSONArray containing the values of the members of this - * JSONObject. - * @param names A JSONArray containing a list of key strings. This - * determines the sequence of the values in the result. - * @return A JSONArray of values. - * @throws JSONException If any of the values are non-finite numbers. - */ - public JSONArray toJSONArray(JSONArray names) throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - JSONArray ja = new JSONArray(); - for (int i = 0; i < names.length(); i += 1) { - ja.put(this.opt(names.getString(i))); - } - return ja; - } - - /** - * Make a JSON text of this JSONObject. For compactness, no whitespace - * is added. If this would not result in a syntactically correct JSON text, - * then null will be returned instead. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, portable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - */ - public String toString() { - try { - Iterator keys = this.keys(); - StringBuffer sb = new StringBuffer("{"); - - while (keys.hasNext()) { - if (sb.length() > 1) { - sb.append(','); - } - Object o = keys.next(); - sb.append(quote(o.toString())); - sb.append(':'); - sb.append(valueToString(this.map.get(o))); - } - sb.append('}'); - return sb.toString(); - } catch (Exception e) { - return null; - } - } - - - /** - * Make a prettyprinted JSON text of this JSONObject. - *

- * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @return a printable, displayable, portable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws JSONException If the object contains an invalid number. - */ - public String toString(int indentFactor) throws JSONException { - return this.toString(indentFactor, 0); - } - - - /** - * Make a prettyprinted JSON text of this JSONObject. - *

- * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @param indent The indentation of the top level. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws JSONException If the object contains an invalid number. - */ - String toString(int indentFactor, int indent) throws JSONException { - int i; - int length = this.length(); - if (length == 0) { - return "{}"; - } - Iterator keys = this.keys(); - int newindent = indent + indentFactor; - Object object; - StringBuffer sb = new StringBuffer("{"); - if (length == 1) { - object = keys.next(); - sb.append(quote(object.toString())); - sb.append(": "); - sb.append(valueToString(this.map.get(object), indentFactor, - indent)); - } else { - while (keys.hasNext()) { - object = keys.next(); - if (sb.length() > 1) { - sb.append(",\n"); - } else { - sb.append('\n'); - } - for (i = 0; i < newindent; i += 1) { - sb.append(' '); - } - sb.append(quote(object.toString())); - sb.append(": "); - sb.append(valueToString(this.map.get(object), indentFactor, - newindent)); - } - if (sb.length() > 1) { - sb.append('\n'); - for (i = 0; i < indent; i += 1) { - sb.append(' '); - } - } - } - sb.append('}'); - return sb.toString(); - } - - - /** - * Make a JSON text of an Object value. If the object has an - * value.toJSONString() method, then that method will be used to produce - * the JSON text. The method is required to produce a strictly - * conforming text. If the object does not contain a toJSONString - * method (which is the most common case), then a text will be - * produced by other means. If the value is an array or Collection, - * then a JSONArray will be made from it and its toJSONString method - * will be called. If the value is a MAP, then a JSONObject will be made - * from it and its toJSONString method will be called. Otherwise, the - * value's toString method will be called, and the result will be quoted. - * - *

- * Warning: This method assumes that the data structure is acyclical. - * @param value The value to be serialized. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws JSONException If the value is or contains an invalid number. - */ - public static String valueToString(Object value) throws JSONException { - if (value == null || value.equals(null)) { - return "null"; - } - if (value instanceof JSONString) { - Object object; - try { - object = ((JSONString)value).toJSONString(); - } catch (Exception e) { - throw new JSONException(e); - } - if (object instanceof String) { - return (String)object; - } - throw new JSONException("Bad value from toJSONString: " + object); - } - if (value instanceof Number) { - return numberToString((Number) value); - } - if (value instanceof Boolean || value instanceof JSONObject || - value instanceof JSONArray) { - return value.toString(); - } - if (value instanceof Map) { - return new JSONObject((Map)value).toString(); - } - if (value instanceof Collection) { - return new JSONArray((Collection)value).toString(); - } - if (value.getClass().isArray()) { - return new JSONArray(value).toString(); - } - return quote(value.toString()); - } - - - /** - * Make a prettyprinted JSON text of an object value. - *

- * Warning: This method assumes that the data structure is acyclical. - * @param value The value to be serialized. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @param indent The indentation of the top level. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws JSONException If the object contains an invalid number. - */ - static String valueToString( - Object value, - int indentFactor, - int indent - ) throws JSONException { - if (value == null || value.equals(null)) { - return "null"; - } - try { - if (value instanceof JSONString) { - Object o = ((JSONString)value).toJSONString(); - if (o instanceof String) { - return (String)o; - } - } - } catch (Exception ignore) { - } - if (value instanceof Number) { - return numberToString((Number) value); - } - if (value instanceof Boolean) { - return value.toString(); - } - if (value instanceof JSONObject) { - return ((JSONObject)value).toString(indentFactor, indent); - } - if (value instanceof JSONArray) { - return ((JSONArray)value).toString(indentFactor, indent); - } - if (value instanceof Map) { - return new JSONObject((Map)value).toString(indentFactor, indent); - } - if (value instanceof Collection) { - return new JSONArray((Collection)value).toString(indentFactor, indent); - } - if (value.getClass().isArray()) { - return new JSONArray(value).toString(indentFactor, indent); - } - return quote(value.toString()); - } - - - /** - * Wrap an object, if necessary. If the object is null, return the NULL - * object. If it is an array or collection, wrap it in a JSONArray. If - * it is a map, wrap it in a JSONObject. If it is a standard property - * (Double, String, et al) then it is already wrapped. Otherwise, if it - * comes from one of the java packages, turn it into a string. And if - * it doesn't, try to wrap it in a JSONObject. If the wrapping fails, - * then null is returned. - * - * @param object The object to wrap - * @return The wrapped value - */ - public static Object wrap(Object object) { - try { - if (object == null) { - return NULL; - } - if (object instanceof JSONObject || object instanceof JSONArray || - NULL.equals(object) || object instanceof JSONString || - object instanceof Byte || object instanceof Character || - object instanceof Short || object instanceof Integer || - object instanceof Long || object instanceof Boolean || - object instanceof Float || object instanceof Double || - object instanceof String) { - return object; - } - - if (object instanceof Collection) { - return new JSONArray((Collection)object); - } - if (object.getClass().isArray()) { - return new JSONArray(object); - } - if (object instanceof Map) { - return new JSONObject((Map)object); - } - Package objectPackage = object.getClass().getPackage(); - String objectPackageName = objectPackage != null - ? objectPackage.getName() - : ""; - if ( - objectPackageName.startsWith("java.") || - objectPackageName.startsWith("javax.") || - object.getClass().getClassLoader() == null - ) { - return object.toString(); - } - return new JSONObject(object); - } catch(Exception exception) { - return null; - } - } - - - /** - * Write the contents of the JSONObject as JSON text to a writer. - * For compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - try { - boolean commanate = false; - Iterator keys = this.keys(); - writer.write('{'); - - while (keys.hasNext()) { - if (commanate) { - writer.write(','); - } - Object key = keys.next(); - writer.write(quote(key.toString())); - writer.write(':'); - Object value = this.map.get(key); - if (value instanceof JSONObject) { - ((JSONObject)value).write(writer); - } else if (value instanceof JSONArray) { - ((JSONArray)value).write(writer); - } else { - writer.write(valueToString(value)); - } - commanate = true; - } - writer.write('}'); - return writer; - } catch (IOException exception) { - throw new JSONException(exception); - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/org/json/JSONString.java b/subsonic-main/src/main/java/org/json/JSONString.java deleted file mode 100644 index 6efd68e7..00000000 --- a/subsonic-main/src/main/java/org/json/JSONString.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.json; -/** - * The JSONString interface allows a toJSONString() - * method so that a class can change the behavior of - * JSONObject.toString(), JSONArray.toString(), - * and JSONWriter.value(Object). The - * toJSONString method will be used instead of the default behavior - * of using the Object's toString() method and quoting the result. - */ -public interface JSONString { - /** - * The toJSONString method allows a class to produce its own JSON - * serialization. - * - * @return A strictly syntactically correct JSON text. - */ - public String toJSONString(); -} diff --git a/subsonic-main/src/main/java/org/json/JSONStringer.java b/subsonic-main/src/main/java/org/json/JSONStringer.java deleted file mode 100644 index 32c9f7f4..00000000 --- a/subsonic-main/src/main/java/org/json/JSONStringer.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.json; - -/* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.StringWriter; - -/** - * JSONStringer provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of - * JSONStringer can produce one JSON text. - *

- * A JSONStringer instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting cascade style. For example,

- * myString = new JSONStringer()
- *     .object()
- *         .key("JSON")
- *         .value("Hello, World!")
- *     .endObject()
- *     .toString();
which produces the string
- * {"JSON":"Hello, World!"}
- *

- * The first method called must be array or object. - * There are no methods for adding commas or colons. JSONStringer adds them for - * you. Objects and arrays can be nested up to 20 levels deep. - *

- * This can sometimes be easier than using a JSONObject to build a string. - * @author JSON.org - * @version 2008-09-18 - */ -public class JSONStringer extends JSONWriter { - /** - * Make a fresh JSONStringer. It can be used to build one JSON text. - */ - public JSONStringer() { - super(new StringWriter()); - } - - /** - * Return the JSON text. This method is used to obtain the product of the - * JSONStringer instance. It will return null if there was a - * problem in the construction of the JSON text (such as the calls to - * array were not properly balanced with calls to - * endArray). - * @return The JSON text. - */ - public String toString() { - return this.mode == 'd' ? this.writer.toString() : null; - } -} diff --git a/subsonic-main/src/main/java/org/json/JSONTokener.java b/subsonic-main/src/main/java/org/json/JSONTokener.java deleted file mode 100644 index f323f6e6..00000000 --- a/subsonic-main/src/main/java/org/json/JSONTokener.java +++ /dev/null @@ -1,446 +0,0 @@ -package org.json; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * A JSONTokener takes a source string and extracts characters and tokens from - * it. It is used by the JSONObject and JSONArray constructors to parse - * JSON source strings. - * @author JSON.org - * @version 2011-11-24 - */ -public class JSONTokener { - - private int character; - private boolean eof; - private int index; - private int line; - private char previous; - private final Reader reader; - private boolean usePrevious; - - - /** - * Construct a JSONTokener from a Reader. - * - * @param reader A reader. - */ - public JSONTokener(Reader reader) { - this.reader = reader.markSupported() - ? reader - : new BufferedReader(reader); - this.eof = false; - this.usePrevious = false; - this.previous = 0; - this.index = 0; - this.character = 1; - this.line = 1; - } - - - /** - * Construct a JSONTokener from an InputStream. - */ - public JSONTokener(InputStream inputStream) throws JSONException { - this(new InputStreamReader(inputStream)); - } - - - /** - * Construct a JSONTokener from a string. - * - * @param s A source string. - */ - public JSONTokener(String s) { - this(new StringReader(s)); - } - - - /** - * Back up one character. This provides a sort of lookahead capability, - * so that you can test for a digit or letter before attempting to parse - * the next number or identifier. - */ - public void back() throws JSONException { - if (this.usePrevious || this.index <= 0) { - throw new JSONException("Stepping back two steps is not supported"); - } - this.index -= 1; - this.character -= 1; - this.usePrevious = true; - this.eof = false; - } - - - /** - * Get the hex value of a character (base16). - * @param c A character between '0' and '9' or between 'A' and 'F' or - * between 'a' and 'f'. - * @return An int between 0 and 15, or -1 if c was not a hex digit. - */ - public static int dehexchar(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'A' && c <= 'F') { - return c - ('A' - 10); - } - if (c >= 'a' && c <= 'f') { - return c - ('a' - 10); - } - return -1; - } - - public boolean end() { - return this.eof && !this.usePrevious; - } - - - /** - * Determine if the source string still contains characters that next() - * can consume. - * @return true if not yet at the end of the source. - */ - public boolean more() throws JSONException { - this.next(); - if (this.end()) { - return false; - } - this.back(); - return true; - } - - - /** - * Get the next character in the source string. - * - * @return The next character, or 0 if past the end of the source string. - */ - public char next() throws JSONException { - int c; - if (this.usePrevious) { - this.usePrevious = false; - c = this.previous; - } else { - try { - c = this.reader.read(); - } catch (IOException exception) { - throw new JSONException(exception); - } - - if (c <= 0) { // End of stream - this.eof = true; - c = 0; - } - } - this.index += 1; - if (this.previous == '\r') { - this.line += 1; - this.character = c == '\n' ? 0 : 1; - } else if (c == '\n') { - this.line += 1; - this.character = 0; - } else { - this.character += 1; - } - this.previous = (char) c; - return this.previous; - } - - - /** - * Consume the next character, and check that it matches a specified - * character. - * @param c The character to match. - * @return The character. - * @throws JSONException if the character does not match. - */ - public char next(char c) throws JSONException { - char n = this.next(); - if (n != c) { - throw this.syntaxError("Expected '" + c + "' and instead saw '" + - n + "'"); - } - return n; - } - - - /** - * Get the next n characters. - * - * @param n The number of characters to take. - * @return A string of n characters. - * @throws JSONException - * Substring bounds error if there are not - * n characters remaining in the source string. - */ - public String next(int n) throws JSONException { - if (n == 0) { - return ""; - } - - char[] chars = new char[n]; - int pos = 0; - - while (pos < n) { - chars[pos] = this.next(); - if (this.end()) { - throw this.syntaxError("Substring bounds error"); - } - pos += 1; - } - return new String(chars); - } - - - /** - * Get the next char in the string, skipping whitespace. - * @throws JSONException - * @return A character, or 0 if there are no more characters. - */ - public char nextClean() throws JSONException { - for (;;) { - char c = this.next(); - if (c == 0 || c > ' ') { - return c; - } - } - } - - - /** - * Return the characters up to the next close quote character. - * Backslash processing is done. The formal JSON format does not - * allow strings in single quotes, but an implementation is allowed to - * accept them. - * @param quote The quoting character, either - * " (double quote) or - * ' (single quote). - * @return A String. - * @throws JSONException Unterminated string. - */ - public String nextString(char quote) throws JSONException { - char c; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = this.next(); - switch (c) { - case 0: - case '\n': - case '\r': - throw this.syntaxError("Unterminated string"); - case '\\': - c = this.next(); - switch (c) { - case 'b': - sb.append('\b'); - break; - case 't': - sb.append('\t'); - break; - case 'n': - sb.append('\n'); - break; - case 'f': - sb.append('\f'); - break; - case 'r': - sb.append('\r'); - break; - case 'u': - sb.append((char)Integer.parseInt(this.next(4), 16)); - break; - case '"': - case '\'': - case '\\': - case '/': - sb.append(c); - break; - default: - throw this.syntaxError("Illegal escape."); - } - break; - default: - if (c == quote) { - return sb.toString(); - } - sb.append(c); - } - } - } - - - /** - * Get the text up but not including the specified character or the - * end of line, whichever comes first. - * @param delimiter A delimiter character. - * @return A string. - */ - public String nextTo(char delimiter) throws JSONException { - StringBuffer sb = new StringBuffer(); - for (;;) { - char c = this.next(); - if (c == delimiter || c == 0 || c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the text up but not including one of the specified delimiter - * characters or the end of line, whichever comes first. - * @param delimiters A set of delimiter characters. - * @return A string, trimmed. - */ - public String nextTo(String delimiters) throws JSONException { - char c; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = this.next(); - if (delimiters.indexOf(c) >= 0 || c == 0 || - c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the next value. The value can be a Boolean, Double, Integer, - * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. - * @throws JSONException If syntax error. - * - * @return An object. - */ - public Object nextValue() throws JSONException { - char c = this.nextClean(); - String string; - - switch (c) { - case '"': - case '\'': - return this.nextString(c); - case '{': - this.back(); - return new JSONObject(this); - case '[': - this.back(); - return new JSONArray(this); - } - - /* - * Handle unquoted text. This could be the values true, false, or - * null, or it can be a number. An implementation (such as this one) - * is allowed to also accept non-standard forms. - * - * Accumulate characters until we reach the end of the text or a - * formatting character. - */ - - StringBuffer sb = new StringBuffer(); - while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { - sb.append(c); - c = this.next(); - } - this.back(); - - string = sb.toString().trim(); - if ("".equals(string)) { - throw this.syntaxError("Missing value"); - } - return JSONObject.stringToValue(string); - } - - - /** - * Skip characters until the next character is the requested character. - * If the requested character is not found, no characters are skipped. - * @param to A character to skip to. - * @return The requested character, or zero if the requested character - * is not found. - */ - public char skipTo(char to) throws JSONException { - char c; - try { - int startIndex = this.index; - int startCharacter = this.character; - int startLine = this.line; - this.reader.mark(Integer.MAX_VALUE); - do { - c = this.next(); - if (c == 0) { - this.reader.reset(); - this.index = startIndex; - this.character = startCharacter; - this.line = startLine; - return c; - } - } while (c != to); - } catch (IOException exc) { - throw new JSONException(exc); - } - - this.back(); - return c; - } - - - /** - * Make a JSONException to signal a syntax error. - * - * @param message The error message. - * @return A JSONException object, suitable for throwing - */ - public JSONException syntaxError(String message) { - return new JSONException(message + this.toString()); - } - - - /** - * Make a printable string of this JSONTokener. - * - * @return " at {index} [character {character} line {line}]" - */ - public String toString() { - return " at " + this.index + " [character " + this.character + " line " + - this.line + "]"; - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/org/json/JSONWriter.java b/subsonic-main/src/main/java/org/json/JSONWriter.java deleted file mode 100644 index 35b60d90..00000000 --- a/subsonic-main/src/main/java/org/json/JSONWriter.java +++ /dev/null @@ -1,327 +0,0 @@ -package org.json; - -import java.io.IOException; -import java.io.Writer; - -/* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * JSONWriter provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of - * JSONWriter can produce one JSON text. - *

- * A JSONWriter instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting a cascade style. For example,

- * new JSONWriter(myWriter)
- *     .object()
- *         .key("JSON")
- *         .value("Hello, World!")
- *     .endObject();
which writes
- * {"JSON":"Hello, World!"}
- *

- * The first method called must be array or object. - * There are no methods for adding commas or colons. JSONWriter adds them for - * you. Objects and arrays can be nested up to 20 levels deep. - *

- * This can sometimes be easier than using a JSONObject to build a string. - * @author JSON.org - * @version 2011-11-24 - */ -public class JSONWriter { - private static final int maxdepth = 200; - - /** - * The comma flag determines if a comma should be output before the next - * value. - */ - private boolean comma; - - /** - * The current mode. Values: - * 'a' (array), - * 'd' (done), - * 'i' (initial), - * 'k' (key), - * 'o' (object). - */ - protected char mode; - - /** - * The object/array stack. - */ - private final JSONObject stack[]; - - /** - * The stack top index. A value of 0 indicates that the stack is empty. - */ - private int top; - - /** - * The writer that will receive the output. - */ - protected Writer writer; - - /** - * Make a fresh JSONWriter. It can be used to build one JSON text. - */ - public JSONWriter(Writer w) { - this.comma = false; - this.mode = 'i'; - this.stack = new JSONObject[maxdepth]; - this.top = 0; - this.writer = w; - } - - /** - * Append a value. - * @param string A string value. - * @return this - * @throws JSONException If the value is out of sequence. - */ - private JSONWriter append(String string) throws JSONException { - if (string == null) { - throw new JSONException("Null pointer"); - } - if (this.mode == 'o' || this.mode == 'a') { - try { - if (this.comma && this.mode == 'a') { - this.writer.write(','); - } - this.writer.write(string); - } catch (IOException e) { - throw new JSONException(e); - } - if (this.mode == 'o') { - this.mode = 'k'; - } - this.comma = true; - return this; - } - throw new JSONException("Value out of sequence."); - } - - /** - * Begin appending a new array. All values until the balancing - * endArray will be appended to this array. The - * endArray method must be called to mark the array's end. - * @return this - * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). - */ - public JSONWriter array() throws JSONException { - if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { - this.push(null); - this.append("["); - this.comma = false; - return this; - } - throw new JSONException("Misplaced array."); - } - - /** - * End something. - * @param mode Mode - * @param c Closing character - * @return this - * @throws JSONException If unbalanced. - */ - private JSONWriter end(char mode, char c) throws JSONException { - if (this.mode != mode) { - throw new JSONException(mode == 'a' - ? "Misplaced endArray." - : "Misplaced endObject."); - } - this.pop(mode); - try { - this.writer.write(c); - } catch (IOException e) { - throw new JSONException(e); - } - this.comma = true; - return this; - } - - /** - * End an array. This method most be called to balance calls to - * array. - * @return this - * @throws JSONException If incorrectly nested. - */ - public JSONWriter endArray() throws JSONException { - return this.end('a', ']'); - } - - /** - * End an object. This method most be called to balance calls to - * object. - * @return this - * @throws JSONException If incorrectly nested. - */ - public JSONWriter endObject() throws JSONException { - return this.end('k', '}'); - } - - /** - * Append a key. The key will be associated with the next value. In an - * object, every value must be preceded by a key. - * @param string A key string. - * @return this - * @throws JSONException If the key is out of place. For example, keys - * do not belong in arrays or if the key is null. - */ - public JSONWriter key(String string) throws JSONException { - if (string == null) { - throw new JSONException("Null key."); - } - if (this.mode == 'k') { - try { - this.stack[this.top - 1].putOnce(string, Boolean.TRUE); - if (this.comma) { - this.writer.write(','); - } - this.writer.write(JSONObject.quote(string)); - this.writer.write(':'); - this.comma = false; - this.mode = 'o'; - return this; - } catch (IOException e) { - throw new JSONException(e); - } - } - throw new JSONException("Misplaced key."); - } - - - /** - * Begin appending a new object. All keys and values until the balancing - * endObject will be appended to this object. The - * endObject method must be called to mark the object's end. - * @return this - * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). - */ - public JSONWriter object() throws JSONException { - if (this.mode == 'i') { - this.mode = 'o'; - } - if (this.mode == 'o' || this.mode == 'a') { - this.append("{"); - this.push(new JSONObject()); - this.comma = false; - return this; - } - throw new JSONException("Misplaced object."); - - } - - - /** - * Pop an array or object scope. - * @param c The scope to close. - * @throws JSONException If nesting is wrong. - */ - private void pop(char c) throws JSONException { - if (this.top <= 0) { - throw new JSONException("Nesting error."); - } - char m = this.stack[this.top - 1] == null ? 'a' : 'k'; - if (m != c) { - throw new JSONException("Nesting error."); - } - this.top -= 1; - this.mode = this.top == 0 - ? 'd' - : this.stack[this.top - 1] == null - ? 'a' - : 'k'; - } - - /** - * Push an array or object scope. - * @param c The scope to open. - * @throws JSONException If nesting is too deep. - */ - private void push(JSONObject jo) throws JSONException { - if (this.top >= maxdepth) { - throw new JSONException("Nesting too deep."); - } - this.stack[this.top] = jo; - this.mode = jo == null ? 'a' : 'k'; - this.top += 1; - } - - - /** - * Append either the value true or the value - * false. - * @param b A boolean. - * @return this - * @throws JSONException - */ - public JSONWriter value(boolean b) throws JSONException { - return this.append(b ? "true" : "false"); - } - - /** - * Append a double value. - * @param d A double. - * @return this - * @throws JSONException If the number is not finite. - */ - public JSONWriter value(double d) throws JSONException { - return this.value(new Double(d)); - } - - /** - * Append a long value. - * @param l A long. - * @return this - * @throws JSONException - */ - public JSONWriter value(long l) throws JSONException { - return this.append(Long.toString(l)); - } - - - /** - * Append an object value. - * @param object The object to append. It can be null, or a Boolean, Number, - * String, JSONObject, or JSONArray, or an object that implements JSONString. - * @return this - * @throws JSONException If the value is out of sequence. - */ - public JSONWriter value(Object object) throws JSONException { - return this.append(JSONObject.valueToString(object)); - } -} diff --git a/subsonic-main/src/main/java/org/json/XML.java b/subsonic-main/src/main/java/org/json/XML.java deleted file mode 100644 index 82455b33..00000000 --- a/subsonic-main/src/main/java/org/json/XML.java +++ /dev/null @@ -1,508 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - - -/** - * This provides static methods to convert an XML text into a JSONObject, - * and to covert a JSONObject into an XML text. - * @author JSON.org - * @version 2011-02-11 - */ -public class XML { - - /** The Character '&'. */ - public static final Character AMP = new Character('&'); - - /** The Character '''. */ - public static final Character APOS = new Character('\''); - - /** The Character '!'. */ - public static final Character BANG = new Character('!'); - - /** The Character '='. */ - public static final Character EQ = new Character('='); - - /** The Character '>'. */ - public static final Character GT = new Character('>'); - - /** The Character '<'. */ - public static final Character LT = new Character('<'); - - /** The Character '?'. */ - public static final Character QUEST = new Character('?'); - - /** The Character '"'. */ - public static final Character QUOT = new Character('"'); - - /** The Character '/'. */ - public static final Character SLASH = new Character('/'); - - /** - * Replace special characters with XML escapes: - *

-     * & (ampersand) is replaced by &amp;
-     * < (less than) is replaced by &lt;
-     * > (greater than) is replaced by &gt;
-     * " (double quote) is replaced by &quot;
-     * 
- * @param string The string to be escaped. - * @return The escaped string. - */ - public static String escape(String string) { - StringBuffer sb = new StringBuffer(); - for (int i = 0, length = string.length(); i < length; i++) { - char c = string.charAt(i); - switch (c) { - case '&': - sb.append("&"); - break; - case '<': - sb.append("<"); - break; - case '>': - sb.append(">"); - break; - case '"': - sb.append("""); - break; - case '\'': - sb.append("'"); - break; - default: - sb.append(c); - } - } - return sb.toString(); - } - - /** - * Throw an exception if the string contains whitespace. - * Whitespace is not allowed in tagNames and attributes. - * @param string - * @throws JSONException - */ - public static void noSpace(String string) throws JSONException { - int i, length = string.length(); - if (length == 0) { - throw new JSONException("Empty string."); - } - for (i = 0; i < length; i += 1) { - if (Character.isWhitespace(string.charAt(i))) { - throw new JSONException("'" + string + - "' contains a space character."); - } - } - } - - /** - * Scan the content following the named tag, attaching it to the context. - * @param x The XMLTokener containing the source string. - * @param context The JSONObject that will include the new material. - * @param name The tag name. - * @return true if the close tag is processed. - * @throws JSONException - */ - private static boolean parse(XMLTokener x, JSONObject context, - String name) throws JSONException { - char c; - int i; - JSONObject jsonobject = null; - String string; - String tagName; - Object token; - -// Test for and skip past these forms: -// -// -// -// -// Report errors for these forms: -// <> -// <= -// << - - token = x.nextToken(); - -// "); - return false; - } - x.back(); - } else if (c == '[') { - token = x.nextToken(); - if ("CDATA".equals(token)) { - if (x.next() == '[') { - string = x.nextCDATA(); - if (string.length() > 0) { - context.accumulate("content", string); - } - return false; - } - } - throw x.syntaxError("Expected 'CDATA['"); - } - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after ' 0); - return false; - } else if (token == QUEST) { - -// "); - return false; - } else if (token == SLASH) { - -// Close tag - - } else if (token == SLASH) { - if (x.nextToken() != GT) { - throw x.syntaxError("Misshaped tag"); - } - if (jsonobject.length() > 0) { - context.accumulate(tagName, jsonobject); - } else { - context.accumulate(tagName, ""); - } - return false; - -// Content, between <...> and - - } else if (token == GT) { - for (;;) { - token = x.nextContent(); - if (token == null) { - if (tagName != null) { - throw x.syntaxError("Unclosed tag " + tagName); - } - return false; - } else if (token instanceof String) { - string = (String)token; - if (string.length() > 0) { - jsonobject.accumulate("content", - XML.stringToValue(string)); - } - -// Nested element - - } else if (token == LT) { - if (parse(x, jsonobject, tagName)) { - if (jsonobject.length() == 0) { - context.accumulate(tagName, ""); - } else if (jsonobject.length() == 1 && - jsonobject.opt("content") != null) { - context.accumulate(tagName, - jsonobject.opt("content")); - } else { - context.accumulate(tagName, jsonobject); - } - return false; - } - } - } - } else { - throw x.syntaxError("Misshaped tag"); - } - } - } - } - - - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. This is much less ambitious than - * JSONObject.stringToValue, especially because it does not attempt to - * convert plus forms, octal forms, hex forms, or E forms lacking decimal - * points. - * @param string A String. - * @return A simple JSON value. - */ - public static Object stringToValue(String string) { - if ("".equals(string)) { - return string; - } - if ("true".equalsIgnoreCase(string)) { - return Boolean.TRUE; - } - if ("false".equalsIgnoreCase(string)) { - return Boolean.FALSE; - } - if ("null".equalsIgnoreCase(string)) { - return JSONObject.NULL; - } - if ("0".equals(string)) { - return new Integer(0); - } - -// If it might be a number, try converting it. If that doesn't work, -// return the string. - - try { - char initial = string.charAt(0); - boolean negative = false; - if (initial == '-') { - initial = string.charAt(1); - negative = true; - } - if (initial == '0' && string.charAt(negative ? 2 : 1) == '0') { - return string; - } - if ((initial >= '0' && initial <= '9')) { - if (string.indexOf('.') >= 0) { - return Double.valueOf(string); - } else if (string.indexOf('e') < 0 && string.indexOf('E') < 0) { - Long myLong = new Long(string); - if (myLong.longValue() == myLong.intValue()) { - return new Integer(myLong.intValue()); - } else { - return myLong; - } - } - } - } catch (Exception ignore) { - } - return string; - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject. Some information may be lost in this transformation - * because JSON is a data format and XML is a document format. XML uses - * elements, attributes, and content text, while JSON uses unordered - * collections of name/value pairs and arrays of values. JSON does not - * does not like to distinguish between elements and attributes. - * Sequences of similar elements are represented as JSONArrays. Content - * text may be placed in a "content" member. Comments, prologs, DTDs, and - * <[ [ ]]> are ignored. - * @param string The source string. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - XMLTokener x = new XMLTokener(string); - while (x.more() && x.skipPast("<")) { - parse(x, jo, null); - } - return jo; - } - - - /** - * Convert a JSONObject into a well-formed, element-normal XML string. - * @param object A JSONObject. - * @return A string. - * @throws JSONException - */ - public static String toString(Object object) throws JSONException { - return toString(object, null); - } - - - /** - * Convert a JSONObject into a well-formed, element-normal XML string. - * @param object A JSONObject. - * @param tagName The optional name of the enclosing tag. - * @return A string. - * @throws JSONException - */ - public static String toString(Object object, String tagName) - throws JSONException { - StringBuffer sb = new StringBuffer(); - int i; - JSONArray ja; - JSONObject jo; - String key; - Iterator keys; - int length; - String string; - Object value; - if (object instanceof JSONObject) { - -// Emit - - if (tagName != null) { - sb.append('<'); - sb.append(tagName); - sb.append('>'); - } - -// Loop thru the keys. - - jo = (JSONObject)object; - keys = jo.keys(); - while (keys.hasNext()) { - key = keys.next().toString(); - value = jo.opt(key); - if (value == null) { - value = ""; - } - if (value instanceof String) { - string = (String)value; - } else { - string = null; - } - -// Emit content in body - - if ("content".equals(key)) { - if (value instanceof JSONArray) { - ja = (JSONArray)value; - length = ja.length(); - for (i = 0; i < length; i += 1) { - if (i > 0) { - sb.append('\n'); - } - sb.append(escape(ja.get(i).toString())); - } - } else { - sb.append(escape(value.toString())); - } - -// Emit an array of similar keys - - } else if (value instanceof JSONArray) { - ja = (JSONArray)value; - length = ja.length(); - for (i = 0; i < length; i += 1) { - value = ja.get(i); - if (value instanceof JSONArray) { - sb.append('<'); - sb.append(key); - sb.append('>'); - sb.append(toString(value)); - sb.append("'); - } else { - sb.append(toString(value, key)); - } - } - } else if ("".equals(value)) { - sb.append('<'); - sb.append(key); - sb.append("/>"); - -// Emit a new tag - - } else { - sb.append(toString(value, key)); - } - } - if (tagName != null) { - -// Emit the close tag - - sb.append("'); - } - return sb.toString(); - -// XML does not have good support for arrays. If an array appears in a place -// where XML is lacking, synthesize an element. - - } else { - if (object.getClass().isArray()) { - object = new JSONArray(object); - } - if (object instanceof JSONArray) { - ja = (JSONArray)object; - length = ja.length(); - for (i = 0; i < length; i += 1) { - sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName)); - } - return sb.toString(); - } else { - string = (object == null) ? "null" : escape(object.toString()); - return (tagName == null) ? "\"" + string + "\"" : - (string.length() == 0) ? "<" + tagName + "/>" : - "<" + tagName + ">" + string + ""; - } - } - } -} \ No newline at end of file diff --git a/subsonic-main/src/main/java/org/json/XMLTokener.java b/subsonic-main/src/main/java/org/json/XMLTokener.java deleted file mode 100644 index c7ca95f2..00000000 --- a/subsonic-main/src/main/java/org/json/XMLTokener.java +++ /dev/null @@ -1,365 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * The XMLTokener extends the JSONTokener to provide additional methods - * for the parsing of XML texts. - * @author JSON.org - * @version 2010-12-24 - */ -public class XMLTokener extends JSONTokener { - - - /** The table of entity values. It initially contains Character values for - * amp, apos, gt, lt, quot. - */ - public static final java.util.HashMap entity; - - static { - entity = new java.util.HashMap(8); - entity.put("amp", XML.AMP); - entity.put("apos", XML.APOS); - entity.put("gt", XML.GT); - entity.put("lt", XML.LT); - entity.put("quot", XML.QUOT); - } - - /** - * Construct an XMLTokener from a string. - * @param s A source string. - */ - public XMLTokener(String s) { - super(s); - } - - /** - * Get the text in the CDATA block. - * @return The string up to the ]]>. - * @throws JSONException If the ]]> is not found. - */ - public String nextCDATA() throws JSONException { - char c; - int i; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = next(); - if (end()) { - throw syntaxError("Unclosed CDATA"); - } - sb.append(c); - i = sb.length() - 3; - if (i >= 0 && sb.charAt(i) == ']' && - sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { - sb.setLength(i); - return sb.toString(); - } - } - } - - - /** - * Get the next XML outer token, trimming whitespace. There are two kinds - * of tokens: the '<' character which begins a markup tag, and the content - * text between markup tags. - * - * @return A string, or a '<' Character, or null if there is no more - * source text. - * @throws JSONException - */ - public Object nextContent() throws JSONException { - char c; - StringBuffer sb; - do { - c = next(); - } while (Character.isWhitespace(c)); - if (c == 0) { - return null; - } - if (c == '<') { - return XML.LT; - } - sb = new StringBuffer(); - for (;;) { - if (c == '<' || c == 0) { - back(); - return sb.toString().trim(); - } - if (c == '&') { - sb.append(nextEntity(c)); - } else { - sb.append(c); - } - c = next(); - } - } - - - /** - * Return the next entity. These entities are translated to Characters: - * & ' > < ". - * @param ampersand An ampersand character. - * @return A Character or an entity String if the entity is not recognized. - * @throws JSONException If missing ';' in XML entity. - */ - public Object nextEntity(char ampersand) throws JSONException { - StringBuffer sb = new StringBuffer(); - for (;;) { - char c = next(); - if (Character.isLetterOrDigit(c) || c == '#') { - sb.append(Character.toLowerCase(c)); - } else if (c == ';') { - break; - } else { - throw syntaxError("Missing ';' in XML entity: &" + sb); - } - } - String string = sb.toString(); - Object object = entity.get(string); - return object != null ? object : ampersand + string + ";"; - } - - - /** - * Returns the next XML meta token. This is used for skipping over - * and structures. - * @return Syntax characters (< > / = ! ?) are returned as - * Character, and strings and names are returned as Boolean. We don't care - * what the values actually are. - * @throws JSONException If a string is not properly closed or if the XML - * is badly structured. - */ - public Object nextMeta() throws JSONException { - char c; - char q; - do { - c = next(); - } while (Character.isWhitespace(c)); - switch (c) { - case 0: - throw syntaxError("Misshaped meta tag"); - case '<': - return XML.LT; - case '>': - return XML.GT; - case '/': - return XML.SLASH; - case '=': - return XML.EQ; - case '!': - return XML.BANG; - case '?': - return XML.QUEST; - case '"': - case '\'': - q = c; - for (;;) { - c = next(); - if (c == 0) { - throw syntaxError("Unterminated string"); - } - if (c == q) { - return Boolean.TRUE; - } - } - default: - for (;;) { - c = next(); - if (Character.isWhitespace(c)) { - return Boolean.TRUE; - } - switch (c) { - case 0: - case '<': - case '>': - case '/': - case '=': - case '!': - case '?': - case '"': - case '\'': - back(); - return Boolean.TRUE; - } - } - } - } - - - /** - * Get the next XML Token. These tokens are found inside of angle - * brackets. It may be one of these characters: / > = ! ? or it - * may be a string wrapped in single quotes or double quotes, or it may be a - * name. - * @return a String or a Character. - * @throws JSONException If the XML is not well formed. - */ - public Object nextToken() throws JSONException { - char c; - char q; - StringBuffer sb; - do { - c = next(); - } while (Character.isWhitespace(c)); - switch (c) { - case 0: - throw syntaxError("Misshaped element"); - case '<': - throw syntaxError("Misplaced '<'"); - case '>': - return XML.GT; - case '/': - return XML.SLASH; - case '=': - return XML.EQ; - case '!': - return XML.BANG; - case '?': - return XML.QUEST; - -// Quoted string - - case '"': - case '\'': - q = c; - sb = new StringBuffer(); - for (;;) { - c = next(); - if (c == 0) { - throw syntaxError("Unterminated string"); - } - if (c == q) { - return sb.toString(); - } - if (c == '&') { - sb.append(nextEntity(c)); - } else { - sb.append(c); - } - } - default: - -// Name - - sb = new StringBuffer(); - for (;;) { - sb.append(c); - c = next(); - if (Character.isWhitespace(c)) { - return sb.toString(); - } - switch (c) { - case 0: - return sb.toString(); - case '>': - case '/': - case '=': - case '!': - case '?': - case '[': - case ']': - back(); - return sb.toString(); - case '<': - case '"': - case '\'': - throw syntaxError("Bad character in a name"); - } - } - } - } - - - /** - * Skip characters until past the requested string. - * If it is not found, we are left at the end of the source with a result of false. - * @param to A string to skip past. - * @throws JSONException - */ - public boolean skipPast(String to) throws JSONException { - boolean b; - char c; - int i; - int j; - int offset = 0; - int length = to.length(); - char[] circle = new char[length]; - - /* - * First fill the circle buffer with as many characters as are in the - * to string. If we reach an early end, bail. - */ - - for (i = 0; i < length; i += 1) { - c = next(); - if (c == 0) { - return false; - } - circle[i] = c; - } - /* - * We will loop, possibly for all of the remaining characters. - */ - for (;;) { - j = offset; - b = true; - /* - * Compare the circle buffer with the to string. - */ - for (i = 0; i < length; i += 1) { - if (circle[j] != to.charAt(i)) { - b = false; - break; - } - j += 1; - if (j >= length) { - j -= length; - } - } - /* - * If we exit the loop with b intact, then victory is ours. - */ - if (b) { - return true; - } - /* - * Get the next character. If there isn't one, then defeat is ours. - */ - c = next(); - if (c == 0) { - return false; - } - /* - * Shove the character in the circle buffer and advance the - * circle offset. The offset is mod n. - */ - circle[offset] = c; - offset += 1; - if (offset >= length) { - offset -= length; - } - } - } -} -- cgit v1.2.3