public long getLastModified(HttpServletRequest request) {
    String path = request.getParameter("path");
    if (StringUtils.trimToNull(path) == null) {
      return 0;
    }

    File file = new File(path);
    if (!FileUtil.exists(file)) {
      return -1;
    }

    return FileUtil.lastModified(file);
  }
  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;
    }
  }
  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;
  }
Пример #4
0
 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);
   }
 }
Пример #5
0
  /**
   * Returns a number of random songs.
   *
   * @param criteria Search criteria.
   * @return List of random songs.
   */
  public List<MediaFile> getRandomSongs(RandomSearchCriteria criteria) {
    List<MediaFile> result = new ArrayList<MediaFile>();

    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<Integer> rangeQuery =
            NumericRangeQuery.newIntRange(
                FIELD_YEAR, criteria.getFromYear(), criteria.getToYear(), true, true);
        query.add(rangeQuery, BooleanClause.Occur.MUST);
      }

      List<SpanTermQuery> musicFolderQueries = new ArrayList<SpanTermQuery>();
      for (MusicFolder musicFolder : criteria.getMusicFolders()) {
        musicFolderQueries.add(
            new SpanTermQuery(new Term(FIELD_FOLDER, musicFolder.getPath().getPath())));
      }
      query.add(
          new SpanOrQuery(musicFolderQueries.toArray(new SpanQuery[musicFolderQueries.size()])),
          BooleanClause.Occur.MUST);

      TopDocs topDocs = searcher.search(query, null, Integer.MAX_VALUE);
      List<ScoreDoc> scoreDocs = Lists.newArrayList(topDocs.scoreDocs);
      Random random = new Random(System.currentTimeMillis());

      while (!scoreDocs.isEmpty() && result.size() < criteria.getCount()) {
        int index = random.nextInt(scoreDocs.size());
        Document doc = searcher.doc(scoreDocs.remove(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);
        }
      }

    } catch (Throwable x) {
      LOG.error("Failed to search or random songs.", x);
    } finally {
      FileUtil.closeQuietly(reader);
    }
    return result;
  }
  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");
    boolean typArtist = ServletRequestUtils.getBooleanParameter(request, "typArtist", false);

    if (typArtist == true) {
      if (file == null) {
        sendDefaultArtist(size, response);
        return null;
      }
    } else {
      if (file == null) {
        sendDefault(size, request, 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, request, response);
    }

    return null;
  }
Пример #7
0
 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);
     }
   }
 }
Пример #8
0
  /**
   * Returns all music files that are children of this music file.
   *
   * @param includeFiles Whether files should be included in the result.
   * @param includeDirectories Whether directories should be included in the result.
   * @throws IOException If an I/O error occurs.
   */
  public List<MediaFile> getChildren(FileFilter filter) throws IOException {
    File[] children = FileUtil.listFiles(file, filter);
    List<MediaFile> result = new ArrayList<MediaFile>(children.length);

    for (File child : children) {
      try {
        if (acceptMedia(child)) {
          result.add(createMediaFile(child));
        }
      } catch (SecurityException x) {
        LOG.warn("Failed to create mediaFile for " + child, x);
      }
    }

    Collections.sort(result);

    return result;
  }
Пример #9
0
  /**
   * Returns a number of random albums, using ID3 tag.
   *
   * @param count Number of albums to return.
   * @param musicFolders Only return albums from these folders.
   * @return List of random albums.
   */
  public List<Album> getRandomAlbumsId3(int count, List<MusicFolder> musicFolders) {
    List<Album> result = new ArrayList<Album>();

    IndexReader reader = null;
    try {
      reader = createIndexReader(ALBUM_ID3);
      Searcher searcher = new IndexSearcher(reader);

      List<SpanTermQuery> musicFolderQueries = new ArrayList<SpanTermQuery>();
      for (MusicFolder musicFolder : musicFolders) {
        musicFolderQueries.add(
            new SpanTermQuery(
                new Term(FIELD_FOLDER_ID, NumericUtils.intToPrefixCoded(musicFolder.getId()))));
      }
      Query query =
          new SpanOrQuery(musicFolderQueries.toArray(new SpanQuery[musicFolderQueries.size()]));
      TopDocs topDocs = searcher.search(query, null, Integer.MAX_VALUE);
      List<ScoreDoc> scoreDocs = Lists.newArrayList(topDocs.scoreDocs);
      Random random = new Random(System.currentTimeMillis());

      while (!scoreDocs.isEmpty() && result.size() < count) {
        int index = random.nextInt(scoreDocs.size());
        Document doc = searcher.doc(scoreDocs.remove(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;
  }
Пример #10
0
  public SearchResult search(
      SearchCriteria criteria, List<MusicFolder> musicFolders, 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());

      BooleanQuery query = new BooleanQuery();
      query.add(queryParser.parse(analyzeQuery(criteria.getQuery())), BooleanClause.Occur.MUST);

      List<SpanTermQuery> musicFolderQueries = new ArrayList<SpanTermQuery>();
      for (MusicFolder musicFolder : musicFolders) {
        if (indexType == ALBUM_ID3 || indexType == ARTIST_ID3) {
          musicFolderQueries.add(
              new SpanTermQuery(
                  new Term(FIELD_FOLDER_ID, NumericUtils.intToPrefixCoded(musicFolder.getId()))));
        } else {
          musicFolderQueries.add(
              new SpanTermQuery(new Term(FIELD_FOLDER, musicFolder.getPath().getPath())));
        }
      }
      query.add(
          new SpanOrQuery(musicFolderQueries.toArray(new SpanQuery[musicFolderQueries.size()])),
          BooleanClause.Occur.MUST);

      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;
  }
Пример #11
0
 public boolean exists() {
   return FileUtil.exists(getFile());
 }