KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > security > auth > PolicyParser


1 /*
2  * @(#)PolicyParser.java 1.41 04/05/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.security.auth;
9
10 import java.io.*;
11 import java.lang.RuntimePermission JavaDoc;
12 import java.net.MalformedURLException JavaDoc;
13 import java.net.SocketPermission JavaDoc;
14 import java.net.URL JavaDoc;
15 import java.util.Enumeration JavaDoc;
16 import java.util.Hashtable JavaDoc;
17 import java.util.LinkedList JavaDoc;
18 import java.util.ListIterator JavaDoc;
19 import java.util.Vector JavaDoc;
20 import java.util.StringTokenizer JavaDoc;
21 import java.security.GeneralSecurityException JavaDoc;
22 import sun.security.util.PropertyExpander;
23
24 /**
25  * The policy for a Java runtime (specifying
26  * which permissions are available for code from various principals)
27  * is represented as a separate
28  * persistent configuration. The configuration may be stored as a
29  * flat ASCII file, as a serialized binary file of
30  * the Policy class, or as a database. <p>
31  *
32  * <p>The Java runtime creates one global Policy object, which is used to
33  * represent the static policy configuration file. It is consulted by
34  * a ProtectionDomain when the protection domain initializes its set of
35  * permissions. <p>
36  *
37  * <p>The Policy <code>init</code> method parses the policy
38  * configuration file, and then
39  * populates the Policy object. The Policy object is agnostic in that
40  * it is not involved in making policy decisions. It is merely the
41  * Java runtime representation of the persistent policy configuration
42  * file. <p>
43  *
44  * <p>When a protection domain needs to initialize its set of
45  * permissions, it executes code such as the following
46  * to ask the global Policy object to populate a
47  * Permissions object with the appropriate permissions:
48  * <pre>
49  * policy = Policy.getPolicy();
50  * Permissions perms = policy.getPermissions(MyCodeSource)
51  * </pre>
52  *
53  * <p>The protection domain passes in a CodeSource
54  * object, which encapsulates its codebase (URL) and public key attributes.
55  * The Policy object evaluates the global policy in light of who the
56  * principal is and returns an appropriate Permissions object.
57  *
58  * @deprecated As of JDK&nbsp;1.4, replaced by
59  * {@link sun.security.provider.PolicyParser}.
60  * This class is entirely deprecated.
61  *
62  * @version 1.41, 05/18/04
63  * @author Roland Schemers
64  *
65  * @since JDK1.2
66  */

67 @Deprecated JavaDoc
68 class PolicyParser {
69
70     private static final java.util.ResourceBundle JavaDoc rb =
71           (java.util.ResourceBundle JavaDoc)java.security.AccessController.doPrivileged
72           (new java.security.PrivilegedAction JavaDoc() {
73               public Object JavaDoc run() {
74                   return (java.util.ResourceBundle.getBundle
75                                 ("sun.security.util.AuthResources"));
76               }
77       });
78
79     private Vector JavaDoc grantEntries;
80
81     // Convenience variables for parsing
82
private static final sun.security.util.Debug debug =
83     sun.security.util.Debug.getInstance("parser", "\t[Auth Policy Parser]");
84     private StreamTokenizer st;
85     private int lookahead;
86     private int linenum;
87     private boolean expandProp = false;
88     private String JavaDoc keyStoreUrlString = null; // unexpanded
89
private String JavaDoc keyStoreType = null;
90
91     private String JavaDoc expand(String JavaDoc value)
92     throws PropertyExpander.ExpandException
93     {
94     if (expandProp)
95         return PropertyExpander.expand(value);
96     else
97         return value;
98     }
99     /**
100      * Creates a PolicyParser object.
101      */

102
103     public PolicyParser() {
104     grantEntries = new Vector JavaDoc();
105     }
106
107
108     public PolicyParser(boolean expandProp) {
109     this();
110     this.expandProp = expandProp;
111     }
112
113     /**
114      * Reads a policy configuration into the Policy object using a
115      * Reader object. <p>
116      *
117      * @param policy the policy Reader object.
118      *
119      * @exception ParsingException if the policy configuration contains
120      * a syntax error.
121      *
122      * @exception IOException if an error occurs while reading the policy
123      * configuration.
124      */

125
126     public void read(Reader policy)
127     throws ParsingException, IOException
128     {
129     if (!(policy instanceof BufferedReader)) {
130         policy = new BufferedReader(policy);
131     }
132
133     /**
134      * Configure the stream tokenizer:
135      * Recognize strings between "..."
136      * Don't convert words to lowercase
137      * Recognize both C-style and C++-style comments
138      * Treat end-of-line as white space, not as a token
139      */

140     st = new StreamTokenizer(policy);
141
142     st.resetSyntax();
143     st.wordChars('a', 'z');
144     st.wordChars('A', 'Z');
145     st.wordChars('.', '.');
146     st.wordChars('0', '9');
147     st.wordChars('_', '_');
148     st.wordChars('$', '$');
149     st.wordChars(128 + 32, 255);
150     st.whitespaceChars(0, ' ');
151     st.commentChar('/');
152     st.quoteChar('\'');
153     st.quoteChar('"');
154     st.lowerCaseMode(false);
155     st.ordinaryChar('/');
156     st.slashSlashComments(true);
157     st.slashStarComments(true);
158
159     /**
160      * The main parsing loop. The loop is executed once
161      * for each entry in the config file. The entries
162      * are delimited by semicolons. Once we've read in
163      * the information for an entry, go ahead and try to
164      * add it to the policy vector.
165      *
166      */

167
168     lookahead = st.nextToken();
169     while (lookahead != StreamTokenizer.TT_EOF) {
170         if (peek("grant")) {
171         GrantEntry ge = parseGrantEntry();
172         // could be null if we couldn't expand a property
173
if (ge != null)
174             add(ge);
175         } else if (peek("keystore") && keyStoreUrlString==null) {
176         // only one keystore entry per policy file, others will be
177
// ignored
178
parseKeyStoreEntry();
179         } else {
180         // error?
181
}
182         match(";");
183     }
184     }
185
186     public void add(GrantEntry ge)
187     {
188     grantEntries.addElement(ge);
189     }
190
191     public void replace(GrantEntry origGe, GrantEntry newGe)
192     {
193     grantEntries.setElementAt(newGe, grantEntries.indexOf(origGe));
194     }
195
196     public boolean remove(GrantEntry ge)
197     {
198     return grantEntries.removeElement(ge);
199     }
200
201     /**
202      * Returns the (possibly expanded) keystore location, or null if the
203      * expansion fails.
204      */

205     public String JavaDoc getKeyStoreUrl() {
206     try {
207         if (keyStoreUrlString!=null && keyStoreUrlString.length()!=0) {
208         return expand(keyStoreUrlString).replace(File.separatorChar,
209                              '/');
210         }
211     } catch (PropertyExpander.ExpandException peee) {
212         return null;
213     }
214     return null;
215     }
216
217     public void setKeyStoreUrl(String JavaDoc url) {
218     keyStoreUrlString = url;
219     }
220
221     public String JavaDoc getKeyStoreType() {
222     return keyStoreType;
223     }
224
225     public void setKeyStoreType(String JavaDoc type) {
226     keyStoreType = type;
227     }
228
229     /**
230      * Enumerate all the entries in the global policy object.
231      * This method is used by policy admin tools. The tools
232      * should use the Enumeration methods on the returned object
233      * to fetch the elements sequentially.
234      */

235     public Enumeration JavaDoc grantElements(){
236     return grantEntries.elements();
237     }
238
239     /**
240      * write out the policy
241      */

242
243     public void write(Writer policy)
244     {
245     PrintWriter out = new PrintWriter(new BufferedWriter(policy));
246
247     Enumeration JavaDoc enum_ = grantElements();
248
249     out.println("/* AUTOMATICALLY GENERATED ON "+
250             (new java.util.Date JavaDoc()) + "*/");
251     out.println("/* DO NOT EDIT */");
252     out.println();
253
254     // write the (unexpanded) keystore entry as the first entry of the
255
// policy file
256
if (keyStoreUrlString != null) {
257         writeKeyStoreEntry(out);
258     }
259
260     // write "grant" entries
261
while (enum_.hasMoreElements()) {
262         GrantEntry ge = (GrantEntry) enum_.nextElement();
263         ge.write(out);
264         out.println();
265     }
266     out.flush();
267     }
268
269     /**
270      * parses a keystore entry
271      */

272     private void parseKeyStoreEntry() throws ParsingException, IOException {
273     match("keystore");
274     keyStoreUrlString = match("quoted string");
275
276     // parse keystore type
277
if (!peek(",")) {
278         return; // default type
279
}
280     match(",");
281
282     if (peek("\"")) {
283         keyStoreType = match("quoted string");
284     } else {
285         throw new ParsingException(st.lineno(),
286             rb.getString("expected keystore type"));
287     }
288     }
289
290     /**
291      * writes the (unexpanded) keystore entry
292      */

293     private void writeKeyStoreEntry(PrintWriter out) {
294     out.print("keystore \"");
295     out.print(keyStoreUrlString);
296     out.print('"');
297     if (keyStoreType != null && keyStoreType.length() > 0)
298         out.print(", \"" + keyStoreType + "\"");
299     out.println(";");
300     out.println();
301     }
302
303     /**
304      * parse a Grant entry
305      */

306     private GrantEntry parseGrantEntry()
307     throws ParsingException, IOException
308     {
309     GrantEntry e = new GrantEntry();
310     LinkedList JavaDoc principals = null;
311     boolean ignoreEntry = false;
312
313     match("grant");
314
315     while(!peek("{")) {
316
317         if (peekAndMatch("Codebase")) {
318         e.codeBase = match("quoted string");
319         peekAndMatch(",");
320         } else if (peekAndMatch("SignedBy")) {
321         e.signedBy = match("quoted string");
322         peekAndMatch(",");
323         } else if (peekAndMatch("Principal")) {
324         if (principals == null) {
325             principals = new LinkedList JavaDoc();
326         }
327
328         // check for principalClass wildcard
329
String JavaDoc principalClass;
330         if (peek("*")) {
331             match("*");
332             principalClass = PrincipalEntry.WILDCARD_CLASS;
333         } else {
334             principalClass = match("principal type");
335         }
336
337         // check for principalName wildcard
338
String JavaDoc principalName;
339         if (peek("*")) {
340             match("*");
341             principalName = PrincipalEntry.WILDCARD_NAME;
342         } else {
343             principalName = match("quoted string");
344         }
345
346         // disallow WILDCARD_CLASS && actual name
347
if (principalClass.equals(PrincipalEntry.WILDCARD_CLASS) &&
348             !principalName.equals(PrincipalEntry.WILDCARD_NAME)) {
349             if (debug != null)
350             debug.println("disallowing principal that has " +
351                 "WILDCARD class but no WILDCARD name");
352             throw new ParsingException
353             (st.lineno(),
354             rb.getString("can not specify Principal with a ") +
355             rb.getString("wildcard class without a wildcard name"));
356         }
357
358         try {
359             principalName = expand(principalName);
360             principals.add
361             (new PrincipalEntry(principalClass, principalName));
362         } catch (PropertyExpander.ExpandException peee) {
363             // ignore the entire policy entry
364
// but continue parsing all the info
365
// so we can get to the next entry
366
if (debug != null)
367             debug.println("principal name expansion failed: " +
368                     principalName);
369             ignoreEntry = true;
370         }
371         peekAndMatch(",");
372         } else {
373         throw new
374          ParsingException(st.lineno(),
375             rb.getString("expected codeBase or SignedBy"));
376         }
377     }
378
379     // disallow non principal-based grant entries
380
if (principals == null) {
381         throw new ParsingException
382         (st.lineno(),
383         rb.getString("only Principal-based grant entries permitted"));
384     }
385
386     e.principals = principals;
387     match("{");
388
389     while(!peek("}")) {
390         if (peek("Permission")) {
391         try {
392             PermissionEntry pe = parsePermissionEntry();
393             e.add(pe);
394         } catch (PropertyExpander.ExpandException peee) {
395             // ignore. The add never happened
396
skipEntry(); // BugId 4219343
397
}
398         match(";");
399         } else {
400         throw new
401             ParsingException(st.lineno(),
402             rb.getString("expected permission entry"));
403         }
404     }
405     match("}");
406
407     try {
408         if (e.codeBase != null)
409           e.codeBase = expand(e.codeBase).replace(File.separatorChar, '/');
410         e.signedBy = expand(e.signedBy);
411     } catch (PropertyExpander.ExpandException peee) {
412         return null;
413     }
414
415     return (ignoreEntry == true) ? null : e;
416     }
417
418     /**
419      * parse a Permission entry
420      */

421     private PermissionEntry parsePermissionEntry()
422     throws ParsingException, IOException, PropertyExpander.ExpandException
423     {
424     PermissionEntry e = new PermissionEntry();
425
426     // Permission
427
match("Permission");
428     e.permission = match("permission type");
429
430     if (peek("\"")) {
431         // Permission name
432
e.name = expand(match("quoted string"));
433     }
434
435     if (!peek(",")) {
436         return e;
437     }
438     match(",");
439
440     if (peek("\"")) {
441         e.action = expand(match("quoted string"));
442         if (!peek(",")) {
443             return e;
444         }
445         match(",");
446     }
447
448     if (peekAndMatch("SignedBy")) {
449         e.signedBy = expand(match("quoted string"));
450     }
451     return e;
452     }
453
454     private boolean peekAndMatch(String JavaDoc expect)
455     throws ParsingException, IOException
456     {
457     if (peek(expect)) {
458         match(expect);
459         return true;
460     } else {
461         return false;
462     }
463     }
464
465     private boolean peek(String JavaDoc expect) {
466     boolean found = false;
467
468     switch (lookahead) {
469
470     case StreamTokenizer.TT_WORD:
471         if (expect.equalsIgnoreCase(st.sval))
472         found = true;
473         break;
474     case ',':
475         if (expect.equalsIgnoreCase(","))
476         found = true;
477         break;
478     case '{':
479         if (expect.equalsIgnoreCase("{"))
480         found = true;
481         break;
482     case '}':
483         if (expect.equalsIgnoreCase("}"))
484         found = true;
485         break;
486     case '"':
487         if (expect.equalsIgnoreCase("\""))
488         found = true;
489         break;
490     case '*':
491         if (expect.equalsIgnoreCase("*"))
492         found = true;
493         break;
494     default:
495         
496     }
497     return found;
498     }
499
500     private String JavaDoc match(String JavaDoc expect)
501     throws ParsingException, IOException
502     {
503     String JavaDoc value = null;
504
505     switch (lookahead) {
506     case StreamTokenizer.TT_NUMBER:
507         throw new ParsingException(st.lineno(), expect,
508                     rb.getString("number ") +
509                     String.valueOf(st.nval));
510     case StreamTokenizer.TT_EOF:
511        throw new ParsingException
512         (rb.getString("expected ") + expect +
513         rb.getString(", read end of file"));
514     case StreamTokenizer.TT_WORD:
515         if (expect.equalsIgnoreCase(st.sval)) {
516         lookahead = st.nextToken();
517         } else if (expect.equalsIgnoreCase("permission type")) {
518         value = st.sval;
519         lookahead = st.nextToken();
520         } else if (expect.equalsIgnoreCase("principal type")) {
521         value = st.sval;
522         lookahead = st.nextToken();
523         } else {
524         throw new ParsingException(st.lineno(), expect, st.sval);
525         }
526         break;
527     case '"':
528         if (expect.equalsIgnoreCase("quoted string")) {
529         value = st.sval;
530         lookahead = st.nextToken();
531         } else if (expect.equalsIgnoreCase("permission type")) {
532         value = st.sval;
533         lookahead = st.nextToken();
534         } else if (expect.equalsIgnoreCase("principal type")) {
535         value = st.sval;
536         lookahead = st.nextToken();
537         } else {
538         throw new ParsingException(st.lineno(), expect, st.sval);
539         }
540         break;
541     case ',':
542         if (expect.equalsIgnoreCase(","))
543         lookahead = st.nextToken();
544         else
545         throw new ParsingException(st.lineno(), expect, ",");
546         break;
547     case '{':
548         if (expect.equalsIgnoreCase("{"))
549         lookahead = st.nextToken();
550         else
551         throw new ParsingException(st.lineno(), expect, "{");
552         break;
553     case '}':
554         if (expect.equalsIgnoreCase("}"))
555         lookahead = st.nextToken();
556         else
557         throw new ParsingException(st.lineno(), expect, "}");
558         break;
559     case ';':
560         if (expect.equalsIgnoreCase(";"))
561         lookahead = st.nextToken();
562         else
563         throw new ParsingException(st.lineno(), expect, ";");
564         break;
565     case '*':
566         if (expect.equalsIgnoreCase("*"))
567         lookahead = st.nextToken();
568         else
569         throw new ParsingException(st.lineno(), expect, "*");
570         break;
571     default:
572         throw new ParsingException(st.lineno(), expect,
573                    new String JavaDoc(new char[] {(char)lookahead}));
574     }
575     return value;
576     }
577
578     /**
579      * skip all tokens for this entry leaving the delimiter ";"
580      * in the stream.
581      */

582     private void skipEntry()
583     throws ParsingException, IOException
584     {
585       while(lookahead != ';') {
586     switch (lookahead) {
587     case StreamTokenizer.TT_NUMBER:
588         throw new ParsingException(st.lineno(), ";",
589                        rb.getString("number ") +
590                     String.valueOf(st.nval));
591     case StreamTokenizer.TT_EOF:
592       throw new ParsingException
593         (rb.getString("expected ';', read end of file"));
594     default:
595       lookahead = st.nextToken();
596     }
597       }
598     }
599
600     /**
601      * Each grant entry in the policy configuration file is
602      * represented by a
603      * GrantEntry object. <p>
604      *
605      * <p>
606      * For example, the entry
607      * <pre>
608      * grant signedBy "Duke" {
609      * permission java.io.FilePermission "/tmp", "read,write";
610      * };
611      *
612      * </pre>
613      * is represented internally
614      * <pre>
615      *
616      * pe = new PermissionEntry("java.io.FilePermission",
617      * "/tmp", "read,write");
618      *
619      * ge = new GrantEntry("Duke", null);
620      *
621      * ge.add(pe);
622      *
623      * </pre>
624      *
625      * @author Roland Schemers
626      *
627      * version 1.19, 05/21/98
628      */

629
630     static class GrantEntry {
631
632     public String JavaDoc signedBy;
633     public String JavaDoc codeBase;
634     public LinkedList JavaDoc principals;
635     public Vector JavaDoc permissionEntries;
636
637     public GrantEntry() {
638         permissionEntries = new Vector JavaDoc();
639     }
640
641     public GrantEntry(String JavaDoc signedBy, String JavaDoc codeBase) {
642         this.codeBase = codeBase;
643         this.signedBy = signedBy;
644         permissionEntries = new Vector JavaDoc();
645     }
646
647     public void add(PermissionEntry pe)
648     {
649         permissionEntries.addElement(pe);
650     }
651
652     public boolean remove(PermissionEntry pe)
653     {
654         return permissionEntries.removeElement(pe);
655     }
656
657     public boolean contains(PermissionEntry pe)
658     {
659         return permissionEntries.contains(pe);
660     }
661
662     /**
663      * Enumerate all the permission entries in this GrantEntry.
664      */

665     public Enumeration JavaDoc permissionElements(){
666         return permissionEntries.elements();
667     }
668
669
670     public void write(PrintWriter out) {
671         out.print("grant");
672         if (signedBy != null) {
673         out.print(" signedBy \"");
674         out.print(signedBy);
675         out.print('"');
676         if (codeBase != null)
677             out.print(", ");
678         }
679         if (codeBase != null) {
680         out.print(" codeBase \"");
681         out.print(codeBase);
682         out.print('"');
683         if (principals != null && principals.size() > 0)
684             out.print(",\n");
685         }
686         if (principals != null && principals.size() > 0) {
687         ListIterator JavaDoc pli = principals.listIterator();
688         while (pli.hasNext()) {
689             out.print("\tPrincipal ");
690             PrincipalEntry pe = (PrincipalEntry)pli.next();
691             out.print((String JavaDoc)pe.principalClass +
692                 " \"" + pe.principalName + "\"");
693             if (pli.hasNext())
694             out.print(",\n");
695         }
696         }
697         out.println(" {");
698         Enumeration JavaDoc enum_ = permissionEntries.elements();
699         while (enum_.hasMoreElements()) {
700         PermissionEntry pe =
701             (PermissionEntry) enum_.nextElement();
702         out.write(" ");
703         pe.write(out);
704         }
705         out.println("};");
706     }
707
708     }
709
710     /**
711      * Principal info (class and name) in a grant entry
712      */

713     static class PrincipalEntry {
714
715     static final String JavaDoc WILDCARD_CLASS = "WILDCARD_PRINCIPAL_CLASS";
716     static final String JavaDoc WILDCARD_NAME = "WILDCARD_PRINCIPAL_NAME";
717
718     String JavaDoc principalClass;
719     String JavaDoc principalName;
720
721     /**
722      * A PrincipalEntry consists of the <code>Principal</code>
723      * class and <code>Principal</code> name.
724      *
725      * <p>
726      *
727      * @param principalClass the <code>Principal</code> class. <p>
728      *
729      * @param principalName the <code>Principal</code> name. <p>
730      */

731     public PrincipalEntry(String JavaDoc principalClass, String JavaDoc principalName) {
732         if (principalClass == null || principalName == null)
733         throw new NullPointerException JavaDoc
734             ("null principalClass or principalName");
735         this.principalClass = principalClass;
736         this.principalName = principalName;
737     }
738
739     /**
740      * Test for equality between the specified object and this object.
741      * Two PrincipalEntries are equal if their PrincipalClass and
742      * PrincipalName values are equal.
743      *
744      * <p>
745      *
746      * @param obj the object to test for equality with this object.
747      *
748      * @return true if the objects are equal, false otherwise.
749      */

750     public boolean equals(Object JavaDoc obj) {
751         if (this == obj)
752         return true;
753
754         if (!(obj instanceof PrincipalEntry))
755         return false;
756
757         PrincipalEntry that = (PrincipalEntry)obj;
758         if (this.principalClass.equals(that.principalClass) &&
759         this.principalName.equals(that.principalName)) {
760         return true;
761         }
762
763         return false;
764     }
765
766     /**
767      * Return a hashcode for this <code>PrincipalEntry</code>.
768      *
769      * <p>
770      *
771      * @return a hashcode for this <code>PrincipalEntry</code>.
772      */

773     public int hashCode() {
774         return principalClass.hashCode();
775     }
776     }
777
778     /**
779      * Each permission entry in the policy configuration file is
780      * represented by a
781      * PermissionEntry object. <p>
782      *
783      * <p>
784      * For example, the entry
785      * <pre>
786      * permission java.io.FilePermission "/tmp", "read,write";
787      * </pre>
788      * is represented internally
789      * <pre>
790      *
791      * pe = new PermissionEntry("java.io.FilePermission",
792      * "/tmp", "read,write");
793      * </pre>
794      *
795      * @author Roland Schemers
796      *
797      * version 1.19, 05/21/98
798      */

799
800     static class PermissionEntry {
801
802     public String JavaDoc permission;
803     public String JavaDoc name;
804     public String JavaDoc action;
805     public String JavaDoc signedBy;
806
807     public PermissionEntry() {
808     }
809
810     public PermissionEntry(String JavaDoc permission,
811             String JavaDoc name,
812             String JavaDoc action) {
813         this.permission = permission;
814         this.name = name;
815         this.action = action;
816     }
817
818     /**
819      * Calculates a hash code value for the object. Objects
820      * which are equal will also have the same hashcode.
821      */

822     public int hashCode() {
823         int retval = permission.hashCode();
824         if (name != null) retval ^= name.hashCode();
825         if (action != null) retval ^= action.hashCode();
826         return retval;
827     }
828
829     public boolean equals(Object JavaDoc obj) {
830         if (obj == this)
831         return true;
832
833         if (! (obj instanceof PermissionEntry))
834         return false;
835
836         PermissionEntry that = (PermissionEntry) obj;
837
838         if (this.permission == null) {
839         if (that.permission != null) return false;
840         } else {
841         if (!this.permission.equals(that.permission)) return false;
842         }
843
844         if (this.name == null) {
845         if (that.name != null) return false;
846         } else {
847         if (!this.name.equals(that.name)) return false;
848         }
849
850         if (this.action == null) {
851         if (that.action != null) return false;
852         } else {
853         if (!this.action.equals(that.action)) return false;
854         }
855
856         if (this.signedBy == null) {
857         if (that.signedBy != null) return false;
858         } else {
859         if (!this.signedBy.equals(that.signedBy)) return false;
860         }
861
862         // everything matched -- the 2 objects are equal
863
return true;
864     }
865
866     public void write(PrintWriter out) {
867         out.print("permission ");
868         out.print(permission);
869         if (name != null) {
870         out.print(" \"");
871
872         // have to add escape chars for quotes
873
if (name.indexOf("\"") != -1) {
874             int numQuotes = 0;
875             char[] chars = name.toCharArray();
876
877             // count the number of quote chars
878
for (int i = 0; i < chars.length; i++) {
879             if (chars[i] == '"')
880                 numQuotes++;
881             }
882
883             // now, add an escape char before each quote
884
char[] newChars = new char[chars.length + numQuotes];
885             for (int i = 0, j = 0; i < chars.length; i++) {
886             if (chars[i] != '"') {
887                 newChars[j++] = chars[i];
888             } else {
889                 newChars[j++] = '\\';
890                 newChars[j++] = chars[i];
891             }
892             }
893             name = new String JavaDoc(newChars);
894         }
895         out.print(name);
896         out.print('"');
897         }
898         if (action != null) {
899         out.print(", \"");
900         out.print(action);
901         out.print('"');
902         }
903         if (signedBy != null) {
904         out.print(", signedBy \"");
905         out.print(signedBy);
906         out.print('"');
907         }
908         out.println(";");
909     }
910     }
911
912     static class ParsingException extends GeneralSecurityException JavaDoc {
913
914     private static final long serialVersionUID = 8240970523155877400L;
915
916     /**
917      * Constructs a ParsingException with the specified
918      * detail message. A detail message is a String that describes
919      * this particular exception, which may, for example, specify which
920      * algorithm is not available.
921      *
922      * @param msg the detail message.
923      */

924     public ParsingException(String JavaDoc msg) {
925         super(msg);
926     }
927
928     public ParsingException(int line, String JavaDoc msg) {
929         super(rb.getString("line ") + line + rb.getString(": ") + msg);
930     }
931
932     public ParsingException(int line, String JavaDoc expect, String JavaDoc actual) {
933         super(rb.getString("line ") + line + rb.getString(": expected '") +
934         expect + rb.getString("', found '") + actual +
935         rb.getString("'"));
936     }
937     }
938
939     public static void main(String JavaDoc arg[]) throws Exception JavaDoc {
940     PolicyParser pp = new PolicyParser(true);
941     pp.read(new FileReader(arg[0]));
942     FileWriter fr = new FileWriter(arg[1]);
943     pp.write(fr);
944         fr.close();
945     }
946 }
947
Popular Tags