/* Package GeoTools/WMS Implementation * Copyright (C) 2001 Cameron Shorter (camerons@users.sourceforge.net) * Artur Hefczyc (kobit@users.sourceforge.net) * * 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. * * $Id: OGCCapabilities.java,v 1.15 2002/01/31 10:16:58 ianturton Exp $ * $Author: ianturton $ * $Date: 2002/01/31 10:16:58 $ */ package uk.ac.leeds.ccg.ogc; import java.util.*; import java.io.*; import org.apache.xerces.parsers.DOMParser; import org.w3c.dom.*; import org.apache.xerces.dom.*; import org.apache.xml.serialize.*; import org.xml.sax.*; /** * Class OGCCapabilities contains methods for parsing * WMSCapabilities data in XML format. * As a result of parsing, instance of this class, may return information * if this is realy capabilities file and than can create objects * representing special kind of info stored in capabilities.
* For example, after parsing capabilities file you can request * for available services on WMSServer. As a result * you will get array with class instances representing every * kind of service available on WMSServer.
* Through the service instance you can exchange data between * service on WMSServer and local client displaing * geo data on the screen. *

Probably the most important and often used service * is OGCWebMapService. According to OGC implementation * specification ver. 1.1.0 every Web Map Server should make * accesible at least Web Map Service. * * @author Cameron Shorter * @author Artur Hefczyc * @version $Revision: 1.15 $ */ public class OGCCapabilities { private Document doc = null; private String capa_version = null; private int parseWarnings = 0; private int parseErrors = 0; private int parseFatalErrors = 0; /** * Creates a new OGCCapabilities instance. * * @param is an InputStream value * @exception IOException if an error occurs * @exception SAXException if an error occurs */ public OGCCapabilities(InputStream is) throws IOException, SAXException, Exception { parseCapabilities(is); } /** * initialize method initializes OGCCapabilities * object for reuse with another document to parse. * */ public void initialize() { doc = null; capa_version = null; parseWarnings = 0; parseErrors = 0; parseFatalErrors = 0; } /** * parseCapabilities method checks correctness of capability * data received from Web Map Server. It checks both XML syntax and * structure. * * @param is an InputStream where from method should read capability data. */ public void parseCapabilities(InputStream is) throws Exception { /* I am not sure if "is" should be checked that it is not equal null */ if(is != null) { CapabilitiesParser parser = new CapabilitiesParser(); //try { doc = parser.parse(is); System.out.println("Finished reading/parsing capabilities"); is.close(); try { Element root = doc.getDocumentElement(); Attr at = root.getAttributeNode(OGCXMLConstants.ATT_VERSION); capa_version = new String(at.getValue()); } catch(NullPointerException npe) { capa_version = null; } //} catch (Exception e) { //prln("error in OGCCapabilities"); //e.printStackTrace(); //} } } /** * getAvailableServices method returns array of available * WebServices on remote WMS. * * @return an OGCWebService[] value */ /* public OGCWebService[] getAvailableServices() { if(doc != null) { NodeList nl = doc.getElementsByTagName(OGCXMLConstants.TAG_SERVICE); if(nl.getLength() > 0) { OGCWebService[] services = new OGCWebService[nl.getLength()]; for(int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); String service_type = getSubtagText(node, OGCXMLConstants.TAG_NAME); services[i] = OGCServiceFactory.createOGCService(service_type); services[i].setServiceName(getSubtagText(node, OGCXMLConstants.TAG_TITLE)); services[i].setServiceDescription(getSubtagText(node, OGCXMLConstants.TAG_ABSTRACT)); services[i].setCapabilities(this); } return services; } } return null; } */ /** * getAvailableLayers method build list of geo layers available * on remote WebMap Server. * * @return an ArrayList WMS layers list. */ public ArrayList getAvailableLayers() { if(doc != null) { NodeList nl = doc.getElementsByTagName(OGCXMLConstants.TAG_LAYER); System.out.println("OGC Cap: "+nl.getLength()+" layers"); if(nl.getLength() > 0) { ArrayList layers = new ArrayList(); for(int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); System.out.println(""+i+" "+node+" "+node.getNodeType()); if(node.getNodeType() == Node.ELEMENT_NODE) { String attr_value = ((Element)node).getAttribute(OGCXMLConstants.ATT_QUERYABLE); System.out.println("\t"+attr_value); //if(attr_value != null && attr_value.equals("1")) { String lay_name = null, lay_title = null, lay_abstr = null; double ll_maxx = 0, ll_maxy = 0, ll_minx = 0, ll_miny = 0; String st_name = null, st_title = null; double leg_h = 0, leg_w = 0; String leg_format = null, leg_resource = null; lay_name = getSubtagText(node, OGCXMLConstants.TAG_NAME); lay_title = getSubtagText(node, OGCXMLConstants.TAG_TITLE); lay_abstr = getSubtagText(node, OGCXMLConstants.TAG_ABSTRACT); System.out.println("\t"+lay_name+" "+lay_title+" "+lay_abstr); Node sub_node = getFirstSubnodeByTagName(node, OGCXMLConstants.TAG_LAT_LON_BB); try { System.out.println("ll_maxx:"+((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MAXX)); ll_maxx = Double.parseDouble(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MAXX)); ll_maxy = Double.parseDouble(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MAXY)); ll_minx = Double.parseDouble(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MINX)); ll_miny = Double.parseDouble(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_MINY)); } catch(Exception e) { ll_maxx = 0; ll_maxy = 0; ll_minx = 0; ll_miny = 0; } sub_node = getFirstSubnodeByTagName(node, OGCXMLConstants.TAG_STYLE); st_name = getSubtagText(sub_node, OGCXMLConstants.TAG_NAME); st_title = getSubtagText(sub_node, OGCXMLConstants.TAG_TITLE); sub_node = getFirstSubnodeByTagName(sub_node, OGCXMLConstants.TAG_LEGEND_URL); try { leg_h = Integer.parseInt(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_HEIGHT)); leg_w = Integer.parseInt(((Element)sub_node).getAttribute(OGCXMLConstants.ATT_WIDTH)); } catch(Exception e) { leg_h = 0; leg_w = 0; } leg_format = getSubtagText(sub_node, OGCXMLConstants.TAG_FORMAT); sub_node = getFirstSubnodeByTagName(sub_node, OGCXMLConstants.TAG_ONLINE_RES); if(sub_node != null) leg_resource = ((Element)sub_node).getAttribute(OGCXMLConstants.ATT_XLNK_HREF); if(lay_name != null && !lay_name.equals("")) { ExternalWMSLayer ext_wms_lay = new ExternalWMSLayer(lay_name, lay_title, ll_maxx, ll_maxy, ll_minx, ll_miny); ext_wms_lay.setLayerAbstract(lay_abstr); // ext_wms_lay.setLayerStyle(st_name, st_title); ext_wms_lay.setLayerLegend(leg_h, leg_w, leg_format, leg_resource); layers.add(ext_wms_lay); } //} }else{ System.out.println("not a Node.ELEMENT_NODE"); } } return layers; } System.out.println("No layers found"); } System.out.println("OGC Cap - Doc == null"); return null; } /** * getAvailableFormats method builds ArrayList * with available formats which support remote WMS. * * @param service_type a String value * @return an ArrayList value */ public ArrayList getAvailableFormats(String service_type) { ArrayList formats = new ArrayList(); WMSFormat format = new WMSFormat("JPEG"); formats.add(format); return formats; /* if(doc != null) { System.out.println("Asking for "+service_type+" formats"); NodeList service = doc.getElementsByTagName(service_type); for(int i=0;i 0) { ArrayList formats = new ArrayList(); for(int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if(node.getNodeName().equals(OGCXMLConstants.TAG_FORMAT)){ NodeList subnodes = node.getChildNodes(); if(subnodes != null) { for(int j = 0; j < subnodes.getLength(); j++) { Node n = subnodes.item(j); WMSFormat format = new WMSFormat(n.getNodeName()); formats.add(format); } } } // if format node } // for nl return formats; } // >0 } System.out.println("No format nodes"); return null; */ } /** * getCapabilitiesVersion method returns capability version * found in received capability data. * * @return a String value */ String getCapabilitiesVersion() { return capa_version; } protected Node getFirstSubnodeByTagName(Node node, String tagName) { if(node != null) { NodeList nl = ((Element)node).getElementsByTagName(tagName); if(nl.getLength() > 0) return nl.item(0); } return null; } protected String getTagText(Node node) { if(node != null) { Node text_node = node.getFirstChild(); if(text_node.getNodeType() == Node.TEXT_NODE) { return ((Text)text_node).getData(); } } return null; } protected String getSubtagText(Node node, String tagName) { if(node != null) { NodeList subnodes = node.getChildNodes(); for(int i = 0; i < subnodes.getLength(); i++) { if(subnodes.item(i).getNodeName().equals(tagName)) { Node subnode = subnodes.item(i); Node text_node = subnode.getFirstChild(); if(null==text_node) return null; if(text_node.getNodeType() == Node.TEXT_NODE) { return ((Text)text_node).getData(); } } } } return null; } /** * printCapabilitiesXML method sends capability in XML * format to given OutputStream * */ public void printCapabilitiesXML(OutputStream out) { try { OutputFormat of = new OutputFormat(); of.setIndenting(true); of.setIndent(2); of.setLineWidth(80); of.setMethod("xml"); // of.setOmitComments(false); // of.setOmitDocumentType(false); of.setOmitXMLDeclaration(false); // SerializerFactory sf = SerializerFactory.getSerializerFactory("xml"); // DOMSerializer serializer = (DOMSerializer)sf.makeSerializer(out, of); XMLSerializer serializer = new XMLSerializer(out, of); serializer.serialize(doc); } catch(IOException ioe) { ioe.printStackTrace(); } } /** * capabilitiesQuery method returns query for capabilities * to WMS server. * * @param version a String value contains version of WMS * specification which we need to build query. * @return a String value contains query for capabilities * including '?' at the beginning of string. */ public static String capabilitiesQuery(String version) { System.err.println("Version string request "+version); if(version.equals("1.1.0")) return OGCConstants.PAR_V110_VERSION+"="+OGCConstants.VERSION_V110+ "&"+OGCConstants.PAR_V110_SERVICE+"="+OGCConstants.VAL_V110_WMS+ "&"+OGCConstants.PAR_V110_REQUEST+"="+OGCConstants.VAL_V110_GETCAPABILITIES+ "&"+OGCConstants.PAR_V110_UPDATESEQUENCE+"=0"; if(version.equals("1.0.0")) return OGCConstants.PAR_V100_VERSION+"="+OGCConstants.VERSION_V100+ "&"+OGCConstants.PAR_V100_REQUEST+"="+OGCConstants.VAL_V100_GETCAPABILITIES; return null; } protected void prln(String str) { System.err.println(str); } /** * Wraps the Xerces DOM parser and extends NonValidatingDOMParser. * Code based on xercesSamples.dom.wrappers.DOMParser. * @version $id$ */ class CapabilitiesParser implements ErrorHandler { /** Parser. */ private DOMParser parser = new DOMParser(); /** Default constructor. */ public CapabilitiesParser() { try { parser.setFeature( "http://xml.org/sax/features/validation", false); parser.setFeature( "http://apache.org/xml/features/validation/schema", false); parser.setFeature( "http://apache.org/xml/features/validation/dynamic", false); parser.setFeature( "http://apache.org/xml/features/validation/schema-full-checking", false); parser.setFeature( "http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); parser.setFeature( "http://apache.org/xml/features/nonvalidating/load-external-dtd", false); } catch (SAXException e) { prln("error in setting up parser feature"); } parser.setErrorHandler(this); // String[] features = parser.getFeaturesRecognized(); // String[] properts = parser.getPropertiesRecognized(); // System.err.println("Features: "+features.length); // for (int i = 0; i < features.length; i++) { // try { // System.err.println(features[i]+ " = " +parser.getFeature(features[i])); // } catch (SAXException e) { // System.err.println("Problem with: "+features[i]); // } // } // end of for (int i = 0; i < features.length; i++) // System.err.println("Properties: "+properts.length); // for (int i = 0; i < properts.length; i++) { // try { // System.err.println(properts[i]+ " = " +parser.getProperty(properts[i])); // } catch (SAXException e) { // System.err.println("Problem with: "+properts[i]); // } // } // end of for (int i = 0; i < properts.length; i++) } /** Parses the specified URI and returns the document. */ public Document parse(String uri) throws Exception { parser.parse(uri); System.out.println("Cap Parsed"); return parser.getDocument(); } /** Parses the specified URI and returns the document. */ public Document parse(InputStream is) throws Exception { parser.parse(new InputSource(is)); return parser.getDocument(); } public void setFeature(String featureId, boolean state) throws SAXNotRecognizedException, SAXNotSupportedException { try { parser.setFeature(featureId, state); } catch (SAXException e) { prln("error in setting up parser feature"); } } /** Warning. */ public void warning(SAXParseException ex) { parseWarnings++; prln("[Warning] "+getLocationString(ex)+": "+ex.getMessage()); } /** Error. */ public void error(SAXParseException ex) { parseErrors++; prln("[Error] "+getLocationString(ex)+": "+ex.getMessage()); } /** Fatal error. */ public void fatalError(SAXParseException ex) throws SAXException { parseFatalErrors++; prln("[Fatal Error] "+getLocationString(ex)+": "+ex.getMessage()); throw ex; } /** Returns a string of the location. */ private String getLocationString(SAXParseException ex) { StringBuffer str = new StringBuffer(); String systemId = ex.getSystemId(); if(systemId != null) { int index = systemId.lastIndexOf('/'); if (index != -1) systemId = systemId.substring(index + 1); str.append(systemId); } str.append(':'); str.append(ex.getLineNumber()); str.append(':'); str.append(ex.getColumnNumber()); return str.toString(); } } } /* * Changes in file: * * $Log: OGCCapabilities.java,v $ * Revision 1.15 2002/01/31 10:16:58 ianturton * initial changes to support new format xml capabilities files now look like * * * * * * * - at present getFormats just returns jpeg all the time since my mastery of * dom parsers failed. * * Revision 1.14 2001/12/20 15:27:23 ianturton * various fixes and small mods to make WMSExample actually run. Can now * display an image if you remember to choose gif or jpg as output. Still * crashes if you zoom in. * * Revision 1.13 2001/11/19 10:03:33 kobit * *** empty log message *** * * Revision 1.12 2001/11/18 15:57:54 kobit * Use of simple-jprotocols package instead of java.net, DTD validating switched OFF, default version if WMS implementation is set to 1.0.0 * * Revision 1.11 2001/10/24 09:41:51 kobit * Uncommented code commented by camerons for parsing capabilities file - extracting service formats * * */