001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.security.auth;
019:
020: import java.io.IOException;
021: import java.io.ObjectInputStream;
022: import java.io.Serializable;
023: import java.security.Permission;
024: import java.security.PermissionCollection;
025: import java.security.Principal;
026: import java.util.Set;
027:
028: import org.apache.harmony.auth.internal.nls.Messages;
029:
030: public final class PrivateCredentialPermission extends Permission {
031:
032: private static final long serialVersionUID = 5284372143517237068L;
033:
034: // allowed action
035: private static final String READ = "read"; //$NON-NLS-1$
036:
037: private String credentialClass;
038:
039: // current offset
040: private transient int offset;
041:
042: // owners set
043: private transient CredOwner[] set;
044:
045: public PrivateCredentialPermission(String name, String action) {
046: super (name);
047: if (READ.equalsIgnoreCase(action)) {
048: initTargetName(name);
049: } else {
050: throw new IllegalArgumentException(Messages
051: .getString("auth.11")); //$NON-NLS-1$
052: }
053: }
054:
055: /**
056: * Creates a <code>PrivateCredentialPermission</code> from the Credential Class
057: * and Set of Principals
058: *
059: * @param credentialClass - credential class name
060: * @param principals - principal set
061: */
062: PrivateCredentialPermission(String credentialClass,
063: Set<Principal> principals) {
064: super (credentialClass);
065: this .credentialClass = credentialClass;
066:
067: set = new CredOwner[principals.size()];
068: for (Principal p : principals) {
069: CredOwner element = new CredOwner(p.getClass().getName(), p
070: .getName());
071: // check for duplicate elements
072: boolean found = false;
073: for (int ii = 0; ii < offset; ii++) {
074: if (set[ii].equals(element)) {
075: found = true;
076: break;
077: }
078: }
079: if (!found) {
080: set[offset++] = element;
081: }
082: }
083: }
084:
085: /**
086: * Initialize a PrivateCredentialPermission object and checks that a target
087: * name has a correct format: CredentialClass 1*(PrincipalClass
088: * "PrincipalName")
089: */
090: private void initTargetName(String name) {
091:
092: if (name == null) {
093: throw new NullPointerException(Messages
094: .getString("auth.0E")); //$NON-NLS-1$
095: }
096:
097: // check empty string
098: name = name.trim();
099: if (name.length() == 0) {
100: throw new IllegalArgumentException(Messages
101: .getString("auth.0F")); //$NON-NLS-1$
102: }
103:
104: // get CredentialClass
105: int beg = name.indexOf(' ');
106: if (beg == -1) {
107: throw new IllegalArgumentException(Messages
108: .getString("auth.10")); //$NON-NLS-1$
109: }
110: credentialClass = name.substring(0, beg);
111:
112: // get a number of pairs: PrincipalClass "PrincipalName"
113: beg++;
114: int count = 0;
115: int nameLength = name.length();
116: for (int i, j = 0; beg < nameLength; beg = j + 2, count++) {
117: i = name.indexOf(' ', beg);
118: j = name.indexOf('"', i + 2);
119:
120: if (i == -1 || j == -1 || name.charAt(i + 1) != '"') {
121: throw new IllegalArgumentException(Messages
122: .getString("auth.10")); //$NON-NLS-1$
123: }
124: }
125:
126: // name MUST have one pair at least
127: if (count < 1) {
128: throw new IllegalArgumentException(Messages
129: .getString("auth.10")); //$NON-NLS-1$
130: }
131:
132: beg = name.indexOf(' ');
133: beg++;
134:
135: // populate principal set with instances of CredOwner class
136: String principalClass;
137: String principalName;
138:
139: set = new CredOwner[count];
140: for (int index = 0, i, j; index < count; beg = j + 2, index++) {
141: i = name.indexOf(' ', beg);
142: j = name.indexOf('"', i + 2);
143:
144: principalClass = name.substring(beg, i);
145: principalName = name.substring(i + 2, j);
146:
147: CredOwner element = new CredOwner(principalClass,
148: principalName);
149: // check for duplicate elements
150: boolean found = false;
151: for (int ii = 0; ii < offset; ii++) {
152: if (set[ii].equals(element)) {
153: found = true;
154: break;
155: }
156: }
157: if (!found) {
158: set[offset++] = element;
159: }
160: }
161: }
162:
163: private void readObject(ObjectInputStream ois) throws IOException,
164: ClassNotFoundException {
165: ois.defaultReadObject();
166: initTargetName(getName());
167: }
168:
169: public String[][] getPrincipals() {
170:
171: String[][] s = new String[offset][2];
172:
173: for (int i = 0; i < s.length; i++) {
174: s[i][0] = set[i].principalClass;
175: s[i][1] = set[i].principalName;
176: }
177: return s;
178: }
179:
180: @Override
181: public String getActions() {
182: return READ;
183: }
184:
185: public String getCredentialClass() {
186: return credentialClass;
187: }
188:
189: @Override
190: public int hashCode() {
191: int hash = 0;
192: for (int i = 0; i < offset; i++) {
193: hash = hash + set[i].hashCode();
194: }
195: return getCredentialClass().hashCode() + hash;
196: }
197:
198: @Override
199: public boolean equals(Object obj) {
200: if (obj == this ) {
201: return true;
202: }
203:
204: if (obj == null || this .getClass() != obj.getClass()) {
205: return false;
206: }
207:
208: PrivateCredentialPermission that = (PrivateCredentialPermission) obj;
209:
210: return credentialClass.equals(that.credentialClass)
211: && (offset == that.offset)
212: && sameMembers(set, that.set, offset);
213: }
214:
215: @Override
216: public boolean implies(Permission permission) {
217:
218: if (permission == null
219: || this .getClass() != permission.getClass()) {
220: return false;
221: }
222:
223: PrivateCredentialPermission that = (PrivateCredentialPermission) permission;
224:
225: if (!("*".equals(credentialClass) || credentialClass //$NON-NLS-1$
226: .equals(that.getCredentialClass()))) {
227: return false;
228: }
229:
230: if (that.offset == 0) {
231: return true;
232: }
233:
234: CredOwner[] this Co = set;
235: CredOwner[] thatCo = that.set;
236: int this PrincipalsSize = offset;
237: int thatPrincipalsSize = that.offset;
238: for (int i = 0, j; i < this PrincipalsSize; i++) {
239: for (j = 0; j < thatPrincipalsSize; j++) {
240: if (this Co[i].implies(thatCo[j])) {
241: break;
242: }
243: }
244: if (j == thatCo.length) {
245: return false;
246: }
247: }
248: return true;
249: }
250:
251: @Override
252: public PermissionCollection newPermissionCollection() {
253: return null;
254: }
255:
256: /**
257: * Returns true if the two arrays have the same length, and every member of
258: * one array is contained in another array
259: */
260: private boolean sameMembers(Object[] ar1, Object[] ar2, int length) {
261: if (ar1 == null && ar2 == null) {
262: return true;
263: }
264: if (ar1 == null || ar2 == null) {
265: return false;
266: }
267: boolean found;
268: for (int i = 0; i < length; i++) {
269: found = false;
270: for (int j = 0; j < length; j++) {
271: if (ar1[i].equals(ar2[j])) {
272: found = true;
273: break;
274: }
275: }
276: if (!found) {
277: return false;
278: }
279: }
280: return true;
281: }
282:
283: private static final class CredOwner implements Serializable {
284:
285: private static final long serialVersionUID = -5607449830436408266L;
286:
287: String principalClass;
288:
289: String principalName;
290:
291: // whether class name contains wildcards
292: private transient boolean isClassWildcard;
293:
294: // whether pname contains wildcards
295: private transient boolean isPNameWildcard;
296:
297: // Creates a new CredOwner with the specified Principal Class and Principal Name
298: CredOwner(String principalClass, String principalName) {
299: super ();
300: if ("*".equals(principalClass)) { //$NON-NLS-1$
301: isClassWildcard = true;
302: }
303:
304: if ("*".equals(principalName)) { //$NON-NLS-1$
305: isPNameWildcard = true;
306: }
307:
308: if (isClassWildcard && !isPNameWildcard) {
309: throw new IllegalArgumentException(Messages
310: .getString("auth.12")); //$NON-NLS-1$
311: }
312:
313: this .principalClass = principalClass;
314: this .principalName = principalName;
315: }
316:
317: // Checks if this CredOwner implies the specified Object.
318: boolean implies(Object obj) {
319: if (obj == this ) {
320: return true;
321: }
322:
323: CredOwner co = (CredOwner) obj;
324:
325: if (isClassWildcard
326: || principalClass.equals(co.principalClass)) {
327: if (isPNameWildcard
328: || principalName.equals(co.principalName)) {
329: return true;
330: }
331: }
332: return false;
333: }
334:
335: // Checks two CredOwner objects for equality.
336: @Override
337: public boolean equals(Object obj) {
338: return principalClass
339: .equals(((CredOwner) obj).principalClass)
340: && principalName
341: .equals(((CredOwner) obj).principalName);
342: }
343:
344: // Returns the hash code value for this object.
345: @Override
346: public int hashCode() {
347: return principalClass.hashCode() + principalName.hashCode();
348: }
349: }
350: }
|