Merge remote-tracking branch 'origin/pr/1434'

master
Andrew DeMaria 5 years ago
commit ec426fc1ed
No known key found for this signature in database
GPG Key ID: 0A3F5E91F8364EDF
  1. 4
      airsonic-main/src/main/java/org/airsonic/player/ajax/LyricsService.java
  2. 4
      airsonic-main/src/main/java/org/airsonic/player/ajax/PlayQueueService.java
  3. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/AvatarUploadController.java
  4. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/ChangeCoverArtController.java
  5. 8
      airsonic-main/src/main/java/org/airsonic/player/controller/CoverArtController.java
  6. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/EditTagsController.java
  7. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/GeneralSettingsController.java
  8. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/HomeController.java
  9. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/LeftController.java
  10. 4
      airsonic-main/src/main/java/org/airsonic/player/controller/M3UController.java
  11. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/MainController.java
  12. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/MoreController.java
  13. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/PersonalSettingsController.java
  14. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/PlayerSettingsController.java
  15. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/PodcastController.java
  16. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/ProxyController.java
  17. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/RecoverController.java
  18. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/RightController.java
  19. 2
      airsonic-main/src/main/java/org/airsonic/player/controller/SettingsController.java
  20. 10
      airsonic-main/src/main/java/org/airsonic/player/controller/ShareManagementController.java
  21. 3
      airsonic-main/src/main/java/org/airsonic/player/controller/SubsonicRESTController.java
  22. 8
      airsonic-main/src/main/java/org/airsonic/player/dao/AbstractDao.java
  23. 2
      airsonic-main/src/main/java/org/airsonic/player/dao/MusicFolderDao.java
  24. 4
      airsonic-main/src/main/java/org/airsonic/player/domain/InternetRadioSource.java
  25. 2
      airsonic-main/src/main/java/org/airsonic/player/domain/MediaFileComparator.java
  26. 24
      airsonic-main/src/main/java/org/airsonic/player/domain/PlayQueue.java
  27. 4
      airsonic-main/src/main/java/org/airsonic/player/monitor/MetricsManager.java
  28. 10
      airsonic-main/src/main/java/org/airsonic/player/security/JWTRequestParameterProcessingFilter.java
  29. 15
      airsonic-main/src/main/java/org/airsonic/player/service/InternetRadioService.java
  30. 15
      airsonic-main/src/main/java/org/airsonic/player/service/MediaScannerService.java
  31. 2
      airsonic-main/src/main/java/org/airsonic/player/service/NetworkService.java
  32. 2
      airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java
  33. 6
      airsonic-main/src/main/java/org/airsonic/player/service/UPnPService.java
  34. 20
      airsonic-main/src/main/java/org/airsonic/player/service/search/AnalyzerFactory.java
  35. 18
      airsonic-main/src/main/java/org/airsonic/player/service/search/DocumentFactory.java
  36. 18
      airsonic-main/src/main/java/org/airsonic/player/service/search/FieldNames.java
  37. 4
      airsonic-main/src/main/java/org/airsonic/player/service/search/IndexManager.java
  38. 10
      airsonic-main/src/main/java/org/airsonic/player/service/search/IndexType.java
  39. 14
      airsonic-main/src/main/java/org/airsonic/player/service/search/QueryFactory.java
  40. 6
      airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceImpl.java
  41. 4
      airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceUtilities.java
  42. 2
      airsonic-main/src/main/java/org/airsonic/player/service/upnp/AlbumUpnpProcessor.java
  43. 2
      airsonic-main/src/main/java/org/airsonic/player/service/upnp/ArtistUpnpProcessor.java
  44. 2
      airsonic-main/src/main/java/org/airsonic/player/service/upnp/GenreUpnpProcessor.java
  45. 2
      airsonic-main/src/main/java/org/airsonic/player/service/upnp/UpnpContentProcessor.java
  46. 2
      airsonic-main/src/main/java/org/airsonic/player/spring/RegisterPrecompiledJSPInitializer.java
  47. 2
      airsonic-main/src/main/java/org/airsonic/player/util/StringUtil.java
  48. 48
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_da.properties
  49. 2
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_is.properties
  50. 2
      airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_ko.properties
  51. 2
      airsonic-main/src/test/java/org/airsonic/player/MissingTranslations.java
  52. 2
      airsonic-main/src/test/java/org/airsonic/player/domain/PlayQueueTestCase.java
  53. 2
      airsonic-main/src/test/java/org/airsonic/player/domain/VersionTestCase.java
  54. 2
      airsonic-main/src/test/java/org/airsonic/player/service/search/AbstractAirsonicHomeTest.java
  55. 8
      airsonic-main/src/test/java/org/airsonic/player/service/search/AirsonicHomeTest.java
  56. 8
      airsonic-main/src/test/java/org/airsonic/player/service/search/AnalyzerFactoryTestCase.java
  57. 2
      airsonic-main/src/test/java/org/airsonic/player/service/search/IndexManagerTestCase.java
  58. 8
      airsonic-main/src/test/java/org/airsonic/player/service/search/QueryFactoryTestCase.java
  59. 24
      airsonic-main/src/test/java/org/airsonic/player/service/search/SearchServiceSpecialGenreTestCase.java
  60. 4
      airsonic-main/src/test/java/org/airsonic/player/service/search/SearchServiceSpecialPathTestCase.java
  61. 2
      airsonic-main/src/test/java/org/airsonic/player/service/search/SearchServiceStartWithStopwardsTestCase.java
  62. 2
      airsonic-main/src/test/java/org/airsonic/player/service/search/SearchServiceTestCase.java
  63. 2
      airsonic-main/src/test/java/org/airsonic/player/validator/PasswordSettingsValidatorTestCase.java
  64. 8
      checkstyle.xml

@ -97,8 +97,8 @@ public class LyricsService {
Namespace ns = root.getNamespace(); Namespace ns = root.getNamespace();
String lyric = StringUtils.trimToNull(root.getChildText("Lyric", ns)); String lyric = StringUtils.trimToNull(root.getChildText("Lyric", ns));
String song = root.getChildText("LyricSong", ns); String song = root.getChildText("LyricSong", ns);
String artist = root.getChildText("LyricArtist", ns); String artist = root.getChildText("LyricArtist", ns);
return new LyricsInfo(lyric, artist, song); return new LyricsInfo(lyric, artist, song);
} }

@ -244,7 +244,9 @@ public class PlayQueueService {
HttpServletRequest request = WebContextFactory.get().getHttpServletRequest(); HttpServletRequest request = WebContextFactory.get().getHttpServletRequest();
InternetRadio radio = internetRadioDao.getInternetRadioById(id); InternetRadio radio = internetRadioDao.getInternetRadioById(id);
if (!radio.isEnabled()) { throw new Exception("Radio is not enabled"); } if (!radio.isEnabled()) {
throw new Exception("Radio is not enabled");
}
Player player = resolvePlayer(); Player player = resolvePlayer();
return doPlayInternetRadio(request, player, radio).setStartPlayerAt(0); return doPlayInternetRadio(request, player, radio).setStartPlayerAt(0);

@ -56,7 +56,7 @@ import java.util.Map;
*/ */
@Controller @Controller
@RequestMapping("/avatarUpload") @RequestMapping("/avatarUpload")
public class AvatarUploadController { public class AvatarUploadController {
private static final Logger LOG = LoggerFactory.getLogger(AvatarUploadController.class); private static final Logger LOG = LoggerFactory.getLogger(AvatarUploadController.class);
private static final int MAX_AVATAR_SIZE = 64; private static final int MAX_AVATAR_SIZE = 64;

@ -42,7 +42,7 @@ import java.util.Map;
*/ */
@Controller @Controller
@RequestMapping("/changeCoverArt") @RequestMapping("/changeCoverArt")
public class ChangeCoverArtController { public class ChangeCoverArtController {
@Autowired @Autowired
private MediaFileService mediaFileService; private MediaFileService mediaFileService;

@ -300,7 +300,7 @@ public class CoverArtController implements LastModified {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} else { } else {
is = new FileInputStream(file); is = new FileInputStream(file);
mimeType = StringUtil.getMimeType(FilenameUtils.getExtension(file.getName())); mimeType = StringUtil.getMimeType(FilenameUtils.getExtension(file.getName()));
} }
return Pair.of(is, mimeType); return Pair.of(is, mimeType);
@ -385,13 +385,11 @@ public class CoverArtController implements LastModified {
in = getImageInputStream(coverArt); in = getImageInputStream(coverArt);
if (in == null) { if (in == null) {
reason = "getImageInputStream"; reason = "getImageInputStream";
} } else {
else {
BufferedImage bimg = ImageIO.read(in); BufferedImage bimg = ImageIO.read(in);
if (bimg == null) { if (bimg == null) {
reason = "ImageIO.read"; reason = "ImageIO.read";
} } else {
else {
return scale(bimg, size, size); return scale(bimg, size, size);
} }
} }

@ -47,7 +47,7 @@ import java.util.Map;
*/ */
@Controller @Controller
@RequestMapping("/editTags") @RequestMapping("/editTags")
public class EditTagsController { public class EditTagsController {
@Autowired @Autowired
private MetaDataParserFactory metaDataParserFactory; private MetaDataParserFactory metaDataParserFactory;

@ -40,7 +40,7 @@ import java.util.Locale;
*/ */
@Controller @Controller
@RequestMapping("/generalSettings") @RequestMapping("/generalSettings")
public class GeneralSettingsController { public class GeneralSettingsController {
@Autowired @Autowired
private SettingsService settingsService; private SettingsService settingsService;

@ -42,7 +42,7 @@ import static org.springframework.web.bind.ServletRequestUtils.getStringParamete
*/ */
@Controller @Controller
@RequestMapping("/home") @RequestMapping("/home")
public class HomeController { public class HomeController {
private static final int LIST_SIZE = 40; private static final int LIST_SIZE = 40;

@ -45,7 +45,7 @@ import java.util.*;
*/ */
@Controller @Controller
@RequestMapping("/left") @RequestMapping("/left")
public class LeftController { public class LeftController {
// Update this time if you want to force a refresh in clients. // Update this time if you want to force a refresh in clients.
private static final Calendar LAST_COMPATIBILITY_TIME = Calendar.getInstance(); private static final Calendar LAST_COMPATIBILITY_TIME = Calendar.getInstance();

@ -46,7 +46,7 @@ import java.util.List;
*/ */
@Controller @Controller
@RequestMapping("/play.m3u") @RequestMapping("/play.m3u")
public class M3UController { public class M3UController {
@Autowired @Autowired
private PlayerService playerService; private PlayerService playerService;
@ -89,7 +89,7 @@ public class M3UController {
} }
out.println("#EXTINF:" + duration + "," + mediaFile.getArtist() + " - " + mediaFile.getTitle()); out.println("#EXTINF:" + duration + "," + mediaFile.getArtist() + " - " + mediaFile.getTitle());
String urlNoAuth = url + "player=" + player.getId() + "&id=" + mediaFile.getId() + "&suffix=." + String urlNoAuth = url + "player=" + player.getId() + "&id=" + mediaFile.getId() + "&suffix=." +
transcodingService.getSuffix(player, mediaFile, null); transcodingService.getSuffix(player, mediaFile, null);
String urlWithAuth = jwtSecurityService.addJWTToken(urlNoAuth); String urlWithAuth = jwtSecurityService.addJWTToken(urlNoAuth);
out.println(urlWithAuth); out.println(urlWithAuth);

@ -44,7 +44,7 @@ import java.util.stream.Collectors;
*/ */
@Controller @Controller
@RequestMapping("/main") @RequestMapping("/main")
public class MainController { public class MainController {
@Autowired @Autowired
private SecurityService securityService; private SecurityService securityService;

@ -48,7 +48,7 @@ import java.util.Map;
*/ */
@Controller @Controller
@RequestMapping("/more") @RequestMapping("/more")
public class MoreController { public class MoreController {
@Autowired @Autowired
private SettingsService settingsService; private SettingsService settingsService;

@ -45,7 +45,7 @@ import java.util.Locale;
*/ */
@Controller @Controller
@RequestMapping("/personalSettings") @RequestMapping("/personalSettings")
public class PersonalSettingsController { public class PersonalSettingsController {
@Autowired @Autowired
private SettingsService settingsService; private SettingsService settingsService;

@ -49,7 +49,7 @@ import java.util.List;
*/ */
@Controller @Controller
@RequestMapping("/playerSettings") @RequestMapping("/playerSettings")
public class PlayerSettingsController { public class PlayerSettingsController {
@Autowired @Autowired
private PlayerService playerService; private PlayerService playerService;

@ -45,7 +45,7 @@ import java.util.*;
*/ */
@Controller @Controller
@RequestMapping("/podcast") @RequestMapping("/podcast")
public class PodcastController { public class PodcastController {
private static final DateFormat RSS_DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); private static final DateFormat RSS_DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
@Autowired @Autowired

@ -46,7 +46,7 @@ import static org.springframework.http.HttpStatus.OK;
*/ */
@Controller @Controller
@RequestMapping("/proxy") @RequestMapping("/proxy")
public class ProxyController { public class ProxyController {
@GetMapping @GetMapping
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

@ -65,7 +65,7 @@ public class RecoverController {
} else { } else {
captchaOk = true; captchaOk = true;
} }
if (!captchaOk) { if (!captchaOk) {
map.put("error", "recover.error.invalidcaptcha"); map.put("error", "recover.error.invalidcaptcha");
} else if (user == null) { } else if (user == null) {

@ -41,7 +41,7 @@ import java.util.Map;
*/ */
@Controller @Controller
@RequestMapping("/right") @RequestMapping("/right")
public class RightController { public class RightController {
@Autowired @Autowired
private SettingsService settingsService; private SettingsService settingsService;

@ -37,7 +37,7 @@ import javax.servlet.http.HttpServletRequest;
*/ */
@Controller @Controller
@RequestMapping("/settings") @RequestMapping("/settings")
public class SettingsController { public class SettingsController {
@Autowired @Autowired
private SecurityService securityService; private SecurityService securityService;

@ -44,7 +44,7 @@ import java.util.*;
*/ */
@Controller @Controller
@RequestMapping("/createShare") @RequestMapping("/createShare")
public class ShareManagementController { public class ShareManagementController {
@Autowired @Autowired
private MediaFileService mediaFileService; private MediaFileService mediaFileService;
@ -109,15 +109,11 @@ public class ShareManagementController {
for (int index : indexes) { for (int index : indexes) {
result.add(children.get(index)); result.add(children.get(index));
} }
} } else if (playerId != null) {
else if (playerId != null) {
Player player = playerService.getPlayerById(playerId); Player player = playerService.getPlayerById(playerId);
PlayQueue playQueue = player.getPlayQueue(); PlayQueue playQueue = player.getPlayQueue();
result = playQueue.getFiles(); result = playQueue.getFiles();
} } else if (playlistId != null) {
else if (playlistId != null) {
result = playlistService.getFilesInPlaylist(playlistId); result = playlistService.getFilesInPlaylist(playlistId);
} }

@ -2244,8 +2244,7 @@ public class SubsonicRESTController {
private AlbumInfo getAlbumInfoInternal(AlbumNotes albumNotes) { private AlbumInfo getAlbumInfoInternal(AlbumNotes albumNotes) {
AlbumInfo result = new AlbumInfo(); AlbumInfo result = new AlbumInfo();
if (albumNotes != null) if (albumNotes != null) {
{
result.setNotes(albumNotes.getNotes()); result.setNotes(albumNotes.getNotes());
result.setMusicBrainzId(albumNotes.getMusicBrainzId()); result.setMusicBrainzId(albumNotes.getMusicBrainzId());
result.setLastFmUrl(albumNotes.getLastFmUrl()); result.setLastFmUrl(albumNotes.getLastFmUrl());

@ -40,7 +40,7 @@ import java.util.concurrent.TimeUnit;
*/ */
public class AbstractDao { public class AbstractDao {
private static final Logger LOG = LoggerFactory.getLogger(AbstractDao.class); private static final Logger LOG = LoggerFactory.getLogger(AbstractDao.class);
@Autowired @Autowired
private DaoHelper daoHelper; private DaoHelper daoHelper;
@ -60,7 +60,7 @@ public class AbstractDao {
} }
protected String questionMarks(String columns) { protected String questionMarks(String columns) {
int numberOfColumns = StringUtils.countMatches(columns, ",") + 1; int numberOfColumns = StringUtils.countMatches(columns, ",") + 1;
return StringUtils.repeat("?", ", ", numberOfColumns); return StringUtils.repeat("?", ", ", numberOfColumns);
} }
@ -179,6 +179,8 @@ public class AbstractDao {
this.daoHelper = daoHelper; this.daoHelper = daoHelper;
} }
public void checkpoint() { daoHelper.checkpoint(); } public void checkpoint() {
daoHelper.checkpoint();
}
} }

@ -43,7 +43,7 @@ public class MusicFolderDao extends AbstractDao {
private static final String INSERT_COLUMNS = "path, name, enabled, changed"; private static final String INSERT_COLUMNS = "path, name, enabled, changed";
private static final String QUERY_COLUMNS = "id, " + INSERT_COLUMNS; private static final String QUERY_COLUMNS = "id, " + INSERT_COLUMNS;
private final MusicFolderRowMapper rowMapper = new MusicFolderRowMapper(); private final MusicFolderRowMapper rowMapper = new MusicFolderRowMapper();
@Autowired @Autowired
private UserDao userDao; private UserDao userDao;

@ -7,5 +7,7 @@ public class InternetRadioSource {
this.streamUrl = streamUrl; this.streamUrl = streamUrl;
} }
public String getStreamUrl() { return streamUrl; } public String getStreamUrl() {
return streamUrl;
}
} }

@ -74,7 +74,7 @@ public class MediaFileComparator implements Comparator<MediaFile> {
return a.getPath().compareToIgnoreCase(b.getPath()); return a.getPath().compareToIgnoreCase(b.getPath());
} }
private <T extends Comparable<T>> int nullSafeCompare(T a, T b, boolean nullIsSmaller) { private <T extends Comparable<T>> int nullSafeCompare(T a, T b, boolean nullIsSmaller) {
if (a == null && b == null) { if (a == null && b == null) {
return 0; return 0;
} }

@ -356,14 +356,18 @@ public class PlayQueue {
* *
* @return Whether the play queue is a shuffle radio mode. * @return Whether the play queue is a shuffle radio mode.
*/ */
public synchronized boolean isShuffleRadioEnabled() { return this.randomSearchCriteria != null; } public synchronized boolean isShuffleRadioEnabled() {
return this.randomSearchCriteria != null;
}
/** /**
* Returns whether the play queue is a internet radio mode. * Returns whether the play queue is a internet radio mode.
* *
* @return Whether the play queue is a internet radio mode. * @return Whether the play queue is a internet radio mode.
*/ */
public synchronized boolean isInternetRadioEnabled() { return this.internetRadio != null; } public synchronized boolean isInternetRadioEnabled() {
return this.internetRadio != null;
}
/** /**
* Revert the last operation. * Revert the last operation.
@ -405,28 +409,36 @@ public class PlayQueue {
* *
* @param internetRadio An internet radio, or <code>null</code> if this is not an internet radio playlist * @param internetRadio An internet radio, or <code>null</code> if this is not an internet radio playlist
*/ */
public void setInternetRadio(InternetRadio internetRadio) { this.internetRadio = internetRadio; } public void setInternetRadio(InternetRadio internetRadio) {
this.internetRadio = internetRadio;
}
/** /**
* Gets the current internet radio * Gets the current internet radio
* *
* @return The current internet radio, or <code>null</code> if this is not an internet radio playlist * @return The current internet radio, or <code>null</code> if this is not an internet radio playlist
*/ */
public InternetRadio getInternetRadio() { return internetRadio; } public InternetRadio getInternetRadio() {
return internetRadio;
}
/** /**
* Returns the criteria used to generate this random playlist * Returns the criteria used to generate this random playlist
* *
* @return The search criteria, or <code>null</code> if this is not a random playlist. * @return The search criteria, or <code>null</code> if this is not a random playlist.
*/ */
public synchronized RandomSearchCriteria getRandomSearchCriteria() { return randomSearchCriteria; } public synchronized RandomSearchCriteria getRandomSearchCriteria() {
return randomSearchCriteria;
}
/** /**
* Sets the criteria used to generate this random playlist * Sets the criteria used to generate this random playlist
* *
* @param randomSearchCriteria The search criteria, or <code>null</code> if this is not a random playlist. * @param randomSearchCriteria The search criteria, or <code>null</code> if this is not a random playlist.
*/ */
public synchronized void setRandomSearchCriteria(RandomSearchCriteria randomSearchCriteria) { this.randomSearchCriteria = randomSearchCriteria; } public synchronized void setRandomSearchCriteria(RandomSearchCriteria randomSearchCriteria) {
this.randomSearchCriteria = randomSearchCriteria;
}
/** /**
* Returns the total length in bytes. * Returns the total length in bytes.

@ -99,7 +99,7 @@ public class MetricsManager {
public Timer timer(Class clazz, String name) { public Timer timer(Class clazz, String name) {
com.codahale.metrics.Timer t = metrics.timer(MetricRegistry.name(clazz,name)); com.codahale.metrics.Timer t = metrics.timer(MetricRegistry.name(clazz,name));
com.codahale.metrics.Timer.Context tContext = t.time(); com.codahale.metrics.Timer.Context tContext = t.time();
return new Timer(tContext); return new Timer(tContext);
} }
@ -143,7 +143,7 @@ public class MetricsManager {
} }
@Override @Override
public void close() { public void close() {
// Does nothing // Does nothing
} }
} }

@ -76,19 +76,15 @@ public class JWTRequestParameterProcessingFilter implements Filter {
// authentication // authentication
return; return;
} }
} } catch (InternalAuthenticationServiceException failed) {
catch (InternalAuthenticationServiceException failed) {
LOG.error( LOG.error(
"An internal error occurred while trying to authenticate the user.", "An internal error occurred while trying to authenticate the user.",
failed); failed);
unsuccessfulAuthentication(request, response, failed); unsuccessfulAuthentication(request, response, failed);
return; return;
} } catch (AuthenticationException e) {
catch (AuthenticationException failed) { unsuccessfulAuthentication(request, response, e);
// Authentication failed
unsuccessfulAuthentication(request, response, failed);
return; return;
} }

@ -43,14 +43,18 @@ public class InternetRadioService {
* Generic exception class for playlists. * Generic exception class for playlists.
*/ */
private class PlaylistException extends Exception { private class PlaylistException extends Exception {
public PlaylistException(String message) { super(message); } public PlaylistException(String message) {
super(message);
}
} }
/** /**
* Exception thrown when the remote playlist is too large to be parsed completely. * Exception thrown when the remote playlist is too large to be parsed completely.
*/ */
private class PlaylistTooLarge extends PlaylistException { private class PlaylistTooLarge extends PlaylistException {
public PlaylistTooLarge(String message) { super(message); } public PlaylistTooLarge(String message) {
super(message);
}
} }
/** /**
@ -66,7 +70,9 @@ public class InternetRadioService {
* Exception thrown when too many redirects occurred when retrieving a remote playlist. * Exception thrown when too many redirects occurred when retrieving a remote playlist.
*/ */
private class PlaylistHasTooManyRedirects extends PlaylistException { private class PlaylistHasTooManyRedirects extends PlaylistException {
public PlaylistHasTooManyRedirects(String message) { super(message); } public PlaylistHasTooManyRedirects(String message) {
super(message);
}
} }
public InternetRadioService() { public InternetRadioService() {
@ -233,8 +239,7 @@ public class InternetRadioService {
} else { } else {
playlist = SpecificPlaylistFactory.getInstance().readFrom(in, contentEncoding); playlist = SpecificPlaylistFactory.getInstance().readFrom(in, contentEncoding);
} }
} } finally {
finally {
urlConnection.disconnect(); urlConnection.disconnect();
} }
if (playlist == null) { if (playlist == null) {

@ -52,9 +52,9 @@ public class MediaScannerService {
private static final Logger LOG = LoggerFactory.getLogger(MediaScannerService.class); private static final Logger LOG = LoggerFactory.getLogger(MediaScannerService.class);
private boolean scanning; private boolean scanning;
private ScheduledExecutorService scheduler; private ScheduledExecutorService scheduler;
@Autowired @Autowired
private SettingsService settingsService; private SettingsService settingsService;
@Autowired @Autowired
@ -88,7 +88,7 @@ public class MediaScannerService {
if (scheduler != null) { if (scheduler != null) {
scheduler.shutdown(); scheduler.shutdown();
} }
long daysBetween = settingsService.getIndexCreationInterval(); long daysBetween = settingsService.getIndexCreationInterval();
int hour = settingsService.getIndexCreationHour(); int hour = settingsService.getIndexCreationHour();
@ -96,16 +96,16 @@ public class MediaScannerService {
LOG.info("Automatic media scanning disabled."); LOG.info("Automatic media scanning disabled.");
return; return;
} }
scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler = Executors.newSingleThreadScheduledExecutor();
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
LocalDateTime nextRun = now.withHour(hour).withMinute(0).withSecond(0); LocalDateTime nextRun = now.withHour(hour).withMinute(0).withSecond(0);
if (now.compareTo(nextRun) > 0) if (now.compareTo(nextRun) > 0)
nextRun = nextRun.plusDays(1); nextRun = nextRun.plusDays(1);
long initialDelay = ChronoUnit.MILLIS.between(now, nextRun); long initialDelay = ChronoUnit.MILLIS.between(now, nextRun);
scheduler.scheduleAtFixedRate(() -> scanLibrary(), initialDelay, TimeUnit.DAYS.toMillis(daysBetween), TimeUnit.MILLISECONDS); scheduler.scheduleAtFixedRate(() -> scanLibrary(), initialDelay, TimeUnit.DAYS.toMillis(daysBetween), TimeUnit.MILLISECONDS);
LOG.info("Automatic media library scanning scheduled to run every {} day(s), starting at {}", daysBetween, nextRun); LOG.info("Automatic media library scanning scheduled to run every {} day(s), starting at {}", daysBetween, nextRun);
@ -270,8 +270,7 @@ public class MediaScannerService {
} }
if (file.isAlbum()) { if (file.isAlbum()) {
genres.incrementAlbumCount(genre); genres.incrementAlbumCount(genre);
} } else if (file.isAudio()) {
else if (file.isAudio()) {
genres.incrementSongCount(genre); genres.incrementSongCount(genre);
} }
} }

@ -53,7 +53,7 @@ public class NetworkService {
} }
String baseUrl = uri.toString() + "/"; String baseUrl = uri.toString() + "/";
LOG.debug("Calculated base url to " + baseUrl); LOG.debug("Calculated base url to " + baseUrl);
return baseUrl; return baseUrl;
} catch (MalformedURLException | URISyntaxException e) { } catch (MalformedURLException | URISyntaxException e) {
throw new RuntimeException("Could not calculate base url: " + e.getMessage()); throw new RuntimeException("Could not calculate base url: " + e.getMessage());

@ -211,7 +211,7 @@ public class SettingsService {
private static final String DEFAULT_DATABASE_CONFIG_JNDI_NAME = null; private static final String DEFAULT_DATABASE_CONFIG_JNDI_NAME = null;
private static final Integer DEFAULT_DATABASE_MYSQL_VARCHAR_MAXLENGTH = 512; private static final Integer DEFAULT_DATABASE_MYSQL_VARCHAR_MAXLENGTH = 512;
private static final String DEFAULT_DATABASE_USERTABLE_QUOTE = null; private static final String DEFAULT_DATABASE_USERTABLE_QUOTE = null;
private static final int DEFAULT_UPNP_PORT = 4041; private static final int DEFAULT_UPNP_PORT = 4041;
// Array of obsolete keys. Used to clean property file. // Array of obsolete keys. Used to clean property file.

@ -61,13 +61,13 @@ public class UPnPService {
@Autowired @Autowired
private SettingsService settingsService; private SettingsService settingsService;
private UpnpService upnpService; private UpnpService upnpService;
@Autowired @Autowired
@Qualifier("dispatchingContentDirectory") @Qualifier("dispatchingContentDirectory")
private CustomContentDirectory dispatchingContentDirectory; private CustomContentDirectory dispatchingContentDirectory;
private AtomicReference<Boolean> running = new AtomicReference<>(false); private AtomicReference<Boolean> running = new AtomicReference<>(false);
@PostConstruct @PostConstruct

@ -61,10 +61,10 @@ public final class AnalyzerFactory {
/* /*
* XXX 3.x -> 8.x : Convert UAX#29 Underscore Analysis to Legacy Analysis * XXX 3.x -> 8.x : Convert UAX#29 Underscore Analysis to Legacy Analysis
* *
* Because changes in underscores before and after words * Because changes in underscores before and after words
* have a major effect on user's forward match search. * have a major effect on user's forward match search.
* *
* @see AnalyzerFactoryTestCase * @see AnalyzerFactoryTestCase
*/ */
private void addTokenFilterForUnderscoreRemovalAroundToken(Builder builder) throws IOException { private void addTokenFilterForUnderscoreRemovalAroundToken(Builder builder) throws IOException {
@ -77,14 +77,14 @@ public final class AnalyzerFactory {
/* /*
* XXX 3.x -> 8.x : Handle brackets correctly * XXX 3.x -> 8.x : Handle brackets correctly
* *
* Process the input value of Genre search for search of domain value. * Process the input value of Genre search for search of domain value.
* *
* The tag parser performs special character conversion * The tag parser performs special character conversion
* when converting input values from a file. * when converting input values from a file.
* Therefore, the domain value may be different from the original value. * Therefore, the domain value may be different from the original value.
* This filter allows searching by user readable value (file tag value). * This filter allows searching by user readable value (file tag value).
* *
* @see org.jaudiotagger.tag.id3.framebody.FrameBodyTCON#convertID3v23GenreToGeneric * @see org.jaudiotagger.tag.id3.framebody.FrameBodyTCON#convertID3v23GenreToGeneric
* (TCON stands for Genre with ID3 v2.3-v2.4) * (TCON stands for Genre with ID3 v2.3-v2.4)
* Such processing exists because brackets in the Gener string have a special meaning. * Such processing exists because brackets in the Gener string have a special meaning.
@ -140,10 +140,10 @@ public final class AnalyzerFactory {
/** /**
* Returns the Analyzer to use when generating the index. * Returns the Analyzer to use when generating the index.
* *
* Whether this analyzer is applied to input values depends on * Whether this analyzer is applied to input values depends on
* the definition of the document's fields. * the definition of the document's fields.
* *
* @return analyzer for index * @return analyzer for index
* @see DocumentFactory * @see DocumentFactory
*/ */
@ -168,15 +168,15 @@ public final class AnalyzerFactory {
/** /**
* Returns the analyzer to use when generating a query for index search. * Returns the analyzer to use when generating a query for index search.
* *
* String processing handled by QueryFactory * String processing handled by QueryFactory
* is limited to Lucene's modifier. * is limited to Lucene's modifier.
* *
* The processing of the operands is expressed * The processing of the operands is expressed
* in the AnalyzerFactory implementation. * in the AnalyzerFactory implementation.
* Rules for tokenizing/converting input values * Rules for tokenizing/converting input values
* should not be described in QueryFactory. * should not be described in QueryFactory.
* *
* @return analyzer for query * @return analyzer for query
* @see QueryFactory * @see QueryFactory
*/ */

@ -97,10 +97,10 @@ public class DocumentFactory {
doc.add(new StoredField(field, value, TYPE_KEY)); doc.add(new StoredField(field, value, TYPE_KEY));
}; };
private BiConsumer<@NonNull Document, @NonNull String> fieldMediatype = (doc, value) -> private BiConsumer<@NonNull Document, @NonNull String> fieldMediatype = (doc, value) ->
fieldKey.accept(doc, FieldNames.MEDIA_TYPE, value); fieldKey.accept(doc, FieldNames.MEDIA_TYPE, value);
private BiConsumer<@NonNull Document, @NonNull String> fieldFolderPath = (doc, value) -> private BiConsumer<@NonNull Document, @NonNull String> fieldFolderPath = (doc, value) ->
fieldKey.accept(doc, FieldNames.FOLDER, value); fieldKey.accept(doc, FieldNames.FOLDER, value);
private BiConsumer<@NonNull Document, @Nullable String> fieldGenre = (doc, value) -> { private BiConsumer<@NonNull Document, @Nullable String> fieldGenre = (doc, value) -> {
@ -143,7 +143,7 @@ public class DocumentFactory {
/** /**
* Create a document. * Create a document.
* *
* @param mediaFile target of document * @param mediaFile target of document
* @return document * @return document
* @since legacy * @since legacy
@ -159,7 +159,7 @@ public class DocumentFactory {
/** /**
* Create a document. * Create a document.
* *
* @param mediaFile target of document * @param mediaFile target of document
* @return document * @return document
* @since legacy * @since legacy
@ -174,7 +174,7 @@ public class DocumentFactory {
/** /**
* Create a document. * Create a document.
* *
* @param album target of document * @param album target of document
* @return document * @return document
* @since legacy * @since legacy
@ -190,7 +190,7 @@ public class DocumentFactory {
/** /**
* Create a document. * Create a document.
* *
* @param artist target of document * @param artist target of document
* @param musicFolder target folder exists * @param musicFolder target folder exists
* @return document * @return document
@ -200,10 +200,10 @@ public class DocumentFactory {
* XXX 3.x -> 8.x : * XXX 3.x -> 8.x :
* Only null check specification of createArtistId3Document is different from legacy. * Only null check specification of createArtistId3Document is different from legacy.
* (The reason is only to simplify the function.) * (The reason is only to simplify the function.)
* *
* Since the field of domain object Album is nonnull, * Since the field of domain object Album is nonnull,
* null check was not performed. * null check was not performed.
* *
* In implementation ARTIST and ALBUM became nullable, * In implementation ARTIST and ALBUM became nullable,
* but null is not input at this point in data flow. * but null is not input at this point in data flow.
*/ */
@ -217,7 +217,7 @@ public class DocumentFactory {
/** /**
* Create a document. * Create a document.
* *
* @param mediaFile target of document * @param mediaFile target of document
* @return document * @return document
* @since legacy * @since legacy

@ -31,63 +31,63 @@ class FieldNames {
/** /**
* A field same to a legacy server, id field. * A field same to a legacy server, id field.
* *
* @since legacy * @since legacy
**/ **/
public static final String ID = "id"; public static final String ID = "id";
/** /**
* A field same to a legacy server, id field. * A field same to a legacy server, id field.
* *
* @since legacy * @since legacy
**/ **/
public static final String FOLDER_ID = "folderId"; public static final String FOLDER_ID = "folderId";
/** /**
* A field same to a legacy server, numeric field. * A field same to a legacy server, numeric field.
* *
* @since legacy * @since legacy
**/ **/
public static final String YEAR = "year"; public static final String YEAR = "year";
/** /**
* A field same to a legacy server, key field. * A field same to a legacy server, key field.
* *
* @since legacy * @since legacy
**/ **/
public static final String GENRE = "genre"; public static final String GENRE = "genre";
/** /**
* A field same to a legacy server, key field. * A field same to a legacy server, key field.
* *
* @since legacy * @since legacy
**/ **/
public static final String MEDIA_TYPE = "mediaType"; public static final String MEDIA_TYPE = "mediaType";
/** /**
* A field same to a legacy server, key field. * A field same to a legacy server, key field.
* *
* @since legacy * @since legacy
**/ **/
public static final String FOLDER = "folder"; public static final String FOLDER = "folder";
/** /**
* A field same to a legacy server, usually with common word parsing. * A field same to a legacy server, usually with common word parsing.
* *
* @since legacy * @since legacy
**/ **/
public static final String ARTIST = "artist"; public static final String ARTIST = "artist";
/** /**
* A field same to a legacy server, usually with common word parsing. * A field same to a legacy server, usually with common word parsing.
* *
* @since legacy * @since legacy
**/ **/
public static final String ALBUM = "album"; public static final String ALBUM = "album";
/** /**
* A field same to a legacy server, usually with common word parsing. * A field same to a legacy server, usually with common word parsing.
* *
* @since legacy * @since legacy
**/ **/
public static final String TITLE = "title"; public static final String TITLE = "title";

@ -54,7 +54,7 @@ import static org.springframework.util.ObjectUtils.isEmpty;
/** /**
* Function class that is strongly linked to the lucene index implementation. * Function class that is strongly linked to the lucene index implementation.
* Legacy has an implementation in SearchService. * Legacy has an implementation in SearchService.
* *
* If the index CRUD and search functionality are in the same class, * If the index CRUD and search functionality are in the same class,
* there is often a dependency conflict on the class used. * there is often a dependency conflict on the class used.
* Although the interface of SearchService is left to maintain the legacy implementation, * Although the interface of SearchService is left to maintain the legacy implementation,
@ -68,7 +68,7 @@ public class IndexManager {
/** /**
* Schema version of Airsonic index. * Schema version of Airsonic index.
* It may be incremented in the following cases: * It may be incremented in the following cases:
* *
* - Incompatible update case in Lucene index implementation * - Incompatible update case in Lucene index implementation
* - When schema definition is changed due to modification of AnalyzerFactory, * - When schema definition is changed due to modification of AnalyzerFactory,
* DocumentFactory or the class that they use. * DocumentFactory or the class that they use.

@ -44,7 +44,7 @@ public enum IndexType {
ALBUM( ALBUM(
fieldNames( fieldNames(
FieldNames.ALBUM, FieldNames.ALBUM,
FieldNames.ARTIST), FieldNames.ARTIST),
// FieldNames.FOLDER), // XXX 3.x -> 8.x : Remove folder from multi-field search condition // FieldNames.FOLDER), // XXX 3.x -> 8.x : Remove folder from multi-field search condition
boosts( boosts(
entry(FieldNames.ALBUM, 1.1F))), entry(FieldNames.ALBUM, 1.1F))),
@ -72,7 +72,7 @@ public enum IndexType {
/** /**
* Define the field's applied boost value when searching IndexType. * Define the field's applied boost value when searching IndexType.
* *
* @param entry {@link #entry(String, float)}. * @param entry {@link #entry(String, float)}.
* When specifying multiple values, enumerate entries. * When specifying multiple values, enumerate entries.
* @return Map of boost values to be applied to the field * @return Map of boost values to be applied to the field
@ -86,7 +86,7 @@ public enum IndexType {
/** /**
* Create an entry representing the boost value for the field. * Create an entry representing the boost value for the field.
* *
* @param k Field name defined by FieldNames * @param k Field name defined by FieldNames
* @param v Boost value * @param v Boost value
*/ */
@ -114,7 +114,7 @@ public enum IndexType {
/** /**
* Returns a map of fields and boost values. * Returns a map of fields and boost values.
* *
* @return Map of fields and boost values * @return Map of fields and boost values
* @since legacy * @since legacy
* @see org.apache.lucene.search.BoostQuery * @see org.apache.lucene.search.BoostQuery
@ -125,7 +125,7 @@ public enum IndexType {
/** /**
* Return some of the fields defined in the index. * Return some of the fields defined in the index.
* *
* @return Fields mainly used in multi-field search * @return Fields mainly used in multi-field search
* @since legacy * @since legacy
*/ */

@ -95,7 +95,7 @@ public class QueryFactory {
* XXX 3.x -> 8.x : * XXX 3.x -> 8.x :
* In order to support wildcards, * In order to support wildcards,
* MultiFieldQueryParser has been replaced by the following process. * MultiFieldQueryParser has been replaced by the following process.
* *
* - There is also an override of MultiFieldQueryParser, but it is known to be high cost. * - There is also an override of MultiFieldQueryParser, but it is known to be high cost.
* - MultiFieldQueryParser was created before Java API was modernized. * - MultiFieldQueryParser was created before Java API was modernized.
* - The spec of Parser has changed from time to time. Using parser does not reduce library update risk. * - The spec of Parser has changed from time to time. Using parser does not reduce library update risk.
@ -163,7 +163,7 @@ public class QueryFactory {
/** /**
* Query generation expression extracted from * Query generation expression extracted from
* {@link org.airsonic.player.service.SearchService#search(SearchCriteria, List, IndexType)}. * {@link org.airsonic.player.service.SearchService#search(SearchCriteria, List, IndexType)}.
* *
* @param criteria criteria * @param criteria criteria
* @param musicFolders musicFolders * @param musicFolders musicFolders
* @param indexType {@link IndexType} * @param indexType {@link IndexType}
@ -192,9 +192,9 @@ public class QueryFactory {
public Query getRandomSongs(RandomSearchCriteria criteria) throws IOException { public Query getRandomSongs(RandomSearchCriteria criteria) throws IOException {
BooleanQuery.Builder query = new BooleanQuery.Builder(); BooleanQuery.Builder query = new BooleanQuery.Builder();
Analyzer analyzer = analyzerFactory.getQueryAnalyzer(); Analyzer analyzer = analyzerFactory.getQueryAnalyzer();
// Unanalyzed field // Unanalyzed field
query.add(new TermQuery(new Term(FieldNames.MEDIA_TYPE, MediaType.MUSIC.name())), Occur.MUST); query.add(new TermQuery(new Term(FieldNames.MEDIA_TYPE, MediaType.MUSIC.name())), Occur.MUST);
@ -222,7 +222,7 @@ public class QueryFactory {
/** /**
* Query generation expression extracted from * Query generation expression extracted from
* {@link org.airsonic.player.service.SearchService#searchByName( String, String, int, int, List, Class)}. * {@link org.airsonic.player.service.SearchService#searchByName( String, String, int, int, List, Class)}.
* *
* @param fieldName {@link FieldNames} * @param fieldName {@link FieldNames}
* @return Query * @return Query
* @throws IOException When parsing of QueryParser fails * @throws IOException When parsing of QueryParser fails
@ -263,7 +263,7 @@ public class QueryFactory {
/** /**
* Query generation expression extracted from * Query generation expression extracted from
* {@link org.airsonic.player.service.SearchService#getRandomAlbums(int, List)}. * {@link org.airsonic.player.service.SearchService#getRandomAlbums(int, List)}.
* *
* @param musicFolders musicFolders * @param musicFolders musicFolders
* @return Query * @return Query
*/ */
@ -276,7 +276,7 @@ public class QueryFactory {
/** /**
* Query generation expression extracted from * Query generation expression extracted from
* {@link org.airsonic.player.service.SearchService#getRandomAlbumsId3(int, List)}. * {@link org.airsonic.player.service.SearchService#getRandomAlbumsId3(int, List)}.
* *
* @param musicFolders musicFolders * @param musicFolders musicFolders
* @return Query * @return Query
*/ */

@ -44,9 +44,9 @@ public class SearchServiceImpl implements SearchService {
private static final Logger LOG = LoggerFactory.getLogger(SearchServiceImpl.class); private static final Logger LOG = LoggerFactory.getLogger(SearchServiceImpl.class);
@Autowired @Autowired
private QueryFactory queryFactory; private QueryFactory queryFactory;
@Autowired @Autowired
private IndexManager indexManager; private IndexManager indexManager;
@Autowired @Autowired
private SearchServiceUtilities util; private SearchServiceUtilities util;
@ -93,7 +93,7 @@ public class SearchServiceImpl implements SearchService {
/** /**
* Common processing of random method. * Common processing of random method.
* *
* @param count Number of albums to return. * @param count Number of albums to return.
* @param id2ListCallBack Callback to get D from id and store it in List * @param id2ListCallBack Callback to get D from id and store it in List
*/ */

@ -43,11 +43,11 @@ import static org.springframework.util.ObjectUtils.isEmpty;
/** /**
* Termination used by SearchService. * Termination used by SearchService.
* *
* Since SearchService operates as a proxy for storage (DB) using lucene, * Since SearchService operates as a proxy for storage (DB) using lucene,
* there are many redundant descriptions different from essential data processing. * there are many redundant descriptions different from essential data processing.
* This class is a transfer class for saving those redundant descriptions. * This class is a transfer class for saving those redundant descriptions.
* *
* Exception handling is not termination, * Exception handling is not termination,
* so do not include exception handling in this class. * so do not include exception handling in this class.
*/ */

@ -117,7 +117,7 @@ public class AlbumUpnpProcessor extends UpnpContentProcessor <Album, MediaFile>
List<Album> albumList = null; List<Album> albumList = null;
if (album.getComment().startsWith(ALL_BY_ARTIST)) { if (album.getComment().startsWith(ALL_BY_ARTIST)) {
ArtistUpnpProcessor ap = getDispatcher().getArtistProcessor(); ArtistUpnpProcessor ap = getDispatcher().getArtistProcessor();
albumList = ap.getChildren(ap.getItemById(album.getComment().replaceAll(ALL_BY_ARTIST + "_", ""))); albumList = ap.getChildren(ap.getItemById(album.getComment().replaceAll(ALL_BY_ARTIST + "_", "")));
} else if (album.getComment().equalsIgnoreCase(ALL_RECENT)) { } else if (album.getComment().equalsIgnoreCase(ALL_RECENT)) {
albumList = getDispatcher().getRecentAlbumProcessor().getAllItems(); albumList = getDispatcher().getRecentAlbumProcessor().getAllItems();
} else { } else {

@ -73,7 +73,7 @@ public class ArtistUpnpProcessor extends UpnpContentProcessor <Artist, Album> {
return getArtistDao().getArtist(Integer.parseInt(id)); return getArtistDao().getArtist(Integer.parseInt(id));
} }
public List<Album> getChildren(Artist artist) { public List<Album> getChildren(Artist artist) {
List<MusicFolder> allFolders = getDispatcher().getSettingsService().getAllMusicFolders(); List<MusicFolder> allFolders = getDispatcher().getSettingsService().getAllMusicFolders();
List<Album> allAlbums = getAlbumProcessor().getAlbumDao().getAlbumsForArtist(artist.getName(), allFolders); List<Album> allAlbums = getAlbumProcessor().getAlbumDao().getAlbumsForArtist(artist.getName(), allFolders);
if (allAlbums.size() > 1) { if (allAlbums.size() > 1) {

@ -93,7 +93,7 @@ public class GenreUpnpProcessor extends UpnpContentProcessor <Genre, MediaFile>
return null; return null;
} }
public List<MediaFile> getChildren(Genre item) { public List<MediaFile> getChildren(Genre item) {
List<MusicFolder> allFolders = getDispatcher().getSettingsService().getAllMusicFolders(); List<MusicFolder> allFolders = getDispatcher().getSettingsService().getAllMusicFolders();
return getDispatcher().getMediaFileProcessor().getMediaFileDao().getSongsByGenre(item.getName(), 0, Integer.MAX_VALUE, allFolders); return getDispatcher().getMediaFileProcessor().getMediaFileDao().getSongsByGenre(item.getName(), 0, Integer.MAX_VALUE, allFolders);
} }

@ -125,7 +125,7 @@ public abstract class UpnpContentProcessor<T extends Object, U extends Object> {
SortCriterion[] orderBy) { SortCriterion[] orderBy) {
DIDLContent didl = new DIDLContent(); DIDLContent didl = new DIDLContent();
Class clazz = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; Class clazz = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
try { try {
List<MusicFolder> allFolders = getDispatchingContentDirectory().getSettingsService().getAllMusicFolders(); List<MusicFolder> allFolders = getDispatchingContentDirectory().getSettingsService().getAllMusicFolders();

@ -38,7 +38,7 @@ public class RegisterPrecompiledJSPInitializer implements ServletContextInitiali
private static void registerPrecompiledJSPs(ServletContext servletContext) { private static void registerPrecompiledJSPs(ServletContext servletContext) {
WebApp webApp = parseXmlFragment(); WebApp webApp = parseXmlFragment();
for (ServletDef def : webApp.getServletDefs()) { for (ServletDef def : webApp.getServletDefs()) {
LOG.trace("Registering precompiled JSP: {} -> {}", def.getName(), def.getSclass()); LOG.trace("Registering precompiled JSP: {} -> {}", def.getName(), def.getSclass());
ServletRegistration.Dynamic reg = servletContext.addServlet(def.getName(), def.getSclass()); ServletRegistration.Dynamic reg = servletContext.addServlet(def.getName(), def.getSclass());
// Need to set loadOnStartup somewhere between 0 and 128. 0 is highest priority. 99 should be fine // Need to set loadOnStartup somewhere between 0 and 128. 0 is highest priority. 99 should be fine

@ -145,7 +145,7 @@ public final class StringUtil {
NumberFormat teraByteFormat = new DecimalFormat("0.00 TB", new DecimalFormatSymbols(locale)); NumberFormat teraByteFormat = new DecimalFormat("0.00 TB", new DecimalFormatSymbols(locale));
return teraByteFormat.format(byteCount / ((double) 1024 * 1024 * 1024 * 1024)); return teraByteFormat.format(byteCount / ((double) 1024 * 1024 * 1024 * 1024));
} }
// More than 1 GB? // More than 1 GB?
if (byteCount >= 1024L * 1024 * 1024) { if (byteCount >= 1024L * 1024 * 1024) {
NumberFormat gigaByteFormat = new DecimalFormat("0.00 GB", new DecimalFormatSymbols(locale)); NumberFormat gigaByteFormat = new DecimalFormat("0.00 GB", new DecimalFormatSymbols(locale));

@ -647,7 +647,7 @@ lyrics.trylater=Sorry, the lyrics search engine allows just one search every 20
helppopup.title={0} Hj\u00E6lp helppopup.title={0} Hj\u00E6lp
helppopup.transcode.title=Max bitrate helppopup.transcode.title=Max bitrate
helppopup.transcode.text= Hvis du har begr\u00E6nset b\u00E5ndbredde, kan du s\u00E6tte en \u00F8vre gr\u00E6nse for bithastighed af musikken str\u00F8mme. For eksempel, hvis din oprindelige mp3 filer er kodet ved hj\u00E6lp af 256 Kbps (kilobit pr sekund), fasts\u00E6ttelse af max bitrate til 128 vil g\u00F8re {0} automatisk resample musikken fra 256 til 128 Kbps. helppopup.transcode.text= Hvis du har begr\u00E6nset b\u00E5ndbredde, kan du s\u00E6tte en \u00F8vre gr\u00E6nse for bithastighed af musikken str\u00F8mme. For eksempel, hvis din oprindelige mp3 filer er kodet ved hj\u00E6lp af 256 Kbps (kilobit pr sekund), fasts\u00E6ttelse af max bitrate til 128 vil g\u00F8re {0} automatisk resample musikken fra 256 til 128 Kbps.
helppopup.databaseConfigType.title=Data Source Config Type helppopup.databaseConfigType.title=Data Source Config Type
helppopup.databaseConfigType.text=Legacy will default to an embedded H2 database, which is the backwards compatible option. Embedded JDBC will connect to a JDBC database with the provided settings. JNDI will look up a DataSource connection already set up in your application container. helppopup.databaseConfigType.text=Legacy will default to an embedded H2 database, which is the backwards compatible option. Embedded JDBC will connect to a JDBC database with the provided settings. JNDI will look up a DataSource connection already set up in your application container.
helppopup.mysqlvarcharmaxlength.title=MySQL Varchar Max Length helppopup.mysqlvarcharmaxlength.title=MySQL Varchar Max Length
@ -661,61 +661,61 @@ helppopup.embeddriver.text=JDBC Driver dependent class name that implments java.
helppopup.excludepattern.title=Exclude Pattern helppopup.excludepattern.title=Exclude Pattern
helppopup.excludepattern.text=Airsonic will not import any files matching this regular expression pattern. helppopup.excludepattern.text=Airsonic will not import any files matching this regular expression pattern.
helppopup.playlistfolder.title=Playlist mappe helppopup.playlistfolder.title=Playlist mappe
helppopup.playlistfolder.text= Lader dig angive den mappe, hvor dine spillelister er beliggende. helppopup.playlistfolder.text= Lader dig angive den mappe, hvor dine spillelister er beliggende.
helppopup.musicmask.title=Music maske helppopup.musicmask.title=Music maske
helppopup.musicmask.text= Lader dig angive den type filer, der skal anerkendes som medie, n\u00E5r du browser gennem medie mappe. helppopup.musicmask.text= Lader dig angive den type filer, der skal anerkendes som medie, n\u00E5r du browser gennem medie mappe.
helppopup.videomask.title=Video maske helppopup.videomask.title=Video maske
helppopup.videomask.text=<p> Lader dig angive, hvilken type filer, der skal genkendes som video.</ p> helppopup.videomask.text=<p> Lader dig angive, hvilken type filer, der skal genkendes som video.</ p>
helppopup.coverartmask.title=Cover maske helppopup.coverartmask.title=Cover maske
helppopup.coverartmask.text= Lader dig angive den type filer, der skal anerkendes som Cover n\u00E5r du browser gennem medie mappe. helppopup.coverartmask.text= Lader dig angive den type filer, der skal anerkendes som Cover n\u00E5r du browser gennem medie mappe.
helppopup.downsamplecommand.title=Downsample kommando helppopup.downsamplecommand.title=Downsample kommando
helppopup.downsamplecommand.text= Lader dig angiver kommandoen til at udf\u00F8re, n\u00E5r downsampling til lavere bitrates. </p> <p> (% s = Filen skal downsamplet,% b = Max bithastighed af afspilleren) helppopup.downsamplecommand.text= Lader dig angiver kommandoen til at udf\u00F8re, n\u00E5r downsampling til lavere bitrates. </p> <p> (% s = Filen skal downsamplet,% b = Max bithastighed af afspilleren)
helppopup.hlscommand.title=HTTP Live Streaming command helppopup.hlscommand.title=HTTP Live Streaming command
helppopup.hlscommand.text=The command used to create video segments for Apple''s HTTP Live Streaming (HLS) protocol. helppopup.hlscommand.text=The command used to create video segments for Apple''s HTTP Live Streaming (HLS) protocol.
helppopup.index.title=Indeks helppopup.index.title=Indeks
helppopup.index.text= Lader dig angive, hvordan indekset (placeret \u00F8verst p\u00E5 sk\u00E6rmen) skal se ud. Filer og mapper direkte i roden medie mappe er nemt tilg\u00E6ngelige ved hj\u00E6lp af dette indeks. </p> <p> Varespecifikationen er et rum-separeret liste over opslagsord. Normalt hver indrejse er blot et enkelt tegn, men du kan ogs\u00E5 angive flere tegn. F.eks indrejse <em> </ em> vil linke til alle filer og mapper, der begynder med "I". </p> <p> Du kan ogs\u00E5 oprette en post ved hj\u00E6lp af en gruppe af indeks tegn i parentes. F.eks indrejse <em> AE (ABCDE) </ em> vises som <em> AE </ em> og link til alle filer og mapper, der begynder med enten A, B, C, D eller E. Det kan v\u00E6re nyttigt til at samle de mindre hyppigt anvendte tegn (s\u00E5dan og X, Y og Z) eller for gruppering accent tegn (s\u00E5som A, \u00C0 og \u00C1) </p> <p> filer og mapper, der ikke er omfattet af et opslagsord vil blive placeret under opslagsord "#". helppopup.index.text= Lader dig angive, hvordan indekset (placeret \u00F8verst p\u00E5 sk\u00E6rmen) skal se ud. Filer og mapper direkte i roden medie mappe er nemt tilg\u00E6ngelige ved hj\u00E6lp af dette indeks. </p> <p> Varespecifikationen er et rum-separeret liste over opslagsord. Normalt hver indrejse er blot et enkelt tegn, men du kan ogs\u00E5 angive flere tegn. F.eks indrejse <em> </ em> vil linke til alle filer og mapper, der begynder med "I". </p> <p> Du kan ogs\u00E5 oprette en post ved hj\u00E6lp af en gruppe af indeks tegn i parentes. F.eks indrejse <em> AE (ABCDE) </ em> vises som <em> AE </ em> og link til alle filer og mapper, der begynder med enten A, B, C, D eller E. Det kan v\u00E6re nyttigt til at samle de mindre hyppigt anvendte tegn (s\u00E5dan og X, Y og Z) eller for gruppering accent tegn (s\u00E5som A, \u00C0 og \u00C1) </p> <p> filer og mapper, der ikke er omfattet af et opslagsord vil blive placeret under opslagsord "#".
helppopup.ignoredarticles.title=Ord som skal ignoreres helppopup.ignoredarticles.title=Ord som skal ignoreres
helppopup.ignoredarticles.text= Lader dig angive en liste over artikler (s\u00E5som "De"), som vil blive ignoreret, n\u00E5r der skabes indekset. helppopup.ignoredarticles.text= Lader dig angive en liste over artikler (s\u00E5som "De"), som vil blive ignoreret, n\u00E5r der skabes indekset.
helppopup.shortcuts.title=Genveje helppopup.shortcuts.title=Genveje
helppopup.shortcuts.text= A space-separeret liste over \u00F8verste niveau mapper til at oprette genveje til. Brug anf\u00F8rselstegn til at gruppere ord, for eksempel: </p> <p> <em> New Indg\u00E5ende "lydspor" </ em> helppopup.shortcuts.text= A space-separeret liste over \u00F8verste niveau mapper til at oprette genveje til. Brug anf\u00F8rselstegn til at gruppere ord, for eksempel: </p> <p> <em> New Indg\u00E5ende "lydspor" </ em>
helppopup.language.title=Sprog helppopup.language.title=Sprog
helppopup.language.text= Lader dig v\u00E6lge sprog til brug. helppopup.language.text= Lader dig v\u00E6lge sprog til brug.
helppopup.visibility.title=Synlighed helppopup.visibility.title=Synlighed
helppopup.visibility.text= V\u00E6lg, hvilke oplysninger der skal vises for hver sang, samt billedtekst cutoff. Dette er den maksimale Antallet af tegn til at vise for sang titel, album og kunstner. helppopup.visibility.text= V\u00E6lg, hvilke oplysninger der skal vises for hver sang, samt billedtekst cutoff. Dette er den maksimale Antallet af tegn til at vise for sang titel, album og kunstner.
helppopup.partymode.title=Fest indstilling helppopup.partymode.title=Fest indstilling
helppopup.partymode.text= N\u00E5r fest indstilling er aktiveret, brugergr\u00E6nsefladen er forenklet og lettere at betjene for ikke-erfarne brugere. Is\u00E6r utilsigtet Messing op afspilningslisten undg\u00E5s. helppopup.partymode.text= N\u00E5r fest indstilling er aktiveret, brugergr\u00E6nsefladen er forenklet og lettere at betjene for ikke-erfarne brugere. Is\u00E6r utilsigtet Messing op afspilningslisten undg\u00E5s.
helppopup.theme.title=Tema helppopup.theme.title=Tema
helppopup.theme.text= Lader dig v\u00E6lge tema til brug. Et tema definerer udseendet og fornemmelsen af {0} i form af farver, skrifter, billeder osv. helppopup.theme.text= Lader dig v\u00E6lge tema til brug. Et tema definerer udseendet og fornemmelsen af {0} i form af farver, skrifter, billeder osv.
helppopup.welcomemessage.title=Velkomstmeddelelse helppopup.welcomemessage.title=Velkomstmeddelelse
helppopup.welcomemessage.text= besked, der vises p\u00E5 hjemmesiden. helppopup.welcomemessage.text= besked, der vises p\u00E5 hjemmesiden.
helppopup.loginmessage.title=Login besked helppopup.loginmessage.title=Login besked
helppopup.loginmessage.text=Besked, der vises p\u00E5 loginsiden. helppopup.loginmessage.text=Besked, der vises p\u00E5 loginsiden.
helppopup.coverartlimit.title=Cover gr\u00E6nse helppopup.coverartlimit.title=Cover gr\u00E6nse
helppopup.coverartlimit.text= Det maksimale antal Cover billeder skal vises p\u00E5 en enkelt side. helppopup.coverartlimit.text= Det maksimale antal Cover billeder skal vises p\u00E5 en enkelt side.
helppopup.downloadlimit.title=Download gr\u00E6nse helppopup.downloadlimit.title=Download gr\u00E6nse
helppopup.downloadlimit.text= en \u00F8vre gr\u00E6nse for, hvor meget b\u00E5ndbredde vil blive brugt til at downloade filer. helppopup.downloadlimit.text= en \u00F8vre gr\u00E6nse for, hvor meget b\u00E5ndbredde vil blive brugt til at downloade filer.
helppopup.uploadlimit.title=Upload gr\u00E6nse helppopup.uploadlimit.title=Upload gr\u00E6nse
helppopup.uploadlimit.text= en \u00F8vre gr\u00E6nse for, hvor meget b\u00E5ndbredde vil blive brugt til at uploade filer. helppopup.uploadlimit.text= en \u00F8vre gr\u00E6nse for, hvor meget b\u00E5ndbredde vil blive brugt til at uploade filer.
helppopup.streamport.title=Ikke-SSL stream havn helppopup.streamport.title=Ikke-SSL stream havn
helppopup.streamport.text= Denne valgmulighed er kun relevant, hvis du bruger {0} p\u00E5 en server med SSL (HTTPS). </p> <p> Nogle spillere (s\u00E5som Winamp) don''t st\u00F8tte streaming via SSL. Angiv portnummeret for regelm\u00E6ssig http (normalt 80 eller 4040), hvis du don''t \u00F8nsker streams, der skal sendes via SSL. Bem\u00E6rk, at streams ikke vil v\u00E6re krypteret. helppopup.streamport.text= Denne valgmulighed er kun relevant, hvis du bruger {0} p\u00E5 en server med SSL (HTTPS). </p> <p> Nogle spillere (s\u00E5som Winamp) don''t st\u00F8tte streaming via SSL. Angiv portnummeret for regelm\u00E6ssig http (normalt 80 eller 4040), hvis du don''t \u00F8nsker streams, der skal sendes via SSL. Bem\u00E6rk, at streams ikke vil v\u00E6re krypteret.
helppopup.ldap.title=LDAP autentificering helppopup.ldap.title=LDAP autentificering
helppopup.ldap.text= Brugere kan blive bekr\u00E6ftet af en ekstern LDAP server (herunder Windows Active Directory). N\u00E5r LDAP-aktiverede brugere logge p\u00E5 {0}, brugernavnet og adgangskoden er kontrolleret af den eksterne server, ikke af {0} selv. helppopup.ldap.text= Brugere kan blive bekr\u00E6ftet af en ekstern LDAP server (herunder Windows Active Directory). N\u00E5r LDAP-aktiverede brugere logge p\u00E5 {0}, brugernavnet og adgangskoden er kontrolleret af den eksterne server, ikke af {0} selv.
helppopup.ldapurl.title=LDAP URL helppopup.ldapurl.title=LDAP URL
helppopup.ldapurl.text= Webadressen p\u00E5 LDAP-serveren. Protokollen skal enten v\u00E6re <em> ldap ://</ em> eller <em> ldaps ://</ em> (for LDAP over SSL). Se <a href="http://java.sun.com/products/jndi/tutorial/ldap/misc/url.html" target="_blank"> her </a> for en mere detaljeret beskrivelse. helppopup.ldapurl.text= Webadressen p\u00E5 LDAP-serveren. Protokollen skal enten v\u00E6re <em> ldap ://</ em> eller <em> ldaps ://</ em> (for LDAP over SSL). Se <a href="http://java.sun.com/products/jndi/tutorial/ldap/misc/url.html" target="_blank"> her </a> for en mere detaljeret beskrivelse.
helppopup.ldapsearchfilter.title=LDAP s\u00F8gefilter helppopup.ldapsearchfilter.title=LDAP s\u00F8gefilter
helppopup.ldapsearchfilter.text= Filteret udtryk anvendes i brugernes s\u00F8gning. Dette er et LDAP s\u00F8gefilter (som defineret i <a href="http://www.ietf.org/rfc/rfc2254.txt" target="_blank"> RFC 2254 </a>). M\u00F8nsteret "'{0}'" affattes brugernavn, for eksempel: <ul> <li> (uid = '{0}') - dette vil s\u00F8ge efter et brugernavn passer p\u00E5 uid attribut. </ li> <li> (sAMAccountName = '{0}') - typisk bruges til godkendelse i Microsoft Active Directory. </ li> </ ul> helppopup.ldapsearchfilter.text= Filteret udtryk anvendes i brugernes s\u00F8gning. Dette er et LDAP s\u00F8gefilter (som defineret i <a href="http://www.ietf.org/rfc/rfc2254.txt" target="_blank"> RFC 2254 </a>). M\u00F8nsteret "'{0}'" affattes brugernavn, for eksempel: <ul> <li> (uid = '{0}') - dette vil s\u00F8ge efter et brugernavn passer p\u00E5 uid attribut. </ li> <li> (sAMAccountName = '{0}') - typisk bruges til godkendelse i Microsoft Active Directory. </ li> </ ul>
helppopup.ldapmanagerdn.title=LDAP manager DN helppopup.ldapmanagerdn.title=LDAP manager DN
helppopup.ldapmanagerdn.text= Hvis LDAP-serveren doesn''t st\u00F8tte anonyme bindende skal du angive DN (<em> Distinguished Name </ em>) og din adgangskode i LDAP bruger til bruger, n\u00E5r bindende. helppopup.ldapmanagerdn.text= Hvis LDAP-serveren doesn''t st\u00F8tte anonyme bindende skal du angive DN (<em> Distinguished Name </ em>) og din adgangskode i LDAP bruger til bruger, n\u00E5r bindende.
helppopup.ldapautoshadowing.title=automatisk oprette LDAP brugere i {0} helppopup.ldapautoshadowing.title=automatisk oprette LDAP brugere i {0}
helppopup.ldapautoshadowing.text= Med denne indstilling v\u00E6lges, LDAP brugere don''t skal manuelt oprettede i {0} f\u00F8r logger p\u00E5. </p> <p> BEM\u00C6RK! Det betyder, at alle brugere med en gyldig LDAP brugernavn og kodeord kan logge p\u00E5 {0}, som m\u00E5ske ikke er, hvad du vil. helppopup.ldapautoshadowing.text= Med denne indstilling v\u00E6lges, LDAP brugere don''t skal manuelt oprettede i {0} f\u00F8r logger p\u00E5. </p> <p> BEM\u00C6RK! Det betyder, at alle brugere med en gyldig LDAP brugernavn og kodeord kan logge p\u00E5 {0}, som m\u00E5ske ikke er, hvad du vil.
helppopup.playername.title=Spiller navn helppopup.playername.title=Spiller navn
helppopup.playername.text= Lader dig angiver en nem at huske navnet p\u00E5 en spiller, som "Work" eller "Stue". helppopup.playername.text= Lader dig angiver en nem at huske navnet p\u00E5 en spiller, som "Work" eller "Stue".
helppopup.autocontrol.title=Control afspilleren automatisk helppopup.autocontrol.title=Control afspilleren automatisk
helppopup.autocontrol.text= Med denne indstilling v\u00E6lges, {0} vil automatisk starte afspilleren, n\u00E5r du klikker p\u00E5 "play" p\u00E5 afspilningslisten. Ellers skal du begynde og slutte spilleren selv. helppopup.autocontrol.text= Med denne indstilling v\u00E6lges, {0} vil automatisk starte afspilleren, n\u00E5r du klikker p\u00E5 "play" p\u00E5 afspilningslisten. Ellers skal du begynde og slutte spilleren selv.
helppopup.m3ubom.title=Apply BOM in M3U file helppopup.m3ubom.title=Apply BOM in M3U file
helppopup.m3ubom.text=Apply a BOM mark in generated M3U playlists for Unicode compatibility. helppopup.m3ubom.text=Apply a BOM mark in generated M3U playlists for Unicode compatibility.
helppopup.dynamicip.title=dynamisk IP-adresse helppopup.dynamicip.title=dynamisk IP-adresse
helppopup.dynamicip.text= Sl\u00E5 denne mulighed, hvis spilleren anvender en statisk IP-adresse. helppopup.dynamicip.text= Sl\u00E5 denne mulighed, hvis spilleren anvender en statisk IP-adresse.
helppopup.smtpServer.title=SMTP Server helppopup.smtpServer.title=SMTP Server
helppopup.smtpServer.text=The hostname of the SMTP server. This server will be used to send e-mails to users who have requested a password reset. helppopup.smtpServer.text=The hostname of the SMTP server. This server will be used to send e-mails to users who have requested a password reset.
helppopup.smtpPort.title=SMTP Port helppopup.smtpPort.title=SMTP Port

@ -647,7 +647,7 @@ lyrics.trylater=Sorry, the lyrics search engine allows just one search every 20
helppopup.title={0} Hj\u00E1lp helppopup.title={0} Hj\u00E1lp
helppopup.transcode.title=Max Bitrate helppopup.transcode.title=Max Bitrate
helppopup.transcode.text= Ef \u00FE\u00FA ert nau\u00F0ugur bandwidth, getur \u00FE\u00FA sett efri m\u00F6rk fyrir bitrate \u00E1 t\u00F3nlist \u00E1. Fyrir d\u00E6mi, ef \u00FEinn frumeintak MP3 skr\u00E1r eru umrita \u00ED dulm\u00E1l me\u00F0 256 Kbps (kilobits \u00E1 sek\u00FAndu), setja max bitrate til 128 vilja gera (0) sj\u00E1lfkrafa resample t\u00F3nlistin 256-128 Kbps. helppopup.transcode.text= Ef \u00FE\u00FA ert nau\u00F0ugur bandwidth, getur \u00FE\u00FA sett efri m\u00F6rk fyrir bitrate \u00E1 t\u00F3nlist \u00E1. Fyrir d\u00E6mi, ef \u00FEinn frumeintak MP3 skr\u00E1r eru umrita \u00ED dulm\u00E1l me\u00F0 256 Kbps (kilobits \u00E1 sek\u00FAndu), setja max bitrate til 128 vilja gera (0) sj\u00E1lfkrafa resample t\u00F3nlistin 256-128 Kbps.
helppopup.databaseConfigType.title=Data Source Config Type helppopup.databaseConfigType.title=Data Source Config Type
helppopup.databaseConfigType.text=Legacy will default to an embedded H2 database, which is the backwards compatible option. Embedded JDBC will connect to a JDBC database with the provided settings. JNDI will look up a DataSource connection already set up in your application container. helppopup.databaseConfigType.text=Legacy will default to an embedded H2 database, which is the backwards compatible option. Embedded JDBC will connect to a JDBC database with the provided settings. JNDI will look up a DataSource connection already set up in your application container.
helppopup.mysqlvarcharmaxlength.title=MySQL Varchar Max Length helppopup.mysqlvarcharmaxlength.title=MySQL Varchar Max Length

@ -711,7 +711,7 @@ helppopup.ldapautoshadowing.text=With this option selected, LDAP users don''t ha
helppopup.playername.title=\uC7AC\uC0DD\uAE30 \uC774\uB984 helppopup.playername.title=\uC7AC\uC0DD\uAE30 \uC774\uB984
helppopup.playername.text="\uAC70\uC2E4"\uC774\uB098 "\uC11C\uC7AC" \uAC19\uC740 \uAE30\uC5B5\uD558\uAE30 \uC26C\uC6B4 \uC774\uB984\uC744 \uC7AC\uC0DD\uAE30\uC5D0 \uC9C0\uC815\uD569\uB2C8\uB2E4. helppopup.playername.text="\uAC70\uC2E4"\uC774\uB098 "\uC11C\uC7AC" \uAC19\uC740 \uAE30\uC5B5\uD558\uAE30 \uC26C\uC6B4 \uC774\uB984\uC744 \uC7AC\uC0DD\uAE30\uC5D0 \uC9C0\uC815\uD569\uB2C8\uB2E4.
helppopup.autocontrol.title=\uC7AC\uC0DD\uAE30\uB97C \uC790\uB3D9\uC73C\uB85C \uC81C\uC5B4 helppopup.autocontrol.title=\uC7AC\uC0DD\uAE30\uB97C \uC790\uB3D9\uC73C\uB85C \uC81C\uC5B4
helppopup.autocontrol.text=\uC774 \uC635\uC158\uC774 \uC120\uD0DD\uB418\uC5B4 \uC788\uB2E4\uBA74, "\uC7AC\uC0DD" \uBC84\uD2BC\uC744 \uB204\uB974\uBA74 \uC7AC\uC0DD\uBAA9\uB85D\uC5D0\uC11C {0} \uC774(\uAC00) \uC790\uB3D9\uC73C\uB85C \uC7AC\uC0DD\uC744 \uC2DC\uC791\uD569\uB2C8\uB2E4. \uADF8\uB807\uC9C0 \uC54A\uB2E4\uBA74, \uB2F9\uC2E0\uC740 \uC2DC\uC791\uD558\uACE0 \uC7AC\uC0DD\uAE30\uB97C \uC9C1\uC811 \uC5F0\uACB0\uD574\uC57C \uD569\uB2C8\uB2E4. helppopup.autocontrol.text=\uC774 \uC635\uC158\uC774 \uC120\uD0DD\uB418\uC5B4 \uC788\uB2E4\uBA74, "\uC7AC\uC0DD" \uBC84\uD2BC\uC744 \uB204\uB974\uBA74 \uC7AC\uC0DD\uBAA9\uB85D\uC5D0\uC11C {0} \uC774(\uAC00) \uC790\uB3D9\uC73C\uB85C \uC7AC\uC0DD\uC744 \uC2DC\uC791\uD569\uB2C8\uB2E4. \uADF8\uB807\uC9C0 \uC54A\uB2E4\uBA74, \uB2F9\uC2E0\uC740 \uC2DC\uC791\uD558\uACE0 \uC7AC\uC0DD\uAE30\uB97C \uC9C1\uC811 \uC5F0\uACB0\uD574\uC57C \uD569\uB2C8\uB2E4.
helppopup.m3ubom.title=Apply BOM in M3U file helppopup.m3ubom.title=Apply BOM in M3U file
helppopup.m3ubom.text=Apply a BOM mark in generated M3U playlists for Unicode compatibility. helppopup.m3ubom.text=Apply a BOM mark in generated M3U playlists for Unicode compatibility.
helppopup.dynamicip.title=\uB3D9\uC801 IP \uC8FC\uC18C helppopup.dynamicip.title=\uB3D9\uC801 IP \uC8FC\uC18C

@ -6,7 +6,7 @@ import java.util.Properties;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TreeMap; import java.util.TreeMap;
public class MissingTranslations { public class MissingTranslations {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
String[] locales = {"da", "de", "es", "pt", "fi", "fr", "is", "it", "ja_JP", "mk", "nl", "no", "pl", "ru", "sl", "sv", "zh_CN", "zh_TW"}; String[] locales = {"da", "de", "es", "pt", "fi", "fr", "is", "it", "ja_JP", "mk", "nl", "no", "pl", "ru", "sl", "sv", "zh_CN", "zh_TW"};

@ -301,7 +301,7 @@ public class PlayQueueTestCase extends TestCase {
public String getAlbumName() { public String getAlbumName() {
return album; return album;
} }
@Override @Override
public File getFile() { public File getFile() {
return new File(name); return new File(name);

@ -31,7 +31,7 @@ public class VersionTestCase extends TestCase {
/** /**
* Tests that equals(), hashCode(), toString() and compareTo() works. * Tests that equals(), hashCode(), toString() and compareTo() works.
*/ */
public void testVersion() { public void testVersion() {
doTestVersion("0.0", "0.1"); doTestVersion("0.0", "0.1");
doTestVersion("1.5", "2.3"); doTestVersion("1.5", "2.3");
doTestVersion("2.3", "2.34"); doTestVersion("2.3", "2.34");

@ -81,7 +81,7 @@ public abstract class AbstractAirsonicHomeTest implements AirsonicHomeTest {
public AtomicBoolean dataBaseReady() { public AtomicBoolean dataBaseReady() {
return dataBaseReady; return dataBaseReady;
} }
@Override @Override
public final void populateDatabaseOnlyOnce() { public final void populateDatabaseOnlyOnce() {
if (!dataBasePopulated().get()) { if (!dataBasePopulated().get()) {

@ -13,7 +13,7 @@ public interface AirsonicHomeTest {
/** /**
* MusicFolder used by test class. * MusicFolder used by test class.
* *
* @return MusicFolder used by test class * @return MusicFolder used by test class
*/ */
default List<MusicFolder> getMusicFolders() { default List<MusicFolder> getMusicFolders() {
@ -22,7 +22,7 @@ public interface AirsonicHomeTest {
/** /**
* Whether the data input has been completed. * Whether the data input has been completed.
* *
* @return Static AtomicBoolean indicating whether the data injection has been * @return Static AtomicBoolean indicating whether the data injection has been
* completed * completed
*/ */
@ -30,12 +30,12 @@ public interface AirsonicHomeTest {
/** /**
* Whether the data input has been completed. * Whether the data input has been completed.
* *
* @return Static AtomicBoolean indicating whether the data injection has been * @return Static AtomicBoolean indicating whether the data injection has been
* completed * completed
*/ */
abstract AtomicBoolean dataBaseReady(); abstract AtomicBoolean dataBaseReady();
/** /**
* Populate the database only once. * Populate the database only once.
* It is called in the @Before granted method. * It is called in the @Before granted method.

@ -156,7 +156,7 @@ public class AnalyzerFactoryTestCase {
/** /**
* Detailed tests on Stopward. * Detailed tests on Stopward.
* *
* @see org.apache.lucene.analysis.core.StopAnalyzer#ENGLISH_STOP_WORDS_SET * @see org.apache.lucene.analysis.core.StopAnalyzer#ENGLISH_STOP_WORDS_SET
*/ */
@Test @Test
@ -275,7 +275,7 @@ public class AnalyzerFactoryTestCase {
terms = toTermString(queryFullWidth); terms = toTermString(queryFullWidth);
/* /*
* XXX 3.x -> 8.x : * XXX 3.x -> 8.x :
* *
* This is not a change due to the library but an intentional change. * This is not a change due to the library but an intentional change.
* The filter order has been changed properly * The filter order has been changed properly
* as it is probably not a deliberate specification. * as it is probably not a deliberate specification.
@ -477,7 +477,7 @@ public class AnalyzerFactoryTestCase {
assertEquals("walker", terms.get(2)); assertEquals("walker", terms.get(2));
assertEquals("nash", terms.get(3)); assertEquals("nash", terms.get(3));
assertEquals("ensemble", terms.get(4)); assertEquals("ensemble", terms.get(4));
// Space // Space
assertEquals(asList("abc", "def"), toTermString(" ABC DEF ")); assertEquals(asList("abc", "def"), toTermString(" ABC DEF "));
assertEquals(asList("abc1", "def"), toTermString(" ABC1 DEF ")); assertEquals(asList("abc1", "def"), toTermString(" ABC1 DEF "));
@ -655,7 +655,7 @@ public class AnalyzerFactoryTestCase {
assertEquals(1, terms.size()); assertEquals(1, terms.size());
assertEquals("{ }", terms.get(0)); assertEquals("{ }", terms.get(0));
} }
private List<String> toTermString(String str) { private List<String> toTermString(String str) {
return toTermString(null, str); return toTermString(null, str);
} }

@ -174,7 +174,7 @@ public class IndexManagerTestCase extends AbstractAirsonicHomeTest {
indexManager.expunge(); indexManager.expunge();
indexManager.stopIndexing(indexManager.getStatistics()); indexManager.stopIndexing(indexManager.getStatistics());
/* /*
* Subsequent search results. * Subsequent search results.
* Results can also be confirmed with Luke. * Results can also be confirmed with Luke.
*/ */

@ -65,18 +65,18 @@ public class QueryFactoryTestCase {
private static final MusicFolder MUSIC_FOLDER1 = private static final MusicFolder MUSIC_FOLDER1 =
new MusicFolder(FID1, new File(PATH1), "music1", true, new java.util.Date()); new MusicFolder(FID1, new File(PATH1), "music1", true, new java.util.Date());
private static final MusicFolder MUSIC_FOLDER2 = private static final MusicFolder MUSIC_FOLDER2 =
new MusicFolder(FID2, new File(PATH2), "music2", true, new java.util.Date()); new MusicFolder(FID2, new File(PATH2), "music2", true, new java.util.Date());
private static final List<MusicFolder> SINGLE_FOLDERS = Arrays.asList(MUSIC_FOLDER1); private static final List<MusicFolder> SINGLE_FOLDERS = Arrays.asList(MUSIC_FOLDER1);
private static final List<MusicFolder> MULTI_FOLDERS = Arrays.asList(MUSIC_FOLDER1, MUSIC_FOLDER2); private static final List<MusicFolder> MULTI_FOLDERS = Arrays.asList(MUSIC_FOLDER1, MUSIC_FOLDER2);
/* /*
* XXX 3.x -> 8.x : * XXX 3.x -> 8.x :
* It does not change the basic functional requirements for the query. * It does not change the basic functional requirements for the query.
* However, some minor improvements are included. * However, some minor improvements are included.
* *
* - Use 'Or' instead of 'SpanOr'. * - Use 'Or' instead of 'SpanOr'.
* This is suitable for 8.x document definition and query grammar. * This is suitable for 8.x document definition and query grammar.
* A more rigorous comparison. * A more rigorous comparison.
@ -89,7 +89,7 @@ public class QueryFactoryTestCase {
* Currently, these are "key" strings, both in the requirements and in the implementation. * Currently, these are "key" strings, both in the requirements and in the implementation.
* The legacy "normalize" is dirty code that compensates for the incomplete analytics implementation * The legacy "normalize" is dirty code that compensates for the incomplete analytics implementation
* and is not necessary as long as proper key comparison can be done. * and is not necessary as long as proper key comparison can be done.
* *
* => Treating these strictly as keys enables DB reference. * => Treating these strictly as keys enables DB reference.
* For example, can support multi-genre by creating a new genre field that implements another Tokenizer. * For example, can support multi-genre by creating a new genre field that implements another Tokenizer.
* *

@ -48,12 +48,12 @@ public class SearchServiceSpecialGenreTestCase extends AbstractAirsonicHomeTest
* in src/test/resources/MEDIAS/Search/SpecialGenre/ARTIST1/ALBUM_A. * in src/test/resources/MEDIAS/Search/SpecialGenre/ARTIST1/ALBUM_A.
* In FILE01 to FILE16, Special strings for Lucene syntax are stored * In FILE01 to FILE16, Special strings for Lucene syntax are stored
* as tag values of Genre. * as tag values of Genre.
* *
* Legacy can not search all these genres. * Legacy can not search all these genres.
* (Strictly speaking, the genre field is not created at index creation.) * (Strictly speaking, the genre field is not created at index creation.)
* *
* // XXX 3.x -> 8.x : Do the process more strictly. * // XXX 3.x -> 8.x : Do the process more strictly.
* *
* - Values that can be cross-referenced with DB are stored in the index. * - Values that can be cross-referenced with DB are stored in the index.
* - Search is also possible with user's readable value (file tag value). * - Search is also possible with user's readable value (file tag value).
* - However, there is an exception in parentheses. * - However, there is an exception in parentheses.
@ -91,10 +91,10 @@ public class SearchServiceSpecialGenreTestCase extends AbstractAirsonicHomeTest
/* /*
* // XXX 3.x -> 8.x : Brackets () * // XXX 3.x -> 8.x : Brackets ()
* *
* Lucene can handle these. * Lucene can handle these.
* However, brackets are specially parsed before the index creation process. * However, brackets are specially parsed before the index creation process.
* *
* This string is never stored in the index. * This string is never stored in the index.
* This is the only exception. * This is the only exception.
*/ */
@ -106,16 +106,16 @@ public class SearchServiceSpecialGenreTestCase extends AbstractAirsonicHomeTest
/* /*
* // XXX 3.x -> 8.x : Brackets {}[] * // XXX 3.x -> 8.x : Brackets {}[]
* *
* Lucene can handle these. * Lucene can handle these.
* However, brackets are specially parsed before the index creation process. * However, brackets are specially parsed before the index creation process.
* *
* This can be done with a filter that performs the reverse process * This can be done with a filter that performs the reverse process
* on the input values when searching. * on the input values when searching.
* As a result, the values stored in the file can be retrieved by search. * As a result, the values stored in the file can be retrieved by search.
* *
* @see AnalyzerFactory * @see AnalyzerFactory
* *
* >>>>> * >>>>>
*/ */
songs = searchService.getRandomSongs(simpleStringCriteria.apply("{}")); songs = searchService.getRandomSongs(simpleStringCriteria.apply("{}"));
@ -204,7 +204,7 @@ public class SearchServiceSpecialGenreTestCase extends AbstractAirsonicHomeTest
/* /*
* Search by genre string registered in file. * Search by genre string registered in file.
* *
* The value stored in the index is different from legacy. * The value stored in the index is different from legacy.
* Domain value is kept as it is. * Domain value is kept as it is.
*/ */
@ -256,12 +256,12 @@ public class SearchServiceSpecialGenreTestCase extends AbstractAirsonicHomeTest
/* /*
* Other special strings. (FILE19) * Other special strings. (FILE19)
* *
* {'[@ $+]FULLWIDTHCæsar's * {'[@ $+]FULLWIDTHCæsar's
* *
* Legacy stores with Analyze, * Legacy stores with Analyze,
* so searchable characters are different. * so searchable characters are different.
* *
*/ */
@Test @Test
public void testOthers() { public void testOthers() {

@ -20,10 +20,10 @@ import static org.springframework.util.ObjectUtils.isEmpty;
/* /*
* Test cases related to #1139. * Test cases related to #1139.
* Confirming whether shuffle search can be performed correctly in MusicFolder containing special strings. * Confirming whether shuffle search can be performed correctly in MusicFolder containing special strings.
* *
* (Since the query of getRandomAlbums consists of folder paths only, * (Since the query of getRandomAlbums consists of folder paths only,
* this verification is easy to perform.) * this verification is easy to perform.)
* *
* This test case is a FalsePattern for search, * This test case is a FalsePattern for search,
* but there may be problems with the data flow prior to creating the search index. * but there may be problems with the data flow prior to creating the search index.
*/ */

@ -20,7 +20,7 @@ import static org.springframework.util.ObjectUtils.isEmpty;
/* /*
* Test cases related to #1142. * Test cases related to #1142.
* The filter is not properly applied when analyzing the query, * The filter is not properly applied when analyzing the query,
* *
* In the process of hardening the Analyzer implementation, * In the process of hardening the Analyzer implementation,
* this problem is solved side by side. * this problem is solved side by side.
*/ */

@ -55,7 +55,7 @@ public class SearchServiceTestCase extends AbstractAirsonicHomeTest {
List<MusicFolder> allMusicFolders = musicFolderDao.getAllMusicFolders(); List<MusicFolder> allMusicFolders = musicFolderDao.getAllMusicFolders();
Assert.assertEquals(3, allMusicFolders.size()); Assert.assertEquals(3, allMusicFolders.size());
// *** testSearch() *** // *** testSearch() ***
String query = "Sarah Walker"; String query = "Sarah Walker";

@ -21,7 +21,7 @@ public class PasswordSettingsValidatorTestCase extends TestCase {
PasswordSettingsValidator psv = new PasswordSettingsValidator(); PasswordSettingsValidator psv = new PasswordSettingsValidator();
Errors errors = new BeanPropertyBindingResult(psc, "psv"); Errors errors = new BeanPropertyBindingResult(psc, "psv");
psv.validate(psc, errors); psv.validate(psc, errors);
return errors; return errors;
} }
public void testValidateEmptyPassword() { public void testValidateEmptyPassword() {

@ -10,6 +10,11 @@
<property name="fileExtensions" value="java, properties, xml"/> <property name="fileExtensions" value="java, properties, xml"/>
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="message" value="Unnecessary trailing whitespace"/>
</module>
<module name="FileTabCharacter"/> <module name="FileTabCharacter"/>
<!-- This is a temporary workaround until ^M line endings is added to upstream checkstyle --> <!-- This is a temporary workaround until ^M line endings is added to upstream checkstyle -->
@ -39,6 +44,7 @@
<module name="EqualsHashCode"/> <module name="EqualsHashCode"/>
<module name="Indentation"/> <module name="Indentation"/>
<module name="InnerAssignment"/> <module name="InnerAssignment"/>
<module name="LeftCurly"/>
<module name="MethodParamPad"/> <module name="MethodParamPad"/>
<module name="MultipleVariableDeclarations"/> <module name="MultipleVariableDeclarations"/>
<module name="NoWhitespaceBefore"> <module name="NoWhitespaceBefore">
@ -50,8 +56,10 @@
<module name="ParenPadCheck"/> <module name="ParenPadCheck"/>
<module name="RedundantImport"/> <module name="RedundantImport"/>
<module name="RequireThis"/> <module name="RequireThis"/>
<module name="RightCurly"/>
<module name="SimplifyBooleanExpression"/> <module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/> <module name="SimplifyBooleanReturn"/>
<module name="SingleSpaceSeparator"/>
<module name="StringLiteralEquality"/> <module name="StringLiteralEquality"/>
<module name="SuperClone"/> <module name="SuperClone"/>
<module name="SuperFinalize"/> <module name="SuperFinalize"/>

Loading…
Cancel
Save