001    /*
002     * Copyright 1999,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.feedparser.network;
018    
019    import java.io.ByteArrayInputStream;
020    import java.io.ByteArrayOutputStream;
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.OutputStream;
024    import java.net.HttpURLConnection;
025    import java.util.HashMap;
026    import java.util.Iterator;
027    
028    /**
029     * 
030     * @author <a href="mailto:burton@openprivacy.org">Kevin A. Burton</a>
031     * @version $Id: BaseResourceRequest.java 373622 2006-01-30 22:53:00Z mvdb $
032     */
033    public abstract class BaseResourceRequest implements ResourceRequest {
034    
035        public static boolean FOLLOW_REDIRECTS = true;
036        
037        private String resource = null;
038    
039        private DataEvent event = new DataEvent();
040    
041        private long _ifModifiedSince = -1;
042    
043        private long _responseCode = HttpURLConnection.HTTP_OK;
044    
045        private String _etag = null;
046        
047        private byte[] data = new byte[0];
048    
049        private boolean localCache = false;
050    
051        private boolean followRedirects = FOLLOW_REDIRECTS;
052    
053        /**
054         * A single resource request can now have a given event listener.
055         */
056        private NetworkEventListener eventListener = null;
057    
058        private HashMap requestHeaders = new HashMap();
059        
060        /**
061         * 
062         * Get the value of <code>resource</code>.
063         *
064         * 
065         */
066        public String getResource() { 
067            
068            return this.resource;
069            
070        }
071    
072        /**
073         * 
074         * Set the value of <code>resource</code>.
075         *
076         * 
077         */
078        public void setResource( String resource ) { 
079            
080            this.resource = resource;
081            
082        }
083    
084        /**
085         * Fire a new ArchiveEvent
086         *
087         * 
088         */
089        public void fireDataEvent( long count ) {
090    
091            event.count = count;
092            event.resource = resource;
093            
094            fireDataEvent( event );
095            
096        }
097    
098        public void fireInit() {
099    
100            DataEvent event = new DataEvent();
101            event.request = this;
102            
103            Iterator i = ResourceRequestFactory.getNetworkEventListeners();
104    
105            while ( i.hasNext() ) {
106                ((NetworkEventListener)i.next()).init( event );
107            } 
108    
109            if ( eventListener != null )
110                eventListener.init( event );
111        }
112    
113        /**
114         * Fire a new ArchiveEvent
115         *
116         * 
117         */
118        public void fireDataEvent( DataEvent event ) {
119    
120            event.request = this;
121            
122            Iterator i = ResourceRequestFactory.getNetworkEventListeners();
123    
124            while ( i.hasNext() ) {
125                ((NetworkEventListener)i.next()).dataEvent( event );
126            } 
127    
128            if ( eventListener != null )
129                eventListener.dataEvent( event );
130        }
131    
132        public void fireOnClosed() {
133    
134            Iterator i = ResourceRequestFactory.getNetworkEventListeners();
135    
136            while ( i.hasNext() ) {
137                ((NetworkEventListener)i.next()).onClosed();
138            } 
139    
140            if ( eventListener != null )
141                eventListener.onClosed();
142        }
143    
144        /**
145         * @see ResourceRequest
146         * 
147         */
148        public String getInputStreamAsString() throws IOException {
149            return new String( getInputStreamAsByteArray() );
150        }
151    
152        /**
153         * @see ResourceRequest
154         * 
155         */
156        public byte[] getInputStreamAsByteArray() throws IOException {
157    
158            InputStream is = getInputStream();
159    
160            int contentLength = -1;
161    
162            try {
163    
164                contentLength = getContentLength() + 5000;
165    
166            } catch ( IOException e ) { e.printStackTrace(); }
167    
168            if ( contentLength == -1  ) {
169    
170                //use a larger default than what's provided with the
171                //ByteArrayOutputStream
172    
173                contentLength = 100000;
174            } 
175    
176            //include length of content from the original site with contentLength
177            ByteArrayOutputStream bos = new ByteArrayOutputStream( contentLength );
178          
179            //now process the Reader...
180            byte data[] = new byte[200];
181        
182            int readCount = 0;
183    
184            while( ( readCount = is.read( data )) > 0 ) {
185                bos.write( data, 0, readCount );
186            }
187    
188            is.close();
189            bos.close();
190    
191            return bos.toByteArray();
192    
193        }
194    
195        /**
196         * @see ResourceRequest
197         * 
198         */
199        public InputStream getLocalInputStream() throws NetworkException {
200    
201            try { 
202                
203                byte[] data;
204                
205                if ( this.data.length > 0 ) {
206                    
207                    //we have cached this... return the cached value.
208                    data = this.data;
209                    
210                } else {
211                    
212                    data = getInputStreamAsByteArray();
213                    
214                    if ( localCache )
215                        this.data = data;
216                    
217                }
218                
219                return new ByteArrayInputStream( data );
220                
221            } catch ( NetworkException n ) {
222                throw n;
223            } catch ( Throwable t ) {
224                throw new NetworkException( t );
225            }
226    
227        }
228    
229        public byte[] getLocalInputStreamAsByteArray() throws IOException {
230            //FIXME: this needs to use the cache.
231            return this.data;
232        }
233    
234        public void setLocalCache( boolean v ) {
235            this.localCache = v;
236        }
237        
238        /**
239         * Copy this resource request to the given OutputStream
240         *
241         * 
242         */
243        public void toOutputStream( OutputStream out ) throws IOException {
244    
245            InputStream is = getInputStream();
246            
247            //now process the Reader...
248            byte data[] = new byte[200];
249        
250            int readCount = 0;
251    
252            while( ( readCount = is.read( data )) > 0 ) {
253                
254                out.write( data, 0, readCount );
255            }
256    
257            is.close();
258    
259        }
260    
261        public long getIfModifiedSince() {
262            return _ifModifiedSince;
263        }
264    
265        public void setIfModifiedSince( long ifModifiedSince ) {
266            this._ifModifiedSince = ifModifiedSince;
267        }
268    
269        public String getEtag() {
270            return _etag;
271        }
272        
273        public void setEtag( String etag ) {
274            this._etag = etag;
275        }
276    
277        /**
278         * Get and set an HTTP style response code.  Only used with HTTP URLs.
279         *
280         * 
281         */
282        public long getResponseCode() {
283            return this._responseCode;
284        }
285        
286        public void setResponseCode( int responseCode ) {
287            this._responseCode = responseCode;
288        }
289    
290        public int getContentLength() throws IOException {
291            return -1;
292        }
293    
294        public void setEventListener( NetworkEventListener eventListener ) {
295            this.eventListener = eventListener;
296        }
297        
298       public String getHeaderField( String name ) {
299           //default impl always returns null
300           return  null;
301        }
302    
303        public void setRequestHeaderField( String name, String value ) {
304            requestHeaders.put( name, value );
305        }
306    
307        public Iterator getRequestHeaderFields() {
308            return requestHeaders.keySet().iterator();
309        }
310    
311        public String getRequestHeaderField( String name ) {
312            return (String)requestHeaders.get( name );
313        }
314    
315        public void setRequestMethod( String method ) throws NetworkException {
316            throw new NetworkException( "not implemented" );
317        }
318    
319        public boolean getFollowRedirects() {
320            return followRedirects;
321        }
322    
323        public void setFollowRedirects( boolean v ) {
324            this.followRedirects = v;
325        }
326    
327        public String getResourceFromRedirect() {
328            return getResource();
329        }
330        
331    }