All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.vfny.geoserver.action.MapPreviewAction Maven / Gradle / Ivy

The newest version!
/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org.  All rights reserved.
 * This code is licensed under the GPL 2.0 license, availible at the root
 * application directory.
 */
package org.vfny.geoserver.action;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import org.apache.struts.util.MessageResources;
import org.geoserver.ows.util.RequestUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;
import org.vfny.geoserver.global.CoverageInfo;
import org.vfny.geoserver.global.Data;
import org.vfny.geoserver.global.FeatureTypeInfo;
import org.vfny.geoserver.global.GeoServer;
import org.vfny.geoserver.global.WMS;
import org.vfny.geoserver.util.requests.CapabilitiesRequest;
import org.vfny.geoserver.wms.servlets.Capabilities;

import com.vividsolutions.jts.geom.Envelope;


/**
 * MapPreviewAction
Sep 26, 2005
* Purpose:
* Gathers up all the FeatureTypes in use and returns the informaion to the * .jsp .
* It will also generate requests to the WMS "openlayers" output format.
* This will communicate to a .jsp and return it three arrays of strings that contain:
* - The Featuretype's name
* - The DataStore name of the FeatureType
* - The bounding box of the FeatureType
* To change what data is output to the .jsp, you must change struts-config.xml.
* Look for the line:
* <form-bean
* name="mapPreviewForm"
* * @author Brent Owens (The Open Planning Project) * @version */ public class MapPreviewAction extends GeoServerAction { // the layer is a coverage, or is made exclusively of coverages public static final Integer LAYER_IS_COVERAGE = new Integer(0); // the layer is a group with at least one coverage public static final Integer LAYER_HAS_COVERAGE = new Integer(1); // the layer or group is made of vectors only public static final Integer LAYER_IS_VECTOR = new Integer(2); /* (non-Javadoc) * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ArrayList dsList = new ArrayList(); ArrayList ftList = new ArrayList(); ArrayList bboxList = new ArrayList(); ArrayList srsList = new ArrayList(); ArrayList ftnsList = new ArrayList(); ArrayList widthList = new ArrayList(); ArrayList heightList = new ArrayList(); ArrayList coverageStatus = new ArrayList(); // 1) get the capabilities info so we can find out our feature types WMS wms = getWMS(request); CapabilitiesRequest capRequest = new CapabilitiesRequest("WMS", wms); capRequest.setHttpServletRequest(request); Data catalog = wms.getData(); List ftypes = new ArrayList(catalog.getFeatureTypeInfos().values()); for (Iterator it = ftypes.iterator(); it.hasNext();) { FeatureTypeInfo ft = (FeatureTypeInfo) it.next(); if(!ft.isEnabled()) it.remove(); } Collections.sort(ftypes, new FeatureTypeInfoNameComparator()); List ctypes = new ArrayList(catalog.getCoverageInfos().values()); for (Iterator it = ctypes.iterator(); it.hasNext();) { CoverageInfo ci = (CoverageInfo) it.next(); if(!ci.isEnabled()) it.remove(); } Collections.sort(ctypes, new CoverageInfoNameComparator()); List bmtypes = new ArrayList(wms.getBaseMapLayers().keySet()); Collections.sort(bmtypes); // 2) delete any existing generated files in the generation directory ServletContext sc = request.getSession().getServletContext(); //File rootDir = GeoserverDataDirectory.getGeoserverDataDirectory(sc); //File previewDir = new File(sc.getRealPath("data/generated")); if (sc.getRealPath("preview") == null) { //There's a problem here, since we can't get a real path for the "preview" directory. //On tomcat this happens when "unpackWars=false" is set for this context. throw new RuntimeException( "Couldn't populate preview directory...is the war running in unpacked mode?"); } File previewDir = new File(sc.getRealPath("preview")); //File previewDir = new File(rootDir, "data/generated"); if (!previewDir.exists()) { previewDir.mkdirs(); } // We need to create a 4326 CRS for comparison to layer's crs CoordinateReferenceSystem latLonCrs = null; try { // get the CRS object for lat/lon 4326 latLonCrs = CRS.decode("EPSG:" + 4326); } catch (NoSuchAuthorityCodeException e) { String msg = "Error looking up SRS for EPSG: " + 4326 + ":" + e.getLocalizedMessage(); LOGGER.warning(msg); } catch (FactoryException e) { String msg = "Error looking up SRS for EPSG: " + 4326 + ":" + e.getLocalizedMessage(); LOGGER.warning(msg); } // 3) Go through each *FeatureType* and collect information && write out config files for (Iterator it = ftypes.iterator(); it.hasNext();) { FeatureTypeInfo layer = (FeatureTypeInfo) it.next(); try { if (!layer.isEnabled() || layer.isGeometryless()) { continue; // if it isn't enabled, move to the next layer } CoordinateReferenceSystem layerCrs = layer.getDeclaredCRS(); /* A quick and efficient way to grab the bounding box is to get it * from the featuretype info where the lat/lon bbox is loaded * from the DTO. We do this with layer.getLatLongBoundingBox(). * We need to reproject the bounding box from lat/lon to the layer crs * for display */ Envelope orig_bbox = layer.getLatLongBoundingBox(); if ((orig_bbox.getWidth() == 0) || (orig_bbox.getHeight() == 0)) { orig_bbox.expandBy(0.1); } ReferencedEnvelope bbox = new ReferencedEnvelope(orig_bbox, latLonCrs); if (!CRS.equalsIgnoreMetadata(layerCrs, latLonCrs)) { // first check if we have a native bbox bbox = layer.getBoundingBox(); } // we now have a bounding box in the same CRS as the layer if ((bbox.getWidth() == 0) || (bbox.getHeight() == 0)) { bbox.expandBy(0.1); } if (layer.isEnabled()) { // prepare strings for web output ftList.add(layer.getNameSpace().getPrefix() + "_" + layer.getFeatureType().getTypeName()); // FeatureType name ftnsList.add(layer.getNameSpace().getPrefix() + ":" + layer.getFeatureType().getTypeName()); dsList.add(layer.getDataStoreInfo().getId()); // DataStore info // bounding box of the FeatureType // expand bbox by 5% to allow large symbolizers to fit the map bbox.expandBy(bbox.getWidth() / 20, bbox.getHeight() / 20); bboxList.add(bbox.getMinX() + "," + bbox.getMinY() + "," + bbox.getMaxX() + "," + bbox.getMaxY()); srsList.add("EPSG:" + layer.getSRS()); int[] imageBox = getMapWidthHeight(bbox); widthList.add(String.valueOf(imageBox[0])); heightList.add(String.valueOf(imageBox[1])); // not a coverage coverageStatus.add(LAYER_IS_VECTOR); } } catch(Exception e) { LOGGER.log(Level.WARNING, "Error trying to access layer " + layer.getName(), e); } } // 3.5) Go through each *Coverage* and collect its info for (Iterator it = ctypes.iterator(); it.hasNext();) { CoverageInfo layer = (CoverageInfo) it.next(); try { // upper right corner? lower left corner? Who knows?! Better naming conventions needed guys. double[] lowerLeft = layer.getEnvelope().getLowerCorner().getCoordinates(); double[] upperRight = layer.getEnvelope().getUpperCorner().getCoordinates(); Envelope bbox = new Envelope(lowerLeft[0], upperRight[0], lowerLeft[1], upperRight[1]); if (layer.isEnabled()) { // prepare strings for web output String shortLayerName = layer.getName().split(":")[1]; // we don't want the namespace prefix ftList.add(layer.getNameSpace().getPrefix() + "_" + shortLayerName); // Coverage name ftnsList.add(layer.getNameSpace().getPrefix() + ":" + shortLayerName); dsList.add(layer.getFormatInfo().getId()); // DataStore info // bounding box of the Coverage bboxList.add(bbox.getMinX() + "," + bbox.getMinY() + "," + bbox.getMaxX() + "," + bbox.getMaxY()); srsList.add(layer.getSrsName()); int[] imageBox = getMapWidthHeight(bbox); widthList.add(String.valueOf(imageBox[0])); heightList.add(String.valueOf(imageBox[1])); // this layer is a coverage, all right coverageStatus.add(LAYER_IS_COVERAGE); } } catch(Exception e) { LOGGER.log(Level.WARNING, "Error trying to access layer " + layer.getName(), e); } } // 3.6) Go thru base map layers Locale locale = (Locale) request.getLocale(); MessageResources messages = getResources(request); String baseMap = messages.getMessage(locale, "label.baseMap"); for (Iterator it = bmtypes.iterator(); it.hasNext();) { String baseMapTitle = (String) it.next(); try { ftList.add(baseMapTitle); ftnsList.add(baseMapTitle); dsList.add(baseMap); GeneralEnvelope bmBbox = ((GeneralEnvelope) wms.getBaseMapEnvelopes().get(baseMapTitle)); Envelope bbox = new Envelope(bmBbox.getMinimum(0), bmBbox.getMaximum(0), bmBbox.getMinimum(1), bmBbox.getMaximum(1)); bboxList.add(bbox.getMinX() + "," + bbox.getMinY() + "," + bbox.getMaxX() + "," + bbox.getMaxY()); try { Integer epsgCode = CRS.lookupEpsgCode(bmBbox.getCoordinateReferenceSystem(), false) ; if ( epsgCode != null ) { srsList.add( "EPSG:" + epsgCode ); } } catch (FactoryException e) { throw (IOException) new IOException().initCause(e); } int[] imageBox = getMapWidthHeight(bbox); widthList.add(String.valueOf(imageBox[0])); heightList.add(String.valueOf(imageBox[1])); // this depends on the composition, we raise the flag if the layer has at least // one coverage coverageStatus.add(computeGroupCoverageStatus(wms, baseMapTitle)); } catch(Exception e) { LOGGER.log(Level.WARNING, "Error trying to access group " + baseMapTitle, e); } } // Build up a list of url-encoded layer names, they might contain chars that are invalid // in urls List escapedFtnsist = new ArrayList(); for (Iterator it = ftnsList.iterator(); it.hasNext();) { String ft = (String) it.next(); escapedFtnsist.add(URLEncoder.encode(ft, "UTF-8")); } // 4) send off gathered information to the .jsp DynaActionForm myForm = (DynaActionForm) form; myForm.set("DSNameList", dsList.toArray(new String[dsList.size()])); myForm.set("FTNameList", ftList.toArray(new String[ftList.size()])); myForm.set("BBoxList", bboxList.toArray(new String[bboxList.size()])); myForm.set("SRSList", srsList.toArray(new String[srsList.size()])); myForm.set("WidthList", widthList.toArray(new String[widthList.size()])); myForm.set("HeightList", heightList.toArray(new String[heightList.size()])); myForm.set("FTNamespaceList", ftnsList.toArray(new String[ftnsList.size()])); myForm.set("EscapedFTNamespaceList", ftnsList.toArray(new String[escapedFtnsist.size()])); myForm.set("CoverageStatus", coverageStatus.toArray(new Integer[coverageStatus.size()])); //String proxifiedBaseUrl = RequestUtils.baseURL(request); GeoServer gs = (GeoServer)GeoServerExtensions.extensions(GeoServer.class).get(0); //proxifiedBaseUrl = RequestUtils.proxifiedBaseURL(proxifiedBaseUrl, gs.getProxyBaseUrl()); myForm.set("BaseUrl", "" ); return mapping.findForward("success"); } /** * Computes the coverage status flag for the specified layer * @param baseMapTitle * @return */ private Integer computeGroupCoverageStatus(WMS wms, String baseMapTitle) { String layerParam = (String) wms.getBaseMapLayers().get(baseMapTitle); String[] layers = layerParam.split(","); int coverageCount = 0; for (int i = 0; i < layers.length; i++) { if(wms.getData().getLayerType(layers[i]) == Data.TYPE_RASTER) coverageCount++; } if(coverageCount == 0) return LAYER_IS_VECTOR; else if(coverageCount < layers.length) return LAYER_HAS_COVERAGE; else return LAYER_IS_COVERAGE; } private int[] getMapWidthHeight(Envelope bbox) { int width; int height; double ratio = bbox.getHeight() / bbox.getWidth(); if (ratio < 1) { width = 750; height = (int) Math.round(750 * ratio); } else { width = (int) Math.round(550 / ratio); height = 550; } // make sure we reach some minimal dimensions (300 pixels is more or less // the height of the zoom bar) if (width < 300) { width = 300; } if (height < 300) { height = 300; } // add 50 pixels horizontally to account for the zoom bar return new int[] { width + 50, height }; } private static class FeatureTypeInfoNameComparator implements Comparator { public int compare(Object o1, Object o2) { FeatureTypeInfo ft1 = (FeatureTypeInfo) o1; FeatureTypeInfo ft2 = (FeatureTypeInfo) o2; String ft1Name = ft1.getNameSpace().getPrefix() + ft1.getName(); String ft2Name = ft2.getNameSpace().getPrefix() + ft2.getName(); return ft1Name.compareTo(ft2Name); } } private static class CoverageInfoNameComparator implements Comparator { public int compare(Object o1, Object o2) { CoverageInfo c1 = (CoverageInfo) o1; CoverageInfo c2 = (CoverageInfo) o2; String ft1Name = c1.getNameSpace().getPrefix() + c1.getName(); String ft2Name = c2.getNameSpace().getPrefix() + c2.getName(); return ft1Name.compareTo(ft2Name); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy