001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2006, Institut de Recherche pour le Développement
006: * (C) 2006, Geomatys
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Lesser General Public
010: * License as published by the Free Software Foundation;
011: * version 2.1 of the License.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Lesser General Public License for more details.
017: */
018: package org.geotools.image.io.stream;
019:
020: // J2SE dependencies
021: import java.util.Locale;
022: import java.io.File;
023: import java.io.InputStream;
024: import java.io.IOException; //import java.net.Proxy;
025: import java.net.URL;
026: import java.net.URLConnection;
027: import java.net.SocketException;
028: import java.net.InetSocketAddress;
029: import javax.imageio.spi.ImageInputStreamSpi;
030: import javax.imageio.stream.ImageInputStream;
031: import javax.imageio.stream.FileCacheImageInputStream;
032:
033: import org.geotools.util.logging.Logging;
034:
035: /**
036: * A service provider for {@link ImageInputStream} from {@link URL} connection.
037: *
038: * @since 2.4
039: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/coverageio/src/main/java/org/geotools/image/io/stream/UrlInputSpi.java $
040: * @version $Id: UrlInputSpi.java 27862 2007-11-12 19:51:19Z desruisseaux $
041: * @author Martin Desruisseaux
042: */
043: public class UrlInputSpi extends ImageInputStreamSpi {
044: /**
045: * Maximum number of retries when a connection failed.
046: */
047: private static final int RETRY = 3;
048:
049: /**
050: * The proxy.
051: *
052: * @todo Uncomment when we will be allowed to compile for J2SE 1.5.
053: */
054: // private final Proxy proxy;
055: /**
056: * Creates a new instance with no proxy.
057: *
058: * @todo Uncomment when we will be allowed to compile for J2SE 1.5.
059: */
060: // public UrlInputSpi() {
061: // this(Proxy.NO_PROXY);
062: // }
063: //
064: // /**
065: // * Creates a new instance with the specified proxy.
066: // */
067: public UrlInputSpi(/*final Proxy proxy*/) {
068: super ("Geotools", "2.4", URL.class);
069: // this.proxy = proxy;
070: }
071:
072: /**
073: * Returns a brief, human-readable description of this service
074: * provider and its associated implementation.
075: */
076: public String getDescription(final Locale locale) {
077: return "Stream from a URL."; // TODO: localize
078: }
079:
080: /**
081: * Returns {@code true} since the input stream requires the use of a cache file.
082: */
083: //@Override
084: public boolean needsCacheFile() {
085: return true;
086: }
087:
088: /**
089: * Constructs an input stream for an URL.
090: */
091: public ImageInputStream createInputStreamInstance(
092: final Object input, final boolean useCache,
093: final File cacheDir) throws IOException {
094: final URL url = (URL) input;
095: final URLConnection connection = url.openConnection(/*proxy*/); // TODO: uncomment with J2SE 1.5.
096: int retry = RETRY;
097: InputStream stream;
098: while (true) {
099: try {
100: stream = connection.getInputStream();
101: break;
102: } catch (SocketException exception) {
103: if (--retry < 0) {
104: throw exception;
105: }
106: Logging.getLogger("org.geotools.image.io.stream")
107: .warning(exception.toString());
108: }
109: /*
110: * Failed to get the connection. After we logged a warning, wait a little bit, run
111: * the finalization and try again. Experience suggests that running the finalizers
112: * sometime help, but also sometime freeze the system. FinalizationStopper may help
113: * to unfreeze the system after a timeout.
114: */
115: try {
116: Thread.sleep(1000);
117: } catch (InterruptedException ignore) {
118: // Someone doesn't want to let us sleep. Go back to work...
119: }
120: System.gc();
121: Thread.interrupted(); // Clears the interrupted flag.
122: final FinalizationStopper stopper = new FinalizationStopper(
123: 4000);
124: System.runFinalization();
125: stopper.cancel();
126: // Thread.interrupted() must be first in order to clear the flag.
127: if (Thread.interrupted() || stopper.interrupted) {
128: Logging
129: .getLogger("org.geotools.image.io.stream")
130: .warning(
131: "System.runFinalization() was blocked.");
132: }
133: }
134: return new FileCacheImageInputStream(stream, cacheDir);
135: }
136: }
|