package tv.dyndns.kishibe.qmaclone.server.image;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketImageLink;
import tv.dyndns.kishibe.qmaclone.client.packet.PacketProblem;
import tv.dyndns.kishibe.qmaclone.server.database.ProblemProcessable;
import tv.dyndns.kishibe.qmaclone.server.util.Downloader;
import tv.dyndns.kishibe.qmaclone.server.util.DownloaderException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.io.Files;
import com.google.inject.Inject;
public class ImageLinkChecker implements ProblemProcessable {
public interface Factory {
ImageLinkChecker create();
}
private static final Logger logger = Logger.getLogger(ImageLinkChecker.class.toString());
@VisibleForTesting
static final int STATUS_CODE_MALFORMED_URL_EXCEPTION = -1;
@VisibleForTesting
static final int STATUS_CODE_DOWNLOAD_FAILURE = -2;
private final ImageUtils imageUtils;
private final Downloader downloader;
private final List<PacketImageLink> imageLinks = new ArrayList<>();
private final Map<String, Integer> urlToStatusCode = new HashMap<>();
@Inject
public ImageLinkChecker(ImageUtils imageUtils, Downloader downloader) {
this.imageUtils = Preconditions.checkNotNull(imageUtils);
this.downloader = Preconditions.checkNotNull(downloader);
}
@Override
public void process(PacketProblem problem) {
for (String url : problem.getImageUrls()) {
File inputCacheFile = imageUtils.getInputCacheFile(url);
int statusCode;
if (urlToStatusCode.containsKey(url)) {
statusCode = urlToStatusCode.get(url);
} else {
try {
Files.createParentDirs(inputCacheFile);
} catch (IOException e) {
logger.log(Level.WARNING, "入力画像キャッシュディレクトリの作成に失敗しました。処理を続行します: inputCacheFile="
+ inputCacheFile, e);
continue;
}
try {
downloader.downloadToFile(new URL(url), inputCacheFile);
statusCode = 200;
} catch (MalformedURLException e) {
logger.log(Level.WARNING, "不正なURLです: url=" + url, e);
// URLが不正な場合はダミーステータスコードを表示する
statusCode = STATUS_CODE_MALFORMED_URL_EXCEPTION;
} catch (DownloaderException e) {
logger.log(Level.WARNING, "ダウンロードに失敗しました: url=" + url, e);
// ダウンロードに失敗した場合はステータスコードまたはダミーステータスコードを表示する
statusCode = e.hasStatusCode() ? e.getStatusCode() : STATUS_CODE_DOWNLOAD_FAILURE;
}
urlToStatusCode.put(url, statusCode);
}
// 正常取得かつ正常画像の場合はエラー出力をしない
if (statusCode / 100 == 2 && imageUtils.isImage(inputCacheFile)) {
continue;
}
PacketImageLink imageLink = new PacketImageLink();
imageLink.problemId = problem.id;
imageLink.url = url;
imageLink.statusCode = statusCode;
imageLinks.add(imageLink);
logger.info(String.format("リンク切れ画像を検出しました: |imageLinks|=%s imageLink=%s", imageLinks.size(),
imageLink));
}
}
public List<PacketImageLink> getImageLinks() {
return Preconditions.checkNotNull(imageLinks);
}
}