/*
* The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
* for visualizing and manipulating spatial features with geometry and attributes.
*
* Copyright (C) 2003 Vivid Solutions
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* For more information, contact:
*
* Vivid Solutions
* Suite #1A
* 2328 Government Street
* Victoria BC V8T 5G5
* Canada
*
* (250)385-6040
* www.vividsolutions.com
*/
package com.vividsolutions.wms;
import static java.net.URLEncoder.encode;
import java.awt.Image;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageIO;
import net.iharder.Base64;
import org.apache.log4j.Logger;
/**
* Represents all of the parameters of a getMap request from a WMS server.
* @author Chris Hodgson chodgson@refractions.net
*/
public class MapRequest {
private static Logger LOG = Logger.getLogger(MapRequest.class);
private WMService service;
private int imgWidth;
private int imgHeight;
private List layerList;
private BoundingBox bbox;
private boolean transparent;
private String format;
//[UT]
private String version = WMService.WMS_1_0_0;
/**
* Creates a new MapRequest.
* @param service the WMService which this MapRequest will use
*/
public MapRequest(WMService service) {
this.service = service;
imgWidth = 100;
imgHeight = 100;
layerList = new ArrayList();
bbox = service.getCapabilities().getTopLayer().getBoundingBox();
transparent = false;
format = null;
}
/**
* Gets the WMService that this object will make requests from.
* @return the WMService that this object will make requests from
*/
public WMService getService() {
return service;
}
/**
* Returns the format of this request.
* This may be a string such as GIF, JPEG, or PNG for a WMS 1.0 server, or
* a mime-type string in the case of a WMS 1.1 server. It may also be null if
* the format has not yet been set.
* @return the string representing the format of this request
*/
public String getFormat() {
return format;
}
/**
* Gets the width of the requested image, in pixels.
* The default image width is 100.
* @return the width of the requested image
*/
public int getImageWidth() {
return imgWidth;
}
/**
* Gets the height of the requested image, in pixels.
* The default image height is 100.
* @return the height of the requested image
*/
public int getImageHeight() {
return imgHeight;
}
/**
* Returns the list of layers to be requested. Each item in the
* list should be a String which is the name of a layer.
* @return the list of layer names to be requested
*/
public List getLayers() {
//<<TODO:NAMING>> Might be clearer to name this method getLayerNames [Jon Aquino]
return Collections.unmodifiableList(layerList);
}
/**
* Gets the BoundingBox of the image being requested.
* @return the BoundingBox of the image being requested
*/
public BoundingBox getBoundingBox() {
return bbox;
}
/**
* Gets whether or not a transparent image is being requested.
* @return true if a transparent image is being requested, false otherwise
*/
public boolean getTransparent() {
return transparent;
}
/**
* Sets the format of this request. The format must be a string which is in
* the list of supported formats as provided by getSupportedFormatList()
* (not necessarily the same String object, but the same sequence of characters).
* This will be an unformatted string for a WMS 1.0 server (GIF, JPEG, PNG) or
* a mime-type string for a WMS 1.1 server (image/gif, image/jpeg, image/png).
* If the format specified is not in the list, an IllegalArgumentException
* will be thrown.
*
* @param format a format string which is in the list of supported formats
* @throws IllegalArgumentException if the specified format isn't in the list of supported formats
* @see MapImageFormatChooser
*
*/
public void setFormat( String format ) throws IllegalArgumentException {
// <<TODO:UNCOMMENT>> Temporarily commented out, until mapserver is fixed [Chris Hodgson]
// Temporarily removing the requirement that the requested format
// be in the list of supported formats, in order to work around a Mapserver bug.
//String[] formats = service.getCapabilities().getMapFormats();
//for( int i = 0; i < formats.length; i++ ) {
// if( formats[i].equals( format ) ) {
this.format = format;
return;
// }
//}
//throw new IllegalArgumentException();
}
/**
* Sets the width of the image being requested.
* @param imageWidth the width of the image being requested
*/
public void setImageWidth( int imageWidth ) {
this.imgWidth = imageWidth;
}
/**
* Sets the height of the image being requested.
* @param imageHeight the height of the image being requested
*/
public void setImageHeight( int imageHeight ) {
this.imgHeight = imageHeight;
}
/**
* Sets the width and height of the image being requested.
* @param imageWidth the width of the image being requested
* @param imageHeight the height of the image being requested
*/
public void setImageSize( int imageWidth, int imageHeight ) {
this.imgWidth = imageWidth;
this.imgHeight = imageHeight;
}
/**
* Sets the layers to be requested. Each item in the list should be a string
* which corresponds to the name of a layer. The order of the list is
* important as the layers are rendered in the same order they are listed.
* @param layerList an ordered List of the names of layers to be displayed
*/
public void setLayers( List layerList ) {
//<<TODO:NAMING>> Might be clearer to name this method setLayerNames [Jon Aquino]
this.layerList = layerList;
}
/**
* Sets the BoundingBox of the image being requested.
* @param bbox the BoundingBox of the image being requested
*/
public void setBoundingBox( BoundingBox bbox ) {
this.bbox = bbox;
}
/**
* Sets whether or not to request an image with a transparent background.
* Requesting a transparent background doesn't guarantee that the resulting
* image will actually have a transparent background. Not all servers
* support transparency, and not all formats support transparency.
* @param transparent true to request a transparent background, false otherwise.
*/
public void setTransparent( boolean transparent ) {
this.transparent = transparent;
}
/**
* Returns a String containing the string representations of each item in the
* list (as provided by toString()), separated by commas.
* @param list the list to be returned as a coma-separated String
* @return a comma-separted String of the items in the list
*/
//[UT] 02.05.2005 made static and public
public static String listToString( List list ) {
Iterator it = list.iterator();
StringBuffer buf = new StringBuffer();
while( it.hasNext() ) {
String layer = (String)it.next();
buf.append( layer );
if( it.hasNext() ) {
buf.append( "," );
}
}
return buf.toString();
}
/**
* @return the URL for this request
* @throws MalformedURLException if there is a problem building the URL for some reason
*/
//[UT] changed to accept WMS 1.1.1
public URL getURL() throws MalformedURLException {
StringBuffer urlBuf = new StringBuffer();
String ver = "REQUEST=map&WMTVER=1.0";
if ( WMService.WMS_1_1_0.equals( version )){
ver = "REQUEST=GetMap&SERVICE=WMS&VERSION=1.1.0";
} else if ( WMService.WMS_1_1_1.equals( version ) ){
ver = "REQUEST=GetMap&SERVICE=WMS&VERSION=1.1.1";
}
urlBuf.append( service.getCapabilities().getGetMapURL() + ver + "&WIDTH=" + imgWidth + "&HEIGHT=" + imgHeight );
try {
urlBuf.append( "&LAYERS=" + encode(listToString( layerList ), "UTF-8") );
} catch (UnsupportedEncodingException e1) {
LOG.debug("UTF8 not supported by Java version", e1);
}
if( transparent ) {
urlBuf.append( "&TRANSPARENT=TRUE" );
}
if( format != null ) {
try {
urlBuf.append( "&FORMAT=" + encode(format, "UTF-8") );
} catch (UnsupportedEncodingException e) {
LOG.debug("UTF8 not supported by Java version", e);
}
}
if( bbox != null ) {
urlBuf.append( "&BBOX=" + bbox.getMinX() + "," + bbox.getMinY()
+ "," + bbox.getMaxX() + "," + bbox.getMaxY() );
if( bbox.getSRS() != null && !bbox.getSRS().equals( "LatLon" ) ) {
urlBuf.append( "&SRS=" + bbox.getSRS() );
}
}
// [UT] some style info is *required*, so add this to be spec conform
urlBuf.append( "&STYLES=" );
LOG.info(urlBuf.toString());
return new URL( urlBuf.toString() );
}
/**
* Connect to the service and get an Image of the map.
* @return the retrieved map Image
*/
public Image getImage() throws IOException {
URL requestUrl = getURL();
URLConnection con = requestUrl.openConnection();
if(requestUrl.getUserInfo() != null)
con.setRequestProperty("Authorization", "Basic " +
Base64.encodeBytes(requestUrl.getUserInfo().getBytes()));
return ImageIO.read(con.getInputStream());
}
//UT
public void setVersion( String ver ){
this.version = ver;
}
}