alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.autoupdate;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParsePosition;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.openide.ErrorManager;

import org.w3c.dom.*;
import org.xml.sax.*;

import org.openide.util.*;


/** Serves for building an UpdateCache from XML Document
 * @author  Petr Hrebejk
 */
class XMLUpdates extends Updates {

    /** XML Element tag names */
    private static final String TAG_MODULE_UPDATES = "module_updates"; // NOI18N
    private static final String TAG_MODULE = "module"; // NOI18N
    private static final String TAG_MODULE_GROUP = "module_group"; // NOI18N
    private static final String TAG_NOTIFICATION = "notification"; // NOI18N
    private static final String ATTR_NOTIFICATION_URL = "url"; // NOI18N
    private static final String TAG_ERROR = "error"; // NOI18N
    private static final String TAG_AUTH_ERROR = "auth_error"; // NOI18N
    private static final String TAG_OTHER_ERROR = "other_error"; // NOI18N
    private static final String ATTR_MESSAGE_ERROR = "message"; // NOI18N
    
    /** List of all modules */
    private ArrayList modules;
    private HashMap checkOnceMore;

    /** The tree structure of Modules and Groups */
    private ModuleGroup rootGroup;
    
    private int pError = NO_ERROR;
    
    private String errorMess = null;

    /** The timeStamp of downloaded xml */
    private Date timeStamp = null;

    /** Text of the notification if any */
    private String notificationText = null;

    /** URL of the notification if any */
    private URL notificationURL = null;

    /** The URL of the document */
    private URL xmlURL;

    /** The list of files in case of installing downloaded modules */
    private File[] files;
    
    /** Temporary list of files to be installed as group */
    private static ArrayList groupFiles = new ArrayList();
    /** Is timer process to install group of selected files set? */
    private static boolean timerSet = false;
    /** Does installation of group of selected files start? */
    private static boolean groupStarted = false;
    private static int oldGroupSize = 0;
    
    /** The XML Document */
    private Document document = null;
    
    private InputSource xmlInputSource = null;

    private AutoupdateType currentAT = null;
    
    /** Creates new Updates
     */
    XMLUpdates(URL xmlURL) {
        this.xmlURL = xmlURL;        
    }

    /** Create new Updates for files list - used
     * for installing downloaded modules
     */
    XMLUpdates(File[] files) {
        this.files = files;        
    }
    
    /** Start wizard for whole group of files requesting
     * installation at once.
     * Timer process is used to wait for all requests.
     */
    static void startGroupUpdates( File file ) {
        if ( groupStarted )
            new XMLUpdates( new File[]{ file } ).go();
        else {
            groupFiles.add( file );
            setTimer();
        }
    }
    
    private static void setTimer() {
        if ( ! timerSet ) {
            timerSet = true;
            oldGroupSize = groupFiles.size();
            org.openide.util.RequestProcessor.getDefault().post( new Runnable() {
                public void run() {
                    if ( oldGroupSize < groupFiles.size() ) {
                        oldGroupSize = groupFiles.size();
                        org.openide.util.RequestProcessor.getDefault().post(
                                this,
                                500
                            );
                    }
                    else {
                        timerSet  = false;
                        groupStarted = true;
                        File[] arrFiles = new File[ groupFiles.size() ];
                        Iterator it = groupFiles.iterator();
                        for ( int j = 0; it.hasNext(); j++ ) {
                            File fn = (File)it.next();
                            if ( fn != null ) {
                                arrFiles[j] = fn;
                            }
                        }
                        groupFiles.clear();
                        groupStarted = false;
                        new XMLUpdates( arrFiles ).go();
                    }
                }
            },
            500);
        }            
    }

    private void go() {
        HashMap allUpdates = new HashMap();
        allUpdates.put(this, this);
        Wizard wiz = Wizard.go( allUpdates, 1 );
        if ( wiz != null ) {
            checkDownloadedModules();
            wiz.refreshUpdatePanel();
        }
    }
    
    /** Checks for updates in separate thread. Displays progress in a dialog
     */
    public void checkUpdates( final Wizard.Validator validator ) {
        checkUpdates(validator, "");  // NOI18N
    }

    /** Checks for updates in separate thread. Displays progress in a dialog
     */
    public void checkUpdates( final Wizard.Validator validator, String ucname ) {
        checkUpdates( validator, AutoupdateType.find( ucname ) );
    }
        
    /** Checks for updates in separate thread. Displays progress in a dialog
     */
    public void checkUpdates( final Wizard.Validator validator, final AutoupdateType at ) {

        currentAT = at;
        pError = NO_ERROR;
        checkCanceled = false;

        final java.awt.Dialog connDialog = ConnectingDialog.getDialog( at != null ? at.getName() : null );
        Runnable task = new Runnable () {
                            public void run() {
                                try {
                                    parseDocument();
                                    Settings.getShared().setLastCheck( new Date() );
                                    if ( pError == NO_ERROR && document != null )
                                        buildStructures();
                                    else {
                                        if (pError == NO_ERROR) pError = UNKNOWN_ERROR;
                                    }
                                    //Settings.getShared().setLastStamp( getTimeStamp() );
                                    validator.setValid( true );
                                    int countOfAvailableModules = 0;
                                    if (getModules () != null) countOfAvailableModules = getModules ().size ();
                                    if (countOfAvailableModules == 0 && pError == NO_ERROR) {
                                        // wrong, display warning and don't forward
                                        errorMess = at.getName ();
                                        pError = NO_AVAILABLE_MODULES;
                                    }
                                } catch (Exception x) {
                                    // bugfix #39049, check if a proxy is available
                                    pError = NO_NETWORK;
                                    ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, x);
                                } finally {
                                    if (connDialog != null) {
                                        ConnectingDialog.closeDialog(connDialog);
                                    }
                                }
                            }
                        };
        Wizard.getRequestProcessor().post( task );
        connDialog.show();
        if (ConnectingDialog.isCanceled()) {
            cancelCheck();
        }
    }
    
    public void cancelCheck() {
        checkCanceled = true;
        if ( xmlInputSource != null) {
            try {
                if (xmlInputSource.getByteStream() != null)
                    xmlInputSource.getByteStream().close();         
            } catch (java.io.IOException e) {                
            }
        }
    }


    /** Gets the root of the module/module group tree
     * @return The group in the root of the tree.
     */
    public ModuleGroup getRootGroup() {
        return rootGroup;
    }

    /** Gets the linear structure of all module updates i.e. Collection
     */
    public Collection getModules() {
        return modules;
    }

    /** Gets the state of pError the file was not parsed */
    public boolean isError() {
        return ( pError > NO_ERROR );
    }
    
    /** Gets the state of pError the file was not parsed */
    public int getError() {
        return pError;
    }
    
    /** Gets the server error message if there is any */
    public String getErrorMessage() {
        return errorMess;
    }
    
    /** Returns the time stamp of the downloaded XML file */
    public Date getTimeStamp() {
        return timeStamp;
    }

    /** Returns notification text if specified otherwise null */
    public String getNotificationText() {
        return notificationText;
    }

    /** Returns notification URL if specified otherwise null */
    public URL getNotificationURL() {
        return notificationURL;
    }

    /** Builds structures for downloaded modules, the structures are onbly
     * linear 
     */
    void checkDownloadedModules() {
        modules = new ArrayList();        
        rootGroup = new ModuleGroup();
        checkOnceMore = new HashMap();

        for ( int i = 0; i < files.length; i++ ) {
            ModuleUpdate update = ModuleUpdate.getModuleUpdate( files[i] );

            if ( update != null ) {

                if ( update.isUpdateAvailable() ) {
                    modules.add( update );
                    rootGroup.addItem( update );
                }
                else if ( update instanceof L10NUpdate ) {
                    checkOnceMore.put( update, rootGroup );
                }
            }
        }
        checkAvailablesOnceMore();
    }
    
    void checkAvailablesOnceMore() {
        Iterator it = checkOnceMore.entrySet().iterator();
        while ( it.hasNext() ) {
            Map.Entry entry = (Map.Entry) it.next();
            L10NUpdate update = (L10NUpdate) entry.getKey();
            if ( update.isRemoteModuleAvailable( modules ) ) {
                modules.add( update );
                ( (ModuleGroup) entry.getValue() ).addItem( update );
            }
        }
    }

    /** Calls static parsing method in XMLDataObject to parse the
     * document
     */ 
    private void parseDocument() {

        if ( checkCanceled )
            return;

        String showStr = System.getProperty("autoupdate.show.url"); // NOI18N
        if ( showStr != null && Boolean.valueOf( showStr ).booleanValue() )
            System.out.println("URL : " + xmlURL ); // NOI18N
        
        try {
            java.net.HttpURLConnection.setFollowRedirects( true );
            //document = XMLDataObject.parse( xmlURL, new ErrorCatcher() );
            
            xmlInputSource = new InputSource( xmlURL.toExternalForm() );
            if ( checkCanceled )
                return;
            document = org.netbeans.updater.XMLUtil.parse( xmlInputSource, false, false, new ErrorCatcher(), org.netbeans.updater.XMLUtil.createAUResolver () );            
        }
        catch ( SAXException e ) {
            pError = PARSE_ERROR;
            showParseError(e);
        }
        catch ( java.io.IOException e ) {
            pError = NO_NETWORK;
            showParseError(e);
        }
    }
    
    private void showParseError(Throwable t) {
        ErrorManager.getDefault().annotate(t, ErrorManager.UNKNOWN, "URL: " + xmlURL, null, null, null); // NOI18N
        ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, t);
    }

    /** Builds the linear and the tree structure of module updates.
     */
    private void buildStructures() {

        if ( checkCanceled )
            return;

        if ( document.getDocumentElement() == null ) {
            // System.out.println( "WARNING  is not element tag" ); // NOI18N
        }
        else {
            modules = new ArrayList();
            rootGroup = new ModuleGroup();
            checkOnceMore = new HashMap();

            // check if there is error tag in XML
            if ( detectErrorType () )
                return;
            
            NodeList allModules = document.getElementsByTagName( TAG_MODULE );
            
            processElement( document.getDocumentElement(), rootGroup );

            // Try to read timestamp
            Node attr = document.getDocumentElement().getAttributes().getNamedItem( "timestamp" ); // NOI18N
            if ( attr != null ) {
                String timeString = attr.getNodeValue() + "/GMT"; // NOI18N
                SimpleDateFormat formatter = new SimpleDateFormat( "ss/mm/HH/dd/MM/yyyy/zzz" ); // NOI18N
                ParsePosition pos = new ParsePosition(0);
                timeStamp = formatter.parse(timeString, pos);
            }
            checkAvailablesOnceMore();
        }
    }
    
    private boolean detectErrorType () {
        NodeList errors = document.getElementsByTagName(TAG_ERROR);
        
        // document contains error section
        if ( errors.getLength() > 0 ) {    
            NodeList auth_errors = document.getElementsByTagName(TAG_AUTH_ERROR);
            if ( auth_errors.getLength() > 0 )
                pError = AUTH_ERROR;
            else {
                pError = PARSE_ERROR;
                NodeList other_errors = document.getElementsByTagName(TAG_OTHER_ERROR);
                if ( other_errors.getLength() > 0 )
                    errorMess = other_errors.item( 0 ).getAttributes().
                        getNamedItem(ATTR_MESSAGE_ERROR).getNodeValue();                                          
            }
        }
        return ( pError > NO_ERROR );
    }

    /** Finds module and module_group elements in the node's children and
     * process them
     *@param element The DOM Element node to be read.
     */
    private void processElement( Element element, ModuleGroup moduleGroup ) {

        NodeList nodeList = element.getChildNodes();
        for( int i = 0; i < nodeList.getLength(); i++ ) {

            if ( checkCanceled )
                return;

            Node node = nodeList.item( i );

            if ( node.getNodeType() != Node.ELEMENT_NODE ) {
                continue;
            }

            if ( ((Element)node).getTagName().equals( TAG_MODULE ) ) {
                ModuleUpdate update = ModuleUpdate.getModuleUpdate( xmlURL, node, document.getDocumentElement(), currentAT );

                if ( update != null ) {
                    if ( update.isUpdateAvailable() ) {
                        modules.add( update );
                        moduleGroup.addItem( update );
                    }
                    else if ( update instanceof L10NUpdate ) {
                        checkOnceMore.put( update, moduleGroup );
                    }
                }
            }
            else if ( ((Element)node).getTagName().equals( TAG_MODULE_GROUP ) ) {
                ModuleGroup group = new ModuleGroup( node );
                moduleGroup.addItem( group );
                processElement( (Element)node, group );
            }
            else if ( ((Element)node).getTagName().equals( TAG_NOTIFICATION ) ) {
                readNotification( node );
            }
        }
    }    
    
    /** Reads the notification */
    private void readNotification( Node node ) {

        if ( getNotificationText() != null ) {
            return;
        }

        try {
            Node attr = node.getAttributes().getNamedItem( ATTR_NOTIFICATION_URL );
            String textURL = attr == null ? null : attr.getNodeValue();

            if ( textURL != null )
                notificationURL = new URL( textURL );
        }
        catch ( java.net.MalformedURLException e ) {
            // TopManager.getDefault().notifyException( e );
            // let homepage set to null
        }

        StringBuffer sb = new StringBuffer();

        NodeList innerList = node.getChildNodes();

        for( int i = 0; i < innerList.getLength(); i++ ) {
            if ( innerList.item( i ).getNodeType() == Node.TEXT_NODE )  {
                sb.append( innerList.item( i ).getNodeValue() );
            }
        }

        if ( sb.length() > 0 )
            notificationText = sb.toString();
        else
            notificationText = null;

    }


    class ErrorCatcher implements org.xml.sax.ErrorHandler {
        
        public void error (SAXParseException e) throws SAXParseException {
            // normally a validity error (though we are not validating currently)
            throw e;
        }

        public void warning (SAXParseException e) throws SAXParseException {
            showParseError(e);
            // but continue...
        }

        public void fatalError (SAXParseException e) throws SAXParseException {
            throw e;
        }
        
    } //end of inner class ErrorPrinter

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.