Java tutorial
/* * Copyright 2012 M3, Inc. * * 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. */ package com.zz.globalsession; import java.io.Serializable; import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.zz.globalsession.store.SessionStore; @SuppressWarnings("deprecation") public class GlobalHttpSession implements HttpSession { public static class Metadata implements Serializable { private Boolean invalidated; private Date creationTime; private Date lastAccessedTime; public Metadata() { } public Boolean getInvalidated() { return invalidated; } public void setInvalidated(Boolean invalidated) { this.invalidated = invalidated; } public Date getCreationTime() { return creationTime; } public void setCreationTime(Date creationTime) { this.creationTime = creationTime; } public Date getLastAccessedTime() { return lastAccessedTime; } public void setLastAccessedTime(Date lastAccessedTime) { this.lastAccessedTime = lastAccessedTime; } @Override public String toString() { return "com.m3.globalsession.GlobalHttpSession$Metadata(invalidated: " + getInvalidated() + ", creationTime: " + getCreationTime() + ", lastAccessedTime: " + getLastAccessedTime() + ")"; } } public static final String ATTRIBUTES_KEY = "__attributes__"; public static final String METADATA_KEY = "__metadata__"; private static final Log log = LogFactory.getLog(GlobalHttpSession.class); // should be Serializable type private ConcurrentHashMap<String, Object> attributes = new ConcurrentHashMap<String, Object>(); private Metadata metadata; private final String sessionId; private final SessionStore store; private final HttpSession session; private final StoreKeyGenerator keyGenerator; private boolean isNewlyCreated = false; private Integer maxInactiveIntervalSeconds = null; public StoreKeyGenerator getKeyGenerator() { return keyGenerator; } public boolean isValid() { Metadata metadata = store.get(keyGenerator.generate(METADATA_KEY)); boolean isNotInvalidated = metadata != null && metadata.getInvalidated() != null && metadata.getInvalidated() == false; boolean isNotExpired = store.get(keyGenerator.generate(ATTRIBUTES_KEY)) != null; if (log.isDebugEnabled()) { log.debug("isValid is called. (isNotInvalidated: " + isNotInvalidated + ", isNotExpired: " + isNotExpired + ")"); } return isNotInvalidated && isNotExpired; } public synchronized void reloadAttributes() { attributes.clear(); ConcurrentHashMap<String, Object> cachedAttributes = store.get(keyGenerator.generate(ATTRIBUTES_KEY)); if (cachedAttributes != null) { attributes.putAll(cachedAttributes); } } public ConcurrentHashMap<String, Object> toMap() { return attributes; } public void save() { if (isValid()) { saveAttributesToStore(); if (!isNewlyCreated) { metadata.setLastAccessedTime(new Date()); } store.set(keyGenerator.generate(METADATA_KEY), getMaxInactiveInterval(), metadata); } else { removeAttributesFromStore(); } } public GlobalHttpSession(String sessionId, SessionStore store, String namespace, Integer timeoutMinutes, HttpSession session) { if (sessionId == null || sessionId.trim().length() == 0) { throw new IllegalArgumentException("sessionId should not be empty."); } if (store == null) { throw new IllegalArgumentException("store should not be empty."); } if (namespace == null || namespace.trim().length() == 0) { throw new IllegalArgumentException("namespace should not be empty."); } if (timeoutMinutes == null) { throw new IllegalArgumentException("timeoutMinutes should not be empty."); } if (session == null) { throw new IllegalArgumentException("session should not be empty."); } this.sessionId = sessionId; this.store = store; this.session = session; this.keyGenerator = new StoreKeyGenerator(sessionId, namespace); setMaxInactiveInterval(timeoutMinutes * 60); metadata = store.get(keyGenerator.generate(METADATA_KEY)); if (metadata == null) { isNewlyCreated = true; metadata = new Metadata(); metadata.setInvalidated(false); metadata.setCreationTime(new Date()); store.set(keyGenerator.generate(METADATA_KEY), getMaxInactiveInterval(), metadata); store.set(keyGenerator.generate(ATTRIBUTES_KEY), getMaxInactiveInterval(), attributes); } reloadAttributes(); if (log.isDebugEnabled()) { log.debug("A new GlobalHttpSession is created. (sessionId: " + sessionId + ", attributes: " + attributes + ")"); } } @Override public Object getAttribute(String name) { Object value = null; if (isValid()) { value = attributes.get(name); } else { value = null; } if (log.isDebugEnabled()) { log.debug("getAttribute is called. (sessionId: " + sessionId + ", " + name + " -> " + value + ")"); } return value; } @Override public Enumeration<?> getAttributeNames() { if (isValid()) { final Iterator<String> names = attributes.keySet().iterator(); return new Enumeration<Object>() { public boolean hasMoreElements() { return names.hasNext(); } public Object nextElement() { return names.next(); } }; } else { return new Enumeration<Object>() { public boolean hasMoreElements() { return false; } public Object nextElement() { return null; } }; } } @Override public void invalidate() { if (log.isDebugEnabled()) { log.debug("invalidate is called. (sessionId: " + sessionId + ")"); } session.invalidate(); attributes.clear(); metadata.setInvalidated(true); removeAttributesFromStore(); } @Override public void removeAttribute(String name) { reloadAttributes(); attributes.remove(name); saveAttributesToStore(); } @Override public void setAttribute(String name, Object value) { if (log.isDebugEnabled()) { log.debug("setAttribute is called. (sessionId: " + sessionId + ", " + name + " -> " + value + ")"); } if (value == null) { removeAttribute(name); } if (value instanceof Serializable) { reloadAttributes(); attributes.put(name, (Serializable) value); saveAttributesToStore(); } else { String message = "The value should be an instance of java.io.Serializable. (" + value + ")"; throw new IllegalArgumentException(message); } } @Override public Object getValue(String name) { return getAttribute(name); } @Override public String[] getValueNames() { Enumeration<String> names = (Enumeration<String>) getAttributeNames(); return Collections.list(names).toArray(new String[] {}); } @Override public String getId() { return sessionId; } @Override public long getCreationTime() { if (metadata == null || metadata.getCreationTime() == null) { return 0L; } else { return metadata.getCreationTime().getTime(); } } @Override public long getLastAccessedTime() { if (metadata == null || metadata.getLastAccessedTime() == null) { return 0L; } else { return metadata.getLastAccessedTime().getTime(); } } @Override public int getMaxInactiveInterval() { return this.maxInactiveIntervalSeconds; } @Override public ServletContext getServletContext() { return session.getServletContext(); } @Override public HttpSessionContext getSessionContext() { // We don't support HttpSessionContext as a part of GlobalHttpSession // because it's already deprecated API. return session.getSessionContext(); } @Override public boolean isNew() { return isNewlyCreated; } @Override public void putValue(String name, Object value) { setAttribute(name, value); } @Override public void removeValue(String name) { removeAttribute(name); } @Override public void setMaxInactiveInterval(int interval) { this.maxInactiveIntervalSeconds = interval; session.setMaxInactiveInterval(interval); } private void saveAttributesToStore() { store.set(keyGenerator.generate(ATTRIBUTES_KEY), getMaxInactiveInterval(), toMap()); } private void removeAttributesFromStore() { store.remove(keyGenerator.generate(ATTRIBUTES_KEY)); } @Override public String toString() { StringBuilder attributes = new StringBuilder(); for (Object attr : Collections.list(getAttributeNames())) { attributes.append(attr); attributes.append(","); } return "com.m3.globalsession.GlobalHttpSession(id: " + getId() + ", attributes: [" + attributes.toString().replaceFirst(",$", "") + "], creationTime: " + getCreationTime() + ", lastAccessedTime: " + getLastAccessedTime() + ", maxInactiveInterval: " + getMaxInactiveInterval() + ")"; } }