KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > autoupdate > XMLUpdates


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

19
20 package org.netbeans.modules.autoupdate;
21
22 import java.io.BufferedInputStream JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.net.URL JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.Date JavaDoc;
29 import java.text.SimpleDateFormat JavaDoc;
30 import java.text.ParsePosition JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.logging.Level JavaDoc;
35 import java.util.logging.Logger JavaDoc;
36 import java.util.zip.GZIPInputStream JavaDoc;
37 import javax.swing.SwingUtilities JavaDoc;
38 import org.openide.util.Exceptions;
39 import org.openide.util.RequestProcessor;
40
41 import org.w3c.dom.*;
42 import org.xml.sax.*;
43 import org.xml.sax.SAXException JavaDoc;
44
45
46 /** Serves for building an UpdateCache from XML Document
47  * @author Petr Hrebejk
48  */

49 class XMLUpdates extends Updates {
50
51     /** XML Element tag names */
52     private static final String JavaDoc TAG_MODULE_UPDATES = "module_updates"; // NOI18N
53
private static final String JavaDoc TAG_MODULE = "module"; // NOI18N
54
private static final String JavaDoc TAG_MODULE_GROUP = "module_group"; // NOI18N
55
private static final String JavaDoc TAG_NOTIFICATION = "notification"; // NOI18N
56
private static final String JavaDoc ATTR_NOTIFICATION_URL = "url"; // NOI18N
57
private static final String JavaDoc TAG_ERROR = "error"; // NOI18N
58
private static final String JavaDoc TAG_AUTH_ERROR = "auth_error"; // NOI18N
59
private static final String JavaDoc TAG_OTHER_ERROR = "other_error"; // NOI18N
60
private static final String JavaDoc ATTR_MESSAGE_ERROR = "message"; // NOI18N
61

62     private static final Logger JavaDoc err = Logger.getLogger("org.netbeans.modules.autoupdate.XMLUpdates"); // NOI18N
63

64     /** List of all modules */
65     private ArrayList JavaDoc modules;
66     private HashMap JavaDoc checkOnceMore;
67
68     /** The tree structure of Modules and Groups */
69     private ModuleGroup rootGroup;
70     
71     private int pError = NO_ERROR;
72     
73     private String JavaDoc errorMess = null;
74
75     /** The timeStamp of downloaded xml */
76     private Date JavaDoc timeStamp = null;
77
78     /** Text of the notification if any */
79     private String JavaDoc notificationText = null;
80
81     /** URL of the notification if any */
82     private URL JavaDoc notificationURL = null;
83
84     /** The URL of the document */
85     private URL JavaDoc xmlURL;
86
87     /** The list of files in case of installing downloaded modules */
88     private File JavaDoc[] files;
89     
90     /** Temporary list of files to be installed as group */
91     private static ArrayList JavaDoc groupFiles = new ArrayList JavaDoc();
92     /** Is timer process to install group of selected files set? */
93     private static boolean timerSet = false;
94     /** Does installation of group of selected files start? */
95     private static boolean groupStarted = false;
96     private static int oldGroupSize = 0;
97     
98     /** The XML Document */
99     //private Document document = null;
100

101     private InputSource xmlInputSource = null;
102
103     private AutoupdateType currentAT = null;
104
105     private static String JavaDoc GZIP_EXTENSION = ".gz"; // NOI18N
106

107     /** Creates new Updates
108      */

109     XMLUpdates(URL JavaDoc xmlURL) {
110         this.xmlURL = xmlURL;
111     }
112
113     /** Create new Updates for files list - used
114      * for installing downloaded modules
115      */

116     XMLUpdates(File JavaDoc[] files) {
117         this.files = files;
118     }
119     
120     /** Start wizard for whole group of files requesting
121      * installation at once.
122      * Timer process is used to wait for all requests.
123      */

124     static void startGroupUpdates( File JavaDoc file ) {
125         if ( groupStarted )
126             new XMLUpdates( new File JavaDoc[]{ file } ).go();
127         else {
128             groupFiles.add( file );
129             setTimer();
130         }
131     }
132     
133     private static void setTimer() {
134         if ( ! timerSet ) {
135             timerSet = true;
136             oldGroupSize = groupFiles.size();
137             org.openide.util.RequestProcessor.getDefault().post( new Runnable JavaDoc() {
138                 public void run() {
139                     if (! SwingUtilities.isEventDispatchThread ()) {
140                         SwingUtilities.invokeLater (this);
141                         return ;
142                     }
143                     if ( oldGroupSize < groupFiles.size() ) {
144                         oldGroupSize = groupFiles.size();
145                         org.openide.util.RequestProcessor.getDefault().post(
146                                 this,
147                                 500
148                             );
149                     }
150                     else {
151                         timerSet = false;
152                         groupStarted = true;
153                         File JavaDoc[] arrFiles = new File JavaDoc[ groupFiles.size() ];
154                         Iterator JavaDoc it = groupFiles.iterator();
155                         for ( int j = 0; it.hasNext(); j++ ) {
156                             File JavaDoc fn = (File JavaDoc)it.next();
157                             if ( fn != null ) {
158                                 arrFiles[j] = fn;
159                             }
160                         }
161                         groupFiles.clear();
162                         groupStarted = false;
163                         new XMLUpdates( arrFiles ).go();
164                     }
165                 }
166             },
167             500);
168         }
169     }
170
171     private void go() {
172         HashMap JavaDoc allUpdates = new HashMap JavaDoc();
173         allUpdates.put(this, this);
174         Wizard wiz = Wizard.go( allUpdates, 1 );
175         if ( wiz != null ) {
176             checkDownloadedModules();
177             wiz.refreshUpdatePanel();
178         }
179     }
180     
181     /** Checks for updates in separate thread. Displays progress in a dialog
182      */

183     public void checkUpdates( final Wizard.Validator validator ) {
184         checkUpdates(validator, ""); // NOI18N
185
}
186
187     /** Checks for updates in separate thread. Displays progress in a dialog
188      */

189     public void checkUpdates( final Wizard.Validator validator, String JavaDoc ucname ) {
190         checkUpdates( validator, AutoupdateType.find( ucname ) );
191     }
192     
193     public void checkUpdates( final Wizard.Validator validator, final AutoupdateType at ) {
194         checkUpdates (validator, at, false);
195     }
196         
197     /** Checks for updates in separate thread. Displays progress in a dialog
198      */

199     public void checkUpdates (final Wizard.Validator validator, final AutoupdateType at, boolean hidden) {
200
201         currentAT = at;
202         pError = NO_ERROR;
203         checkCanceled = false;
204
205         final java.awt.Dialog JavaDoc connDialog = ConnectingDialog.getDialog( at != null ? at.getName() : null );
206         Runnable JavaDoc runConnect = new Runnable JavaDoc() {
207
208             public void run() {
209                 try {
210                     Document document = parseDocument();
211
212                     if (pError == NO_ERROR && document != null) {
213                         buildStructures(document);
214                         if (!checkCanceled) {
215                             Settings.getShared().setLastCheck(new Date JavaDoc());
216                         }
217                     } else {
218                         if (pError == NO_ERROR) {
219                             assert document != null || checkCanceled : "Document is not null or connecting is canceled if no error caught.";
220                         }
221                     }
222                     validator.setValid(true);
223                     int countOfAvailableModules = 0;
224
225                     if (getModules() != null)
226                         countOfAvailableModules = getModules().size();
227                     if (countOfAvailableModules == 0 && pError == NO_ERROR) {
228                         // wrong, display warning and don't forward
229
errorMess = at.getName();
230                         pError = NO_AVAILABLE_MODULES;
231                     }
232                 }
233                 catch (Exception JavaDoc x) {
234                     // bugfix #39049, check if a proxy is available
235
pError = NO_NETWORK;
236                     err.log(Level.INFO, null, x);
237                 }
238                 finally {
239                     if (connDialog != null) {
240                         ConnectingDialog.closeDialog(connDialog);
241                     }
242                 }
243             }
244         };
245         RequestProcessor.Task task = RequestProcessor.getDefault ().post (runConnect);
246         if (!hidden) {
247             connDialog.setVisible (true);
248             if (ConnectingDialog.isCanceled()) {
249                 cancelCheck();
250             }
251         } else {
252             task.waitFinished ();
253         }
254     }
255     
256     public void cancelCheck() {
257         checkCanceled = true;
258         if ( xmlInputSource != null) {
259             try {
260                 if (xmlInputSource.getByteStream() != null)
261                     xmlInputSource.getByteStream().close();
262             } catch (java.io.IOException JavaDoc e) {
263             }
264         }
265     }
266
267
268     /** Gets the root of the module/module group tree
269      * @return The group in the root of the tree.
270      */

271     public ModuleGroup getRootGroup() {
272         return rootGroup;
273     }
274
275     /** Gets the linear structure of all module updates i.e. Collection
276      */

277     public Collection JavaDoc getModules() {
278         return modules;
279     }
280
281     /** Gets the state of pError the file was not parsed */
282     public boolean isError() {
283         return ( pError > NO_ERROR );
284     }
285     
286     /** Gets the state of pError the file was not parsed */
287     public int getError() {
288         return pError;
289     }
290     
291     /** Gets the server error message if there is any */
292     public String JavaDoc getErrorMessage() {
293         return errorMess;
294     }
295     
296     /** Returns the time stamp of the downloaded XML file */
297     public Date JavaDoc getTimeStamp() {
298         return timeStamp;
299     }
300
301     /** Returns notification text if specified otherwise null */
302     public String JavaDoc getNotificationText() {
303         return notificationText;
304     }
305
306     /** Returns notification URL if specified otherwise null */
307     public URL JavaDoc getNotificationURL() {
308         return notificationURL;
309     }
310
311     /** Builds structures for downloaded modules, the structures are only
312      * linear
313      */

314     void checkDownloadedModules() {
315         modules = new ArrayList JavaDoc();
316         rootGroup = new ModuleGroup();
317         checkOnceMore = new HashMap JavaDoc();
318
319         for ( int i = 0; i < files.length; i++ ) {
320             ModuleUpdate update = ModuleUpdate.getModuleUpdate( files[i] );
321
322             if ( update != null ) {
323
324                 if ( update.isUpdateAvailable() ) {
325                     modules.add( update );
326                     rootGroup.addItem( update );
327                 }
328                 else if ( update instanceof L10NUpdate ) {
329                     checkOnceMore.put( update, rootGroup );
330                 }
331             }
332         }
333         checkAvailablesOnceMore();
334     }
335     
336     void checkAvailablesOnceMore() {
337         Iterator JavaDoc it = checkOnceMore.entrySet().iterator();
338         while ( it.hasNext() ) {
339             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
340             L10NUpdate update = (L10NUpdate) entry.getKey();
341             if ( update.isRemoteModuleAvailable( modules ) ) {
342                 modules.add( update );
343                 ( (ModuleGroup) entry.getValue() ).addItem( update );
344             }
345         }
346     }
347
348     /** Calls static parsing method in XMLDataObject to parse the
349      * document
350      */

351     private Document parseDocument() {
352         Document document = null;
353
354         if ( checkCanceled )
355             return null;
356
357         String JavaDoc showStr = System.getProperty("autoupdate.show.url"); // NOI18N
358
if ( showStr != null && Boolean.valueOf( showStr ).booleanValue() )
359             System.out.println("URL: " + xmlURL ); // NOI18N
360

361         try {
362             document = parseDocumentImpl ();
363         } catch ( SAXException JavaDoc e ) {
364             pError = PARSE_ERROR;
365             showParseError(e);
366         } catch ( IOException JavaDoc e ) {
367             pError = NO_NETWORK;
368             
369             if (!checkCanceled) {
370                 showParseError (e);
371             }
372
373         }
374         
375         return document;
376     }
377
378     private Document parseDocumentImpl() throws SAXException JavaDoc, IOException JavaDoc {
379         Document document = null;
380         java.net.HttpURLConnection.setFollowRedirects( true );
381         
382         err.log(Level.FINE, "Processing URL: " + xmlURL); // NOI18N
383

384         URL JavaDoc urlToGZip = null;
385
386         try {
387             
388             String JavaDoc gzipFile = xmlURL.getPath () + GZIP_EXTENSION;
389             String JavaDoc query = xmlURL.getQuery ();
390             if (query != null && query.trim ().length () > 0) {
391                 gzipFile = gzipFile + '?' + query; // NOI18N
392
}
393             urlToGZip = new URL JavaDoc (xmlURL.getProtocol (), xmlURL.getHost (), xmlURL.getPort (), gzipFile);
394             
395             xmlInputSource = new InputSource(new BufferedInputStream JavaDoc(new GZIPInputStream JavaDoc(urlToGZip.openStream())));
396             err.log(Level.FINE, "Successfully read URL " + urlToGZip); // NOI18N
397

398         } catch (IOException JavaDoc ioe) {
399             err.log(Level.FINE,
400                     "Reading GZIP URL " + urlToGZip + " failed (" + ioe +
401                     "). Try read XML directly " + xmlURL); // NOI18N
402
xmlInputSource = new InputSource( xmlURL.toExternalForm() );
403             err.log(Level.FINE, "Successfully read URL " + xmlURL); // NOI18N
404
}
405         
406         if ( checkCanceled ) {
407             err.log(Level.FINE, "Connection canceled on user\'s demand."); // NOI18N
408
return null;
409         }
410         
411         document = org.netbeans.updater.XMLUtil.parse( xmlInputSource, false, false, new ErrorCatcher(), org.netbeans.updater.XMLUtil.createAUResolver () );
412         
413         assert document != null : "Parser in XMLUtil return not null document for input " + xmlInputSource;
414         
415         return document;
416     }
417     
418     private void showParseError(Throwable JavaDoc t) {
419         Exceptions.attachMessage(t, "URL: " + xmlURL); // NOI18N
420
err.log(Level.INFO, null, t);
421     }
422
423     /** Builds the linear and the tree structure of module updates.
424      */

425     private void buildStructures (Document document) {
426
427         if ( checkCanceled )
428             return;
429
430         if ( document.getDocumentElement() == null ) {
431             // System.out.println( "WARNING <MODULE> is not element tag" ); // NOI18N
432
}
433         else {
434             modules = new ArrayList JavaDoc();
435             rootGroup = new ModuleGroup();
436             checkOnceMore = new HashMap JavaDoc();
437
438             // check if there is error tag in XML
439
if ( detectErrorType (document) )
440                 return;
441             
442             NodeList allModules = document.getElementsByTagName( TAG_MODULE );
443             
444             processElement( document, document.getDocumentElement(), rootGroup );
445
446             // Try to read timestamp
447
Node attr = document.getDocumentElement().getAttributes().getNamedItem( "timestamp" ); // NOI18N
448
if ( attr != null ) {
449                 String JavaDoc timeString = attr.getNodeValue() + "/GMT"; // NOI18N
450
SimpleDateFormat JavaDoc formatter = new SimpleDateFormat JavaDoc( "ss/mm/HH/dd/MM/yyyy/zzz" ); // NOI18N
451
ParsePosition JavaDoc pos = new ParsePosition JavaDoc(0);
452                 timeStamp = formatter.parse(timeString, pos);
453             }
454             checkAvailablesOnceMore();
455         }
456     }
457     
458     private boolean detectErrorType (Document document) {
459         NodeList errors = document.getElementsByTagName(TAG_ERROR);
460         
461         // document contains error section
462
if ( errors.getLength() > 0 ) {
463             NodeList auth_errors = document.getElementsByTagName(TAG_AUTH_ERROR);
464             if ( auth_errors.getLength() > 0 ) {
465                 pError = AUTH_ERROR;
466                 assert false : "Unexcepted " + TAG_AUTH_ERROR + " in document " + document;
467             } else {
468                 pError = PARSE_ERROR;
469                 NodeList other_errors = document.getElementsByTagName(TAG_OTHER_ERROR);
470                 if ( other_errors.getLength() > 0 )
471                     errorMess = other_errors.item( 0 ).getAttributes().
472                         getNamedItem(ATTR_MESSAGE_ERROR).getNodeValue();
473             }
474         }
475         return ( pError > NO_ERROR );
476     }
477
478     /** Finds module and module_group elements in the node's children and
479      * process them
480      *@param element The DOM Element node to be read.
481      */

482     private void processElement( Document document, Element element, ModuleGroup moduleGroup ) {
483
484         NodeList nodeList = element.getChildNodes();
485         for( int i = 0; i < nodeList.getLength(); i++ ) {
486
487             if ( checkCanceled )
488                 return;
489
490             Node node = nodeList.item( i );
491
492             if ( node.getNodeType() != Node.ELEMENT_NODE ) {
493                 continue;
494             }
495
496             if ( ((Element)node).getTagName().equals( TAG_MODULE ) ) {
497                 ModuleUpdate update = ModuleUpdate.getModuleUpdate( xmlURL, node, document.getDocumentElement(), currentAT );
498
499                 if ( update != null ) {
500                     if ( update.isUpdateAvailable() ) {
501                         modules.add( update );
502                         moduleGroup.addItem( update );
503                     }
504                     else if ( update instanceof L10NUpdate ) {
505                         checkOnceMore.put( update, moduleGroup );
506                     }
507                 }
508             }
509             else if ( ((Element)node).getTagName().equals( TAG_MODULE_GROUP ) ) {
510                 ModuleGroup group = new ModuleGroup( node );
511                 moduleGroup.addItem( group );
512                 processElement( document, (Element)node, group );
513             }
514             else if ( ((Element)node).getTagName().equals( TAG_NOTIFICATION ) ) {
515                 readNotification( node );
516             }
517         }
518     }
519     
520     /** Reads the notification */
521     private void readNotification( Node node ) {
522
523         if ( getNotificationText() != null ) {
524             return;
525         }
526
527         try {
528             Node attr = node.getAttributes().getNamedItem( ATTR_NOTIFICATION_URL );
529             String JavaDoc textURL = attr == null ? null : attr.getNodeValue();
530
531             if ( textURL != null )
532                 notificationURL = new URL JavaDoc( textURL );
533         }
534         catch ( java.net.MalformedURLException JavaDoc e ) {
535             // TopManager.getDefault().notifyException( e );
536
// let homepage set to null
537
}
538
539         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
540
541         NodeList innerList = node.getChildNodes();
542
543         for( int i = 0; i < innerList.getLength(); i++ ) {
544             if ( innerList.item( i ).getNodeType() == Node.TEXT_NODE ) {
545                 sb.append( innerList.item( i ).getNodeValue() );
546             }
547         }
548
549         if ( sb.length() > 0 )
550             notificationText = sb.toString();
551         else
552             notificationText = null;
553
554     }
555
556
557     class ErrorCatcher implements org.xml.sax.ErrorHandler JavaDoc {
558         
559         public void error (SAXParseException e) throws SAXParseException {
560             // normally a validity error (though we are not validating currently)
561
throw e;
562         }
563
564         public void warning (SAXParseException e) throws SAXParseException {
565             showParseError(e);
566             // but continue...
567
}
568
569         public void fatalError (SAXParseException e) throws SAXParseException {
570             throw e;
571         }
572         
573     } //end of inner class ErrorPrinter
574

575 }
576
Popular Tags