Package org.infoglue.deliver.util.ioqueue

Source Code of org.infoglue.deliver.util.ioqueue.PublicationQueue

/* ===============================================================================
*
* Part of the InfoGlue Content Management Platform (www.infoglue.org)
*
* ===============================================================================
*
*  Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2, as published by the
* Free Software Foundation. See the file LICENSE.html for more information.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
* Place, Suite 330 / Boston, MA 02111-1307 / USA.
*
* ===============================================================================
*/

package org.infoglue.deliver.util.ioqueue;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.infoglue.cms.applications.common.VisualFormatter;
import org.infoglue.cms.controllers.kernel.impl.simple.TransactionHistoryController;
import org.infoglue.cms.util.NotificationMessage;
import org.infoglue.deliver.util.LiveInstanceMonitor;

/*
*  This class keeps track of all live deliver states by polling them with regular intervals.
*  It also acts as a message queue so publication messages are resent if not successful the first time.
*/

public class PublicationQueue implements Runnable
{
    private final static Logger logger = Logger.getLogger(PublicationQueue.class.getName());

  private static PublicationQueue singleton = null;
 
  private Map<String, Set<PublicationQueueBean>> instancePublicationQueueBeans = new HashMap<String, Set<PublicationQueueBean>>();
  private Map<String, String> instancePublicationQueueMeta = new HashMap<String, String>();
   
  private boolean keepRunning = true;
 
  private PublicationQueue()
  {
  }

  /**
   * Get the singleton and start the thread if not active
   */
  public static PublicationQueue getPublicationQueue()
  {
    if(singleton == null)
    {
      singleton = new PublicationQueue();
      Thread thread = new Thread (singleton);
      thread.start();
    }
   
    return singleton;
  }
 
  public Map<String, Set<PublicationQueueBean>> getInstancePublicationQueueBeans()
  {
    return instancePublicationQueueBeans;
  }
 
  /**
   * This method gets when the queue for a specific instance was cleared manually last.
   */
  public String getInstancePublicationQueueManualClearTimestamp(String serverURL)
  {
    String timestamp = instancePublicationQueueMeta.get(serverURL + "_manualClearTimestamp");
    if(timestamp != null && !timestamp.equals(""))
    {
      VisualFormatter vf = new VisualFormatter();
      return vf.formatDate(Long.parseLong(timestamp), "yyyy-MM-dd HH:mm:ss");
    }
    else
      return "Never cleared";
  }

  /**
   * This method gets when the queued beans for a specific instance.
   */
  public Set<PublicationQueueBean> getInstancePublicationQueueBeans(String serverURL)
  {
    if(instancePublicationQueueBeans.containsKey(serverURL))
      return instancePublicationQueueBeans.get(serverURL);
    else
      return new HashSet<PublicationQueueBean>();
  }

  /**
   * This method allows you to add a publication queue bean and register it against a certain deliver instance.
   * It makes sure each bean is unique.
   */
  public void addPublicationQueueBean(String liveInstanceValidationUrl, PublicationQueueBean bean)
  {
    logger.info("Adding url..");
    Set<PublicationQueueBean> publicationQueueBeans = instancePublicationQueueBeans.get(liveInstanceValidationUrl);
    if(publicationQueueBeans == null)
    {
      publicationQueueBeans = Collections.synchronizedSet(new HashSet<PublicationQueueBean>());
      instancePublicationQueueBeans.put(liveInstanceValidationUrl, publicationQueueBeans);
    }
   
    synchronized(publicationQueueBeans)
    {
      if(publicationQueueBeans.size() < 1000)
        publicationQueueBeans.add(bean);
      else
        logger.error("Skipping publication queue for this bean as to many beans allready is in queue - must be something very wrong with the instance");
    }
    logger.info("Done...");
  }

  /**
   * Allows for manual clearing of a live instance queue.
   */
  public void clearPublicationQueueBean(String liveInstanceValidationUrl)
  {
    logger.error("Clearing queue manually for " + liveInstanceValidationUrl);
    Set<PublicationQueueBean> publicationQueueBeans = instancePublicationQueueBeans.get(liveInstanceValidationUrl);
    if(publicationQueueBeans == null)
    {
      publicationQueueBeans = Collections.synchronizedSet(new HashSet<PublicationQueueBean>());
      instancePublicationQueueBeans.put(liveInstanceValidationUrl, publicationQueueBeans);
    }
   
    synchronized(publicationQueueBeans)
    {
      publicationQueueBeans.clear();
    }
    instancePublicationQueueMeta.put(liveInstanceValidationUrl + "_manualClearTimestamp", "" + System.currentTimeMillis());
  }

  /**
   * The thread runner - with each run it goes through all the queues and tries to call (POST) the deliver instance
   * If the post fails the beans is kept in the queue and retried later if the instance is up at that time. 
   */
  
  public synchronized void run()
  {
    logger.info("Running HttpUniqueRequestQueue...");
    while(keepRunning)
    {
      logger.info("Running..");
      Map<String, Set<PublicationQueueBean>> localPublicationQueueBeans = new HashMap<String, Set<PublicationQueueBean>>();
      synchronized (instancePublicationQueueBeans)
      {
        localPublicationQueueBeans.putAll(instancePublicationQueueBeans);
        instancePublicationQueueBeans.clear();
      }
      if(logger.isInfoEnabled())
        logger.info("Released lock - got " + localPublicationQueueBeans.size() + " urls.");
     
      Iterator<String> serverBaseUrlsIterator = localPublicationQueueBeans.keySet().iterator();
      while(serverBaseUrlsIterator.hasNext())
      {
        String serverBaseUrl = serverBaseUrlsIterator.next();
        Boolean status = LiveInstanceMonitor.getInstance().getServerStatus(serverBaseUrl);
        Set<PublicationQueueBean> beans = localPublicationQueueBeans.get(serverBaseUrl);
        if(status != null && status)
        {
          Iterator<PublicationQueueBean> beansIterator = beans.iterator();
          while(beansIterator.hasNext())
          {
            PublicationQueueBean publicationQueueBean = beansIterator.next();
            if(logger.isInfoEnabled())
              logger.info("publicationQueueBean URL:" + publicationQueueBean.getUrlAddress());
            try
            {
              try
              {
                String response = postToUrl(publicationQueueBean.getUrlAddress(), publicationQueueBean.getRequestParameters());
                if(logger.isInfoEnabled())
                  logger.info("response:" + response);
                               
                NotificationMessage notificationMessage = new NotificationMessage("Publishing notification solved", "Publication", "SYSTEM", NotificationMessage.LIVE_NOTIFICATION_SOLVED, "" + publicationQueueBean.getRequestParameters().get("0.objectId"), "" + serverBaseUrl);
                TransactionHistoryController.getController().create(notificationMessage);

                beansIterator.remove();
              }
              catch(Exception e)
              {
                synchronized (instancePublicationQueueBeans)
                {
                  Map<String, Set<PublicationQueueBean>> currentLiveInstancePublicationQueueBeans = instancePublicationQueueBeans;
                  Set<PublicationQueueBean> currentPublicationQueueBeans = currentLiveInstancePublicationQueueBeans.get(serverBaseUrl);
                  if(currentPublicationQueueBeans == null)
                  {
                    currentPublicationQueueBeans = new HashSet<PublicationQueueBean>();
                    currentLiveInstancePublicationQueueBeans.put(serverBaseUrl, currentPublicationQueueBeans);
                  }
                  currentPublicationQueueBeans.addAll(beans);
                }

                logger.error("Error updating cache at " + publicationQueueBean.getUrlAddress() + ". We skip further tries for now and queue it:" + e.getMessage());
              }
            }
            catch (Exception e)
            {
              logger.error("Error posting data to:" + publicationQueueBean.getUrlAddress() + " - reason:" + e.getMessage());
            }
          }
        }
        else
        {
          if(LiveInstanceMonitor.getInstance().getInstanceStatusMap().containsKey(serverBaseUrl))
          {
            synchronized (instancePublicationQueueBeans)
            {
              Map<String, Set<PublicationQueueBean>> currentLiveInstancePublicationQueueBeans = instancePublicationQueueBeans;
              Set<PublicationQueueBean> currentPublicationQueueBeans = currentLiveInstancePublicationQueueBeans.get(serverBaseUrl);
              if(currentPublicationQueueBeans == null)
              {
                currentPublicationQueueBeans = new HashSet<PublicationQueueBean>();
                currentLiveInstancePublicationQueueBeans.put(serverBaseUrl, currentPublicationQueueBeans);
              }
              currentPublicationQueueBeans.addAll(beans);
            }
            //logger.warn("The instance seems to be down. Let's try later instead.");
          }
          else
          {
            logger.warn("The live server at " + serverBaseUrl + " does not seem to be registered any more. Removing it's queue.");
          }
        }
      }
 
      try
      {
        Thread.sleep(10000);
        }
      catch( InterruptedException e )
      {
        logger.error("Interrupted Exception caught");
        }
    }
  }

 
    /**
     * This method post information to an URL and returns a string.It throws
     * an exception if anything goes wrong.
     * (Works like most 'doPost' methods)
     *
     * @param urlAddress The address of the URL you would like to post to.
     * @param inHash The parameters you would like to post to the URL.
     * @return The result of the postToUrl method as a string.
     * @exception java.lang.Exception
     */
   
    private String postToUrl(String urlAddress, Hashtable map) throws Exception
    {       
        URL url = new URL(urlAddress);
        URLConnection urlConn = url.openConnection();
        urlConn.setConnectTimeout(10000);
        urlConn.setReadTimeout(10000);
        urlConn.setAllowUserInteraction(false);
        urlConn.setDoOutput (true);
        urlConn.setDoInput (true);
        urlConn.setUseCaches (false);
        urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        PrintWriter printout = new PrintWriter(urlConn.getOutputStream(), true);
        String argString = "";
        if(map != null)
        {
            argString = toEncodedString(map);
        }
        printout.print(argString);
        printout.flush();
        printout.close ();
        InputStream inStream = null;
        inStream = urlConn.getInputStream();
        InputStreamReader inStreamReader = new InputStreamReader(inStream);
        BufferedReader buffer = new BufferedReader(inStreamReader);           
        StringBuffer strbuf = new StringBuffer();  
        String line;
        while((line = buffer.readLine()) != null)
        {
            strbuf.append(line);
        }                                             
        String readData = strbuf.toString();  
        buffer.close();
        return readData;            
    }
 
 
    /**
   * Encodes a hash table to an URL encoded string.
   *
   * @param inHash The hash table you would like to encode
   * @return A URL encoded string.
   */
   
  private String toEncodedString(Hashtable inHash) throws Exception
  {
      StringBuffer buffer = new StringBuffer();
      Enumeration names = inHash.keys();
      while(names.hasMoreElements())
      {
          String name = names.nextElement().toString();
          String value = inHash.get(name).toString();
          buffer.append(URLEncoder.encode(name, "UTF-8") + "=" + URLEncoder.encode(value, "UTF-8"));
          if(names.hasMoreElements())
          {
              buffer.append("&");
          }
      }
      return buffer.toString();
  }

}
TOP

Related Classes of org.infoglue.deliver.util.ioqueue.PublicationQueue

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.