001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.catalog.wfs;
017:
018: import org.geotools.catalog.AbstractService;
019: import org.geotools.catalog.Catalog;
020: import org.geotools.catalog.ResolveChangeEvent;
021: import org.geotools.catalog.ResolveDelta;
022: import org.geotools.catalog.ServiceInfo;
023: import org.geotools.catalog.defaults.DefaultResolveChangeEvent;
024: import org.geotools.catalog.defaults.DefaultResolveDelta;
025: import org.geotools.catalog.defaults.DefaultServiceInfo;
026: import org.geotools.data.DataStore;
027: import org.geotools.data.ows.WFSCapabilities;
028: import org.geotools.data.wfs.WFSDataStore;
029: import org.geotools.data.wfs.WFSDataStoreFactory;
030: import org.geotools.util.ProgressListener;
031: import org.geotools.xml.wfs.WFSSchema;
032: import org.xml.sax.SAXException;
033: import java.io.IOException;
034: import java.net.URI;
035: import java.net.URL;
036: import java.util.LinkedList;
037: import java.util.List;
038: import java.util.Map;
039: import javax.swing.Icon;
040:
041: /**
042: * Handle for a WFS service.
043: *
044: * @since 0.6
045: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/plugin/wfs/src/main/java/org/geotools/catalog/wfs/WFSService.java $
046: */
047: public class WFSService extends AbstractService {
048: private URI uri = null;
049: private Map params = null;
050: private List members = null;
051: private ServiceInfo info = null;
052: private Throwable msg = null;
053: private MyWFSDataStore ds = null;
054:
055: public WFSService(Catalog parent, URI uri, Map params) {
056: super (parent);
057:
058: this .uri = uri;
059: this .params = params;
060: }
061:
062: /*
063: * Required adaptions:
064: * <ul>
065: * <li>IServiceInfo.class
066: * <li>List.class <IGeoResource>
067: * </ul>
068: */
069: public Object resolve(Class adaptee, ProgressListener monitor)
070: throws IOException {
071: if (adaptee == null) {
072: return null;
073: }
074:
075: if (adaptee.isAssignableFrom(ServiceInfo.class)) {
076: return this .getInfo(monitor);
077: }
078:
079: if (adaptee.isAssignableFrom(List.class)) {
080: return this .members(monitor);
081: }
082:
083: if (adaptee.isAssignableFrom(WFSDataStore.class)) {
084: return getDS();
085: }
086:
087: return null;
088: }
089:
090: public boolean canResolve(Class adaptee) {
091: if (adaptee == null) {
092: return false;
093: }
094:
095: return (adaptee.isAssignableFrom(ServiceInfo.class)
096: || adaptee.isAssignableFrom(List.class) || adaptee
097: .isAssignableFrom(WFSDataStore.class));
098: }
099:
100: public List members(ProgressListener monitor) throws IOException {
101: if (members == null) {
102: synchronized (getDS()) {
103: if (members == null) {
104: members = new LinkedList();
105:
106: String[] typenames = ds.getTypeNames();
107:
108: if (typenames != null) {
109: for (int i = 0; i < typenames.length; i++) {
110: members.add(new WFSGeoResource(this ,
111: typenames[i]));
112: }
113: }
114: }
115: }
116: }
117:
118: return members;
119: }
120:
121: public ServiceInfo getInfo(ProgressListener monitor)
122: throws IOException {
123: getDS(); // load ds
124:
125: if ((info == null) && (ds != null)) {
126: synchronized (ds) {
127: if (info == null) {
128: info = new IServiceWFSInfo(ds);
129: }
130: }
131:
132: Catalog parent = (Catalog) parent(monitor);
133:
134: if (parent != null) {
135: ResolveDelta delta = new DefaultResolveDelta(this ,
136: ResolveDelta.Kind.CHANGED);
137: ResolveChangeEvent event = new DefaultResolveChangeEvent(
138: this , ResolveChangeEvent.Type.POST_CHANGE,
139: delta);
140: parent.fire(event);
141: }
142: }
143:
144: return info;
145: }
146:
147: /*
148: * @see net.refractions.udig.catalog.IService#getConnectionParams()
149: */
150: public Map getConnectionParams() {
151: return params;
152: }
153:
154: MyWFSDataStore getDS() throws IOException {
155: if (ds == null) {
156: synchronized (MyWFSDataStore.class) {
157: if (ds == null) {
158: WFSDataStoreFactory dsf = new MyWFSDataStoreFactory();
159:
160: if (dsf.canProcess(params)) {
161: try {
162: ds = (MyWFSDataStore) dsf
163: .createDataStore(params);
164: } catch (IOException e) {
165: msg = e;
166: throw e;
167: }
168: }
169: }
170: }
171:
172: Catalog parent = (Catalog) parent(null);
173:
174: if (parent != null) {
175: ResolveDelta delta = new DefaultResolveDelta(this ,
176: ResolveDelta.Kind.CHANGED);
177: ResolveChangeEvent event = new DefaultResolveChangeEvent(
178: this , ResolveChangeEvent.Type.POST_CHANGE,
179: delta);
180:
181: parent.fire(event);
182: }
183: }
184:
185: return ds;
186: }
187:
188: /*
189: * @see net.refractions.udig.catalog.IResolve#getStatus()
190: */
191: public Status getStatus() {
192: return (msg != null) ? Status.BROKEN
193: : ((ds == null) ? Status.NOTCONNECTED
194: : Status.CONNECTED);
195: }
196:
197: /*
198: * @see net.refractions.udig.catalog.IResolve#getMessage()
199: */
200: public Throwable getMessage() {
201: return msg;
202: }
203:
204: /*
205: * @see net.refractions.udig.catalog.IResolve#getIdentifier()
206: */
207: public URI getIdentifier() {
208: return uri;
209: }
210:
211: private static class MyWFSDataStoreFactory extends
212: WFSDataStoreFactory {
213: public DataStore createNewDataStore(Map params)
214: throws IOException {
215: URL host = (URL) URL.lookUp(params);
216:
217: Boolean protocol = (Boolean) PROTOCOL.lookUp(params);
218:
219: String user;
220: String pass;
221: user = pass = null;
222:
223: int timeout = 3000;
224: int buffer = 10;
225: boolean tryGZIP = true;
226:
227: if (params.containsKey(TIMEOUT.key)) {
228: Integer i = (Integer) TIMEOUT.lookUp(params);
229:
230: if (i != null) {
231: timeout = i.intValue();
232: }
233: }
234:
235: if (params.containsKey(BUFFER_SIZE.key)) {
236: Integer i = (Integer) BUFFER_SIZE.lookUp(params);
237:
238: if (i != null) {
239: buffer = i.intValue();
240: }
241: }
242:
243: if (params.containsKey(TRY_GZIP.key)) {
244: Boolean b = (Boolean) TRY_GZIP.lookUp(params);
245: if (b != null)
246: tryGZIP = b.booleanValue();
247: }
248:
249: if (params.containsKey(USERNAME.key)) {
250: user = (String) USERNAME.lookUp(params);
251: }
252:
253: if (params.containsKey(PASSWORD.key)) {
254: pass = (String) PASSWORD.lookUp(params);
255: }
256:
257: if (((user == null) && (pass != null))
258: || ((pass == null) && (user != null))) {
259: throw new IOException(
260: "Username / password cannot be null");
261: }
262:
263: DataStore ds = null;
264:
265: try {
266: ds = new MyWFSDataStore(host, protocol, user, pass,
267: timeout, buffer, tryGZIP);
268: cache.put(params, ds);
269: } catch (SAXException e) {
270: throw new RuntimeException(e);
271: }
272:
273: return ds;
274: }
275: }
276:
277: static class MyWFSDataStore extends WFSDataStore {
278: MyWFSDataStore(URL host, Boolean protocol, String username,
279: String password, int timeout, int buffer,
280: boolean tryGZIP) throws SAXException, IOException {
281: super (host, protocol, username, password, timeout, buffer,
282: tryGZIP);
283: }
284:
285: public WFSCapabilities getCapabilities() {
286: return capabilities;
287: }
288:
289: protected static URL createGetCapabilitiesRequest(URL host) {
290: return WFSDataStore.createGetCapabilitiesRequest(host);
291: }
292: }
293:
294: private class IServiceWFSInfo extends DefaultServiceInfo {
295: private WFSCapabilities caps = null;
296:
297: IServiceWFSInfo(MyWFSDataStore resource) {
298: super ();
299:
300: try {
301: caps = resource.getCapabilities();
302: } catch (Throwable t) {
303: t.printStackTrace();
304: caps = null;
305: }
306: }
307:
308: /*
309: * @see net.refractions.udig.catalog.IServiceInfo#getAbstract()
310: */
311: public String getAbstract() {
312: return (caps == null) ? null
313: : ((caps.getService() == null) ? null : caps
314: .getService().get_abstract());
315: }
316:
317: /*
318: * @see net.refractions.udig.catalog.IServiceInfo#getIcon()
319: */
320: public Icon getIcon() {
321: //TODO: get an icon
322: return null;
323: }
324:
325: /*
326: * @see net.refractions.udig.catalog.IServiceInfo#getKeywords()
327: */
328: public String[] getKeywords() {
329: return (caps == null) ? null
330: : ((caps.getService() == null) ? null : caps
331: .getService().getKeywordList());
332: }
333:
334: /*
335: * @see net.refractions.udig.catalog.IServiceInfo#getSchema()
336: */
337: public URI getSchema() {
338: return WFSSchema.NAMESPACE;
339: }
340:
341: public String getDescription() {
342: return getIdentifier().toString();
343: }
344:
345: public URI getSource() {
346: return getIdentifier();
347: }
348:
349: public String getTitle() {
350: return ((caps == null) || (caps.getService() == null)) ? ((getIdentifier() == null) ? "BROKEN"
351: : getIdentifier().toString())
352: : caps.getService().getTitle();
353: }
354: }
355: }
|