History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/security/auth/PolicyParser.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/security/auth/PolicyParser.java+964−0
@@ -0,0 +1,964 @@
1/*
2 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.security.auth;
27
28import java.io.*;
29import java.lang.RuntimePermission;
30import java.net.MalformedURLException;
31import java.net.SocketPermission;
32import java.net.URL;
33import java.security.GeneralSecurityException;
34import java.text.MessageFormat;
35import java.util.Enumeration;
36import java.util.Hashtable;
37import java.util.LinkedList;
38import java.util.ListIterator;
39import java.util.Vector;
40import java.util.StringTokenizer;
41import sun.security.util.PropertyExpander;
42
43/**
44 * The policy for a Java runtime (specifying
45 * which permissions are available for code from various principals)
46 * is represented as a separate
47 * persistent configuration. The configuration may be stored as a
48 * flat ASCII file, as a serialized binary file of
49 * the Policy class, or as a database. <p>
50 *
51 * <p>The Java runtime creates one global Policy object, which is used to
52 * represent the static policy configuration file. It is consulted by
53 * a ProtectionDomain when the protection domain initializes its set of
54 * permissions. <p>
55 *
56 * <p>The Policy <code>init</code> method parses the policy
57 * configuration file, and then
58 * populates the Policy object. The Policy object is agnostic in that
59 * it is not involved in making policy decisions. It is merely the
60 * Java runtime representation of the persistent policy configuration
61 * file. <p>
62 *
63 * <p>When a protection domain needs to initialize its set of
64 * permissions, it executes code such as the following
65 * to ask the global Policy object to populate a
66 * Permissions object with the appropriate permissions:
67 * <pre>
68 * policy = Policy.getPolicy();
69 * Permissions perms = policy.getPermissions(MyCodeSource)
70 * </pre>
71 *
72 * <p>The protection domain passes in a CodeSource
73 * object, which encapsulates its codebase (URL) and public key attributes.
74 * The Policy object evaluates the global policy in light of who the
75 * principal is and returns an appropriate Permissions object.
76 *
77 * @deprecated As of JDK&nbsp;1.4, replaced by
78 * {@link sun.security.provider.PolicyParser}.
79 * This class is entirely deprecated.
80 *
81 * @author Roland Schemers
82 *
83 * @since 1.2
84 */
85@Deprecated
86class PolicyParser {
87
88 private static final java.util.ResourceBundle rb =
89 java.security.AccessController.doPrivileged
90 (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
91 public java.util.ResourceBundle run() {
92 return (java.util.ResourceBundle.getBundle
93 ("sun.security.util.AuthResources"));
94 }
95 });
96
97 private Vector<GrantEntry> grantEntries;
98
99 // Convenience variables for parsing
100 private static final sun.security.util.Debug debug =
101 sun.security.util.Debug.getInstance("parser", "\t[Auth Policy Parser]");
102 private StreamTokenizer st;
103 private int lookahead;
104 private int linenum;
105 private boolean expandProp = false;
106 private String keyStoreUrlString = null; // unexpanded
107 private String keyStoreType = null;
108
109 private String expand(String value)
110 throws PropertyExpander.ExpandException
111 {
112 if (expandProp)
113 return PropertyExpander.expand(value);
114 else
115 return value;
116 }
117 /**
118 * Creates a PolicyParser object.
119 */
120
121 public PolicyParser() {
122 grantEntries = new Vector<GrantEntry>();
123 }
124
125
126 public PolicyParser(boolean expandProp) {
127 this();
128 this.expandProp = expandProp;
129 }
130
131 /**
132 * Reads a policy configuration into the Policy object using a
133 * Reader object. <p>
134 *
135 * @param policy the policy Reader object.
136 *
137 * @exception ParsingException if the policy configuration contains
138 * a syntax error.
139 *
140 * @exception IOException if an error occurs while reading the policy
141 * configuration.
142 */
143
144 public void read(Reader policy)
145 throws ParsingException, IOException
146 {
147 if (!(policy instanceof BufferedReader)) {
148 policy = new BufferedReader(policy);
149 }
150
151 /**
152 * Configure the stream tokenizer:
153 * Recognize strings between "..."
154 * Don't convert words to lowercase
155 * Recognize both C-style and C++-style comments
156 * Treat end-of-line as white space, not as a token
157 */
158 st = new StreamTokenizer(policy);
159
160 st.resetSyntax();
161 st.wordChars('a', 'z');
162 st.wordChars('A', 'Z');
163 st.wordChars('.', '.');
164 st.wordChars('0', '9');
165 st.wordChars('_', '_');
166 st.wordChars('$', '$');
167 st.wordChars(128 + 32, 255);
168 st.whitespaceChars(0, ' ');
169 st.commentChar('/');
170 st.quoteChar('\'');
171 st.quoteChar('"');
172 st.lowerCaseMode(false);
173 st.ordinaryChar('/');
174 st.slashSlashComments(true);
175 st.slashStarComments(true);
176
177 /**
178 * The main parsing loop. The loop is executed once
179 * for each entry in the config file. The entries
180 * are delimited by semicolons. Once we've read in
181 * the information for an entry, go ahead and try to
182 * add it to the policy vector.
183 *
184 */
185
186 lookahead = st.nextToken();
187 while (lookahead != StreamTokenizer.TT_EOF) {
188 if (peek("grant")) {
189 GrantEntry ge = parseGrantEntry();
190 // could be null if we couldn't expand a property
191 if (ge != null)
192 add(ge);
193 } else if (peek("keystore") && keyStoreUrlString==null) {
194 // only one keystore entry per policy file, others will be
195 // ignored
196 parseKeyStoreEntry();
197 } else {
198 // error?
199 }
200 match(";");
201 }
202 }
203
204 public void add(GrantEntry ge)
205 {
206 grantEntries.addElement(ge);
207 }
208
209 public void replace(GrantEntry origGe, GrantEntry newGe)
210 {
211 grantEntries.setElementAt(newGe, grantEntries.indexOf(origGe));
212 }
213
214 public boolean remove(GrantEntry ge)
215 {
216 return grantEntries.removeElement(ge);
217 }
218
219 /**
220 * Returns the (possibly expanded) keystore location, or null if the
221 * expansion fails.
222 */
223 public String getKeyStoreUrl() {
224 try {
225 if (keyStoreUrlString!=null && keyStoreUrlString.length()!=0) {
226 return expand(keyStoreUrlString).replace(File.separatorChar,
227 '/');
228 }
229 } catch (PropertyExpander.ExpandException peee) {
230 return null;
231 }
232 return null;
233 }
234
235 public void setKeyStoreUrl(String url) {
236 keyStoreUrlString = url;
237 }
238
239 public String getKeyStoreType() {
240 return keyStoreType;
241 }
242
243 public void setKeyStoreType(String type) {
244 keyStoreType = type;
245 }
246
247 /**
248 * Enumerate all the entries in the global policy object.
249 * This method is used by policy admin tools. The tools
250 * should use the Enumeration methods on the returned object
251 * to fetch the elements sequentially.
252 */
253 public Enumeration<GrantEntry> grantElements(){
254 return grantEntries.elements();
255 }
256
257 /**
258 * write out the policy
259 */
260
261 public void write(Writer policy)
262 {
263 PrintWriter out = new PrintWriter(new BufferedWriter(policy));
264
265 Enumeration<GrantEntry> enum_ = grantElements();
266
267 out.println("/* AUTOMATICALLY GENERATED ON "+
268 (new java.util.Date()) + "*/");
269 out.println("/* DO NOT EDIT */");
270 out.println();
271
272 // write the (unexpanded) keystore entry as the first entry of the
273 // policy file
274 if (keyStoreUrlString != null) {
275 writeKeyStoreEntry(out);
276 }
277
278 // write "grant" entries
279 while (enum_.hasMoreElements()) {
280 GrantEntry ge = enum_.nextElement();
281 ge.write(out);
282 out.println();
283 }
284 out.flush();
285 }
286
287 /**
288 * parses a keystore entry
289 */
290 private void parseKeyStoreEntry() throws ParsingException, IOException {
291 match("keystore");
292 keyStoreUrlString = match("quoted string");
293
294 // parse keystore type
295 if (!peek(",")) {
296 return; // default type
297 }
298 match(",");
299
300 if (peek("\"")) {
301 keyStoreType = match("quoted string");
302 } else {
303 throw new ParsingException(st.lineno(),
304 rb.getString("expected.keystore.type"));
305 }
306 }
307
308 /**
309 * writes the (unexpanded) keystore entry
310 */
311 private void writeKeyStoreEntry(PrintWriter out) {
312 out.print("keystore \"");
313 out.print(keyStoreUrlString);
314 out.print('"');
315 if (keyStoreType != null && keyStoreType.length() > 0)
316 out.print(", \"" + keyStoreType + "\"");
317 out.println(";");
318 out.println();
319 }
320
321 /**
322 * parse a Grant entry
323 */
324 private GrantEntry parseGrantEntry()
325 throws ParsingException, IOException
326 {
327 GrantEntry e = new GrantEntry();
328 LinkedList<PrincipalEntry> principals = null;
329 boolean ignoreEntry = false;
330
331 match("grant");
332
333 while(!peek("{")) {
334
335 if (peekAndMatch("Codebase")) {
336 e.codeBase = match("quoted string");
337 peekAndMatch(",");
338 } else if (peekAndMatch("SignedBy")) {
339 e.signedBy = match("quoted string");
340 peekAndMatch(",");
341 } else if (peekAndMatch("Principal")) {
342 if (principals == null) {
343 principals = new LinkedList<PrincipalEntry>();
344 }
345
346 // check for principalClass wildcard
347 String principalClass;
348 if (peek("*")) {
349 match("*");
350 principalClass = PrincipalEntry.WILDCARD_CLASS;
351 } else {
352 principalClass = match("principal type");
353 }
354
355 // check for principalName wildcard
356 String principalName;
357 if (peek("*")) {
358 match("*");
359 principalName = PrincipalEntry.WILDCARD_NAME;
360 } else {
361 principalName = match("quoted string");
362 }
363
364 // disallow WILDCARD_CLASS && actual name
365 if (principalClass.equals(PrincipalEntry.WILDCARD_CLASS) &&
366 !principalName.equals(PrincipalEntry.WILDCARD_NAME)) {
367 if (debug != null)
368 debug.println("disallowing principal that has " +
369 "WILDCARD class but no WILDCARD name");
370 throw new ParsingException
371 (st.lineno(),
372 rb.getString("can.not.specify.Principal.with.a." +
373 "wildcard.class.without.a.wildcard.name"));
374 }
375
376 try {
377 principalName = expand(principalName);
378 principals.add
379 (new PrincipalEntry(principalClass, principalName));
380 } catch (PropertyExpander.ExpandException peee) {
381 // ignore the entire policy entry
382 // but continue parsing all the info
383 // so we can get to the next entry
384 if (debug != null)
385 debug.println("principal name expansion failed: " +
386 principalName);
387 ignoreEntry = true;
388 }
389 peekAndMatch(",");
390 } else {
391 throw new
392 ParsingException(st.lineno(),
393 rb.getString("expected.codeBase.or.SignedBy"));
394 }
395 }
396
397 // disallow non principal-based grant entries
398 if (principals == null) {
399 throw new ParsingException
400 (st.lineno(),
401 rb.getString("only.Principal.based.grant.entries.permitted"));
402 }
403
404 e.principals = principals;
405 match("{");
406
407 while(!peek("}")) {
408 if (peek("Permission")) {
409 try {
410 PermissionEntry pe = parsePermissionEntry();
411 e.add(pe);
412 } catch (PropertyExpander.ExpandException peee) {
413 // ignore. The add never happened
414 skipEntry(); // BugId 4219343
415 }
416 match(";");
417 } else {
418 throw new
419 ParsingException(st.lineno(),
420 rb.getString("expected.permission.entry"));
421 }
422 }
423 match("}");
424
425 try {
426 if (e.codeBase != null)
427 e.codeBase = expand(e.codeBase).replace(File.separatorChar, '/');
428 e.signedBy = expand(e.signedBy);
429 } catch (PropertyExpander.ExpandException peee) {
430 return null;
431 }
432
433 return (ignoreEntry == true) ? null : e;
434 }
435
436 /**
437 * parse a Permission entry
438 */
439 private PermissionEntry parsePermissionEntry()
440 throws ParsingException, IOException, PropertyExpander.ExpandException
441 {
442 PermissionEntry e = new PermissionEntry();
443
444 // Permission
445 match("Permission");
446 e.permission = match("permission type");
447
448 if (peek("\"")) {
449 // Permission name
450 e.name = expand(match("quoted string"));
451 }
452
453 if (!peek(",")) {
454 return e;
455 }
456 match(",");
457
458 if (peek("\"")) {
459 e.action = expand(match("quoted string"));
460 if (!peek(",")) {
461 return e;
462 }
463 match(",");
464 }
465
466 if (peekAndMatch("SignedBy")) {
467 e.signedBy = expand(match("quoted string"));
468 }
469 return e;
470 }
471
472 private boolean peekAndMatch(String expect)
473 throws ParsingException, IOException
474 {
475 if (peek(expect)) {
476 match(expect);
477 return true;
478 } else {
479 return false;
480 }
481 }
482
483 private boolean peek(String expect) {
484 boolean found = false;
485
486 switch (lookahead) {
487
488 case StreamTokenizer.TT_WORD:
489 if (expect.equalsIgnoreCase(st.sval))
490 found = true;
491 break;
492 case ',':
493 if (expect.equalsIgnoreCase(","))
494 found = true;
495 break;
496 case '{':
497 if (expect.equalsIgnoreCase("{"))
498 found = true;
499 break;
500 case '}':
501 if (expect.equalsIgnoreCase("}"))
502 found = true;
503 break;
504 case '"':
505 if (expect.equalsIgnoreCase("\""))
506 found = true;
507 break;
508 case '*':
509 if (expect.equalsIgnoreCase("*"))
510 found = true;
511 break;
512 default:
513
514 }
515 return found;
516 }
517
518 private String match(String expect)
519 throws ParsingException, IOException
520 {
521 String value = null;
522
523 switch (lookahead) {
524 case StreamTokenizer.TT_NUMBER:
525 throw new ParsingException(st.lineno(), expect,
526 rb.getString("number.") +
527 String.valueOf(st.nval));
528 case StreamTokenizer.TT_EOF:
529 MessageFormat form = new MessageFormat(
530 rb.getString("expected.expect.read.end.of.file."));
531 Object[] source = {expect};
532 throw new ParsingException(form.format(source));
533 case StreamTokenizer.TT_WORD:
534 if (expect.equalsIgnoreCase(st.sval)) {
535 lookahead = st.nextToken();
536 } else if (expect.equalsIgnoreCase("permission type")) {
537 value = st.sval;
538 lookahead = st.nextToken();
539 } else if (expect.equalsIgnoreCase("principal type")) {
540 value = st.sval;
541 lookahead = st.nextToken();
542 } else {
543 throw new ParsingException(st.lineno(), expect, st.sval);
544 }
545 break;
546 case '"':
547 if (expect.equalsIgnoreCase("quoted string")) {
548 value = st.sval;
549 lookahead = st.nextToken();
550 } else if (expect.equalsIgnoreCase("permission type")) {
551 value = st.sval;
552 lookahead = st.nextToken();
553 } else if (expect.equalsIgnoreCase("principal type")) {
554 value = st.sval;
555 lookahead = st.nextToken();
556 } else {
557 throw new ParsingException(st.lineno(), expect, st.sval);
558 }
559 break;
560 case ',':
561 if (expect.equalsIgnoreCase(","))
562 lookahead = st.nextToken();
563 else
564 throw new ParsingException(st.lineno(), expect, ",");
565 break;
566 case '{':
567 if (expect.equalsIgnoreCase("{"))
568 lookahead = st.nextToken();
569 else
570 throw new ParsingException(st.lineno(), expect, "{");
571 break;
572 case '}':
573 if (expect.equalsIgnoreCase("}"))
574 lookahead = st.nextToken();
575 else
576 throw new ParsingException(st.lineno(), expect, "}");
577 break;
578 case ';':
579 if (expect.equalsIgnoreCase(";"))
580 lookahead = st.nextToken();
581 else
582 throw new ParsingException(st.lineno(), expect, ";");
583 break;
584 case '*':
585 if (expect.equalsIgnoreCase("*"))
586 lookahead = st.nextToken();
587 else
588 throw new ParsingException(st.lineno(), expect, "*");
589 break;
590 default:
591 throw new ParsingException(st.lineno(), expect,
592 new String(new char[] {(char)lookahead}));
593 }
594 return value;
595 }
596
597 /**
598 * skip all tokens for this entry leaving the delimiter ";"
599 * in the stream.
600 */
601 private void skipEntry()
602 throws ParsingException, IOException
603 {
604 while(lookahead != ';') {
605 switch (lookahead) {
606 case StreamTokenizer.TT_NUMBER:
607 throw new ParsingException(st.lineno(), ";",
608 rb.getString("number.") +
609 String.valueOf(st.nval));
610 case StreamTokenizer.TT_EOF:
611 throw new ParsingException
612 (rb.getString("expected.read.end.of.file"));
613 default:
614 lookahead = st.nextToken();
615 }
616 }
617 }
618
619 /**
620 * Each grant entry in the policy configuration file is
621 * represented by a
622 * GrantEntry object. <p>
623 *
624 * <p>
625 * For example, the entry
626 * <pre>
627 * grant signedBy "Duke" {
628 * permission java.io.FilePermission "/tmp", "read,write";
629 * };
630 *
631 * </pre>
632 * is represented internally
633 * <pre>
634 *
635 * pe = new PermissionEntry("java.io.FilePermission",
636 * "/tmp", "read,write");
637 *
638 * ge = new GrantEntry("Duke", null);
639 *
640 * ge.add(pe);
641 *
642 * </pre>
643 *
644 * @author Roland Schemers
645 *
646 * version 1.19, 05/21/98
647 */
648
649 static class GrantEntry {
650
651 public String signedBy;
652 public String codeBase;
653 public LinkedList<PrincipalEntry> principals;
654 public Vector<PermissionEntry> permissionEntries;
655
656 public GrantEntry() {
657 permissionEntries = new Vector<PermissionEntry>();
658 }
659
660 public GrantEntry(String signedBy, String codeBase) {
661 this.codeBase = codeBase;
662 this.signedBy = signedBy;
663 permissionEntries = new Vector<PermissionEntry>();
664 }
665
666 public void add(PermissionEntry pe)
667 {
668 permissionEntries.addElement(pe);
669 }
670
671 public boolean remove(PermissionEntry pe)
672 {
673 return permissionEntries.removeElement(pe);
674 }
675
676 public boolean contains(PermissionEntry pe)
677 {
678 return permissionEntries.contains(pe);
679 }
680
681 /**
682 * Enumerate all the permission entries in this GrantEntry.
683 */
684 public Enumeration<PermissionEntry> permissionElements(){
685 return permissionEntries.elements();
686 }
687
688
689 public void write(PrintWriter out) {
690 out.print("grant");
691 if (signedBy != null) {
692 out.print(" signedBy \"");
693 out.print(signedBy);
694 out.print('"');
695 if (codeBase != null)
696 out.print(", ");
697 }
698 if (codeBase != null) {
699 out.print(" codeBase \"");
700 out.print(codeBase);
701 out.print('"');
702 if (principals != null && principals.size() > 0)
703 out.print(",\n");
704 }
705 if (principals != null && principals.size() > 0) {
706 ListIterator<PrincipalEntry> pli = principals.listIterator();
707 while (pli.hasNext()) {
708 out.print("\tPrincipal ");
709 PrincipalEntry pe = pli.next();
710 out.print(pe.principalClass +
711 " \"" + pe.principalName + "\"");
712 if (pli.hasNext())
713 out.print(",\n");
714 }
715 }
716 out.println(" {");
717 Enumeration<PermissionEntry> enum_ = permissionEntries.elements();
718 while (enum_.hasMoreElements()) {
719 PermissionEntry pe = enum_.nextElement();
720 out.write(" ");
721 pe.write(out);
722 }
723 out.println("};");
724 }
725
726 }
727
728 /**
729 * Principal info (class and name) in a grant entry
730 */
731 static class PrincipalEntry {
732
733 static final String WILDCARD_CLASS = "WILDCARD_PRINCIPAL_CLASS";
734 static final String WILDCARD_NAME = "WILDCARD_PRINCIPAL_NAME";
735
736 String principalClass;
737 String principalName;
738
739 /**
740 * A PrincipalEntry consists of the <code>Principal</code>
741 * class and <code>Principal</code> name.
742 *
743 * <p>
744 *
745 * @param principalClass the <code>Principal</code> class. <p>
746 *
747 * @param principalName the <code>Principal</code> name. <p>
748 */
749 public PrincipalEntry(String principalClass, String principalName) {
750 if (principalClass == null || principalName == null)
751 throw new NullPointerException
752 ("null principalClass or principalName");
753 this.principalClass = principalClass;
754 this.principalName = principalName;
755 }
756
757 /**
758 * Test for equality between the specified object and this object.
759 * Two PrincipalEntries are equal if their PrincipalClass and
760 * PrincipalName values are equal.
761 *
762 * <p>
763 *
764 * @param obj the object to test for equality with this object.
765 *
766 * @return true if the objects are equal, false otherwise.
767 */
768 public boolean equals(Object obj) {
769 if (this == obj)
770 return true;
771
772 if (!(obj instanceof PrincipalEntry))
773 return false;
774
775 PrincipalEntry that = (PrincipalEntry)obj;
776 if (this.principalClass.equals(that.principalClass) &&
777 this.principalName.equals(that.principalName)) {
778 return true;
779 }
780
781 return false;
782 }
783
784 /**
785 * Return a hashcode for this <code>PrincipalEntry</code>.
786 *
787 * <p>
788 *
789 * @return a hashcode for this <code>PrincipalEntry</code>.
790 */
791 public int hashCode() {
792 return principalClass.hashCode();
793 }
794 }
795
796 /**
797 * Each permission entry in the policy configuration file is
798 * represented by a
799 * PermissionEntry object. <p>
800 *
801 * <p>
802 * For example, the entry
803 * <pre>
804 * permission java.io.FilePermission "/tmp", "read,write";
805 * </pre>
806 * is represented internally
807 * <pre>
808 *
809 * pe = new PermissionEntry("java.io.FilePermission",
810 * "/tmp", "read,write");
811 * </pre>
812 *
813 * @author Roland Schemers
814 *
815 * version 1.19, 05/21/98
816 */
817
818 static class PermissionEntry {
819
820 public String permission;
821 public String name;
822 public String action;
823 public String signedBy;
824
825 public PermissionEntry() {
826 }
827
828 public PermissionEntry(String permission,
829 String name,
830 String action) {
831 this.permission = permission;
832 this.name = name;
833 this.action = action;
834 }
835
836 /**
837 * Calculates a hash code value for the object. Objects
838 * which are equal will also have the same hashcode.
839 */
840 public int hashCode() {
841 int retval = permission.hashCode();
842 if (name != null) retval ^= name.hashCode();
843 if (action != null) retval ^= action.hashCode();
844 return retval;
845 }
846
847 public boolean equals(Object obj) {
848 if (obj == this)
849 return true;
850
851 if (! (obj instanceof PermissionEntry))
852 return false;
853
854 PermissionEntry that = (PermissionEntry) obj;
855
856 if (this.permission == null) {
857 if (that.permission != null) return false;
858 } else {
859 if (!this.permission.equals(that.permission)) return false;
860 }
861
862 if (this.name == null) {
863 if (that.name != null) return false;
864 } else {
865 if (!this.name.equals(that.name)) return false;
866 }
867
868 if (this.action == null) {
869 if (that.action != null) return false;
870 } else {
871 if (!this.action.equals(that.action)) return false;
872 }
873
874 if (this.signedBy == null) {
875 if (that.signedBy != null) return false;
876 } else {
877 if (!this.signedBy.equals(that.signedBy)) return false;
878 }
879
880 // everything matched -- the 2 objects are equal
881 return true;
882 }
883
884 public void write(PrintWriter out) {
885 out.print("permission ");
886 out.print(permission);
887 if (name != null) {
888 out.print(" \"");
889
890 // have to add escape chars for quotes
891 if (name.indexOf("\"") != -1) {
892 int numQuotes = 0;
893 char[] chars = name.toCharArray();
894
895 // count the number of quote chars
896 for (int i = 0; i < chars.length; i++) {
897 if (chars[i] == '"')
898 numQuotes++;
899 }
900
901 // now, add an escape char before each quote
902 char[] newChars = new char[chars.length + numQuotes];
903 for (int i = 0, j = 0; i < chars.length; i++) {
904 if (chars[i] != '"') {
905 newChars[j++] = chars[i];
906 } else {
907 newChars[j++] = '\\';
908 newChars[j++] = chars[i];
909 }
910 }
911 name = new String(newChars);
912 }
913 out.print(name);
914 out.print('"');
915 }
916 if (action != null) {
917 out.print(", \"");
918 out.print(action);
919 out.print('"');
920 }
921 if (signedBy != null) {
922 out.print(", signedBy \"");
923 out.print(signedBy);
924 out.print('"');
925 }
926 out.println(";");
927 }
928 }
929
930 static class ParsingException extends GeneralSecurityException {
931
932 private static final long serialVersionUID = 8240970523155877400L;
933
934 /**
935 * Constructs a ParsingException with the specified
936 * detail message. A detail message is a String that describes
937 * this particular exception, which may, for example, specify which
938 * algorithm is not available.
939 *
940 * @param msg the detail message.
941 */
942 public ParsingException(String msg) {
943 super(msg);
944 }
945
946 public ParsingException(int line, String msg) {
947 super(rb.getString("line.") + line + rb.getString("COLON") + msg);
948 }
949
950 public ParsingException(int line, String expect, String actual) {
951 super(rb.getString("line.") + line + rb.getString(".expected.") +
952 expect + rb.getString(".found.") + actual +
953 rb.getString("QUOTE"));
954 }
955 }
956
957 public static void main(String arg[]) throws Exception {
958 PolicyParser pp = new PolicyParser(true);
959 pp.read(new FileReader(arg[0]));
960 FileWriter fr = new FileWriter(arg[1]);
961 pp.write(fr);
962 fr.close();
963 }
964}