public void store(Path output) throws IOException { FileSystem fs = output.getFileSystem(HadoopUtils.createConfiguration()); fs.delete(output, true); OutputStream os = fs.create(output, true); store(os); os.close(); }
public ColumnDefinitionFile(Path path) throws IOException { if (path == null) { throw new IOException("A column file path must be specified."); } FSDataInputStream fdis = path.getFileSystem(HadoopUtils.createConfiguration()).open(path); load(fdis); fdis.close(); }
@Before public void init() { // create a configuration conf = HadoopUtils.createConfiguration(); // set this to a relatively high value - it will be bumped back down in // testMoreWorkersThanMapSlots conf.setInt("mapred.tasktracker.map.tasks.maximum", 100); // create a metadata metadata = new MrsImagePyramidMetadata(); metadata.setTilesize(tileSize); metadata.setTileType(DataBuffer.TYPE_FLOAT); }
@Test(expected = IllegalArgumentException.class) @Category(IntegrationTest.class) public void testMoreWorkersThanMapSlots() throws Exception { HadoopUtils.setupLocalRunner(conf); // find a large enough tile bounds TileBounds tb = new TileBounds(2764, 1365, 2878, 1479); Bounds bounds = TMSUtils.tileToBounds(tb, zoomLevel, tileSize); TiledInputFormatContext ifContext = new TiledInputFormatContext( zoomLevel, tileSize, new HashSet<String>(), bounds.convertNewToOldBounds(), new Properties()); ifContext.save(conf); CostDistanceWorkersConfiguration.getNumWorkers(metadata, conf); }
private void setupConfig(final Job job, final MrsImageDataProvider provider) throws DataProviderException { try { Configuration conf = job.getConfiguration(); DataProviderFactory.saveProviderPropertiesToConfig(provider.getProviderProperties(), conf); context.save(conf); // Add the input pyramid metadata to the job configuration for (final String input : context.getInputs()) { MrsImagePyramid pyramid; try { pyramid = MrsImagePyramid.open(input, context.getProviderProperties()); } catch (IOException e) { throw new DataProviderException("Failure opening input image pyramid: " + input, e); } final MrsImagePyramidMetadata metadata = pyramid.getMetadata(); log.debug( "In HadoopUtils.setupMrsPyramidInputFormat, loading pyramid for " + input + " pyramid instance is " + pyramid + " metadata instance is " + metadata); String image = metadata.getName(context.getZoomLevel()); // if we don't have this zoom level, use the max, then we'll decimate/subsample that one if (image == null) { log.error( "Could not get image in setupMrsPyramidInputFormat at zoom level " + context.getZoomLevel() + " for " + pyramid); image = metadata.getName(metadata.getMaxZoomLevel()); } HadoopUtils.setMetadata(conf, metadata); } } catch (IOException e) { throw new DataProviderException( "Failure configuring map/reduce job " + context.toString(), e); } }
@Path("/tms") public class TileMapServiceResource { private static final Logger log = LoggerFactory.getLogger(TileMapServiceResource.class); private static final MimetypesFileTypeMap mimeTypeMap = new MimetypesFileTypeMap(); private static final String VERSION = "1.0.0"; private static final String SRS = "EPSG:4326"; private static final String GENERAL_ERROR = "An error occurred in Tile Map Service"; private static String imageBaseDir = HadoopUtils.getDefaultImageBaseDirectory(); public static String KML_VERSION = "http://www.opengis.net/kml/2.2"; public static String KML_EXTENSIONS = "http://www.google.com/kml/ext/2.2"; public static String KML_MIME_TYPE = "application/vnd.google-earth.kml+xml"; @Context TmsService service; static Properties props; static { init(); } public static void init() { try { if (props == null) { props = Configuration.getInstance().getProperties(); } } catch (final IllegalStateException e) { log.error( MrGeoConstants.MRGEO_HDFS_IMAGE + " must be specified in the MrGeo configuration file (" + e.getMessage() + ")"); } } protected static Response createEmptyTile( final ImageResponseWriter writer, final int width, final int height) { // return an empty image final int dataType; if (writer.getResponseMimeType().equals("image/jpeg")) { dataType = BufferedImage.TYPE_3BYTE_BGR; } else { // dataType = BufferedImage.TYPE_INT_ARGB; dataType = BufferedImage.TYPE_4BYTE_ABGR; } final BufferedImage bufImg = new BufferedImage(width, height, dataType); final Graphics2D g = bufImg.createGraphics(); g.setColor(new Color(0, 0, 0, 0)); g.fillRect(0, 0, width, height); g.dispose(); return writer.write(bufImg.getData()).build(); } protected static Document mrsPyramidMetadataToTileMapXml( final String raster, final String url, final MrsImagePyramidMetadata mpm) throws ParserConfigurationException { /* * String tileMap = "<?xml version='1.0' encoding='UTF-8' ?>" + * "<TileMap version='1.0.0' tilemapservice='http://localhost/mrgeo-services/api/tms/1.0.0'>" + * " <Title>AfPk Elevation V2</Title>" + " <Abstract>A test of V2 MrsImagePyramid.</Abstract>" * + " <SRS>EPSG:4326</SRS>" + " <BoundingBox minx='68' miny='33' maxx='72' maxy='35' />" + * " <Origin x='68' y='33' />" + * " <TileFormat width='512' height='512' mime-type='image/tiff' extension='tif' />" + * " <TileSets profile='global-geodetic'>" + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/1' units-per-pixel='0.3515625' order='1' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/2' units-per-pixel='0.17578125' order='2' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/3' units-per-pixel='0.08789063' order='3' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/4' units-per-pixel='0.08789063' order='4' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/5' units-per-pixel='0.08789063' order='5' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/6' units-per-pixel='0.08789063' order='6' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/7' units-per-pixel='0.08789063' order='7' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/8' units-per-pixel='0.08789063' order='8' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/9' units-per-pixel='0.08789063' order='9' />" * + * " <TileSet href='http://localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2/10' units-per-pixel='0.08789063' order='10' />" * + " </TileSets>" + "</TileMap>"; */ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); final DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); // root elements final Document doc = docBuilder.newDocument(); final Element rootElement = doc.createElement("TileMap"); doc.appendChild(rootElement); final Attr v = doc.createAttribute("version"); v.setValue(VERSION); rootElement.setAttributeNode(v); final Attr tilemapservice = doc.createAttribute("tilemapservice"); tilemapservice.setValue(normalizeUrl(normalizeUrl(url).replace(raster, ""))); rootElement.setAttributeNode(tilemapservice); // child elements final Element title = doc.createElement("Title"); title.setTextContent(raster); rootElement.appendChild(title); final Element abst = doc.createElement("Abstract"); abst.setTextContent(""); rootElement.appendChild(abst); final Element srs = doc.createElement("SRS"); srs.setTextContent(SRS); rootElement.appendChild(srs); final Element bbox = doc.createElement("BoundingBox"); rootElement.appendChild(bbox); final Attr minx = doc.createAttribute("minx"); minx.setValue(String.valueOf(mpm.getBounds().getMinX())); bbox.setAttributeNode(minx); final Attr miny = doc.createAttribute("miny"); miny.setValue(String.valueOf(mpm.getBounds().getMinY())); bbox.setAttributeNode(miny); final Attr maxx = doc.createAttribute("maxx"); maxx.setValue(String.valueOf(mpm.getBounds().getMaxX())); bbox.setAttributeNode(maxx); final Attr maxy = doc.createAttribute("maxy"); maxy.setValue(String.valueOf(mpm.getBounds().getMaxY())); bbox.setAttributeNode(maxy); final Element origin = doc.createElement("Origin"); rootElement.appendChild(origin); final Attr x = doc.createAttribute("x"); x.setValue(String.valueOf(mpm.getBounds().getMinX())); origin.setAttributeNode(x); final Attr y = doc.createAttribute("y"); y.setValue(String.valueOf(mpm.getBounds().getMinY())); origin.setAttributeNode(y); final Element tileformat = doc.createElement("TileFormat"); rootElement.appendChild(tileformat); final Attr w = doc.createAttribute("width"); w.setValue(String.valueOf(mpm.getTilesize())); tileformat.setAttributeNode(w); final Attr h = doc.createAttribute("height"); h.setValue(String.valueOf(mpm.getTilesize())); tileformat.setAttributeNode(h); final Attr mt = doc.createAttribute("mime-type"); mt.setValue("image/tiff"); tileformat.setAttributeNode(mt); final Attr ext = doc.createAttribute("extension"); ext.setValue("tif"); tileformat.setAttributeNode(ext); final Element tilesets = doc.createElement("TileSets"); rootElement.appendChild(tilesets); final Attr profile = doc.createAttribute("profile"); profile.setValue("global-geodetic"); tilesets.setAttributeNode(profile); for (int i = 0; i <= mpm.getMaxZoomLevel(); i++) { final Element tileset = doc.createElement("TileSet"); tilesets.appendChild(tileset); final Attr href = doc.createAttribute("href"); href.setValue(normalizeUrl(normalizeUrl(url)) + "/" + i); tileset.setAttributeNode(href); final Attr upp = doc.createAttribute("units-per-pixel"); upp.setValue(String.valueOf(180d / 256d / Math.pow(2, i))); tileset.setAttributeNode(upp); final Attr order = doc.createAttribute("order"); order.setValue(String.valueOf(i)); tileset.setAttributeNode(order); } return doc; } protected static Document mrsPyramidToTileMapServiceXml( final String url, final List<String> pyramidNames) throws ParserConfigurationException, DOMException, UnsupportedEncodingException { /* * String tileMapService = "<?xml version='1.0' encoding='UTF-8' ?>" + * "<TileMapService version='1.0.0' services='http://localhost/mrgeo-services/api/tms/'>" + * " <Title>Example Tile Map Service</Title>" + * " <Abstract>This is a longer description of the example tiling map service.</Abstract>" + * " <TileMaps>" + " <TileMap " + " title='AfPk Elevation V2' " + * " srs='EPSG:4326' " + " profile='global-geodetic' " + * " href='http:///localhost/mrgeo-services/api/tms/1.0.0/AfPkElevationV2' />" + * " </TileMaps>" + "</TileMapService>"; */ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); final DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); // root elements final Document doc = docBuilder.newDocument(); final Element rootElement = doc.createElement("TileMapService"); doc.appendChild(rootElement); final Attr v = doc.createAttribute("version"); v.setValue(VERSION); rootElement.setAttributeNode(v); final Attr service = doc.createAttribute("services"); service.setValue(normalizeUrl(normalizeUrl(url).replace(VERSION, ""))); rootElement.setAttributeNode(service); // child elements final Element title = doc.createElement("Title"); title.setTextContent("Tile Map Service"); rootElement.appendChild(title); final Element abst = doc.createElement("Abstract"); abst.setTextContent("MrGeo MrsImagePyramid rasters available as TMS"); rootElement.appendChild(abst); final Element tilesets = doc.createElement("TileMaps"); rootElement.appendChild(tilesets); Collections.sort(pyramidNames); for (final String p : pyramidNames) { final Element tileset = doc.createElement("TileMap"); tilesets.appendChild(tileset); final Attr href = doc.createAttribute("href"); href.setValue(normalizeUrl(url) + "/" + URLEncoder.encode(p, "UTF-8")); tileset.setAttributeNode(href); final Attr maptitle = doc.createAttribute("title"); maptitle.setValue(p); tileset.setAttributeNode(maptitle); final Attr srs = doc.createAttribute("srs"); srs.setValue(SRS); tileset.setAttributeNode(srs); final Attr profile = doc.createAttribute("profile"); profile.setValue("global-geodetic"); tileset.setAttributeNode(profile); } return doc; } protected static String normalizeUrl(final String url) { String newUrl; newUrl = (url.lastIndexOf("/") == url.length() - 1) ? url.substring(0, url.length() - 1) : url; return newUrl; } protected static Document rootResourceXml(final String url) throws ParserConfigurationException { /* * <?xml version="1.0" encoding="UTF-8" ?> <Services> <TileMapService * title="MrGeo Tile Map Service" version="1.0.0" * href="http://localhost:8080/mrgeo-services/api/tms/1.0.0" /> </Services> */ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); final DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); final Document doc = docBuilder.newDocument(); final Element rootElement = doc.createElement("Services"); doc.appendChild(rootElement); final Element tms = doc.createElement("TileMapService"); rootElement.appendChild(tms); final Attr title = doc.createAttribute("title"); title.setValue("MrGeo Tile Map Service"); tms.setAttributeNode(title); final Attr v = doc.createAttribute("version"); v.setValue(VERSION); tms.setAttributeNode(v); final Attr href = doc.createAttribute("href"); href.setValue(normalizeUrl(url) + "/" + VERSION); tms.setAttributeNode(href); return doc; } @GET @Produces("text/xml") public Response getRootResource(@Context final HttpServletRequest hsr) { try { final String url = hsr.getRequestURL().toString(); final Document doc = rootResourceXml(url); final DOMSource source = new DOMSource(doc); return Response.ok(source, "text/xml").header("Content-type", "text/xml").build(); } catch (final ParserConfigurationException ex) { return Response.status(Status.INTERNAL_SERVER_ERROR).entity(GENERAL_ERROR).build(); } } @SuppressWarnings("static-method") @GET @Produces("image/*") @Path("{version}/{raster}/{z}/{x}/{y}.{format}") public Response getTile( @PathParam("version") final String version, @PathParam("raster") String pyramid, @PathParam("z") final Integer z, @PathParam("x") final Integer x, @PathParam("y") final Integer y, @PathParam("format") final String format, @QueryParam("color-scale-name") final String colorScaleName, @QueryParam("color-scale") final String colorScale, @QueryParam("min") final Double min, @QueryParam("max") final Double max, @DefaultValue("1") @QueryParam("maskMax") final Double maskMax, @QueryParam("mask") final String mask) { final ImageRenderer renderer; Raster raster; try { renderer = (ImageRenderer) ImageHandlerFactory.getHandler(format, ImageRenderer.class); // TODO: Need to construct provider properties from the WebRequest using // a new security layer and pass those properties. // Apply mask if requested ProviderProperties providerProperties = SecurityUtils.getProviderProperties(); if (mask != null && !mask.isEmpty()) { raster = renderer.renderImage(pyramid, x, y, z, mask, maskMax, providerProperties); } else { raster = renderer.renderImage(pyramid, x, y, z, providerProperties); } if (!(renderer instanceof TiffImageRenderer) && raster.getNumBands() != 3 && raster.getNumBands() != 4) { ColorScale cs = null; if (colorScaleName != null) { cs = ColorScaleManager.fromName(colorScaleName, props); } else if (colorScale != null) { cs = ColorScaleManager.fromJSON(colorScale); } // else // { // cs = ColorScaleManager.fromPyramid(pyramid, driver); // } final double[] extrema = renderer.getExtrema(); // Check for min/max override values from the request if (min != null) { extrema[0] = min; } if (max != null) { extrema[1] = max; } raster = ((ColorScaleApplier) ImageHandlerFactory.getHandler(format, ColorScaleApplier.class)) .applyColorScale(raster, cs, extrema, renderer.getDefaultValues()); } // Apply mask if requested // if (mask != null && !mask.isEmpty()) // { // try // { // final MrsImagePyramidMetadata maskMetadata = service.getMetadata(mask); // // final Raster maskRaster = renderer.renderImage(mask, x, y, z, props, driver); // final WritableRaster wr = RasterUtils.makeRasterWritable(raster); // // final int band = 0; // final double nodata = maskMetadata.getDefaultValue(band); // // for (int w = 0; w < maskRaster.getWidth(); w++) // { // for (int h = 0; h < maskRaster.getHeight(); h++) // { // final double maskPixel = maskRaster.getSampleDouble(w, h, band); // if (maskPixel > maskMax || Double.compare(maskPixel, nodata) == 0) // { // wr.setSample(w, h, band, nodata); // } // } // } // } // catch (final TileNotFoundException ex) // { // raster = RasterUtils.createEmptyRaster(raster.getWidth(), raster.getHeight(), // raster // .getNumBands(), raster.getTransferType(), 0); // } // } return ((ImageResponseWriter) ImageHandlerFactory.getHandler(format, ImageResponseWriter.class)) .write(raster, renderer.getDefaultValues()) .build(); } catch (final IllegalArgumentException e) { return Response.status(Status.BAD_REQUEST) .entity("Unsupported image format - " + format) .build(); } catch (final IOException e) { return Response.status(Status.NOT_FOUND).entity("Tile map not found - " + pyramid).build(); } catch (final MrsImageException e) { return Response.status(Status.NOT_FOUND) .entity("Tile map not found - " + pyramid + ": " + z) .build(); } catch (final TileNotFoundException e) { // return Response.status(Status.NOT_FOUND).entity("Tile not found").build(); try { final MrsImagePyramidMetadata metadata = service.getMetadata(pyramid); return createEmptyTile( ((ImageResponseWriter) ImageHandlerFactory.getHandler(format, ImageResponseWriter.class)), metadata.getTilesize(), metadata.getTilesize()); } catch (final Exception e1) { log.error( "Exception occurred creating blank tile " + pyramid + "/" + z + "/" + x + "/" + y + "." + format, e1); } } catch (final ColorScale.BadJSONException e) { return Response.status(Status.NOT_FOUND).entity("Unable to parse color scale JSON").build(); } catch (final ColorScale.BadSourceException e) { return Response.status(Status.NOT_FOUND).entity("Unable to open color scale file").build(); } catch (final ColorScale.BadXMLException e) { return Response.status(Status.NOT_FOUND).entity("Unable to parse color scale XML").build(); } catch (final ColorScale.ColorScaleException e) { return Response.status(Status.NOT_FOUND).entity("Unable to open color scale").build(); } catch (final Exception e) { log.error( "Exception occurred getting tile " + pyramid + "/" + z + "/" + x + "/" + y + "." + format, e); } return Response.status(Status.INTERNAL_SERVER_ERROR).entity(GENERAL_ERROR).build(); } @GET @Produces("text/xml") @Path("/{version}/{raster}") public Response getTileMap( @PathParam("version") final String version, @PathParam("raster") String raster, @Context final HttpServletRequest hsr) { try { final String url = hsr.getRequestURL().toString(); // Check cache for metadata, if not found read from pyramid // and store in cache final MrsImagePyramidMetadata mpm = service.getMetadata(raster); final Document doc = mrsPyramidMetadataToTileMapXml(raster, url, mpm); final DOMSource source = new DOMSource(doc); return Response.ok(source, "text/xml").header("Content-type", "text/xml").build(); } catch (final ExecutionException e) { log.error("MrsImagePyramid " + raster + " not found", e); return Response.status(Status.NOT_FOUND).entity("Tile map not found - " + raster).build(); } catch (final ParserConfigurationException ex) { return Response.status(Status.INTERNAL_SERVER_ERROR).entity(GENERAL_ERROR).build(); } } @GET @Produces("text/xml") @Path("/{version}") public Response getTileMapService( @PathParam("version") final String version, @Context final HttpServletRequest hsr) { try { final String url = hsr.getRequestURL().toString(); final Document doc = mrsPyramidToTileMapServiceXml(url, service.listImages()); final DOMSource source = new DOMSource(doc); return Response.ok(source, "text/xml").header("Content-type", "text/xml").build(); } catch (final IOException e) { log.error("File system exception for " + imageBaseDir, e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(GENERAL_ERROR).build(); } catch (final ParserConfigurationException ex) { return Response.status(Status.INTERNAL_SERVER_ERROR).entity(GENERAL_ERROR).build(); } } protected Response returnEmptyTile(final int width, final int height, final String format) throws Exception { // return an empty image ImageResponseWriter writer = (ImageResponseWriter) ImageHandlerFactory.getHandler(format, ImageResponseWriter.class); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bands; Double[] nodatas; if (format.equalsIgnoreCase("jpg") || format.equalsIgnoreCase("jpeg")) { bands = 3; nodatas = new Double[] {0.0, 0.0, 0.0}; } else { bands = 4; nodatas = new Double[] {0.0, 0.0, 0.0, 0.0}; } Raster raster = RasterUtils.createEmptyRaster(width, height, bands, DataBuffer.TYPE_BYTE, nodatas); writer.writeToStream(raster, ArrayUtils.toPrimitive(nodatas), baos); byte[] imageData = baos.toByteArray(); IOUtils.closeQuietly(baos); final String type = mimeTypeMap.getContentType("output." + format); return Response.ok(imageData).header("Content-Type", type).build(); // A 404 - Not Found response may be the most appropriate, but results in pink tiles, // maybe change that behavior on the OpenLayers client? // return Response.status( Response.Status.NOT_FOUND).build(); } }