| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>SimpleSession.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Shiro :: Core</a> > <a href="index.source.html" class="el_package">org.apache.shiro.session.mgt</a> > <span class="el_source">SimpleSession.java</span></div><h1>SimpleSession.java</h1><pre class="source lang-java linenums">/* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| package org.apache.shiro.session.mgt; |
| |
| import org.apache.shiro.session.ExpiredSessionException; |
| import org.apache.shiro.session.InvalidSessionException; |
| import org.apache.shiro.session.StoppedSessionException; |
| import org.apache.shiro.util.CollectionUtils; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.Serializable; |
| import java.text.DateFormat; |
| import java.util.*; |
| |
| |
| /** |
| * Simple {@link org.apache.shiro.session.Session} JavaBeans-compatible POJO implementation, intended to be used on the |
| * business/server tier. |
| * |
| * @since 0.1 |
| */ |
| public class SimpleSession implements ValidatingSession, Serializable { |
| |
| // Serialization reminder: |
| // You _MUST_ change this number if you introduce a change to this class |
| // that is NOT serialization backwards compatible. Serialization-compatible |
| // changes do not require a change to this number. If you need to generate |
| // a new number in this case, use the JDK's 'serialver' program to generate it. |
| private static final long serialVersionUID = -7125642695178165650L; |
| |
| //TODO - complete JavaDoc |
| <span class="fc" id="L52"> private transient static final Logger log = LoggerFactory.getLogger(SimpleSession.class);</span> |
| |
| protected static final long MILLIS_PER_SECOND = 1000; |
| protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND; |
| protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE; |
| |
| //serialization bitmask fields. DO NOT CHANGE THE ORDER THEY ARE DECLARED! |
| <span class="fc" id="L59"> static int bitIndexCounter = 0;</span> |
| <span class="fc" id="L60"> private static final int ID_BIT_MASK = 1 << bitIndexCounter++;</span> |
| <span class="fc" id="L61"> private static final int START_TIMESTAMP_BIT_MASK = 1 << bitIndexCounter++;</span> |
| <span class="fc" id="L62"> private static final int STOP_TIMESTAMP_BIT_MASK = 1 << bitIndexCounter++;</span> |
| <span class="fc" id="L63"> private static final int LAST_ACCESS_TIME_BIT_MASK = 1 << bitIndexCounter++;</span> |
| <span class="fc" id="L64"> private static final int TIMEOUT_BIT_MASK = 1 << bitIndexCounter++;</span> |
| <span class="fc" id="L65"> private static final int EXPIRED_BIT_MASK = 1 << bitIndexCounter++;</span> |
| <span class="fc" id="L66"> private static final int HOST_BIT_MASK = 1 << bitIndexCounter++;</span> |
| <span class="fc" id="L67"> private static final int ATTRIBUTES_BIT_MASK = 1 << bitIndexCounter++;</span> |
| |
| // ============================================================== |
| // NOTICE: |
| // |
| // The following fields are marked as transient to avoid double-serialization. |
| // They are in fact serialized (even though 'transient' usually indicates otherwise), |
| // but they are serialized explicitly via the writeObject and readObject implementations |
| // in this class. |
| // |
| // If we didn't declare them as transient, the out.defaultWriteObject(); call in writeObject would |
| // serialize all non-transient fields as well, effectively doubly serializing the fields (also |
| // doubling the serialization size). |
| // |
| // This finding, with discussion, was covered here: |
| // |
| // http://mail-archives.apache.org/mod_mbox/shiro-user/201109.mbox/%3C4E81BCBD.8060909@metaphysis.net%3E |
| // |
| // ============================================================== |
| private transient Serializable id; |
| private transient Date startTimestamp; |
| private transient Date stopTimestamp; |
| private transient Date lastAccessTime; |
| private transient long timeout; |
| private transient boolean expired; |
| private transient String host; |
| private transient Map<Object, Object> attributes; |
| |
| <span class="fc" id="L95"> public SimpleSession() {</span> |
| <span class="fc" id="L96"> this.timeout = DefaultSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT; //TODO - remove concrete reference to DefaultSessionManager</span> |
| <span class="fc" id="L97"> this.startTimestamp = new Date();</span> |
| <span class="fc" id="L98"> this.lastAccessTime = this.startTimestamp;</span> |
| <span class="fc" id="L99"> }</span> |
| |
| public SimpleSession(String host) { |
| <span class="fc" id="L102"> this();</span> |
| <span class="fc" id="L103"> this.host = host;</span> |
| <span class="fc" id="L104"> }</span> |
| |
| public Serializable getId() { |
| <span class="fc" id="L107"> return this.id;</span> |
| } |
| |
| public void setId(Serializable id) { |
| <span class="fc" id="L111"> this.id = id;</span> |
| <span class="fc" id="L112"> }</span> |
| |
| public Date getStartTimestamp() { |
| <span class="fc" id="L115"> return startTimestamp;</span> |
| } |
| |
| public void setStartTimestamp(Date startTimestamp) { |
| <span class="fc" id="L119"> this.startTimestamp = startTimestamp;</span> |
| <span class="fc" id="L120"> }</span> |
| |
| /** |
| * Returns the time the session was stopped, or <tt>null</tt> if the session is still active. |
| * <p/> |
| * A session may become stopped under a number of conditions: |
| * <ul> |
| * <li>If the user logs out of the system, their current session is terminated (released).</li> |
| * <li>If the session expires</li> |
| * <li>The application explicitly calls {@link #stop()}</li> |
| * <li>If there is an internal system error and the session state can no longer accurately |
| * reflect the user's behavior, such in the case of a system crash</li> |
| * </ul> |
| * <p/> |
| * Once stopped, a session may no longer be used. It is locked from all further activity. |
| * |
| * @return The time the session was stopped, or <tt>null</tt> if the session is still |
| * active. |
| */ |
| public Date getStopTimestamp() { |
| <span class="fc" id="L140"> return stopTimestamp;</span> |
| } |
| |
| public void setStopTimestamp(Date stopTimestamp) { |
| <span class="nc" id="L144"> this.stopTimestamp = stopTimestamp;</span> |
| <span class="nc" id="L145"> }</span> |
| |
| public Date getLastAccessTime() { |
| <span class="fc" id="L148"> return lastAccessTime;</span> |
| } |
| |
| public void setLastAccessTime(Date lastAccessTime) { |
| <span class="fc" id="L152"> this.lastAccessTime = lastAccessTime;</span> |
| <span class="fc" id="L153"> }</span> |
| |
| /** |
| * Returns true if this session has expired, false otherwise. If the session has |
| * expired, no further user interaction with the system may be done under this session. |
| * |
| * @return true if this session has expired, false otherwise. |
| */ |
| public boolean isExpired() { |
| <span class="fc" id="L162"> return expired;</span> |
| } |
| |
| public void setExpired(boolean expired) { |
| <span class="fc" id="L166"> this.expired = expired;</span> |
| <span class="fc" id="L167"> }</span> |
| |
| public long getTimeout() { |
| <span class="fc" id="L170"> return timeout;</span> |
| } |
| |
| public void setTimeout(long timeout) { |
| <span class="fc" id="L174"> this.timeout = timeout;</span> |
| <span class="fc" id="L175"> }</span> |
| |
| public String getHost() { |
| <span class="fc" id="L178"> return host;</span> |
| } |
| |
| public void setHost(String host) { |
| <span class="nc" id="L182"> this.host = host;</span> |
| <span class="nc" id="L183"> }</span> |
| |
| public Map<Object, Object> getAttributes() { |
| <span class="fc" id="L186"> return attributes;</span> |
| } |
| |
| public void setAttributes(Map<Object, Object> attributes) { |
| <span class="fc" id="L190"> this.attributes = attributes;</span> |
| <span class="fc" id="L191"> }</span> |
| |
| public void touch() { |
| <span class="fc" id="L194"> this.lastAccessTime = new Date();</span> |
| <span class="fc" id="L195"> }</span> |
| |
| public void stop() { |
| <span class="pc bpc" id="L198" title="1 of 2 branches missed."> if (this.stopTimestamp == null) {</span> |
| <span class="fc" id="L199"> this.stopTimestamp = new Date();</span> |
| } |
| <span class="fc" id="L201"> }</span> |
| |
| protected boolean isStopped() { |
| <span class="pc bpc" id="L204" title="1 of 2 branches missed."> return getStopTimestamp() != null;</span> |
| } |
| |
| protected void expire() { |
| <span class="fc" id="L208"> stop();</span> |
| <span class="fc" id="L209"> this.expired = true;</span> |
| <span class="fc" id="L210"> }</span> |
| |
| /** |
| * @since 0.9 |
| */ |
| public boolean isValid() { |
| <span class="pc bpc" id="L216" title="2 of 4 branches missed."> return !isStopped() && !isExpired();</span> |
| } |
| |
| /** |
| * Determines if this session is expired. |
| * |
| * @return true if the specified session has expired, false otherwise. |
| */ |
| protected boolean isTimedOut() { |
| |
| <span class="pc bpc" id="L226" title="1 of 2 branches missed."> if (isExpired()) {</span> |
| <span class="nc" id="L227"> return true;</span> |
| } |
| |
| <span class="fc" id="L230"> long timeout = getTimeout();</span> |
| |
| <span class="pc bpc" id="L232" title="1 of 2 branches missed."> if (timeout >= 0l) {</span> |
| |
| <span class="fc" id="L234"> Date lastAccessTime = getLastAccessTime();</span> |
| |
| <span class="pc bpc" id="L236" title="1 of 2 branches missed."> if (lastAccessTime == null) {</span> |
| <span class="nc" id="L237"> String msg = "session.lastAccessTime for session with id [" +</span> |
| <span class="nc" id="L238"> getId() + "] is null. This value must be set at " +</span> |
| "least once, preferably at least upon instantiation. Please check the " + |
| <span class="nc" id="L240"> getClass().getName() + " implementation and ensure " +</span> |
| "this value will be set (perhaps in the constructor?)"; |
| <span class="nc" id="L242"> throw new IllegalStateException(msg);</span> |
| } |
| |
| // Calculate at what time a session would have been last accessed |
| // for it to be expired at this point. In other words, subtract |
| // from the current time the amount of time that a session can |
| // be inactive before expiring. If the session was last accessed |
| // before this time, it is expired. |
| <span class="fc" id="L250"> long expireTimeMillis = System.currentTimeMillis() - timeout;</span> |
| <span class="fc" id="L251"> Date expireTime = new Date(expireTimeMillis);</span> |
| <span class="fc" id="L252"> return lastAccessTime.before(expireTime);</span> |
| } else { |
| <span class="nc bnc" id="L254" title="All 2 branches missed."> if (log.isTraceEnabled()) {</span> |
| <span class="nc" id="L255"> log.trace("No timeout for session with id [" + getId() +</span> |
| "]. Session is not considered expired."); |
| } |
| } |
| |
| <span class="nc" id="L260"> return false;</span> |
| } |
| |
| public void validate() throws InvalidSessionException { |
| //check for stopped: |
| <span class="pc bpc" id="L265" title="1 of 2 branches missed."> if (isStopped()) {</span> |
| //timestamp is set, so the session is considered stopped: |
| <span class="nc" id="L267"> String msg = "Session with id [" + getId() + "] has been " +</span> |
| "explicitly stopped. No further interaction under this session is " + |
| "allowed."; |
| <span class="nc" id="L270"> throw new StoppedSessionException(msg);</span> |
| } |
| |
| //check for expiration |
| <span class="fc bfc" id="L274" title="All 2 branches covered."> if (isTimedOut()) {</span> |
| <span class="fc" id="L275"> expire();</span> |
| |
| //throw an exception explaining details of why it expired: |
| <span class="fc" id="L278"> Date lastAccessTime = getLastAccessTime();</span> |
| <span class="fc" id="L279"> long timeout = getTimeout();</span> |
| |
| <span class="fc" id="L281"> Serializable sessionId = getId();</span> |
| |
| <span class="fc" id="L283"> DateFormat df = DateFormat.getInstance();</span> |
| <span class="fc" id="L284"> String msg = "Session with id [" + sessionId + "] has expired. " +</span> |
| <span class="fc" id="L285"> "Last access time: " + df.format(lastAccessTime) +</span> |
| <span class="fc" id="L286"> ". Current time: " + df.format(new Date()) +</span> |
| ". Session timeout is set to " + timeout / MILLIS_PER_SECOND + " seconds (" + |
| timeout / MILLIS_PER_MINUTE + " minutes)"; |
| <span class="pc bpc" id="L289" title="1 of 2 branches missed."> if (log.isTraceEnabled()) {</span> |
| <span class="fc" id="L290"> log.trace(msg);</span> |
| } |
| <span class="fc" id="L292"> throw new ExpiredSessionException(msg);</span> |
| } |
| <span class="fc" id="L294"> }</span> |
| |
| private Map<Object, Object> getAttributesLazy() { |
| <span class="fc" id="L297"> Map<Object, Object> attributes = getAttributes();</span> |
| <span class="fc bfc" id="L298" title="All 2 branches covered."> if (attributes == null) {</span> |
| <span class="fc" id="L299"> attributes = new HashMap<Object, Object>();</span> |
| <span class="fc" id="L300"> setAttributes(attributes);</span> |
| } |
| <span class="fc" id="L302"> return attributes;</span> |
| } |
| |
| public Collection<Object> getAttributeKeys() throws InvalidSessionException { |
| <span class="fc" id="L306"> Map<Object, Object> attributes = getAttributes();</span> |
| <span class="pc bpc" id="L307" title="1 of 2 branches missed."> if (attributes == null) {</span> |
| <span class="nc" id="L308"> return Collections.emptySet();</span> |
| } |
| <span class="fc" id="L310"> return attributes.keySet();</span> |
| } |
| |
| public Object getAttribute(Object key) { |
| <span class="fc" id="L314"> Map<Object, Object> attributes = getAttributes();</span> |
| <span class="fc bfc" id="L315" title="All 2 branches covered."> if (attributes == null) {</span> |
| <span class="fc" id="L316"> return null;</span> |
| } |
| <span class="fc" id="L318"> return attributes.get(key);</span> |
| } |
| |
| public void setAttribute(Object key, Object value) { |
| <span class="pc bpc" id="L322" title="1 of 2 branches missed."> if (value == null) {</span> |
| <span class="nc" id="L323"> removeAttribute(key);</span> |
| } else { |
| <span class="fc" id="L325"> getAttributesLazy().put(key, value);</span> |
| } |
| <span class="fc" id="L327"> }</span> |
| |
| public Object removeAttribute(Object key) { |
| <span class="fc" id="L330"> Map<Object, Object> attributes = getAttributes();</span> |
| <span class="fc bfc" id="L331" title="All 2 branches covered."> if (attributes == null) {</span> |
| <span class="fc" id="L332"> return null;</span> |
| } else { |
| <span class="fc" id="L334"> return attributes.remove(key);</span> |
| } |
| } |
| |
| /** |
| * Returns {@code true} if the specified argument is an {@code instanceof} {@code SimpleSession} and both |
| * {@link #getId() id}s are equal. If the argument is a {@code SimpleSession} and either 'this' or the argument |
| * does not yet have an ID assigned, the value of {@link #onEquals(SimpleSession) onEquals} is returned, which |
| * does a necessary attribute-based comparison when IDs are not available. |
| * <p/> |
| * Do your best to ensure {@code SimpleSession} instances receive an ID very early in their lifecycle to |
| * avoid the more expensive attributes-based comparison. |
| * |
| * @param obj the object to compare with this one for equality. |
| * @return {@code true} if this object is equivalent to the specified argument, {@code false} otherwise. |
| */ |
| @Override |
| public boolean equals(Object obj) { |
| <span class="pc bpc" id="L352" title="1 of 2 branches missed."> if (this == obj) {</span> |
| <span class="fc" id="L353"> return true;</span> |
| } |
| <span class="nc bnc" id="L355" title="All 2 branches missed."> if (obj instanceof SimpleSession) {</span> |
| <span class="nc" id="L356"> SimpleSession other = (SimpleSession) obj;</span> |
| <span class="nc" id="L357"> Serializable thisId = getId();</span> |
| <span class="nc" id="L358"> Serializable otherId = other.getId();</span> |
| <span class="nc bnc" id="L359" title="All 4 branches missed."> if (thisId != null && otherId != null) {</span> |
| <span class="nc" id="L360"> return thisId.equals(otherId);</span> |
| } else { |
| //fall back to an attribute based comparison: |
| <span class="nc" id="L363"> return onEquals(other);</span> |
| } |
| } |
| <span class="nc" id="L366"> return false;</span> |
| } |
| |
| /** |
| * Provides an attribute-based comparison (no ID comparison) - incurred <em>only</em> when 'this' or the |
| * session object being compared for equality do not have a session id. |
| * |
| * @param ss the SimpleSession instance to compare for equality. |
| * @return true if all the attributes, except the id, are equal to this object's attributes. |
| * @since 1.0 |
| */ |
| protected boolean onEquals(SimpleSession ss) { |
| <span class="nc bnc" id="L378" title="All 6 branches missed."> return (getStartTimestamp() != null ? getStartTimestamp().equals(ss.getStartTimestamp()) : ss.getStartTimestamp() == null) &&</span> |
| <span class="nc bnc" id="L379" title="All 6 branches missed."> (getStopTimestamp() != null ? getStopTimestamp().equals(ss.getStopTimestamp()) : ss.getStopTimestamp() == null) &&</span> |
| <span class="nc bnc" id="L380" title="All 6 branches missed."> (getLastAccessTime() != null ? getLastAccessTime().equals(ss.getLastAccessTime()) : ss.getLastAccessTime() == null) &&</span> |
| <span class="nc bnc" id="L381" title="All 2 branches missed."> (getTimeout() == ss.getTimeout()) &&</span> |
| <span class="nc bnc" id="L382" title="All 2 branches missed."> (isExpired() == ss.isExpired()) &&</span> |
| <span class="nc bnc" id="L383" title="All 6 branches missed."> (getHost() != null ? getHost().equals(ss.getHost()) : ss.getHost() == null) &&</span> |
| <span class="nc bnc" id="L384" title="All 6 branches missed."> (getAttributes() != null ? getAttributes().equals(ss.getAttributes()) : ss.getAttributes() == null);</span> |
| } |
| |
| /** |
| * Returns the hashCode. If the {@link #getId() id} is not {@code null}, its hashcode is returned immediately. |
| * If it is {@code null}, an attributes-based hashCode will be calculated and returned. |
| * <p/> |
| * Do your best to ensure {@code SimpleSession} instances receive an ID very early in their lifecycle to |
| * avoid the more expensive attributes-based calculation. |
| * |
| * @return this object's hashCode |
| * @since 1.0 |
| */ |
| @Override |
| public int hashCode() { |
| <span class="nc" id="L399"> Serializable id = getId();</span> |
| <span class="nc bnc" id="L400" title="All 2 branches missed."> if (id != null) {</span> |
| <span class="nc" id="L401"> return id.hashCode();</span> |
| } |
| <span class="nc bnc" id="L403" title="All 2 branches missed."> int hashCode = getStartTimestamp() != null ? getStartTimestamp().hashCode() : 0;</span> |
| <span class="nc bnc" id="L404" title="All 2 branches missed."> hashCode = 31 * hashCode + (getStopTimestamp() != null ? getStopTimestamp().hashCode() : 0);</span> |
| <span class="nc bnc" id="L405" title="All 2 branches missed."> hashCode = 31 * hashCode + (getLastAccessTime() != null ? getLastAccessTime().hashCode() : 0);</span> |
| <span class="nc" id="L406"> hashCode = 31 * hashCode + Long.valueOf(Math.max(getTimeout(), 0)).hashCode();</span> |
| <span class="nc" id="L407"> hashCode = 31 * hashCode + Boolean.valueOf(isExpired()).hashCode();</span> |
| <span class="nc bnc" id="L408" title="All 2 branches missed."> hashCode = 31 * hashCode + (getHost() != null ? getHost().hashCode() : 0);</span> |
| <span class="nc bnc" id="L409" title="All 2 branches missed."> hashCode = 31 * hashCode + (getAttributes() != null ? getAttributes().hashCode() : 0);</span> |
| <span class="nc" id="L410"> return hashCode;</span> |
| } |
| |
| /** |
| * Returns the string representation of this SimpleSession, equal to |
| * <code>getClass().getName() + &quot;,id=&quot; + getId()</code>. |
| * |
| * @return the string representation of this SimpleSession, equal to |
| * <code>getClass().getName() + &quot;,id=&quot; + getId()</code>. |
| * @since 1.0 |
| */ |
| @Override |
| public String toString() { |
| <span class="fc" id="L423"> StringBuilder sb = new StringBuilder();</span> |
| <span class="fc" id="L424"> sb.append(getClass().getName()).append(",id=").append(getId());</span> |
| <span class="fc" id="L425"> return sb.toString();</span> |
| } |
| |
| /** |
| * Serializes this object to the specified output stream for JDK Serialization. |
| * |
| * @param out output stream used for Object serialization. |
| * @throws IOException if any of this object's fields cannot be written to the stream. |
| * @since 1.0 |
| */ |
| private void writeObject(ObjectOutputStream out) throws IOException { |
| <span class="fc" id="L436"> out.defaultWriteObject();</span> |
| <span class="fc" id="L437"> short alteredFieldsBitMask = getAlteredFieldsBitMask();</span> |
| <span class="fc" id="L438"> out.writeShort(alteredFieldsBitMask);</span> |
| <span class="pc bpc" id="L439" title="1 of 2 branches missed."> if (id != null) {</span> |
| <span class="nc" id="L440"> out.writeObject(id);</span> |
| } |
| <span class="pc bpc" id="L442" title="1 of 2 branches missed."> if (startTimestamp != null) {</span> |
| <span class="fc" id="L443"> out.writeObject(startTimestamp);</span> |
| } |
| <span class="pc bpc" id="L445" title="1 of 2 branches missed."> if (stopTimestamp != null) {</span> |
| <span class="nc" id="L446"> out.writeObject(stopTimestamp);</span> |
| } |
| <span class="pc bpc" id="L448" title="1 of 2 branches missed."> if (lastAccessTime != null) {</span> |
| <span class="fc" id="L449"> out.writeObject(lastAccessTime);</span> |
| } |
| <span class="pc bpc" id="L451" title="1 of 2 branches missed."> if (timeout != 0l) {</span> |
| <span class="fc" id="L452"> out.writeLong(timeout);</span> |
| } |
| <span class="fc bfc" id="L454" title="All 2 branches covered."> if (expired) {</span> |
| <span class="fc" id="L455"> out.writeBoolean(expired);</span> |
| } |
| <span class="fc bfc" id="L457" title="All 2 branches covered."> if (host != null) {</span> |
| <span class="fc" id="L458"> out.writeUTF(host);</span> |
| } |
| <span class="pc bpc" id="L460" title="1 of 2 branches missed."> if (!CollectionUtils.isEmpty(attributes)) {</span> |
| <span class="nc" id="L461"> out.writeObject(attributes);</span> |
| } |
| <span class="fc" id="L463"> }</span> |
| |
| /** |
| * Reconstitutes this object based on the specified InputStream for JDK Serialization. |
| * |
| * @param in the input stream to use for reading data to populate this object. |
| * @throws IOException if the input stream cannot be used. |
| * @throws ClassNotFoundException if a required class needed for instantiation is not available in the present JVM |
| * @since 1.0 |
| */ |
| @SuppressWarnings({"unchecked"}) |
| private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
| <span class="fc" id="L475"> in.defaultReadObject();</span> |
| <span class="fc" id="L476"> short bitMask = in.readShort();</span> |
| |
| <span class="pc bpc" id="L478" title="1 of 2 branches missed."> if (isFieldPresent(bitMask, ID_BIT_MASK)) {</span> |
| <span class="nc" id="L479"> this.id = (Serializable) in.readObject();</span> |
| } |
| <span class="pc bpc" id="L481" title="1 of 2 branches missed."> if (isFieldPresent(bitMask, START_TIMESTAMP_BIT_MASK)) {</span> |
| <span class="fc" id="L482"> this.startTimestamp = (Date) in.readObject();</span> |
| } |
| <span class="pc bpc" id="L484" title="1 of 2 branches missed."> if (isFieldPresent(bitMask, STOP_TIMESTAMP_BIT_MASK)) {</span> |
| <span class="nc" id="L485"> this.stopTimestamp = (Date) in.readObject();</span> |
| } |
| <span class="pc bpc" id="L487" title="1 of 2 branches missed."> if (isFieldPresent(bitMask, LAST_ACCESS_TIME_BIT_MASK)) {</span> |
| <span class="fc" id="L488"> this.lastAccessTime = (Date) in.readObject();</span> |
| } |
| <span class="pc bpc" id="L490" title="1 of 2 branches missed."> if (isFieldPresent(bitMask, TIMEOUT_BIT_MASK)) {</span> |
| <span class="fc" id="L491"> this.timeout = in.readLong();</span> |
| } |
| <span class="fc bfc" id="L493" title="All 2 branches covered."> if (isFieldPresent(bitMask, EXPIRED_BIT_MASK)) {</span> |
| <span class="fc" id="L494"> this.expired = in.readBoolean();</span> |
| } |
| <span class="fc bfc" id="L496" title="All 2 branches covered."> if (isFieldPresent(bitMask, HOST_BIT_MASK)) {</span> |
| <span class="fc" id="L497"> this.host = in.readUTF();</span> |
| } |
| <span class="pc bpc" id="L499" title="1 of 2 branches missed."> if (isFieldPresent(bitMask, ATTRIBUTES_BIT_MASK)) {</span> |
| <span class="nc" id="L500"> this.attributes = (Map<Object, Object>) in.readObject();</span> |
| } |
| <span class="fc" id="L502"> }</span> |
| |
| /** |
| * Returns a bit mask used during serialization indicating which fields have been serialized. Fields that have been |
| * altered (not null and/or not retaining the class defaults) will be serialized and have 1 in their respective |
| * index, fields that are null and/or retain class default values have 0. |
| * |
| * @return a bit mask used during serialization indicating which fields have been serialized. |
| * @since 1.0 |
| */ |
| private short getAlteredFieldsBitMask() { |
| <span class="fc" id="L513"> int bitMask = 0;</span> |
| <span class="pc bpc" id="L514" title="1 of 2 branches missed."> bitMask = id != null ? bitMask | ID_BIT_MASK : bitMask;</span> |
| <span class="pc bpc" id="L515" title="1 of 2 branches missed."> bitMask = startTimestamp != null ? bitMask | START_TIMESTAMP_BIT_MASK : bitMask;</span> |
| <span class="pc bpc" id="L516" title="1 of 2 branches missed."> bitMask = stopTimestamp != null ? bitMask | STOP_TIMESTAMP_BIT_MASK : bitMask;</span> |
| <span class="pc bpc" id="L517" title="1 of 2 branches missed."> bitMask = lastAccessTime != null ? bitMask | LAST_ACCESS_TIME_BIT_MASK : bitMask;</span> |
| <span class="pc bpc" id="L518" title="1 of 2 branches missed."> bitMask = timeout != 0l ? bitMask | TIMEOUT_BIT_MASK : bitMask;</span> |
| <span class="fc bfc" id="L519" title="All 2 branches covered."> bitMask = expired ? bitMask | EXPIRED_BIT_MASK : bitMask;</span> |
| <span class="fc bfc" id="L520" title="All 2 branches covered."> bitMask = host != null ? bitMask | HOST_BIT_MASK : bitMask;</span> |
| <span class="pc bpc" id="L521" title="1 of 2 branches missed."> bitMask = !CollectionUtils.isEmpty(attributes) ? bitMask | ATTRIBUTES_BIT_MASK : bitMask;</span> |
| <span class="fc" id="L522"> return (short) bitMask;</span> |
| } |
| |
| /** |
| * Returns {@code true} if the given {@code bitMask} argument indicates that the specified field has been |
| * serialized and therefore should be read during deserialization, {@code false} otherwise. |
| * |
| * @param bitMask the aggregate bitmask for all fields that have been serialized. Individual bits represent |
| * the fields that have been serialized. A bit set to 1 means that corresponding field has |
| * been serialized, 0 means it hasn't been serialized. |
| * @param fieldBitMask the field bit mask constant identifying which bit to inspect (corresponds to a class attribute). |
| * @return {@code true} if the given {@code bitMask} argument indicates that the specified field has been |
| * serialized and therefore should be read during deserialization, {@code false} otherwise. |
| * @since 1.0 |
| */ |
| private static boolean isFieldPresent(short bitMask, int fieldBitMask) { |
| <span class="fc bfc" id="L538" title="All 2 branches covered."> return (bitMask & fieldBitMask) != 0;</span> |
| } |
| |
| } |
| </pre><div class="footer"><span class="right">Created with <a href="http://www.eclemma.org/jacoco">JaCoCo</a> 0.7.7.201606060606</span></div></body></html> |