View Javadoc

1   /*
2    * FQAN.java
3    *
4    * Created on September 10, 2004, 12:14 PM
5    */
6   
7   package gov.bnl.gums;
8   
9   import java.util.StringTokenizer;
10  import java.util.regex.Matcher;
11  import java.util.regex.Pattern;
12  
13  import org.apache.log4j.Logger;
14  
15  /** 
16   * Represent a VOMS extended proxy credential as defined in
17   * http://edg-wp2.web.cern.ch/edg-wp2/security/voms/edg-voms-credential.pdf.
18   * <p>
19   * A Fully Qualified Attribute Name consists of a VO, a group, a role and
20   * a capability. Only the VO is mandatory. The syntax is
21   * /VO[/group[/subgroup(s)]][/Role=role][/Capability=cap].
22   * <p>
23   * The class will always check that every modification matches the regex
24   * /[\w-\.]+(/[\w-\.]+)*(/Role=[\w-\.]+)?(/Capability=[\w-\.]+)?
25   * which fully defines all the characters allowed. This differs slightly from
26   * the one contained in the specification, as it contained some small errors.
27   * It matches the description of the syntax of the document.
28   *
29   * @author  Gabriele Carcassi, Jay Packard
30   */
31  public class FQAN {
32  	static private Pattern fqanPattern = Pattern.compile("/[\\w-\\.]+(/[\\w-\\.]+)*(/Role=[\\w-\\.]+)?(/Capability=[\\w-\\.]+)?");
33      private String fqan;
34      private String vo;
35      private String group;
36      private String role;
37      private String capability;
38      private boolean checkFormedness = true;
39      
40      /**
41       * Creates a FQAN based on String representation. If the parsing fails, it will
42       * throw an exception.
43       * @param fqan A VOMS FQAN (i.e. "/atlas/production/Role=Leader")
44       */
45      public FQAN(String fqan) {
46         this(fqan, true);
47      }
48      
49      /**
50       * Creates a FQAN based on String representation. If the parsing fails, it will
51       * throw an exception.
52       * @param fqan A VOMS FQAN (i.e. "/atlas/production/Role=Leader")
53       */
54      public FQAN(String fqan, boolean checkFormedness) {
55      	this.checkFormedness = checkFormedness;
56          setFqan(fqan);
57          if (parseFqan(fqan))
58          	generateFqan();
59      }
60      
61      /** Creates a FQAN based on the different pieces of information.
62       * 
63       * @param vo The VO name, which cannot be null (i.e. "atlas")
64       * @param group A group path, including subgroups (i.e. "/production")
65       * @param role The role (i.e. "Leader")
66       * @param capability A capability (i.e. "capability"). Note capabilities are
67       * being deprecated in VOMS.
68       */
69      public FQAN(String vo, String group, String role, String capability) {
70          if (vo == null)
71              throw new IllegalArgumentException("The vo for a FQAN can't be null");
72          setVo(vo);
73          setGroup(group);
74          setRole(role);
75          setCapability(capability);
76          generateFqan();
77      }
78      
79      /** FQANs are equals to each other if their vo, group, role and capability
80       * are the same.
81       * 
82       * @param obj Another object.
83       * @return True if the object was a FQAN with equal information. False otherwise.
84       */
85      public boolean equals(Object obj) {
86          if (obj == null) return false;
87          FQAN fqan2 = (FQAN) obj;
88          return (fqan2.fqan == null) ? fqan == null : fqan2.fqan.equalsIgnoreCase(fqan);
89      }
90  
91      /**
92       *  The capability used within the FQAN.
93       *  
94       * @return The capability or null if none was specified.
95       */
96      public String getCapability() {
97          return this.capability;
98      }
99  
100     /** A full String representation of the FQAN.
101      * 
102      * @return The Fully Qualified Attribute name String representation (i.e. "/atlas/production/Role=Leader")
103      */
104     public String getFqan() {
105         return this.fqan;
106     }
107     
108     /** The path which includes the groups and subgroups within the FQAN.
109      * 
110      * @return The group path (i.e. "/production")
111      */
112     public String getGroup() {
113         return this.group;
114     }
115     
116     /** The role used within the FQAN.
117      * 
118      * @return The role or null if no role was specified
119      */
120     public String getRole() {
121         return this.role;
122     }
123     
124     /** Returns the VO corresponding to the FQAN.
125      * 
126      * @return The VO name (i.e. "atlas")
127      */
128     public String getVo() {
129         return this.vo;
130     }
131     
132     /** A hashcode generated from the string representation.
133      * 
134      * @return A hashcode.
135      */
136     public int hashCode() {
137         if (fqan == null) return 0;
138         return fqan.hashCode();
139     }
140     
141     /** Returns the full string representation of the FQAN.
142      * 
143      * @return The full FQAN (i.e. "/atlas/production/Role=Leader")
144      */
145     public String toString() {
146         return fqan;
147     }
148     
149     private void generateFqan() {
150         if (vo == null) {
151             fqan = null;
152             return;
153         }
154         StringBuffer bf = new StringBuffer();
155         bf.append('/');
156         bf.append(vo);
157         if (group != null)
158             bf.append(group);
159         if (role != null) {
160             bf.append("/Role=");
161             bf.append(role);
162         }
163         if (capability != null) {
164             bf.append("/Capability=");
165             bf.append(capability);
166         }
167         fqan = bf.toString();
168     }
169     
170     private boolean parseFqan(String fqan) {
171         // Matches to the specification.
172     	Matcher m = fqanPattern.matcher(fqan);
173         if (!m.matches()) {
174         	if (checkFormedness)
175         		throw new IllegalArgumentException("FQAN '" + fqan + "' is malformed (syntax: /VO[/group[/subgroup(s)]][/Role=role][/Capability=cap])");
176         	else
177         		return false;
178         }
179         
180         StringTokenizer stk = new StringTokenizer(fqan, "/");
181         vo = stk.nextToken();
182         if (!stk.hasMoreTokens()) {
183             group = null;
184             role = null;
185             capability = null;
186             return true;
187         }
188         String tempGroup = "";
189         String token = stk.nextToken();
190         while ((!token.startsWith("Role=") && !token.startsWith("Capability="))) {
191             tempGroup = tempGroup + "/" + token;
192             group = tempGroup;
193             if (!stk.hasMoreTokens()) {
194                 role = null;
195                 capability = null;
196                 return true;
197             }
198             token =  stk.nextToken();
199         }
200         if (token.startsWith("Role=")) {
201             setRole(token.substring(5));
202             if (!stk.hasMoreTokens()) {
203                 capability = null;
204                 return true;
205             }
206             token = stk.nextToken();
207         }
208         if (token.startsWith("Capability=")) {
209             setCapability(token.substring(11));
210         }
211         
212         return true;
213     }
214     
215     private void setCapability(String capability) {
216         if ((capability != null) && (!capability.matches("[\\w-\\.]+"))) {
217             throw new IllegalArgumentException("The capability '" + capability + "' is malformed");
218         }
219         this.capability = capability;
220         if ("NULL".equalsIgnoreCase(capability)) {
221             this.capability = null;
222         }
223     }
224     
225     private void setFqan(String fqan) {
226         this.fqan = fqan;
227     }
228     
229     private void setGroup(String group) {
230         if ((group != null) && (!group.matches("(/[\\w-\\.]+)+"))) {
231             throw new IllegalArgumentException("The group '" + group + "' is malformed");
232         }
233         this.group = group;
234     }
235     
236     private void setRole(String role) {
237         if ((role != null) && (!role.matches("[\\w-\\.]+"))) {
238             throw new IllegalArgumentException("The role '" + role + "' is malformed");
239         }
240         this.role = role;
241         if ("NULL".equalsIgnoreCase(role)) {
242             this.role = null;
243         }
244     }
245     
246     private void setVo(String vo) {
247         if ((vo != null) && (!vo.matches("[\\w-\\.]+"))) {
248             throw new IllegalArgumentException("The vo '" + vo + "' is malformed");
249         }
250         this.vo = vo;
251     }
252     
253 }