aboutsummaryrefslogtreecommitdiff
path: root/src/share/classes/sun/security/pkcs11/Session.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/classes/sun/security/pkcs11/Session.java')
-rw-r--r--src/share/classes/sun/security/pkcs11/Session.java78
1 files changed, 77 insertions, 1 deletions
diff --git a/src/share/classes/sun/security/pkcs11/Session.java b/src/share/classes/sun/security/pkcs11/Session.java
index 64e216bf3..c5dd04455 100644
--- a/src/share/classes/sun/security/pkcs11/Session.java
+++ b/src/share/classes/sun/security/pkcs11/Session.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
package sun.security.pkcs11;
+import java.lang.ref.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
@@ -59,11 +60,14 @@ final class Session implements Comparable<Session> {
// this could lead to idle sessions being closed early, but that is harmless
private long lastAccess;
+ private final SessionRef sessionRef;
+
Session(Token token, long id) {
this.token = token;
this.id = id;
createdObjects = new AtomicInteger();
id();
+ sessionRef = new SessionRef(this, id, token);
}
public int compareTo(Session other) {
@@ -108,4 +112,76 @@ final class Session implements Comparable<Session> {
return createdObjects.get() != 0;
}
+ void close() {
+ if (hasObjects()) {
+ throw new ProviderException(
+ "Internal error: close session with active objects");
+ }
+ sessionRef.dispose();
+ }
+}
+
+/*
+ * NOTE: Use PhantomReference here and not WeakReference
+ * otherwise the sessions maybe closed before other objects
+ * which are still being finalized.
+ */
+final class SessionRef extends PhantomReference<Session>
+ implements Comparable<SessionRef> {
+
+ private static ReferenceQueue<Session> refQueue =
+ new ReferenceQueue<Session>();
+
+ private static Set<SessionRef> refList =
+ Collections.synchronizedSortedSet(new TreeSet<SessionRef>());
+
+ static ReferenceQueue<Session> referenceQueue() {
+ return refQueue;
+ }
+
+ static int totalCount() {
+ return refList.size();
+ }
+
+ private static void drainRefQueueBounded() {
+ while (true) {
+ SessionRef next = (SessionRef) refQueue.poll();
+ if (next == null) break;
+ next.dispose();
+ }
+ }
+
+ // handle to the native session
+ private long id;
+ private Token token;
+
+ SessionRef(Session session, long id, Token token) {
+ super(session, refQueue);
+ this.id = id;
+ this.token = token;
+ refList.add(this);
+ // TBD: run at some interval and not every time?
+ drainRefQueueBounded();
+ }
+
+ void dispose() {
+ refList.remove(this);
+ try {
+ token.p11.C_CloseSession(id);
+ } catch (PKCS11Exception e1) {
+ // ignore
+ } catch (ProviderException e2) {
+ // ignore
+ } finally {
+ this.clear();
+ }
+ }
+
+ public int compareTo(SessionRef other) {
+ if (this.id == other.id) {
+ return 0;
+ } else {
+ return (this.id < other.id) ? -1 : 1;
+ }
+ }
}