/* This file is part of RouteConverter. RouteConverter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. RouteConverter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RouteConverter; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.navigation.routes.remote; import slash.navigation.rest.Credentials; import slash.navigation.rest.Delete; import slash.navigation.rest.Get; import slash.navigation.rest.Post; import slash.navigation.rest.Put; import slash.navigation.rest.exception.DuplicateNameException; import slash.navigation.rest.exception.ForbiddenException; import slash.navigation.rest.exception.ServiceUnavailableException; import slash.navigation.rest.exception.UnAuthorizedException; import slash.navigation.routes.Catalog; import slash.navigation.routes.Category; import slash.navigation.routes.NotFoundException; import slash.navigation.routes.NotOwnerException; import slash.navigation.routes.Route; import slash.navigation.routes.remote.binding.CatalogType; import slash.navigation.routes.remote.binding.CategoryType; import slash.navigation.routes.remote.binding.FileType; import slash.navigation.routes.remote.binding.RouteType; import javax.xml.bind.JAXBException; import java.io.File; import java.io.IOException; import java.util.logging.Logger; import static java.lang.String.format; import static slash.navigation.rest.HttpRequest.APPLICATION_JSON; import static slash.navigation.routes.remote.helpers.RoutesUtil.unmarshal; /** * Encapsulates REST access to the RemoteCatalog service of RouteConverter. * * @author Christian Pesch */ public class RemoteCatalog implements Catalog { private static final Logger log = Logger.getLogger(RemoteCatalog.class.getName()); private static final String FORMAT_XML = "?format=xml"; private static final String V1 = "v1/"; public static final String CATEGORY_URI = V1 + "categories/"; private static final String ROOT_CATEGORY_URI = CATEGORY_URI + "1/"; public static final String ROUTE_URI = V1 + "routes/"; public static final String FILE_URI = V1 + "files/"; private final String rootUrl; private final Credentials credentials; public RemoteCatalog(String rootUrl, Credentials credentials) { this.rootUrl = rootUrl; this.credentials = credentials; } public Category getRootCategory() { return new RemoteCategory(this, rootUrl + ROOT_CATEGORY_URI, ""); } CatalogType fetch(String url) throws IOException { long start = System.currentTimeMillis(); String urlWithXml = url + FORMAT_XML; try { Get get = new Get(urlWithXml); String result = get.executeAsString(); if (get.isSuccessful()) try { return unmarshal(result); } catch (JAXBException e) { throw new IOException("Cannot unmarshall " + result + ": " + e, e); } } finally { long end = System.currentTimeMillis(); log.info("Fetching from " + urlWithXml + " took " + (end - start) + " milliseconds"); } return null; } /*for test only*/Category getCategory(String url) throws IOException { CatalogType catalogType = fetch(url); if (catalogType == null) return null; CategoryType categoryType = catalogType.getCategory(); return new RemoteCategory(this, url, categoryType.getName()); } /*for test only*/Route getRoute(String url) throws IOException { CatalogType catalogType = fetch(url); if (catalogType == null) return null; RouteType routeType = catalogType.getRoute(); return new RemoteRoute(new RemoteCategory(this, routeType.getCategory()), url, routeType.getDescription(), routeType.getCreator(), routeType.getUrl()); } /*for test only*/FileType getFile(String url) throws IOException { CatalogType catalogType = fetch(url); if (catalogType == null) return null; return catalogType.getFile(); } String addCategory(String categoryUrl, String name) throws IOException { log.info(format("Adding category %s to %s", name, categoryUrl)); Post request = new Post(rootUrl + CATEGORY_URI, credentials); request.setAccept(APPLICATION_JSON); request.addString("parent", categoryUrl); request.addString("name", name); String result = request.executeAsString(); if (request.isUnAuthorized()) throw new UnAuthorizedException("Not authorized to add category " + name, categoryUrl); if (request.isForbidden()) throw new ForbiddenException("Forbidden to add category " + name, categoryUrl); if (request.isBadRequest()) throw new NotFoundException("Category not found", categoryUrl); if (request.isPreconditionFailed()) throw new DuplicateNameException("Category " + name + " already exists", categoryUrl); if (!request.isSuccessful()) throw new IOException("POST on " + (rootUrl + CATEGORY_URI) + " with payload " + name + " not successful: " + result); return request.getLocation(); } void updateCategory(String categoryUrl, String parentUrl, String name) throws IOException { log.info(format("Updating category %s to parent %s and name %s", categoryUrl, parentUrl, name)); Put request = new Put(categoryUrl, credentials); request.setAccept(APPLICATION_JSON); request.addString("parent", parentUrl); request.addString("name", name); String result = request.executeAsString(); if (request.isUnAuthorized()) throw new UnAuthorizedException("Not authorized to update category " + name, categoryUrl); if (request.isForbidden()) throw new ForbiddenException("Forbidden to update category " + name, categoryUrl); if (request.isNotFound()) throw new NotFoundException("Category not found", categoryUrl); if (request.isBadRequest()) throw new NotOwnerException("Not owner of category to update", categoryUrl); if (request.isPreconditionFailed()) throw new DuplicateNameException("Category " + name + " already exists", categoryUrl); if (!request.isSuccessful()) throw new IOException("PUT on " + categoryUrl + " with payload " + parentUrl + "/" + name + " not successful: " + result); } void deleteCategory(String categoryUrl) throws IOException { log.info(format("Deleting category %s", categoryUrl)); Delete request = new Delete(categoryUrl, credentials); request.setAccept(APPLICATION_JSON); String result = request.executeAsString(); if (request.isUnAuthorized()) throw new UnAuthorizedException("Not authorized to delete category", categoryUrl); if (request.isForbidden()) throw new ForbiddenException("Forbidden to delete category", categoryUrl); if (request.isNotFound()) throw new NotFoundException("Category not found", categoryUrl); if (request.isBadRequest()) throw new NotOwnerException("Not owner of category to delete", categoryUrl); if (!request.isSuccessful()) throw new IOException("DELETE on " + categoryUrl + " not successful: " + result); } String addRoute(String categoryUrl, String description, String localFile, String remoteUrl) throws IOException { log.info(format("Adding route %s to category %s with remote url %s", description, categoryUrl, remoteUrl)); Post request = new Post(rootUrl + ROUTE_URI, credentials); request.setAccept(APPLICATION_JSON); request.addString("category", categoryUrl); request.addString("description", description); if (localFile != null) request.addString("localFile", localFile); if (remoteUrl != null) request.addString("remoteUrl", remoteUrl); String result = request.executeAsString(); if (request.isUnAuthorized()) throw new UnAuthorizedException("Not authorized to add route " + description, categoryUrl); if (request.isForbidden()) throw new ForbiddenException("Forbidden to add route " + description, categoryUrl); if (request.isBadRequest()) throw new NotFoundException("Category not found", categoryUrl); if (request.isPreconditionFailed()) throw new DuplicateNameException("Route " + description + " already exists", categoryUrl); if (!request.isSuccessful()) throw new IOException("POST on " + (rootUrl + ROUTE_URI) + " with route " + description + "," + categoryUrl + "," + remoteUrl + " not successful: " + result); return request.getLocation(); } void updateRoute(String routeUrl, String categoryUrl, String description, String localFile, String remoteUrl) throws IOException { log.info(format("Updating route %s to category %s and description %s with remote url %s", routeUrl, categoryUrl, description, remoteUrl)); Put request = new Put(routeUrl, credentials); request.setAccept(APPLICATION_JSON); request.addString("category", categoryUrl); request.addString("description", description); if (localFile != null) request.addString("localFile", localFile); if (remoteUrl != null) request.addString("remoteUrl", remoteUrl); String result = request.executeAsString(); if (request.isUnAuthorized()) throw new UnAuthorizedException("Not authorized to update route", routeUrl); if (request.isForbidden()) throw new ForbiddenException("Forbidden to update route", routeUrl); if (request.isNotFound()) throw new NotFoundException("Route not found", routeUrl); if (request.isBadRequest()) throw new NotOwnerException("Not owner of route to update", routeUrl); if (request.isPreconditionFailed()) throw new DuplicateNameException("Route " + description + " already exists", description); if (!request.isSuccessful()) throw new IOException("PUT on " + routeUrl + " with route " + description + "," + categoryUrl + "," + remoteUrl + " not successful: " + result); } void deleteRoute(String routeUrl) throws IOException { log.info(format("Deleting route %s", routeUrl)); Delete request = new Delete(routeUrl, credentials); request.setAccept(APPLICATION_JSON); String result = request.executeAsString(); if (request.isUnAuthorized()) throw new UnAuthorizedException("Not authorized to delete route", routeUrl); if (request.isForbidden()) throw new ForbiddenException("Forbidden to delete route", routeUrl); if (request.isNotFound()) throw new NotFoundException("Route not found", routeUrl); if (request.isBadRequest()) throw new NotOwnerException("Not owner of route to delete", routeUrl); if (!request.isSuccessful()) throw new IOException("DELETE on " + routeUrl + " not successful: " + result); } String addFile(File file) throws IOException { log.info(format("Adding file %s", file)); String fileUrl = rootUrl + FILE_URI; Post request = new Post(fileUrl, credentials); request.setAccept(APPLICATION_JSON); request.addString("name", file.getName()); request.addFile("file", file); String result = request.executeAsString(); if (request.isUnAuthorized()) throw new UnAuthorizedException("Not authorized to add file " + file, fileUrl); if (request.isForbidden()) throw new ForbiddenException("Forbidden to add file " + file, fileUrl); if (request.isPreconditionFailed()) throw new ServiceUnavailableException("File " + file + " is too large", fileUrl, result); if (!request.isSuccessful()) throw new IOException("POST on " + fileUrl + " with file " + file + " not successful: " + result); return request.getLocation(); } void deleteFile(String fileUrl) throws IOException { log.info(format("Adding file %s", fileUrl)); Delete request = new Delete(fileUrl, credentials); String result = request.executeAsString(); if (request.isUnAuthorized()) throw new UnAuthorizedException("Not authorized to delete file", fileUrl); if (request.isForbidden()) throw new ForbiddenException("Forbidden to delete file", fileUrl); if (request.isNotFound()) throw new NotFoundException("File not found", fileUrl); if (request.isBadRequest()) throw new NotOwnerException("Not owner of file to delete", fileUrl); if (!request.isSuccessful()) throw new IOException("DELETE on " + fileUrl + " not successful: " + result); } }