/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 *     "Apache Jetspeed" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache" or
 *    "Apache Jetspeed", nor may "Apache" appear in their name, without
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

package org.apache.jetspeed.daemon.impl.util.feeddaemon;

//jetspeed stuff
import org.apache.jetspeed.cache.disk.DiskCacheUtils;
import org.apache.jetspeed.cache.disk.JetspeedDiskCache;
import org.apache.jetspeed.om.registry.PortletEntry;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.Registry;
import org.apache.jetspeed.services.PortletFactory;
import org.apache.jetspeed.services.urlmanager.URLManager;
import org.apache.jetspeed.services.urlmanager.URLManagerService;
import org.apache.jetspeed.services.urlmanager.URLFetcher;
import org.apache.jetspeed.services.resources.JetspeedResources;

//Java stuff
import java.io.IOException;

/**
<p>
Given an PortletEntry use the PortletFactory to instantiate this Portlet and
then place it in the cache.  
</p>

<p>
If the URL isn't 

</p>

@author <A HREF="mailto:burton@apache.org">Kevin A. Burton</A>
@version $Id: Instantiator.java,v 1.25 2003/07/23 19:50:10 morciuch Exp $
*/
public class Instantiator implements Runnable {

    /**
    The maximum number of seconds to wait before warning that the URL took
    too long to download
    */
    public static final int MAX_WARN_SECONDS = 3;
    
    /**
    Specify the interval to log when Portlets are instantiated
    */
    public static final int LOG_INTERVAL = 100;
    
    private PortletEntry   entry = null;
    private int            id = 0;

    private boolean        forcePortet = false;
    
    /**
     * Static initialization of the logger for this class
     */
    private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(Instantiator.class.getName());
    
    /**
    Create a Instantiator with info on what to instantiate
    */
    public Instantiator( PortletEntry entry ) { 

        this.entry = entry;
        
    }
    
    /**
    @see #Instantiator( PortletEntry )
    */
    public Instantiator( int id,
                         PortletEntry entry ) {

        this(entry);                     
        this.id = id;
        
    }

    /**
    Get the url from the net and put it on disk
    */
    public void getURL( String url ) throws IOException {

        //if the user wants to download the URL and it isn't in the cache then go for it
        if ( JetspeedResources.getBoolean( JetspeedResources.CONTENTFEEDS_FETCHALL_KEY ) && 
             DiskCacheUtils.isCached( url ) == false ) {
            
            long download_begin = System.currentTimeMillis();        
            try {

                //JetspeedDiskCache.getInstance().getEntry( url, true );
               //SGP
                JetspeedDiskCache.getInstance().getEntry(
                                                         url, 
                                                         URLFetcher.fetch(url, true));
            
                long total = ( System.currentTimeMillis() - download_begin ) / 1000;
            
                if ( total >= MAX_WARN_SECONDS ) {
                    logger.warn( this.getClass().getName() + "  The following URL took too long (" + 
                    total + 
                    " second(s)) to download: " + url );
                }
            
            } catch (IOException e) {
            
                //Not necessary to print a stack trace here because this will 
                //generate too much output
            
                logger.error( "The following URL couldn't be downloaded " + 
                           url + 
                           " and took " + 
                           ( System.currentTimeMillis() - download_begin ) / 1000 +
                           " seconds to download. " );
                throw new IOException( e.getMessage() );
            }
        
        }
        
    }
    
    /**
    Do work necessary to instantiate the current Entry but only do this if it is 
    NOT already in the cache.
    */
    public void run() {

        try {
            
            if(this.entry == null)
                {
                    logger.error("Instantiator: Null Entry");
                    return;
                }

            if(this.entry.getURL() == null)
                {
                    logger.error("Instantiator: Null URL");
                    return;
                }

            this.getURL( this.entry.getURL() );
            
        } catch ( IOException e ) {
            //the real IOException is logged in getURL
            return;
        } catch ( Throwable t) {
            //t.printStackTrace();
            logger.error( "Instantiator: Throwable", t);
        }

        org.apache.jetspeed.om.registry.Registry registry = 
            Registry.get(Registry.PORTLET);

        try {
            if(!registry.hasEntry(this.entry.getName()))
                {
                    registry.addEntry( this.entry );

                    if ( JetspeedResources.getBoolean( JetspeedResources.AUTOCREATE_PORTLETS_KEY ) )
                        {
                  
                            PortletFactory.getPortlet( this.entry.getName(), "0" );

                        }

                }
                                                     
        } catch ( Exception e ) {
            logger.error( "InstantiatorThread: Couldn't create Portlet: ", e );

            //SGP We add the URL to the BadList
            URLManager.register( this.entry.getURL(), URLManagerService.STATUS_BAD, e.toString() );

            //remove this entry because it threw a PortletException so users 
            //should be prevented from seeing this again.
            registry.removeEntry( this.entry.getName() );
        }
        
        //log how many portlets we have instantiated.
        if ( id != 0 &&
             id % LOG_INTERVAL == 0 ) {
            logger.info( "Instantiator:  instanted " + id + " portlet(s)" );
        }
        
    }
    
}

