View Javadoc

1   /*
2    * Copyright 1999,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.feedparser.network;
18  
19  import java.net.URL;
20  import java.util.ArrayList;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  
24  import org.apache.log4j.Logger;
25  
26  /**
27   * Get a ResourceRequest for a given URL.  The request is handled based on the
28   * URL.
29   *
30   * @author <a href="mailto:burton@openprivacy.org">Kevin A. Burton</a>
31   * @version $Id: ResourceRequestFactory.java 373622 2006-01-30 22:53:00Z mvdb $
32   */
33  public class ResourceRequestFactory {
34  
35      private static Logger log = Logger.getLogger( ResourceRequestFactory.class.getName() );
36  
37      /**
38       * Specified in java.security to indicate the caching policy for successful
39       * name lookups from the name service.. The value is specified as as integer
40       * to indicate the number of seconds to cache the successful lookup.
41       * 
42       *
43       * sun.net.inetaddr.ttl:
44       * 
45       * This is a sun private system property which corresponds to
46       * networkaddress.cache.ttl. It takes the same value and has the same meaning,
47       * but can be set as a command-line option. However, the preferred way is to
48       * use the security property mentioned above.
49       * 
50       * A value of -1 indicates "cache forever".
51       */
52      public static int NETWORKADDRESS_CACHE_TTL = 5 * 60;
53      
54      /**
55       * These properties specify the default connect and read timeout (resp.) for
56       * the protocol handler used by java.net.URLConnection.
57       * 
58       * sun.net.client.defaultConnectTimeout specifies the timeout (in
59       * milliseconds) to establish the connection to the host. For example for
60       * http connections it is the timeout when establishing the connection to
61       * the http server. For ftp connection it is the timeout when establishing
62       * the connection to ftp servers.
63       * 
64       * sun.net.client.defaultReadTimeout specifies the timeout (in milliseconds)
65       * when reading from input stream when a connection is established to a
66       * resource.
67       */
68      public static int DEFAULT_CONNECT_TIMEOUT = 1 * 60 * 1000;
69  
70      public static int DEFAULT_READ_TIMEOUT = DEFAULT_CONNECT_TIMEOUT;
71  
72      /**
73       * Specify the maximum number of redirects to use.
74       */
75      public static int DEFAULT_MAX_REDIRECTS = 5;
76  
77      //FIXME: (should this be a linked list?)
78      private static ArrayList listeners = new ArrayList( 30 );
79  
80      private static HashMap schemeMap = null;
81  
82      private static boolean transparentHTCacheEnabled = false;
83  
84      /**
85       * When offline we either throw an exception or return content from the
86       * cache directly.  This can be used to run code that does not depend on the
87       * network.
88       */
89      private static boolean offline = false;
90  
91      public static ResourceRequest getResourceRequest( String resource,
92                                                        long ifModifiedSince ) throws NetworkException {
93  
94          return getResourceRequest( resource, ifModifiedSince, null );
95          
96      }
97  
98      /**
99       * Get a ResourceRequest for the protocol represented in the resource URL.
100      * It is important that we use a ResourceRequest implementation that supports
101      * fetching the URL.
102      *
103      * 
104      */
105     public static ResourceRequest getResourceRequest( String resource,
106                                                       long ifModifiedSince,
107                                                       String etag ) throws NetworkException {
108 
109         //log.debug( resource );
110         
111         //make sure we are initialized correctly.
112         ResourceRequestFactory.init();
113 
114         //make sure we have an index..
115 
116         int schemeIndex = resource.indexOf( ":" );
117 
118         if ( schemeIndex == -1 )
119             throw new NetworkException( "Unknown scheme: '" + resource + "'" );
120 
121         String scheme = resource.substring( 0, schemeIndex );
122 
123         if ( scheme == null || scheme.equals( "" ) )
124             throw new MalformedResourceException( "Not supported: " + resource );
125 
126         Class clazz = (Class)schemeMap.get( scheme );
127 
128         if ( clazz == null ) {
129             throw new MalformedResourceException( "Scheme not supported: " + scheme );
130         } 
131 
132         try { 
133             
134             ResourceRequest request = (ResourceRequest)clazz.newInstance();
135 
136             request.setResource( resource );
137 
138             //setup resource request options.
139             request.setIfModifiedSince( ifModifiedSince );
140 
141             //set the etag... when its null nothing will happen
142             request.setEtag( etag );
143             
144             request.init();
145 
146             return request;
147 
148         } catch ( Throwable t ) {
149             throw new NetworkException( t );
150         }
151 
152     }
153 
154     /**
155      * 
156      * @see #getResourceRequest( String )
157      * 
158      */
159     public static ResourceRequest getResourceRequest( String resource ) throws NetworkException {
160         return getResourceRequest( resource, -1 );
161     }
162     
163     /**
164      * 
165      * @see #getResourceRequest( String )
166      * 
167      */
168     public static ResourceRequest getResourceRequest( URL resource ) throws NetworkException {
169         return getResourceRequest( resource.toString() );
170     }
171 
172     /**
173      * Add an event listener to this instance of the factory.  This provides a
174      * mechanism to give default listeners to each new ResourceRequest.
175      *
176      * 
177      */
178     public static void addEventListener( NetworkEventListener listener ) {
179 
180         listeners.add( listener );
181 
182     }
183 
184     /**
185      * Get all event listeners.
186      *
187      * 
188      */
189     public static Iterator getNetworkEventListeners() {
190 
191         return listeners.iterator();
192         
193     }
194     
195     /**
196      * Make sure the factory is initialized.  Called once per JVM instance.
197      *
198      * 
199      */
200     private synchronized static void init() {
201 
202         //set the authenticator to use
203 
204         //FIXME: remove this until we figure out how to do proxy authentication.
205         //java.net.Authenticator.setDefault ( new Authenticator() );
206 
207         // A full list of properties is available here:
208 
209         // http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
210 
211         System.setProperty( "sun.net.inetaddr.ttl",
212                             Integer.toString( NETWORKADDRESS_CACHE_TTL ) );
213 
214         System.setProperty( "networkaddress.cache.ttl",
215                             Integer.toString( NETWORKADDRESS_CACHE_TTL ) );
216 
217         System.setProperty( "sun.net.client.defaultReadTimeout",
218                             Integer.toString( DEFAULT_READ_TIMEOUT ) );
219 
220         System.setProperty( "sun.net.client.defaultConnectTimeout",
221                             Integer.toString( DEFAULT_CONNECT_TIMEOUT ) );
222 
223         System.setProperty( "http.maxRedirects",
224                             Integer.toString( DEFAULT_MAX_REDIRECTS ) );
225 
226         if ( schemeMap == null ) {
227             
228             schemeMap = new HashMap();
229             
230             schemeMap.put( "file", URLResourceRequest.class );
231             schemeMap.put( "http", URLResourceRequest.class );
232             schemeMap.put( "https", URLResourceRequest.class );
233             schemeMap.put( BlockingResourceRequest.SCHEME, BlockingResourceRequest.class );
234             
235         }
236 
237     }
238 
239     /**
240      * Return true if we support fetching content with the given scheme.
241      * Examples would be "http" and "file"
242      *
243      * 
244      */
245     public static boolean isSupportedScheme( String scheme ) {
246 
247         return schemeMap.get( scheme ) != null;
248         
249     }
250     
251     /**
252      * When the transparent HTCache is enabled we will keep content local
253      * similar to the Mozilla cache and return the cached copy and use
254      * if-Modified-Since when necessary.
255      *
256      * 
257      */
258     public static void setTransparentHTCacheEnabled( boolean enabled ) {
259         transparentHTCacheEnabled = enabled;
260     }
261 
262     /**
263      * Return true if we can enable the htcache.
264      *
265      * 
266      */
267     public static boolean isTransparentHTCacheEnabled() {
268         return transparentHTCacheEnabled;
269     }
270 
271     /**
272      * Enable/disable offline operation.
273      *
274      * 
275      */
276     public static void setOffline( boolean offline ) {
277         ResourceRequestFactory.offline = offline;
278     }
279 
280     /**
281      * 
282      *
283      * 
284      */
285     public static boolean isOffline() {
286         return offline;
287     }
288 
289 }