// *********************************************************************************** // $Source: /home/cvsroot/nodus/src/com/bbn/openmap/plugin/wms/NodusWMSPlugIn.java,v $ // $RCSfile: NodusWMSPlugIn.java,v $ // $Revision: 1.9 $ // $Date: 2004/12/08 15:42:45 $ // $Author: jourquin $ // *********************************************************************************** package com.bbn.openmap.plugin.wms; import java.beans.beancontext.*; import java.io.*; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import org.xml.sax.*; import org.xml.sax.helpers.*; import com.bbn.openmap.image.*; import com.bbn.openmap.proj.*; import com.bbn.openmap.util.*; import org.fucam.gtm.nodus.*; import com.bbn.openmap.plugin.wms.gui.*; /** * *

Title: Nodus 5.0

*

Description: The NodusWMSPlugin extends the original OpenMap's WMSPlugin. Its * main new feature is to allow the user to interactively select the layers to display in a list * obtained from the WMS server by means of a "getcapabilities".

* See the WMS specifications and the OpenMap documentation for more details. *

*

Copyright : Copyright (c) 2004

*

Société : FUCaM-GTM

* @author Bart Jourquin * @version 1.0 */ public class NodusWMSPlugIn extends WMSPlugIn implements ImageServerConstants, BeanContextMembershipListener, INodusConstants { private Properties properties; private String pathPrefix; /** * Intercepts the original setProperties() in order to have access to the properties to store * the available and selected WMS layers * @param prefix String * @param p Properties */ public void setProperties(String prefix, Properties p) { properties = p; this.pathPrefix = ""; if (prefix != null) { this.pathPrefix = prefix; // + "."; } super.setProperties(prefix,p); setAddToBeanContext(true); } /** * Asks the WMS server for a list of available layers. */ public void getCapabilities() { if (queryHeader == null) { return; } // Reset the list of available layers properties.setProperty(pathPrefix + PROP_AVAILABLE_LAYERS, ""); // Example : http://www.geographynetwork.com/servlet/com.esri.wms.Esrimap?&REQUEST=capabilities StringBuffer buf = new StringBuffer(queryHeader); buf.append("?" + "&REQUEST=capabilities"); java.net.URL url = null; try { url = new java.net.URL(buf.toString()); java.net.HttpURLConnection urlc = (java.net.HttpURLConnection)url.openConnection(); if (Debug.debugging("plugin")) { Debug.output("url content type: "+ urlc.getContentType()); } if (urlc == null || urlc.getContentType() == null) { if (layer != null) { layer.fireRequestMessage(getName() + ": unable to connect to " + getServerName()); } else { Debug.error(getName() + ": unable to connect to " + getServerName()); } } // WMS standard states that the return must be an XML file (test) if (urlc.getContentType().indexOf("xml") != -1) { try { InputStreamReader isr = new InputStreamReader(urlc.getInputStream()); XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser"); WmsXmlParser h = new WmsXmlParser(pathPrefix, properties); parser.setContentHandler(h); parser.parse(new InputSource(isr)); return; } catch(IOException ioe) { ioe.printStackTrace(); } catch(SAXException saxe) { saxe.printStackTrace(); } } } catch (java.net.MalformedURLException murle) { Debug.error("NodusWMSPlugin: URL \"" + buf.toString() + "\" is malformed."); } catch (java.io.IOException ioe) { JOptionPane.showMessageDialog(null, getName() + ":\n\n Couldn't connect to " + getServerName(), "Connection Problem", JOptionPane.INFORMATION_MESSAGE); } // Not found... return; } /** * Adds a "Choose layers" button to the original OpenMap's WMSPlugin's getGUI() * @return Component */ public java.awt.Component getGUI() { final JPanel panel = (JPanel) super.getGUI(); Component p = getComponent().getParent(); // Add a new button to existant panel JButton layersButton = new JButton("Choose layers"); if (layer != null) { layersButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { // Fetch layers on server Cursor oldCursor = panel.getCursor(); panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); getCapabilities(); panel.setCursor(oldCursor); WMSLayersChooserDlg wmsLayersChooserDlg = new WMSLayersChooserDlg(null, pathPrefix, properties); wmsLayersChooserDlg.setVisible(true); layers = properties.getProperty(pathPrefix + PROP_DOTLAYERS); } }); } panel.add(layersButton); return panel; } /** * Intercepts the original OpenMap's method in order only accept LLXY and CADRG projections * @param p Projection * @return String */ public String createQueryString(Projection p) { String s = super.createQueryString(p); if (p instanceof LLXY || p instanceof CADRG) { return s.replaceAll("SRS=EPSG:4326", "CRS=CRS:84"); } if (p instanceof Mercator) { return s.replaceAll("SRS=EPSG:4326", "CRS=AUTO2:42001"); } if (p instanceof Orthographic) { return s.replaceAll("SRS=EPSG:4326", "CRS=AUTO2:42003"); } System.out.println("WMS queries doesn't support Gnomonic projections"); return null; } /** * BeanContextMembershipListener method. Called when a new object * is added to the BeanContext of this object. * @param bcme BeanContextMembershipEvent */ public void childrenAdded(BeanContextMembershipEvent bcme) { findAndInit(bcme.iterator()); } /** * BeanContextMembershipListener method. Called when a new object * is removed from the BeanContext of this object. For the Layer, * this method doesn't do anything. If your layer does something * with the childrenAdded method, or findAndInit, you should take * steps in this method to unhook the layer from the object used * in those methods. * * @param bcme BeanContextMembershipEvent */ public void childrenRemoved(BeanContextMembershipEvent bcme) { Iterator it = bcme.iterator(); while (it.hasNext()) { findAndUndo(it.next()); } } /** * This is the method that your object can use to find other * objects within the MapHandler (BeanContext). This method gets * called when the object gets added to the MapHandler, or when * another object gets added to the MapHandler after the object is * a member. * * @param it Iterator to use to go through a list of objects. * Find the ones you need, and hook yourself up. */ public void findAndInit(Iterator it) { while (it.hasNext()) { findAndInit(it.next()); } } /** * The findAndInit method has been made non-abstract, because it * now calls this method for every object that is in the iterator * it receives. This lets subclasses call a method on super * classes so they can handle their needs as well. * * @param obj Object */ public void findAndInit(Object obj) {} /** * The childrenRemoved has been changed to go through its iterator * to call this method with every object. This lets subclasses * call this method on their super class, so it can handle what it * needs to with objects it may be interested in. * @param obj Object */ public void findAndUndo(Object obj) {} }