blob: f208f743f724569996ac18a325601d893173cd5f [file] [log] [blame]
/*
* 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.harmony.xnet.provider.jsse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
/**
*
* SSLSessionContext implementation
* @see javax.net.ssl.SSLSessionContext
*/
public class SSLSessionContextImpl implements SSLSessionContext {
private int cacheSize = 0;
private long timeout = 0;
private final Hashtable<IdKey, SSLSessionImpl> sessions = new Hashtable<IdKey, SSLSessionImpl>();
private final List<IdKey> keys = Collections.synchronizedList(new ArrayList<IdKey>(0));
@SuppressWarnings("unchecked")
public Enumeration getIds() {
return new Enumeration() {
Enumeration<IdKey> keys = sessions.keys();
public boolean hasMoreElements() {
return keys.hasMoreElements();
}
public Object nextElement() {
return keys.nextElement().id;
}
};
}
/**
*
* @see javax.net.ssl.SSLSessionContext.getSession(byte[] sessionId)
*/
public SSLSession getSession(byte[] sessionId) {
return sessions.get(new IdKey(sessionId));
}
/**
* @see javax.net.ssl.SSLSessionContext.getSessionCacheSize()
*/
public int getSessionCacheSize() {
return cacheSize;
}
/**
* @see javax.net.ssl.SSLSessionContext.getSessionTimeout()
*/
public int getSessionTimeout() {
return (int)(timeout/1000);
}
/**
* @see javax.net.ssl.SSLSessionContext.setSessionCacheSize(int size)
*/
public void setSessionCacheSize(int size) throws IllegalArgumentException {
if (size < 0) {
throw new IllegalArgumentException("size < 0");
}
cacheSize = size;
if (size > 0 && sessions.size() > size) {
// remove size-sessions.size() oldest sessions
removeOldest(sessions.size() - size);
}
}
public void setSessionTimeout(int seconds) throws IllegalArgumentException {
if (seconds < 0) {
throw new IllegalArgumentException("seconds < 0");
}
timeout = seconds * 1000;
// Check timeouts and remove expired sessions
for (Enumeration<IdKey> en = sessions.keys(); en.hasMoreElements();) {
IdKey key = en.nextElement();
SSLSessionImpl ses = (sessions.get(key));
if (!ses.isValid()) {
sessions.remove(key);
}
}
}
/**
* Adds session to the session cache
* @param ses
*/
void putSession(SSLSessionImpl ses) {
if (cacheSize > 0 && sessions.size() == cacheSize) {
// remove 1 oldest session
removeOldest(1);
}
ses.context = this;
IdKey idKey = new IdKey(ses.getId());
sessions.put(idKey, ses);
keys.add(idKey);
}
// removes invalidated/oldest sessions from the session cache
private void removeOldest(int num) {
for (int i=0; i<num; i++) {
// The list is ordered. Since we always add to the end of it,
// the element at index 0 will be the oldest
IdKey id = keys.remove(0);
SSLSessionImpl session = sessions.remove(id);
session.context = null;
}
}
private class IdKey {
private byte[] id;
private IdKey(byte[] id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof IdKey)) {
return false;
}
return Arrays.equals(id, ((IdKey)o).id);
}
@Override
public int hashCode() {
return Arrays.hashCode(id);
}
}
}