View Javadoc

1   /*
2    * $Id: XmlUsersHandler.java 125 2004-11-01 19:10:53Z josem $
3    *
4    * Tarsis
5    * Copyright (C) 2002 Talika Open Source Group
6    *
7    * This program is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   *
21   */
22  
23  package org.talika.tarsis.security.memory;
24  
25  import java.io.InputStream;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.HashSet;
29  import java.util.Map;
30  import java.util.Set;
31  import java.util.Stack;
32  import java.util.StringTokenizer;
33  
34  import org.talika.tarsis.security.RoleImpl;
35  import org.xml.sax.Attributes;
36  import org.xml.sax.InputSource;
37  import org.xml.sax.SAXException;
38  import org.xml.sax.SAXParseException;
39  import org.xml.sax.helpers.AttributesImpl;
40  import org.xml.sax.helpers.DefaultHandler;
41  
42  /**
43   * Implementation of SAX handlers for Tarsis MVC Users XML files.
44   *
45   * @author  Jose M. Palomar
46   * @version $Revision: 125 $
47   */
48  public final class XmlUsersHandler extends DefaultHandler {
49  
50      // Constants
51      /**
52       * <tarsis-users> tag.
53       */
54      public static final String USERS_TAG = "tarsis-users";
55  
56      /**
57       * <user> tag.
58       */
59      public static final String USER_TAG = "user";
60  
61      /**
62       * Name attribute.
63       */
64      public static final String NAME_ATTR = "name";
65  
66      /**
67       * Password attribute.
68       */
69      public static final String PASSWORD_ATTR = "password";
70  
71      /**
72       * Roles attribute.
73       */
74      public static final String ROLES_ATTR = "roles";
75  
76      /**
77       * Roles separator.
78       */
79      public static final String ROLES_SEPARATOR = ",";
80  
81      /**
82       * DTD public id.
83       */
84      public static final String DTD_PUBLICID = "-//Talika Open Source Group//Users DTD 1.0//ES";
85      /**
86       * DTD class path.
87       */
88      public static final String DTD_CLASSPATH = "/org/talika/dtds/tarsis-users_1_0.dtd";
89  
90      // Fields
91      /**
92       * Users map.
93       */
94      private Map users = new HashMap();
95  
96      /**
97       * Tag attributes stack.
98       */
99      private Stack stAtts = new Stack();
100 
101     /**
102      * Map of parameters.
103      */
104     private Map auxParams = new HashMap();
105 
106     // Constructors
107     /**
108      * Creates a new <code>XmlUsersHandler</code>.
109      */
110     public XmlUsersHandler() {
111     }
112 
113     // Methods
114     // XML Handler
115     /**
116      * Receive notification of the beginning of a document.
117      *
118      * @throws SAXException Any SAX exception, possibly wrapping another exception.
119      * @see org.xml.sax.ContentHandler#startDocument()
120      */
121     public void startDocument() throws SAXException {
122         // Nothing to do
123     }
124 
125     /**
126      * Receive notification of the end of a document.
127      *
128      * @throws SAXException Any SAX exception, possibly wrapping another exception.
129      * @see org.xml.sax.ContentHandler#endDocument()
130      */
131     public void endDocument() throws SAXException {
132         // Nothing to do
133     }
134 
135     /**
136      * Receive notification of the beginning of an element.
137      *
138      * @param namespaceURI String The Namespace URI, or the empty string if the
139      * element has no Namespace URI or if Namespace processing is not being performed.
140      * @param localName String The local name (without prefix), or the empty string
141      * if Namespace processing is not being performed.
142      * @param name String The qualified name (with prefix), or the empty string if
143      * qualified names are not available.
144      * @param atts Attributes The attributes attached to the element. If there are no
145      * attributes, it shall be an empty Attributes object.
146      * @throws SAXException Any SAX exception, possibly wrapping another exception.
147      * @see org.xml.sax.ContentHandler#startElement(String, String, String, Attributes)
148      */
149     public void startElement(String namespaceURI, String localName, String name, Attributes atts) throws SAXException {
150         stAtts.push(new AttributesImpl(atts));
151     }
152 
153     /**
154      * Receive notification of the end of an element.
155      *
156      * @param namespaceURI String The Namespace URI, or the empty string if the
157      * element has no Namespace URI or if Namespace processing is not being performed.
158      * @param localName String The local name (without prefix), or the empty string
159      * if Namespace processing is not being performed.
160      * @param name String The qualified name (with prefix), or the empty string if
161      * qualified names are not available.
162      * @throws SAXException Any SAX exception, possibly wrapping another exception.
163      * @see org.xml.sax.ContentHandler#endElement(String, String, String)
164      */
165     public void endElement(String namespaceURI, String localName, String name) throws SAXException {
166 
167         Attributes atts = (Attributes) stAtts.pop();
168 
169         if (name.equals(USERS_TAG)) {
170             // Nothing to do
171         }
172         else if (name.equals(USER_TAG)) {
173             processUserTag(atts);
174         }
175 
176     }
177 
178     // Entity Resolver
179     /**
180      * Allow the application to resolve external entities.
181      *
182      * @param publicId String The public identifier of the external entity being
183      * referenced, or <code>null</code> if none was supplied.
184      * @param systemId String The system identifier of the external entity being
185      * referenced.
186      * @return InputSource A Java-specific IO exception, possibly the result of
187      * creating a new <code>InputStream</code> or <code>Reader</code> for the
188      * <code>InputSource</code>.
189      * @see org.xml.sax.EntityResolver#resolveEntity(String, String)
190      */
191     public InputSource resolveEntity (String publicId, String systemId) {
192 
193         if (publicId.equals(DTD_PUBLICID)) {
194 
195             InputStream is = this.getClass().getResourceAsStream(DTD_CLASSPATH);
196             if (is != null) {
197                 return new InputSource(is);
198             }
199 
200         }
201 
202         return null;
203 
204     }
205 
206     // Error Handler
207     /**
208      * Receive notification of a warning.
209      *
210      * @param spe SAXParseException The warning information encapsulated in a SAX
211      * parse exception.
212      * @throws SAXException Any SAX exception, possibly wrapping another exception.
213      * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
214      */
215     public void warning(SAXParseException spe) throws SAXException {
216     }
217 
218     /**
219      * Receive notification of a recoverable error.
220      *
221      * @param spe SAXParseException The error information encapsulated in a SAX parse
222      * exception.
223      * @throws SAXException Any SAX exception, possibly wrapping another exception.
224      * @see org.xml.sax.ErrorHandler#error(SAXParseException)
225      */
226     public void error(SAXParseException spe) throws SAXException {
227         throw new SAXException("** Users parse error\n" +
228                             "  at [" + spe.getLineNumber() +
229                             ":" + spe.getColumnNumber() +
230                             "] in " + spe.getSystemId(), spe);
231     }
232 
233     /**
234      * Receive notification of a non-recoverable error.
235      *
236      * @param spe SAXParseException The error information encapsulated in a SAX parse
237      * exception.
238      * @throws SAXException Any SAX exception, possibly wrapping another exception.
239      * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
240      */
241     public void fatalError(SAXParseException spe) throws SAXException {
242         throw new SAXException("** Users parse error\n" +
243                             "  at [" + spe.getLineNumber() +
244                             ":" + spe.getColumnNumber() +
245                             "] in " + spe.getSystemId(), spe);
246     }
247 
248     // Accesors
249     /**
250      * Returns parsed users map.
251      *
252      * @return Map parsed users map.
253      */
254     public Map getUsers() {
255         return Collections.unmodifiableMap(users);
256     }
257 
258     // Helper
259     /**
260      * Process &lt;user&gt; tag.
261      *
262      * @param atts Attributes tag attributes.
263      * @throws SAXException if there is an error while processing tag.
264      */
265     protected void processUserTag(Attributes atts) throws SAXException {
266 
267         String name = atts.getValue(NAME_ATTR);
268         String password = atts.getValue(PASSWORD_ATTR);
269         String rolesStr = atts.getValue(ROLES_ATTR);
270 
271         Set roles = parseRoles(rolesStr);
272 
273         this.users.put(name, new MemoryUserImpl(name, name, password, roles));
274 
275     }
276 
277     /**
278      * Returns a <code>Set</code> of roles parsed from string.
279      *
280      * @param rolesStr String string to be parsed.
281      * @return Set a <code>Set</code> of roles parsed from string.
282      */
283     protected Set parseRoles(String rolesStr) {
284 
285         StringTokenizer st = new StringTokenizer(rolesStr, ROLES_SEPARATOR);
286 
287         Set roles = new HashSet();
288         while (st.hasMoreTokens()) {
289             String roleName = st.nextToken().trim();
290             roles.add(new RoleImpl(roleName));
291         }
292 
293         return roles;
294     }
295 
296 }