1 /*
2 * Copyright 2004,2005 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.rahas;
18
19 import org.apache.axiom.om.OMElement;
20 import org.apache.ws.security.WSConstants;
21 import org.apache.ws.security.message.token.Reference;
22
23 import javax.xml.namespace.QName;
24
25 import java.util.List;
26 import java.util.Map;
27 import java.util.ArrayList;
28 import java.util.Hashtable;
29 import java.util.Iterator;
30
31 import edu.emory.mathcs.backport.java.util.concurrent.locks.Lock;
32 import edu.emory.mathcs.backport.java.util.concurrent.locks.ReadWriteLock;
33 import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantReadWriteLock;
34
35 /**
36 * In-memory implementation of the token storage
37 */
38 public class SimpleTokenStore implements TokenStorage {
39
40 protected Map tokens = new Hashtable();
41
42 /**
43 * We use a read write lock to improve concurrency while avoiding concurrent modification
44 * exceptions. We allow concurrent reads and avoid concurrent reads and modifications
45 * ReentrantReadWriteLock supports a maximum of 65535 recursive write locks and 65535 read locks
46 */
47 protected final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
48
49 protected final Lock readLock = readWriteLock.readLock();
50
51 protected final Lock writeLock = readWriteLock.writeLock();
52
53 public void add(Token token) throws TrustException {
54
55 if (token != null && !"".equals(token.getId()) && token.getId() != null) {
56
57 writeLock.lock();
58
59 try {
60 if (this.tokens.keySet().size() == 0
61 || (this.tokens.keySet().size() > 0 && !this.tokens
62 .keySet().contains(token.getId()))) {
63 tokens.put(token.getId(), token);
64 } else {
65 throw new TrustException("tokenAlreadyExists",
66 new String[]{token.getId()});
67 }
68 } finally {
69 writeLock.unlock();
70 }
71 }
72 }
73
74 public void update(Token token) throws TrustException {
75
76 if (token != null && token.getId() != null && token.getId().trim().length() != 0) {
77
78 writeLock.lock();
79
80 try {
81 if (!this.tokens.keySet().contains(token.getId())) {
82 throw new TrustException("noTokenToUpdate", new String[]{token.getId()});
83 }
84 this.tokens.put(token.getId(), token);
85 } finally {
86 writeLock.unlock();
87 }
88 }
89
90 }
91
92 public String[] getTokenIdentifiers() throws TrustException {
93 List identifiers = new ArrayList();
94
95 readLock.lock();
96 try {
97 for (Iterator iterator = tokens.keySet().iterator(); iterator.hasNext();) {
98 identifiers.add(iterator.next());
99 }
100 } finally {
101 readLock.unlock();
102 }
103 return (String[]) identifiers.toArray(new String[identifiers.size()]);
104 }
105
106 public Token[] getValidTokens() throws TrustException {
107 return getTokens(new int[]{Token.ISSUED, Token.RENEWED});
108 }
109
110 public Token[] getRenewedTokens() throws TrustException {
111 return getTokens(Token.RENEWED);
112 }
113
114
115 public Token[] getCancelledTokens() throws TrustException {
116 return getTokens(Token.CANCELLED);
117 }
118
119 public Token[] getExpiredTokens() throws TrustException {
120 return getTokens(Token.EXPIRED);
121 }
122
123 private Token[] getTokens(int[] states) throws TrustException {
124 processTokenExpiry();
125 List tokens = new ArrayList();
126
127 readLock.lock();
128
129 try {
130 for (Iterator iterator = this.tokens.values().iterator(); iterator.hasNext();) {
131 Token token = (Token) iterator.next();
132 for (int i = 0; i < states.length; i++) {
133 if (token.getState() == states[i]) {
134 tokens.add(token);
135 break;
136 }
137 }
138 }
139 } finally {
140 readLock.unlock();
141 }
142 return (Token[]) tokens.toArray(new Token[tokens.size()]);
143 }
144
145 private Token[] getTokens(int state) throws TrustException {
146 processTokenExpiry();
147 List tokens = new ArrayList();
148
149 readLock.lock();
150
151 try {
152 for (Iterator iterator = this.tokens.values().iterator(); iterator.hasNext();) {
153 Token token = (Token) iterator.next();
154 if (token.getState() == state) {
155 tokens.add(token);
156 }
157 }
158 } finally {
159 readLock.unlock();
160 }
161 return (Token[]) tokens.toArray(new Token[tokens.size()]);
162 }
163
164 public Token getToken(String id) throws TrustException {
165 processTokenExpiry();
166
167 readLock.lock();
168
169 Token token;
170
171 try {
172
173 token = (Token) this.tokens.get(id);
174
175 if(token == null) {
176 //Try to find the token using attached refs & unattached refs
177 for (Iterator iterator = this.tokens.values().iterator(); iterator.hasNext();) {
178 Token tempToken = (Token) iterator.next();
179 OMElement elem = tempToken.getAttachedReference();
180 if(elem != null && id.equals(this.getIdFromSTR(elem))) {
181 token = tempToken;
182 }
183 elem = tempToken.getUnattachedReference();
184 if(elem != null && id.equals(this.getIdFromSTR(elem))) {
185 token = tempToken;
186 }
187
188 }
189
190 }
191
192 } finally {
193 readLock.unlock();
194 }
195
196 return token;
197 }
198
199 protected void processTokenExpiry() throws TrustException {
200
201 readLock.lock();
202
203 try {
204 for (Iterator iterator = tokens.values().iterator(); iterator.hasNext();) {
205 Token token = (Token) iterator.next();
206 if (token.getExpires() != null &&
207 token.getExpires().getTime() < System.currentTimeMillis()) {
208 token.setState(Token.EXPIRED);
209 }
210 }
211 } finally {
212 readLock.unlock();
213 }
214 }
215
216 public static String getIdFromSTR(OMElement str) {
217 //ASSUMPTION:SecurityTokenReference/KeyIdentifier
218 OMElement child = str.getFirstElement();
219 if(child == null) {
220 return null;
221 }
222
223 if (child.getQName().equals(new QName(WSConstants.SIG_NS, "KeyInfo"))) {
224 return child.getText();
225 } else if(child.getQName().equals(Reference.TOKEN)) {
226 return child.getAttributeValue(new QName("URI")).substring(1);
227 } else {
228 return null;
229 }
230 }
231
232
233
234 }