KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javadoc > httpfs > HTTPRootFileObject


1 /**************************************************************************
2  *
3  * The contents of this file are subject to the terms of the Common Development
4  * and Distribution License (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
8  * or http://www.netbeans.org/cddl.txt.
9  *
10  * When distributing Covered Code, include this CDDL Header Notice in each file
11  * and include the License file at http://www.netbeans.org/cddl.txt.
12  * If applicable, add the following below the CDDL Header, with the fields
13  * enclosed by brackets [] replaced by your own identifying information:
14  * "Portions Copyrighted [year] [name of copyright owner]"
15  *
16  * The Original Software is the HTTP Javadoc Filesystem.
17  * The Initial Developer of the Original Software is Jeffrey A. Keyser.
18  * Portions created by Jeffrey A. Keyser are Copyright (C) 2000-2002.
19  * All Rights Reserved.
20  *
21  * Contributor(s): Jeffrey A. Keyser.
22  *
23  **************************************************************************/

24
25
26 package org.netbeans.modules.javadoc.httpfs;
27
28 import java.io.*;
29 import java.net.HttpURLConnection JavaDoc;
30 import java.util.*;
31
32 import org.openide.cookies.InstanceCookie;
33 import org.openide.filesystems.FileObject;
34 import org.openide.filesystems.Repository;
35 import org.openide.loaders.DataObject;
36 import org.openide.loaders.DataObjectNotFoundException;
37
38 /**
39  * <p>Represents the root file found on the file sysetm.</p>
40  *
41  * @since 3.4
42  */

43 class HTTPRootFileObject
44     extends HTTPFileObject implements Runnable JavaDoc {
45
46     private static final String JavaDoc IDE_SETTINGS_NAME = "Services/org-netbeans-core-IDESettings.settings"; // NOI18N
47
private Thread JavaDoc refreshThread;
48     private Date lastRefreshDate;
49     private boolean threadIsRunning;
50     private boolean refreshPending;
51     
52     private static boolean proxyInit;
53
54     /**
55      * Constructs a <code>HTTPRootFileObject</code> with the file system passed.
56      *
57      * @param parentFileSystem The file system that contains this file.
58      *
59      * @since 3.4
60      */

61     HTTPRootFileObject(
62         HTTPFileSystem parentFileSystem
63     ) {
64
65         super( "/", parentFileSystem ); // NOI18N
66

67         // Start reading the items in the root directory in the background
68
refreshThread = new Thread JavaDoc( this );
69         threadIsRunning = true;
70         refreshPending = false;
71         refreshThread.start( );
72
73     }
74
75
76     /**
77      * Constructs an empty <code>HTTPRootFileObject</code>. This constructor is only
78      * expected to be used during deserialization.
79      *
80      * @since 3.4
81      */

82     protected HTTPRootFileObject(
83     ) {
84
85         super( );
86
87     }
88
89
90     /**
91      * Forces the filesystem to be refreshed.
92      *
93      * @since 3.4
94      */

95     void triggerRefresh( ) {
96
97         refreshPending = true;
98         refreshThread.interrupt( );
99
100     }
101
102
103     /**
104      * Called to initialize the root file object in the background, and to
105      * run the background refresh thread.
106      *
107      * @since 3.4
108      */

109     public void run( ) {
110
111         // Interfal in minutes to check the web site for a new version
112
int refreshInterval;
113         // The next time the web site is scheduled to be checked
114
Calendar nextRefreshTime;
115         // Flags whether the docs have changed
116
boolean docsHaveChanged;
117
118
119         // Start by reading the web site's contents for the first time
120
refreshRootContents( );
121         refreshThread.setPriority( Thread.MIN_PRIORITY );
122
123         while( threadIsRunning ) {
124
125             docsHaveChanged = false;
126
127             // If this file system is configured to be refreshed,
128
refreshInterval = parentFileSystem.getRefreshRate( );
129             if( refreshInterval > 0 ) {
130
131                 // Calculate the next time this file object should try to refresh
132
nextRefreshTime = new GregorianCalendar( );
133                 nextRefreshTime.setTime( lastRefreshDate );
134                 nextRefreshTime.add( Calendar.MINUTE, refreshInterval );
135
136                 // If the next refresh time has passed,
137
if( nextRefreshTime.before( new GregorianCalendar( ) ) ) {
138
139                     // Check if the documentation has changed
140
docsHaveChanged = hasDocumentationChanged( );
141
142                 }
143
144             }
145
146             // If the JavaDocs need to be refreshed,
147
if( docsHaveChanged || refreshPending ) {
148
149                 // Refresh the contents of this root file object
150
refreshPending = false;
151                 refreshRootContents( );
152
153             }
154
155             try {
156
157                 // Test if it's time to check once every minute
158
Thread.sleep( 60 * 1000 );
159
160             } catch( InterruptedException JavaDoc e ) {
161
162                 // Ignore
163

164             }
165
166         }
167
168     }
169
170
171     /**
172      * Checks if the "package-list" on the web site is newer than the version
173      * in memory.
174      *
175      * @return True if the web site has changed, false if not.
176      *
177      * @since 3.4
178      */

179     private boolean hasDocumentationChanged(
180     ) {
181
182         // File object for /package-list
183
HTTPFileObject packageFile;
184         // Connection to the web server for the package-list file
185
HttpURLConnection JavaDoc fileConnection;
186         // Current date/time of the current file in memory
187
Date currentPackageFileDate;
188         // Flag to return if the we site file has changed
189
boolean hasChanged;
190
191
192         // Get the local "package-list" file
193
packageFile = child( "package-list", false ); //NOI18N
194

195         // If there is a local "package-list" file,
196
if( packageFile != null ) {
197
198             try {
199
200                 // Compare the date of the local "package-list" file to the one on the web server
201
currentPackageFileDate = packageFile.lastModified( );
202                 fileConnection = (HttpURLConnection JavaDoc)packageFile.fileURL.openConnection( );
203                 fileConnection.setRequestMethod( "HEAD" ); // NOI18N
204

205                 hasChanged = currentPackageFileDate.before( new Date( fileConnection.getLastModified( ) ) );
206
207                 fileConnection.disconnect( );
208
209             } catch( IOException e ) {
210
211                 // There's a problem at the moment - force the refresh thread to not read this site
212
hasChanged = false;
213
214             }
215
216         // If there is no local "package-list" file,
217
} else {
218
219             // Try again
220
hasChanged = true;
221
222         }
223         return hasChanged;
224
225     }
226
227
228     /**
229      * Reads the base files available at the URL to build the directory tree.
230      *
231      * @since 3.4
232      */

233     private void refreshRootContents( ) {
234         initHTTPProxyHack();
235         // File object for /package-list
236
HTTPFileObject packageFile;
237         // File object for /index-files/ directory
238
HTTPFileObject indexDirectory;
239         // Reader of package names in /package-list
240
BufferedReader packageReader;
241         // Package name read from /package-list
242
String JavaDoc packageName;
243         // File number for the next split index file
244
int indexFileNumber;
245
246
247         // Tell the file system that it is being refreshed
248
parentFileSystem.setState( HTTPFileSystem.STATE_READING );
249         
250         // Remove all existing children from the root file object
251
removeAllChildren( );
252
253         // Add the standard files for a Javadoc directory structre
254
if( addOptionalChild( "/package-list" ) ) { //NOI18N
255

256             packageFile = child( "package-list", false ); //NOI18N
257
addChild( "/allclasses-frame.html" ); //NOI18N
258
addOptionalChild( "/deprecated-list.html" ); //NOI18N
259
addOptionalChild( "/help-doc.html" ); //NOI18N
260
addOptionalChild( "/index.html" ); //NOI18N
261
addChild( "/overview-frame.html" ); //NOI18N
262
addChild( "/overview-summary.html" ); //NOI18N
263
addOptionalChild( "/overview-tree.html" ); //NOI18N
264
addChild( "/packages.html" ); //NOI18N
265
addChild( "/serialized-form.html" ); //NOI18N
266
addChild( "/stylesheet.css" ); //NOI18N
267

268             // Add the full index file
269
if( !addOptionalChild( "/index-all.html" ) ) { //NOI18N
270

271                 // If there was no full index, search for split index files
272
indexFileNumber = 1;
273                 while( addOptionalChild( "/index-" + indexFileNumber + ".html" ) ) { //NOI18N
274

275                     indexFileNumber++;
276
277                 }
278
279                 // If no index were found in the root,
280
if( indexFileNumber == 1 ) {
281
282                     // Look in /index-files/
283
indexDirectory = new HTTPFileObject( "/index-files/", parentFileSystem ); //NOI18N
284
// Add the full index file
285
if( !indexDirectory.addOptionalChild( "/index-files/index-all.html" ) ) { //NOI18N
286

287                         // If there was no full index, search for split index files
288
indexFileNumber = 1;
289                         while( indexDirectory.addOptionalChild( "/index-files/index-" + indexFileNumber + ".html" ) ) { //NOI18N
290

291                             indexFileNumber++;
292
293                         }
294                         // If index file were found in this directory,
295
if( indexFileNumber != 1 ) {
296
297                             addChild( indexDirectory );
298
299                         }
300
301                     // If there was an index file found in this directory,
302

303                     } else {
304
305                         addChild( indexDirectory );
306
307                     }
308
309                 }
310
311             }
312             try {
313
314                 // Read all of the package names from the /package-list file
315
packageReader = new BufferedReader( new InputStreamReader( packageFile.getInputStream( ) ) );
316                 packageName = packageReader.readLine( );
317                 while( packageName != null ) {
318
319                     // Add each package to this file system
320
addPackage( packageName );
321                     packageName = packageReader.readLine( );
322
323                 }
324                 packageReader.close( );
325
326             } catch( IOException e ) {
327
328                 // Ignore packages
329

330             }
331
332         }
333         lastRefreshDate = new Date( );
334
335         // Tell the file system that the refresh is done
336
parentFileSystem.setState( HTTPFileSystem.STATE_COMPLETE );
337
338     }
339
340
341     /**
342      * Adds the named package to this file sytem.
343      *
344      * @param packageName Package name to add to this file system.
345      *
346      * @since 3.4
347      */

348     private void addPackage( String JavaDoc packageName ) {
349         
350         // Parser to break up the package heirarchy
351
StringTokenizer packageParser;
352         // One level of this package heirarchy
353
String JavaDoc packagePart;
354         // The diretory that belongs to the selected package
355
HTTPFileObject packageDirectory;
356         
357         
358         // Pull apart the package heirarchy
359
packageParser = new StringTokenizer( packageName, "." ); //NOI18N
360
packageDirectory = this;
361         
362         // With each level of the package,
363
while( packageParser.hasMoreElements( ) ) {
364             
365             packagePart = (String JavaDoc)packageParser.nextElement( );
366             
367             // Find its directory object
368
if( packageDirectory.child( packagePart, false ) == null ) {
369                 
370                 packageDirectory.addChild( packageDirectory.uriStem + packagePart + "/" ); //NOI18N
371

372             }
373             packageDirectory = packageDirectory.child( packagePart, false );
374
375         }
376         // flag this directory as containing class files
377
packageDirectory.makePackage( );
378
379     }
380
381
382     /**
383      * Cleans up this object when it is finalized.
384      *
385      * @throws Throwable
386      *
387      * @since 3.4
388      */

389     protected void finalize(
390     ) throws Throwable JavaDoc {
391
392         super.finalize( );
393
394         // Close the refresh thread for this file
395
threadIsRunning = false;
396         refreshThread.interrupt( );
397
398     }
399     
400     /**
401      * Note that this is a *hack*, since it depends on some strange name given to the
402      * IDESettings instance by the Core. But otherwise I don't know about a way
403      * how to force the setting to be read.
404      * //!!!
405      */

406     static void initHTTPProxyHack() {
407         if (proxyInit)
408             return;
409         FileObject f = Repository.getDefault().getDefaultFileSystem().findResource(IDE_SETTINGS_NAME);
410         try {
411             DataObject d = DataObject.find(f);
412             InstanceCookie ic = (InstanceCookie)d.getCookie(InstanceCookie.class);
413             if (ic != null) {
414                 Object JavaDoc o = ic.instanceCreate(); // NOPMD
415
// OK, we've initialized.
416
proxyInit = true;
417             }
418         } catch (DataObjectNotFoundException ex) {
419         } catch (IOException ex) {
420             proxyInit = true;
421         } catch (ClassNotFoundException JavaDoc ex) {
422             proxyInit = true;
423         }
424     }
425 }
426
Popular Tags