package info.freelibrary.djatoka; import info.freelibrary.djatoka.util.CacheUtils; import info.freelibrary.util.XMLBundleControl; import info.freelibrary.util.XMLResourceBundle; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.net.UnknownHostException; import java.util.Iterator; import java.util.List; import java.util.ResourceBundle; import nu.xom.Builder; import nu.xom.Document; import nu.xom.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import au.com.bytecode.opencsv.CSVReader; public class TileCache implements IIIFInterface { private static final Logger LOGGER = LoggerFactory .getLogger(TileCache.class); private static final XMLResourceBundle BUNDLE = (XMLResourceBundle) ResourceBundle .getBundle("FreeLib-Djatoka_Messages", new XMLBundleControl()); /** * @param args */ public static void main(String[] args) throws IOException { String[] ids; if (args.length == 2 || args.length == 3) { String server = "http://localhost:8888/"; File csvFile = new File(args[0]); CSVReader csvReader; int index; if (!csvFile.exists()) { LOGGER.error(BUNDLE.get("TC_FILE_NOT_FOUND") + csvFile); printUsageAndExit(); } // Make sure format of supplied server URL is what we expect if (args.length == 3) { if (!args[2].startsWith("http://")) { args[2] = "http://" + args[2]; } if (!args[2].endsWith("/")) { args[2] = args[2] + "/"; } server = args[2]; } if (!isLive(server)) { LOGGER.error(BUNDLE.get("TC_SERVER_404"), server); printUsageAndExit(); } try { csvReader = new CSVReader(new FileReader(csvFile)); index = Integer.parseInt(args[1]) - 1; // columns 1-based while ((ids = csvReader.readNext()) != null) { if (LOGGER.isInfoEnabled()) { LOGGER.info(BUNDLE.get("TC_CACHE_ID"), ids[index]); } cacheImage(server, ids[index]); } } catch (NumberFormatException details) { LOGGER.error(details.getMessage()); printUsageAndExit(); } } // else if (args.length == 1) {} // TODO: descend through directories else { printUsageAndExit(); } } private static void cacheImage(String aServer, String aID) { try { String id = URLEncoder.encode(aID, "UTF-8"); String baseURL = aServer + "view/image/" + id; URL url = new URL(baseURL + "/info.xml"); HttpURLConnection uc = (HttpURLConnection) url.openConnection(); int status = uc.getResponseCode(); if (status == 200) { Document xml = new Builder().build(uc.getInputStream()); Element info = (Element) xml.getRootElement(); Element elem = info.getFirstChildElement("identifier", IIIF_NS); Element hElem = info.getFirstChildElement("height", IIIF_NS); Element wElem = info.getFirstChildElement("width", IIIF_NS); String idValue = elem.getValue(); try { int height = Integer.parseInt(hElem.getValue()); int width = Integer.parseInt(wElem.getValue()); Iterator<String> tileIterator; List<String> tiles; if (idValue.equals(aID) && height > 0 && width > 0) { if (idValue.startsWith("/") && LOGGER.isWarnEnabled()) { LOGGER.warn(BUNDLE.get("TC_SLASH_ID"), aID); } tiles = CacheUtils.getCachingQueries(height, width); tileIterator = tiles.iterator(); while (tileIterator.hasNext()) { cacheTile(baseURL + tileIterator.next()); } } else if (LOGGER.isErrorEnabled()) { LOGGER.error(BUNDLE.get("TC_ID_404"), aID); } } catch (NumberFormatException nfe) { LOGGER.error(BUNDLE.get("TC_INVALID_DIMS"), aID); } } else { LOGGER.error(BUNDLE.get("TC_SERVER_STATUS_CODE"), status); } } catch (Exception details) { LOGGER.error(details.getMessage()); } } private static void cacheTile(String aURL) { try { URL url = new URL(aURL); HttpURLConnection uc = (HttpURLConnection) url.openConnection(); int status = uc.getResponseCode(); if (status == 200) { int contentLength = uc.getContentLength(); if (contentLength == -1) { //LOGGER.debug("Tile '{}' content length: -1", aURL); } } else if (LOGGER.isErrorEnabled()) { LOGGER.error("Problem caching '{}' tile (status: {})", aURL, status); } } catch (Exception details) { } } private static boolean isLive(String aServer) { try { URL url = new URL(aServer + "health"); HttpURLConnection uc = (HttpURLConnection) url.openConnection(); if (LOGGER.isDebugEnabled()) { LOGGER.debug(BUNDLE.get("TC_STATUS_CHECK"), url); } if (uc.getResponseCode() == 200) { Document xml = new Builder().build(uc.getInputStream()); Element response = (Element) xml.getRootElement(); Element health = response.getFirstChildElement("health"); String status = health.getValue(); if (status.equals("dying") || status.equals("sick")) { if (LOGGER.isWarnEnabled()) { LOGGER.warn(BUNDLE.get("TC_SERVER_STATUS"), status); } return true; } else if (status.equals("ok")) { return true; } else { LOGGER.error(BUNDLE.get("TC_UNEXPECTED_STATUS"), status); } } } catch (UnknownHostException details) { LOGGER.error(BUNDLE.get("TC_UNKNOWN_HOST"), details.getMessage()); } catch (Exception details) { LOGGER.error(details.getMessage()); } return false; } private static void printUsageAndExit() { String eol = System.getProperty("line.separator"); StringBuilder sb = new StringBuilder(eol); sb.append(BUNDLE.get("TC_USAGE_1")).append(BUNDLE.get("TC_USAGE_EXEC")); sb.append(BUNDLE.get("TC_ARGS_OPT_1")).append(eol); sb.append(BUNDLE.get("TC_USAGE_2")).append(BUNDLE.get("TC_USAGE_EXEC")); sb.append(BUNDLE.get("TC_ARGS_OPT_2")); System.out.println(sb.toString()); System.exit(1); } }