Package org.openntf.news.http.core

Source Code of org.openntf.news.http.core.WriteCacheJob$WriteClicksJob

package org.openntf.news.http.core;

/*
* Copyright IBM, 2012
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Author: Niklas Heidloff - niklas_heidloff@de.ibm.com
*/

/*
* 2012-09-29 - Jesse Gallagher
* Modified view looping to setAutoUpdate(false), only run
* .getColumnValues() once per entry, and to use .setPreferJavaDates.
* Also fixed a stream-object leak in save/restoreState
*/

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
import lotus.domino.*;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import com.ibm.domino.xsp.module.nsf.ThreadSessionExecutor;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class WriteCacheJob {

  public static void cancel() {
    synchronized (WriteCacheJob.class) {
      if (runningJob != null) {
        runningJob.cancel = true;
      }
    }
  }

  public static void start(HashSet<Click> clicks, String dbName) {
    synchronized (WriteCacheJob.class) {
      if (runningJob == null) {
        runningJob = new WriteClicksJob("News.nsf - Save Clicks", clicks, dbName);
        runningJob.addJobChangeListener(new JobChangeAdapter() {
          @Override
          public void done(IJobChangeEvent event) {
            runningJob = null;
          }
        });
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
          public Object run() {
            runningJob.schedule();
            return null;
          }
        });
      }
    }
  }

  private static WriteClicksJob runningJob;

  private static final class WriteClicksJob extends Job {

    private boolean cancel;

    @SuppressWarnings("unused")
    private String _title;
    private HashSet<Click> _clicks;
    private String _dbName;
    private ThreadSessionExecutor<IStatus> executor;

    public WriteClicksJob(String title, HashSet<Click> clicks, String dbName) {
      super(title);
      _title = title;
      _clicks = clicks;
      _dbName = dbName;

      this.executor = new ThreadSessionExecutor<IStatus>() {
        @SuppressWarnings("unchecked")
        @Override
        protected IStatus run(Session session) throws NotesException {

          main: if (cancel) {
            break main;
          }
        Map<String, Set<Click>> clicksByNID = new HashMap<String, Set<Click>>();

        for(Click click : _clicks) {
          if (clicksByNID.containsKey(click.getNID())) {
            Set<Click> clicks = clicksByNID.get(click.getNID());
            clicks.add(click);
            clicks = removeDublicateIPAddresses(clicks);
            clicksByNID.put(click.getNID(), clicks);
          } else {
            HashSet<Click> newHashSet = new HashSet<Click>();
            newHashSet.add(click);
            clicksByNID.put(click.getNID(), newHashSet);
          }
        }
        Database db = null;
        Document doc = null;
        View newsByIDView = null;
        try {
          db = session.getDatabase(null, _dbName);

          if (db != null) {
            if (!db.isOpen())
              db.open();
            if (db.isOpen()) {
              newsByIDView = db.getView("NewsAllByID");
              newsByIDView.setAutoUpdate(false);

              Iterator iterator = clicksByNID.entrySet().iterator();
              while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator
                .next();
                String nID = (String) entry.getKey();
                Set<Click> clicksFromOneNID = (Set<Click>) entry.getValue();
                session.setConvertMime(false) ;
                doc = newsByIDView.getDocumentByKey(nID,
                    true);
                if (doc != null) {
                  HashSet<Click> storedClicks = (HashSet<Click>)restoreState(session, doc, "NClicks");
                  if (storedClicks != null) {
                    storedClicks.addAll(clicksFromOneNID);
                    clicksFromOneNID = storedClicks;
                  }
                  clicksFromOneNID = removeDublicateIPAddresses(clicksFromOneNID);

                  doc.replaceItemValue("NClicksTotal", clicksFromOneNID.size());
                  doc.replaceItemValue("NClicksLastWeek", getClicksLastWeek(clicksFromOneNID));
                  saveState(session, (Serializable)clicksFromOneNID, doc, "NClicks");
                  doc.save();           
                  session.setConvertMime(true) ;

                  doc.recycle();
                }
                iterator.remove();
              }
            }
          }
        } catch (NotesException e) {
          e.printStackTrace();
        } finally {
          if (newsByIDView != null)
            newsByIDView.recycle();
          if (db != null)
            db.recycle();
        }

        return Status.OK_STATUS;
        }

        int getClicksLastWeek(Set<Click> clicks) {
          int output = 0;
          try {
            for(Click click : clicks) {
              Calendar now = Calendar.getInstance();
              Calendar last = Calendar.getInstance();
              now.setTime(new Date());
              last.setTime(click.getDate());
              long millisecondsNow = now.getTimeInMillis();
              long millisecondsLast = last.getTimeInMillis();
              long diff = millisecondsNow - millisecondsLast;
              long diffDays = diff / (24 * 60 * 60 * 1000);

              if (diffDays <= 7) output = output + 1;
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
          return output;
        }

        Set<Click> removeDublicateIPAddresses(Set<Click> clicks) {
          Set<Click> output = new HashSet<Click>();
          Map<String, Click> uniquesOnly = new HashMap<String, Click>();

          for(Click click : clicks) {
            if (!uniquesOnly.containsKey(click.getIP())) {
              uniquesOnly.put(click.getIP(), click);
            }
          }
          for(Map.Entry<String, Click> entry : uniquesOnly.entrySet()) {
            Click click = entry.getValue();
            output.add(click);
          }
          return output;
        }

        public Serializable restoreState(Session session, Document doc, String itemName) {
          try {
            boolean convertMime = session.isConvertMime();
            session.setConvertMime(false);

            Serializable result = null;
            Stream mimeStream = session.createStream();
            MIMEEntity entity = doc.getMIMEEntity(itemName);
            entity.getContentAsBytes(mimeStream);

            ByteArrayOutputStream streamOut = new ByteArrayOutputStream();
            mimeStream.getContents(streamOut);
            mimeStream.close();
            mimeStream.recycle();

            byte[] stateBytes = streamOut.toByteArray();
            ByteArrayInputStream byteStream = new ByteArrayInputStream(stateBytes);
            ObjectInputStream objectStream;
            if(entity.getHeaders().toLowerCase().contains("content-encoding: gzip")) {
              GZIPInputStream zipStream = new GZIPInputStream(byteStream);
              objectStream = new ObjectInputStream(zipStream);
            } else {
              objectStream = new ObjectInputStream(byteStream);
            }
            Serializable restored = (Serializable)objectStream.readObject();
            result = restored;

            entity.recycle();

            session.setConvertMime(convertMime);

            return result;
          } catch(Exception e) { }
          return null;
        }

        @SuppressWarnings("unused")
        public void saveStateGZIP(Session session, Serializable object, Document doc, String itemName) {
          try {
            boolean convertMime = session.isConvertMime();
            session.setConvertMime(false);

            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            ObjectOutputStream objectStream = new ObjectOutputStream(new GZIPOutputStream(byteStream));
            objectStream.writeObject(object);
            objectStream.flush();
            objectStream.close();

            MIMEEntity entity = null;
            MIMEEntity previousState = doc.getMIMEEntity(itemName);
            if (previousState == null) {
              entity = doc.createMIMEEntity(itemName);
            } else {
              entity = previousState;
            }

            Stream mimeStream = session.createStream();
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteStream.toByteArray());
            mimeStream.setContents(byteIn);
            entity.setContentFromBytes(mimeStream, "application/x-java-serialized-object", MIMEEntity.ENC_NONE);

            MIMEHeader header = entity.getNthHeader("Content-Encoding");
            if(header == null) { header = entity.createHeader("Content-Encoding"); }
            header.setHeaderVal("gzip");

            header.recycle();
            entity.recycle();
            mimeStream.close();
            mimeStream.recycle();

            session.setConvertMime(convertMime);
          } catch (Exception e) { }
        }
        public void saveState(Session session, Serializable object, Document doc, String itemName) {
          try {
            boolean convertMime = session.isConvertMime();
            session.setConvertMime(false);

            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            ObjectOutputStream objectStream = new ObjectOutputStream(byteStream);
            objectStream.writeObject(object);
            objectStream.flush();
            objectStream.close();

            MIMEEntity entity = null;
            MIMEEntity previousState = doc.getMIMEEntity(itemName);
            if (previousState == null) {
              entity = doc.createMIMEEntity(itemName);
            } else {
              entity = previousState;
            }

            Stream mimeStream = session.createStream();
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteStream.toByteArray());
            mimeStream.setContents(byteIn);
            entity.setContentFromBytes(mimeStream, "application/x-java-serialized-object", MIMEEntity.ENC_NONE);

            entity.recycle();
            mimeStream.close();
            mimeStream.recycle();

            session.setConvertMime(convertMime);
          } catch (Exception e) { e.printStackTrace(); }
        }
      };
    }

    @Override
    protected IStatus run(IProgressMonitor monitor) {
      try {
        return executor.run();
      } catch (Exception ex) {
        return Status.CANCEL_STATUS;
      }
    }
  };
}
TOP

Related Classes of org.openntf.news.http.core.WriteCacheJob$WriteClicksJob

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.