Package org.glassfish.ejb.persistent.timer

Source Code of org.glassfish.ejb.persistent.timer.TimerState

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package org.glassfish.ejb.persistent.timer;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Lob;
import javax.persistence.NamedQuery;
import javax.persistence.NamedQueries;
import javax.persistence.PostLoad;
import javax.persistence.Table;
import javax.persistence.Transient;

import java.io.Serializable;
import java.io.IOException;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.sun.ejb.EJBUtils;
import com.sun.ejb.Container;
import com.sun.ejb.containers.EJBTimerService;
import com.sun.ejb.containers.EJBTimerSchedule;
import com.sun.logging.LogDomains;

/**
* TimerState represents the state of a persistent EJB Timer. 
* It is part of the EJB container and is implemented as an Entity.
*
* @author Marina Vatkina
*/
@Entity(name="Timer")
@NamedQueries({
    @NamedQuery(
        name="findTimerIdsByContainer",
        query="SELECT t.timerId FROM Timer t WHERE t.containerId = ?1"
    ),
    @NamedQuery(
        name="findTimerIdsByContainerAndState",
        query="SELECT t.timerId FROM Timer t WHERE t.containerId = ?1 AND t.state=?2"
    ),
    @NamedQuery(
        name="findTimerIdsByContainersAndState",
        query="SELECT t.timerId FROM Timer t WHERE t.state=?2 AND t.containerId IN ?1"
    ),
    @NamedQuery(
        name="findTimerIdsByContainerAndOwner",
        query="SELECT t.timerId FROM Timer t WHERE t.containerId = ?1 AND t.ownerId=?2"
    ),
    @NamedQuery(
        name="findTimerIdsByContainerAndOwnerAndState",
        query="SELECT t.timerId FROM Timer t WHERE t.containerId = ?1 AND t.ownerId=?2 AND t.state=?3"
    ),
    @NamedQuery(
        name="findTimerIdsByOwner",
        query="SELECT t.timerId FROM Timer t WHERE t.ownerId = ?1"
    ),
    @NamedQuery(
        name="findTimerIdsByOwnerAndState",
        query="SELECT t.timerId FROM Timer t WHERE t.ownerId = ?1 AND t.state=?2"
    ),
    @NamedQuery(
        name="findTimersByContainer",
        query="SELECT t FROM Timer t WHERE t.containerId = ?1"
    ),
    @NamedQuery(
        name="findTimersByContainerAndState",
        query="SELECT t FROM Timer t WHERE t.containerId = ?1 AND t.state=?2"
    ),
    @NamedQuery(
        name="findTimersByContainerAndOwner",
        query="SELECT t FROM Timer t WHERE t.containerId = ?1 AND t.ownerId=?2"
    ),
    @NamedQuery(
        name="findTimersByContainerAndOwnerAndState",
        query="SELECT t FROM Timer t WHERE t.containerId = ?1 AND t.ownerId=?2 AND t.state=?3"
    ),
    @NamedQuery(
        // Used also for timer migration, so needs to have predictable return order
        name="findTimersByOwner",
        query="SELECT t FROM Timer t WHERE t.ownerId = ?1 ORDER BY t.timerId"
    ),
    @NamedQuery(
        name="findTimersByOwnerAndState",
        query="SELECT t FROM Timer t WHERE t.ownerId = ?1 AND t.state=?2"
    ),
    @NamedQuery(
        name="countTimersByApplication",
        query="SELECT COUNT(t) FROM Timer t WHERE t.applicationId = ?1"
    ),
    @NamedQuery(
        name="countTimersByOwner",
        query="SELECT COUNT(t) FROM Timer t WHERE t.ownerId = ?1"
    ),
    @NamedQuery(
        name="countTimersByOwnerAndState",
        query="SELECT COUNT(t) FROM Timer t WHERE t.ownerId = ?1 AND t.state=?2"
    ),
    @NamedQuery(
        name="countTimersByContainer",
        query="SELECT COUNT(t) FROM Timer t WHERE t.containerId = ?1"
    ),
    @NamedQuery(
        name="countTimersByContainerAndState",
        query="SELECT COUNT(t) FROM Timer t WHERE t.containerId = ?1 AND t.state=?2"
    ),
    @NamedQuery(
        name="countTimersByContainerAndOwner",
        query="SELECT COUNT(t) FROM Timer t WHERE t.containerId = ?1 AND t.ownerId=?2"
    ),
    @NamedQuery(
        name="countTimersByContainerAndOwnerAndState",
        query="SELECT COUNT(t) FROM Timer t WHERE t.containerId = ?1 AND t.ownerId=?2 AND t.state=?3"
    )
    ,
    @NamedQuery(
        name="updateTimersFromOwnerToNewOwner",
        query="UPDATE Timer t SET t.ownerId = :toOwner WHERE t.ownerId = :fromOwner"
    )
    ,
    @NamedQuery(
        name="deleteTimersByContainer",
        query="DELETE FROM Timer t WHERE t.containerId = :containerId"
    )
    ,
    @NamedQuery(
        name="deleteTimersByApplication",
        query="DELETE FROM Timer t WHERE t.applicationId = :applicationId"
    )
})
@Table(name="EJB__TIMER__TBL")
@IdClass(com.sun.ejb.containers.TimerPrimaryKey.class)
public class TimerState implements Serializable {

    //
    // Persistence fields and access methods
    //

    @Id
    @Column(name="TIMERID")
    private String timerId;

    @Column(name="CREATIONTIMERAW")
    private long creationTimeRaw;

    @Column(name="INITIALEXPIRATIONRAW")
    private long initialExpirationRaw;

    @Column(name="LASTEXPIRATIONRAW")
    private long lastExpirationRaw;

    @Column(name="INTERVALDURATION")
    private long intervalDuration;

    @Column(name="STATE")
    private int state;

    @Column(name="CONTAINERID")
    private long containerId;

    @Column(name="APPLICATIONID")
    private long applicationId;

    @Column(name="PKHASHCODE")
    private int pkHashCode;

    @Column(name="OWNERID")
    private String ownerId;

    @Column(name="SCHEDULE")
    private String schedule;

    @Lob
    @Basic(fetch=FetchType.LAZY)
    @Column(name="BLOB")
    private Blob blob;

    // primary key
    String getTimerId() {
        return timerId;
    }

    void setTimerId(String timerId) {
        this.timerId = timerId;
    }

    String getOwnerId() {
        return ownerId;
    }

    void setOwnerId(String ownerId) {
        this.ownerId = ownerId;
    }

    long getCreationTimeRaw() {
        return creationTimeRaw;
    }

    void setCreationTimeRaw(long creationTime) {
        creationTimeRaw = creationTime;
    }

    long getInitialExpirationRaw() {
        return initialExpirationRaw;
    }

    void setInitialExpirationRaw(long initialExpiration) {
        initialExpirationRaw = initialExpiration;
    }

    long getLastExpirationRaw() {
        return lastExpirationRaw;
    }

    void setLastExpirationRaw(long lastExpiration) {
        lastExpirationRaw = lastExpiration;
    }

    long getIntervalDuration() {
        return intervalDuration;
    }

    void setIntervalDuration(long intervalDuration) {
        this.intervalDuration = intervalDuration;
    }

    int getState() {
        return state;
    }

    void setState(int state) {
        this.state = state;
    }

    long getContainerId() {
        return containerId;
    }

    void setContainerId(long containerId) {
        this.containerId = containerId;
    }

    long getApplicationId() {
        return applicationId;
    }

    void setApplicationId(long applicationId) {
        this.applicationId = applicationId;
    }

    String getSchedule() {
        return schedule;
    }

    void setSchedule(String schedule) {
        this.schedule = schedule;
    }

    Blob getBlob() {
        return blob;
    }

    void setBlob(Blob blob) {
        this.blob = blob;
    }

    int getPkHashCode() {
        return pkHashCode;
    }

    void setPkHashCode(int pkHash) {
        pkHashCode = pkHash;
    }

    EJBTimerSchedule getTimerSchedule() {
        return timerSchedule_;
    }

    //
    // These data members contain derived state for
    // some immutable fields.
    //

    // deserialized state from blob
    @Transient
    private boolean blobLoaded_;

    private transient Object timedObjectPrimaryKey_;
    private transient Serializable info_;

    // Dates
    private transient Date creationTime_;
    private transient Date initialExpiration_;
    private transient Date lastExpiration_;

    private transient EJBTimerSchedule timerSchedule_;
   
    TimerState () {
    }

    TimerState (String timerId, long containerId, long applicationId,
             String ownerId, Object timedObjectPrimaryKey,
             Date initialExpiration, long intervalDuration,
             EJBTimerSchedule schedule, Serializable info) throws IOException {

        this.timerId = timerId;
        this.ownerId = ownerId;

        creationTime_ = new Date();
  creationTimeRaw = creationTime_.getTime();

        initialExpirationRaw = initialExpiration.getTime();
        initialExpiration_ = initialExpiration;

        lastExpirationRaw = 0;
        lastExpiration_ = null;

        this.intervalDuration = intervalDuration;
        timerSchedule_ = schedule;
        if (timerSchedule_ != null) {
            this.schedule = timerSchedule_.getScheduleAsString();
        }

        this.containerId = containerId;
        this.applicationId = applicationId;

        timedObjectPrimaryKey_  = timedObjectPrimaryKey;
        info_ = info;
        blobLoaded_ = true;

        blob = new Blob(timedObjectPrimaryKey, info);
        state = EJBTimerService.STATE_ACTIVE;
    }

    String stateToString() {
        return EJBTimerService.timerStateToString(state);
    }  

    private void loadBlob(ClassLoader cl) {
        try {
            timedObjectPrimaryKey_  = blob.getTimedObjectPrimaryKey(cl);
            info_ = blob.getInfo(cl);
            blobLoaded_ = true;
        } catch(Exception e) {
            RuntimeException ex = new RuntimeException();
            ex.initCause(e);
            throw ex;
        }
    }

    @PostLoad
    void load() {

        lastExpiration_ = (lastExpirationRaw > 0) ?
            new Date(lastExpirationRaw) : null;
       
        // Populate derived state of immutable persistent fields.
        creationTime_ = new Date(creationTimeRaw);
        initialExpiration_ = new Date(initialExpirationRaw);
        if (schedule != null) {
            timerSchedule_ = new EJBTimerSchedule(schedule);
        }

        // Lazily deserialize Blob state.  This makes the
        // Timer bootstrapping code easier, since some of the Timer
        // state must be loaded from the database before the
        // container and application classloader are known.
        timedObjectPrimaryKey_ = null;
        info_       = null;
        blobLoaded_ = false;
    }

    boolean repeats() {
        return (intervalDuration > 0);
    }

    Serializable getInfo() {
        if( !blobLoaded_ ) {
            loadBlob(EJBTimerService.getEJBTimerService().getTimerClassLoader(getContainerId()));
        }
        return info_;
    }

    Object getTimedObjectPrimaryKey() {
        if( !blobLoaded_ ) {
            loadBlob(EJBTimerService.getEJBTimerService().getTimerClassLoader(getContainerId()));
        }
        return timedObjectPrimaryKey_;
    }  

    Date getCreationTime() {
        return creationTime_;
    }

    Date getInitialExpiration() {
        return initialExpiration_;
    }

    Date getLastExpiration() {
        return lastExpiration_;
    }

    void setLastExpiration(Date lastExpiration) {
        // can be null
        lastExpiration_ = lastExpiration;
        lastExpirationRaw = (lastExpiration != null) ?
            lastExpiration.getTime() : 0;
    }

    boolean isActive() {
        return (state == EJBTimerService.STATE_ACTIVE);
    }

    boolean isCancelled() {
        return (state == EJBTimerService.STATE_CANCELLED);
    }

    /**
     * Many DBs have a limitation that at most one field per DB
     * can hold binary data.  As a workaround, store both EJBLocalObject
     * and "info" as a single Serializable blob.  This is necessary
     * since primary key of EJBLocalObject could be a compound object.
     * This class also isolates the portion of Timer data that is
     * associated with the TimedObject itself.  During deserialization,
     * we must use the application class loader for the timed object,
     * since both the primary key and info object can be application
     * classes.
     *
     */
    static class Blob implements Serializable {

        private byte[] primaryKeyBytes_ = null;
        private byte[] infoBytes_ = null;

        // Allow deserialization even if the class has changed
        private static final long serialVersionUID = 5022674828003386360L;

        private static final Logger logger = LogDomains.getLogger(TimerState.class, LogDomains.EJB_LOGGER);

        Blob() {
        }

        Blob(Object primaryKey, Serializable info)
            throws IOException {
            if( primaryKey != null ) {
                primaryKeyBytes_ = EJBUtils.serializeObject(primaryKey);
            }
            if( info != null ) {
                infoBytes_ = EJBUtils.serializeObject(info);
            }
        }

        // To be used to replace TimerBean.Blob on v2.x upgrade
        Blob(byte[] primaryKeyBytes, byte[] infoBytes) {
            primaryKeyBytes_ = primaryKeyBytes;
            infoBytes_ = infoBytes;
        }
       
        Object getTimedObjectPrimaryKey(ClassLoader cl)
            throws Exception {
            Object pKey = null;
            if( primaryKeyBytes_ != null) {
                pKey = EJBUtils.deserializeObject(primaryKeyBytes_, cl);
                if( logger.isLoggable(Level.FINER) ) {
                    logger.log(Level.FINER, "Deserialized blob : " + pKey);
                }
            }
            return pKey;
        }

        Serializable getInfo(ClassLoader cl) throws Exception {
            Serializable info = null;
            if( infoBytes_ != null) {
                info = (Serializable)EJBUtils.deserializeObject(infoBytes_, cl);
                if( logger.isLoggable(Level.FINER) ) {
                    logger.log(Level.FINER, "Deserialized blob : " + info);
                }
            }
            return info;
        }
    }

}
TOP

Related Classes of org.glassfish.ejb.persistent.timer.TimerState

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.