001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2006-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2005, Refractions Research Inc.
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.catalog.wms;
018:
019: import java.io.IOException;
020: import java.net.URI;
021: import java.net.URL;
022: import java.util.LinkedList;
023: import java.util.List;
024: import java.util.Map;
025:
026: import org.geotools.catalog.AbstractService;
027: import org.geotools.catalog.Catalog;
028: import org.geotools.catalog.ResolveChangeEvent;
029: import org.geotools.catalog.ResolveDelta;
030: import org.geotools.catalog.ServiceInfo;
031: import org.geotools.catalog.defaults.DefaultResolveChangeEvent;
032: import org.geotools.catalog.defaults.DefaultResolveDelta;
033: import org.geotools.catalog.defaults.DefaultServiceInfo;
034: import org.geotools.data.ows.GetCapabilitiesRequest;
035: import org.geotools.data.ows.GetCapabilitiesResponse;
036: import org.geotools.data.ows.Layer;
037: import org.geotools.data.ows.Specification;
038: import org.geotools.data.ows.WMSCapabilities;
039: import org.geotools.data.wms.WMS1_0_0;
040: import org.geotools.data.wms.WMS1_1_0;
041: import org.geotools.data.wms.WMS1_1_1;
042: import org.geotools.data.wms.WMSUtils;
043: import org.geotools.data.wms.WebMapServer;
044: import org.geotools.data.wms.request.GetFeatureInfoRequest;
045: import org.geotools.data.wms.request.GetMapRequest;
046: import org.geotools.data.wms.response.GetFeatureInfoResponse;
047: import org.geotools.data.wms.response.GetMapResponse;
048: import org.geotools.data.wms.xml.WMSSchema;
049: import org.geotools.ows.ServiceException;
050: import org.geotools.util.ProgressListener;
051: import org.xml.sax.SAXException;
052:
053: /**
054: * Connect to a WMS.
055: *
056: * @since 0.6
057: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/plugin/wms/src/main/java/org/geotools/catalog/wms/WMSService.java $
058: */
059: public class WMSService extends AbstractService {
060: /**
061: * <code>WMS_URL_KEY</code> field Magic param key for Catalog WMS
062: * persistence.
063: */
064: public static final String WMS_URL_KEY = "net.refractions.udig.catalog.internal.wms.WMSServiceImpl.WMS_URL_KEY"; //$NON-NLS-1$
065: public static final String WMS_WMS_KEY = "net.refractions.udig.catalog.internal.wms.WMSServiceImpl.WMS_WMS_KEY"; //$NON-NLS-1$
066: private Map params;
067: private Throwable error;
068: private URI uri;
069: private WebMapServer wms = null;
070: private WMSServiceInfo info;
071: private List members = null;
072:
073: /**
074: * Construct <code>WMSServiceImpl</code>.
075: *
076: * @param parent
077: * @param uri DOCUMENT ME!
078: * @param params
079: */
080: public WMSService(Catalog parent, URI uri, Map params) {
081: super (parent);
082: this .params = params;
083: this .uri = uri;
084:
085: if (params.containsKey(WMS_WMS_KEY)) {
086: Object obj = params.get(WMS_WMS_KEY);
087:
088: if (obj instanceof WebMapServer) {
089: this .wms = (WebMapServer) obj;
090: }
091: }
092: }
093:
094: public Status getStatus() {
095: return (error != null) ? Status.BROKEN
096: : ((wms == null) ? Status.NOTCONNECTED
097: : Status.CONNECTED);
098: }
099:
100: /**
101: * Aquire the actual geotools WebMapServer instance.
102: *
103: * <p>
104: * Note this method is blocking and throws an IOException to indicate such.
105: * </p>
106: *
107: * @param theUserIsWatching
108: *
109: * @return WebMapServer instance
110: *
111: * @throws IOException
112: */
113: protected WebMapServer getWMS(ProgressListener theUserIsWatching)
114: throws IOException {
115: if (wms == null) {
116: try {
117: URL url1 = (URL) getConnectionParams().get(WMS_URL_KEY);
118: wms = new CustomWMS(url1);
119: } catch (IOException persived) {
120: error = persived;
121: throw persived;
122: } catch (Throwable nak) {
123: IOException broken = new IOException(
124: "Could not connect to WMS. Possible reason: "
125: + nak.getLocalizedMessage());
126:
127: broken.initCause(nak);
128: error = broken;
129: throw broken;
130: }
131:
132: ResolveDelta delta = new DefaultResolveDelta(this ,
133: ResolveDelta.Kind.CHANGED);
134: parent(theUserIsWatching)
135: .fire(
136: new DefaultResolveChangeEvent(
137: this ,
138: ResolveChangeEvent.Type.POST_CHANGE,
139: delta));
140: }
141:
142: return wms;
143: }
144:
145: public ServiceInfo getInfo(ProgressListener monitor)
146: throws IOException {
147: if (info == null) {
148: synchronized (getWMS(monitor)) {
149: if (info == null) {
150: info = new WMSServiceInfo(monitor);
151:
152: ResolveDelta delta = new DefaultResolveDelta(this ,
153: ResolveDelta.Kind.CHANGED);
154: parent(monitor)
155: .fire(
156: new DefaultResolveChangeEvent(
157: this ,
158: ResolveChangeEvent.Type.POST_CHANGE,
159: delta));
160: }
161: }
162: }
163:
164: return info;
165: }
166:
167: /*
168: * @see net.refractions.udig.catalog.IService#resolve(java.lang.Class, org.eclipse.core.runtime.IProgressMonitor)
169: */
170: public Object resolve(Class adaptee, ProgressListener monitor)
171: throws IOException {
172: if (adaptee == null) {
173: return null;
174: }
175:
176: if (adaptee.isAssignableFrom(ServiceInfo.class)) {
177: return getInfo(monitor);
178: }
179:
180: if (adaptee.isAssignableFrom(List.class)) {
181: return members(monitor);
182: }
183:
184: if (adaptee.isAssignableFrom(WebMapServer.class)) {
185: return getWMS(monitor);
186: }
187:
188: return null;
189: }
190:
191: /**
192: * @see net.refractions.udig.catalog.IService#getConnectionParams()
193: */
194: public Map getConnectionParams() {
195: return params;
196: }
197:
198: /*
199: * @see net.refractions.udig.catalog.IResolve#canResolve(java.lang.Class)
200: */
201: public boolean canResolve(Class adaptee) {
202: if (adaptee == null) {
203: return false;
204: }
205:
206: if (adaptee.isAssignableFrom(WebMapServer.class)
207: || adaptee.isAssignableFrom(ServiceInfo.class)
208: || adaptee.isAssignableFrom(List.class)) {
209: return true;
210: }
211:
212: return false;
213: }
214:
215: /*
216: * @see net.refractions.udig.catalog.IResolve#members(org.eclipse.core.runtime.IProgressMonitor)
217: */
218: public List members(ProgressListener monitor) throws IOException {
219: if (members == null) {
220: synchronized (getWMS(monitor)) {
221: if (members == null) {
222: getWMS(monitor); // load ds
223: members = new LinkedList();
224:
225: Layer[] layers = WMSUtils.getNamedLayers(getWMS(
226: monitor).getCapabilities());
227:
228: /*
229: * Retrieved no layers from the WMS - something is wrong,
230: * either the WMS doesn't work, or it has no named layers.
231: */
232: if (layers != null) {
233: for (int i = 0; i < layers.length; i++) {
234: /*
235: * suppress layers that have children
236: * TODO some people might not like this behavior
237: * maybe we should make a preference for it.
238: * TODO should add hasChildren() to geotools
239: */
240: if (layers[i].getChildren().length == 0) {
241: Layer layer = layers[i];
242: members.add(new WMSGeoResource(this ,
243: layer));
244: }
245: }
246: }
247: }
248: }
249: }
250:
251: return members;
252: }
253:
254: /*
255: * @see net.refractions.udig.catalog.IResolve#getMessage()
256: */
257: public Throwable getMessage() {
258: return error;
259: }
260:
261: /*
262: * @see net.refractions.udig.catalog.IResolve#getIdentifier()
263: */
264: public URI getIdentifier() {
265: return uri;
266: }
267:
268: class WMSServiceInfo extends DefaultServiceInfo {
269: private WMSCapabilities caps = null;
270:
271: WMSServiceInfo(ProgressListener monitor) {
272: try {
273: caps = getWMS(monitor).getCapabilities();
274: } catch (Throwable t) {
275: t.printStackTrace();
276: caps = null;
277: }
278:
279: keywords = (caps == null) ? null
280: : ((caps.getService() == null) ? null : caps
281: .getService().getKeywordList());
282:
283: String[] t;
284:
285: if (keywords == null) {
286: t = new String[2];
287: } else {
288: t = new String[keywords.length + 2];
289: System.arraycopy(keywords, 0, t, 2, keywords.length);
290: }
291:
292: t[0] = "WMS"; //$NON-NLS-1$
293: t[1] = getIdentifier().toString();
294: keywords = t;
295: }
296:
297: public String getAbstract() {
298: return (caps == null) ? null
299: : ((caps.getService() == null) ? null : caps
300: .getService().get_abstract());
301: }
302:
303: public String getDescription() {
304: return getIdentifier().toString();
305: }
306:
307: public URI getSchema() {
308: return WMSSchema.NAMESPACE;
309: }
310:
311: public URI getSource() {
312: return getIdentifier();
313: }
314:
315: public String getTitle() {
316: return ((caps == null) || (caps.getService() == null)) ? ((getIdentifier() == null) ? "BROKEN" //$NON-NLS-1$
317: : getIdentifier().toString())
318: : caps.getService().getTitle();
319: }
320: }
321:
322: public class CustomWMS extends WebMapServer {
323: /**
324: * DOCUMENT ME!
325: *
326: * @param serverURL
327: *
328: * @throws IOException
329: * @throws ServiceException
330: * @throws SAXException
331: */
332: public CustomWMS(URL serverURL) throws IOException,
333: ServiceException, SAXException {
334: super (serverURL);
335:
336: if (getCapabilities() == null) {
337: throw new IOException(
338: "Unable to parse capabilities document."); //$NON-NLS-1$
339: }
340: }
341:
342: public GetCapabilitiesResponse issueRequest(
343: GetCapabilitiesRequest arg0) throws IOException,
344: ServiceException {
345: return super .issueRequest(arg0);
346: }
347:
348: public GetFeatureInfoResponse issueRequest(
349: GetFeatureInfoRequest arg0) throws IOException,
350: ServiceException {
351: return super .issueRequest(arg0);
352: }
353:
354: public GetMapResponse issueRequest(GetMapRequest arg0)
355: throws IOException, ServiceException {
356: return super .issueRequest(arg0);
357: }
358:
359: protected void setupSpecifications() {
360: specs = new Specification[3];
361: specs[0] = new WMS1_0_0();
362: specs[1] = new WMS1_1_0();
363: specs[2] = new WMS1_1_1();
364: }
365: }
366: }
|