001: /*
002: * uDig - User Friendly Desktop Internet GIS client
003: * http://udig.refractions.net
004: * (C) 2004, Refractions Research Inc.
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;
009: * version 2.1 of the License.
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: */
017: package net.refractions.udig.catalog.google;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.net.MalformedURLException;
022: import java.net.URL;
023: import java.net.URLConnection;
024: import java.net.URLEncoder;
025: import java.util.ArrayList;
026: import java.util.LinkedList;
027: import java.util.List;
028: import java.util.zip.GZIPInputStream;
029:
030: import net.refractions.udig.catalog.CatalogPlugin;
031: import net.refractions.udig.catalog.ICatalog;
032: import net.refractions.udig.catalog.ICatalogInfo;
033: import net.refractions.udig.catalog.IGeoResource;
034: import net.refractions.udig.catalog.IResolve;
035: import net.refractions.udig.catalog.IResolveChangeEvent;
036: import net.refractions.udig.catalog.IResolveChangeListener;
037: import net.refractions.udig.catalog.IService;
038: import net.refractions.udig.catalog.google.internal.Messages;
039:
040: import org.eclipse.core.runtime.IProgressMonitor;
041: import org.eclipse.jface.util.ListenerList;
042: import org.jdom.Document;
043: import org.jdom.Element;
044: import org.jdom.JDOMException;
045: import org.jdom.input.SAXBuilder;
046:
047: import com.vividsolutions.jts.geom.Envelope;
048:
049: public class GoogleCatalog extends ICatalog {
050:
051: private Throwable msg;
052: URL url = null;
053:
054: /**
055: * Construct <code>GoogleCatalog</code>.
056: *
057: */
058: public GoogleCatalog() {
059: catalogListeners = new ListenerList();
060: try {
061: url = new URL(
062: "http://udig.refractions.net/search/google-xml.php?"); //$NON-NLS-1$
063: } catch (MalformedURLException e) {
064: msg = e;
065: GooglePlugin.log(null, e);
066: }
067: }
068:
069: private ListenerList catalogListeners;
070:
071: /*
072: * @see net.refractions.udig.catalog.ICatalog#add(net.refractions.udig.catalog.IService)
073: */
074: public void add(IService service)
075: throws UnsupportedOperationException {
076: throw new UnsupportedOperationException();
077: }
078:
079: /*
080: * @see net.refractions.udig.catalog.ICatalog#remove(net.refractions.udig.catalog.IService)
081: */
082: public void remove(IService service)
083: throws UnsupportedOperationException {
084: throw new UnsupportedOperationException();
085: }
086:
087: /*
088: * @see net.refractions.udig.catalog.ICatalog#replace(java.net.URL, net.refractions.udig.catalog.IService)
089: */
090: public void replace(URL id, IService service)
091: throws UnsupportedOperationException {
092: throw new UnsupportedOperationException();
093: }
094:
095: /*
096: * Required adaptions:
097: * <ul>
098: * <li>ICatalogInfo.class
099: * <li>List.class <IService>
100: * </ul>
101: * @see net.reurl.fractions.udig.catalog.IResolve#resolve(java.lang.Class, org.eclipse.core.runtime.IProgressMonitor)
102: */
103: public <T> T resolve(Class<T> adaptee, IProgressMonitor monitor)
104: throws IOException {
105: if (adaptee == null)
106: return null;
107: if (adaptee.isAssignableFrom(ICatalogInfo.class)) {
108: return adaptee.cast(getInfo(monitor));
109: }
110: if (adaptee.isAssignableFrom(List.class)) {
111: return adaptee.cast(members(monitor));
112: }
113: return null;
114: }
115:
116: private ICatalogInfo info = null;
117:
118: /*
119: * @see net.refractions.udig.catalog.ICatalog#getInfo(org.eclipse.core.runtime.IProgressMonitor)
120: */
121: public ICatalogInfo getInfo(IProgressMonitor monitor) {
122: if (info != null) {
123: info = new GoogleICatalogInfo();
124: }
125: return info;
126: }
127:
128: private class GoogleICatalogInfo extends ICatalogInfo {
129: GoogleICatalogInfo() {
130: this .title = Messages.GoogleCatalog_title;
131: this .description = Messages.GoogleCatalog_description;
132: this .source = url;
133: this .keywords = new String[] {
134: "Catalog", "Google", "Refractions Research", "Search" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
135: }
136: }
137:
138: /*
139: * @see net.refractions.udig.catalog.ICatalog#find(java.net.URL)
140: */
141: public List<IResolve> find(URL id, IProgressMonitor monitor) {
142: return new LinkedList<IResolve>();
143: }
144:
145: /*
146: * hits the server using soap ...
147: *
148: * @see net.refractions.udig.catalog.ICatalog#search(java.lang.String, com.vividsolutions.jts.geom.Envelope, org.eclipse.core.runtime.IProgressMonitor)
149: */
150: public List<IResolve> search(String pattern, Envelope bbox,
151: IProgressMonitor monitor) throws IOException {
152:
153: monitor.beginTask(Messages.GoogleCatalog_searchMessage
154: + pattern, IProgressMonitor.UNKNOWN);
155:
156: List<IResolve> results = new ArrayList<IResolve>();
157:
158: if (bbox == null || bbox.isNull()) {
159: bbox = new Envelope(-180, 180, -90, 90);
160: }
161:
162: double xmin = bbox.getMinX();
163: double xmax = bbox.getMaxX();
164:
165: double ymin = bbox.getMinY();
166: double ymax = bbox.getMaxY();
167:
168: //keywords=bird&xmin=-180&ymin=-90&xmax=180&ymax=90
169: String urlString = url.toExternalForm();
170:
171: urlString = urlString
172: .concat("keywords=" + URLEncoder.encode(pattern, "UTF-8")); //$NON-NLS-1$ //$NON-NLS-2$
173: urlString = urlString
174: .concat("&xmin=" + xmin + "&ymin=" + ymin + "&xmax=" + xmax + "&ymax=" + ymax); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
175:
176: if (monitor.isCanceled()) {
177: return results;
178: }
179:
180: URL finalURL = new URL(urlString);
181:
182: URLConnection connection = finalURL.openConnection();
183:
184: connection.addRequestProperty("Accept-Encoding", "gzip"); //$NON-NLS-1$ //$NON-NLS-2$
185:
186: InputStream inputStream = connection.getInputStream();
187:
188: if (connection.getContentEncoding() != null
189: && connection.getContentEncoding().indexOf("gzip") != -1) { //$NON-NLS-1$
190: inputStream = new GZIPInputStream(inputStream);
191: }
192:
193: SAXBuilder builder = new SAXBuilder(false);
194: Document document = null;
195:
196: if (monitor.isCanceled()) {
197: return results;
198: }
199:
200: try {
201: document = builder.build(inputStream);
202: } catch (JDOMException e) {
203: throw (IOException) new IOException(
204: Messages.GoogleCatalog_parseError).initCause(e);
205: }
206:
207: if (monitor.isCanceled()) {
208: return results;
209: }
210:
211: for (Object object : document.getRootElement().getChildren("r")) { //$NON-NLS-1$
212:
213: if (monitor.isCanceled()) {
214: return results;
215: }
216:
217: Element rElement = (Element) object;
218:
219: String name = rElement.getChildText("name"); //$NON-NLS-1$
220: String title = rElement.getChildText("title"); //$NON-NLS-1$
221: String description = rElement.getChildText("description"); //$NON-NLS-1$
222: URL onlineResource = new URL(rElement
223: .getChildText("onlineresource")); //$NON-NLS-1$
224: String serverType = rElement.getChildText("servertype"); //$NON-NLS-1$
225: String serverVersion = rElement
226: .getChildText("serverversion"); //$NON-NLS-1$
227: URL id = new URL(rElement.getChildText("id")); //$NON-NLS-1$
228:
229: OGCLayer layer = new OGCLayer(name, title, description,
230: onlineResource, serverType, serverVersion, id);
231:
232: results.add(GoogleResource.getResource(layer));
233: }
234:
235: return results;
236: }
237:
238: /*
239: * @see net.refractions.udig.catalog.IResolve#canResolve(java.lang.Class)
240: */
241: public <T> boolean canResolve(Class<T> adaptee) {
242: return adaptee != null
243: && (adaptee.isAssignableFrom(ICatalogInfo.class) || adaptee
244: .isAssignableFrom(List.class));
245: }
246:
247: /*
248: * @see net.refractions.udig.catalog.IResolve#members(org.eclipse.core.runtime.IProgressMonitor)
249: */
250: public List<? extends IResolve> members(IProgressMonitor monitor)
251: throws IOException {
252: return search("", new Envelope(), monitor); //$NON-NLS-1$
253: }
254:
255: /*
256: * @see net.refractions.udig.catalog.IResolve#getStatus()
257: */
258: public Status getStatus() {
259: return msg == null ? Status.CONNECTED : Status.BROKEN;
260: }
261:
262: /*
263: * @see net.refractions.udig.catalog.IResolve#getMessage()
264: */
265: public Throwable getMessage() {
266: return msg;
267: }
268:
269: /*
270: * @see net.refractions.udig.catalog.IResolve#getIdentifier()
271: */
272: public URL getIdentifier() {
273: return url;
274: }
275:
276: void fire(IResolveChangeEvent event) {
277: Object[] listeners = catalogListeners.getListeners();
278: if (listeners.length == 0)
279: return;
280:
281: for (int i = 0; i < listeners.length; ++i) {
282: try {
283: ((IResolveChangeListener) listeners[i]).changed(event);
284: } catch (Throwable die) {
285: CatalogPlugin.log(null, new Exception(die));
286: }
287: }
288: }
289:
290: /**
291: *
292: * @see net.refractions.udig.catalog.ICatalog#addCatalogListener(net.refractions.udig.catalog.ICatalog.ICatalogListener)
293: * @param listener
294: */
295: public void addCatalogListener(IResolveChangeListener listener) {
296: catalogListeners.add(listener);
297: }
298:
299: /**
300: *
301: * @see net.refractions.udig.catalog.ICatalog#removeCatalogListener(net.refractions.udig.catalog.ICatalog.ICatalogListener)
302: * @param listener
303: */
304: public void removeCatalogListener(IResolveChangeListener listener) {
305: catalogListeners.remove(listener);
306: }
307:
308: @Override
309: public List<IService> findService(URL query) {
310: //This is special.
311: return new ArrayList<IService>();
312: }
313:
314: @Override
315: public <T extends IResolve> T getById(Class<T> type, URL id,
316: IProgressMonitor monitor) {
317: return null;
318: }
319:
320: @Override
321: public IGeoResource createTemporaryResource(Object descriptor)
322: throws IllegalArgumentException {
323: throw new IllegalArgumentException(
324: "This catalog does not create Temporary Resources"); //$NON-NLS-1$
325: }
326:
327: @Override
328: public String[] getTemporaryDescriptorClasses() {
329: return new String[0];
330: }
331:
332: @Override
333: public void dispose(IProgressMonitor monitor) {
334: // do nothing
335: catalogListeners.clear();
336: }
337: }
|