/* * 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.ignite.cache.websession; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionContext; import org.apache.ignite.internal.util.tostring.GridToStringExclude; import org.apache.ignite.internal.util.tostring.GridToStringInclude; import org.apache.ignite.internal.util.typedef.T2; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; import org.jetbrains.annotations.Nullable; /** * Session implementation. */ @SuppressWarnings({"deprecation", "NonSerializableObjectBoundToHttpSession"}) class WebSession implements HttpSession, Externalizable { /** */ private static final long serialVersionUID = 0L; /** Flag indicating if the session is valid. */ private volatile transient boolean isValid = true; /** Empty session context. */ private static final HttpSessionContext EMPTY_SES_CTX = new HttpSessionContext() { @Nullable @Override public HttpSession getSession(String id) { return null; } @Override public Enumeration<String> getIds() { return Collections.enumeration(Collections.<String>emptyList()); } }; /** Session ID. */ private String id; /** Creation time. */ private long createTime; /** Last access time. */ private long accessTime; /** Maximum inactive interval. */ private int maxInactiveInterval; /** Attributes. */ @GridToStringInclude private Map<String, Object> attrs; /** Servlet context. */ @GridToStringExclude private transient ServletContext ctx; /** Web session filter. */ @GridToStringExclude private transient WebSessionFilter filter; /** New session flag. */ private transient boolean isNew; /** Updates list. */ private transient Collection<T2<String, Object>> updates; /** Genuine http session. */ private transient HttpSession genSes; /** * Required by {@link Externalizable}. */ public WebSession() { // No-op. } /** * @param id Session ID. * @param ses Session. */ WebSession(String id, HttpSession ses) { assert id != null; assert ses != null; this.id = id; createTime = ses.getCreationTime(); accessTime = ses.getLastAccessedTime(); maxInactiveInterval = ses.getMaxInactiveInterval(); isNew = ses.isNew(); attrs = new HashMap<>(); Enumeration<String> names = ses.getAttributeNames(); while (names.hasMoreElements()) { String name = names.nextElement(); attrs.put(name, ses.getAttribute(name)); } } /** * @param id Session ID. * @param ses Session. * @param isNew Is new flag. */ WebSession(String id, HttpSession ses, boolean isNew) { this(id, ses); this.isNew = isNew; } /** * Sets the genuine http session. * * @param genSes Genuine http session. */ protected void genSes(HttpSession genSes) { this.genSes = genSes; } /** * @param ctx Servlet context. */ public void servletContext(ServletContext ctx) { assert ctx != null; this.ctx = ctx; } /** * @param filter Filter. */ public void filter(final WebSessionFilter filter) { assert filter != null; this.filter = filter; } /** * Checks if the session is valid. * * @return True is valid, otherwise false. */ protected boolean isValid() { return this.isValid; } /** * Resets updates list. */ public void resetUpdates() { updates = new LinkedList<>(); } /** * @return Updates list. */ public Collection<T2<String, Object>> updates() { Collection<T2<String, Object>> updates0 = updates; updates = null; return updates0; } /** {@inheritDoc} */ @Override public String getId() { return id; } /** * Sets a session id. * * @param id Session id. */ protected void setId(String id) { this.id = id; } /** {@inheritDoc} */ @Override public ServletContext getServletContext() { return ctx; } /** {@inheritDoc} */ @Override public long getCreationTime() { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); return createTime; } /** {@inheritDoc} */ @Override public long getLastAccessedTime() { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); return accessTime; } /** {@inheritDoc} */ @Override public int getMaxInactiveInterval() { return maxInactiveInterval; } /** {@inheritDoc} */ @Override public void setMaxInactiveInterval(int interval) { maxInactiveInterval = interval; } /** {@inheritDoc} */ @Override public Object getAttribute(String name) { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); Object val = attrs.get(name); if (val != null && updates != null) updates.add(new T2<>(name, val)); return val; } /** {@inheritDoc} */ @Override public Object getValue(String name) { return getAttribute(name); } /** {@inheritDoc} */ @Override public Enumeration<String> getAttributeNames() { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); return Collections.enumeration(attrs.keySet()); } /** {@inheritDoc} */ @Override public String[] getValueNames() { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); return attrs.keySet().toArray(new String[attrs.size()]); } /** {@inheritDoc} */ @Override public void setAttribute(String name, Object val) { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); attrs.put(name, val); if (updates != null) updates.add(new T2<>(name, val)); } /** {@inheritDoc} */ @Override public void putValue(String name, Object val) { setAttribute(name, val); } /** {@inheritDoc} */ @Override public void removeAttribute(String name) { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); attrs.remove(name); if (updates != null) updates.add(new T2<>(name, null)); } /** {@inheritDoc} */ @Override public void removeValue(String name) { removeAttribute(name); } /** {@inheritDoc} */ @Override public void invalidate() { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); attrs.clear(); updates = null; filter.destroySession(id); genSes.invalidate(); isValid = false; } /** {@inheritDoc} */ @Override public boolean isNew() { if (!isValid) throw new IllegalStateException("Call on invalidated session!"); return isNew; } /** {@inheritDoc} */ @Override public HttpSessionContext getSessionContext() { return EMPTY_SES_CTX; } /** {@inheritDoc} */ @Override public void writeExternal(ObjectOutput out) throws IOException { U.writeString(out, id); out.writeLong(createTime); out.writeLong(accessTime); out.writeInt(maxInactiveInterval); U.writeMap(out, attrs); } /** {@inheritDoc} */ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { id = U.readString(in); createTime = in.readLong(); accessTime = in.readLong(); maxInactiveInterval = in.readInt(); attrs = U.readMap(in); } /** {@inheritDoc} */ @Override public String toString() { return S.toString(WebSession.class, this); } }