KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > security > classsecurity > ClassAuthentication


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.security.classsecurity;
11
12 import java.io.*;
13 import java.util.*;
14 import java.util.regex.Pattern JavaDoc;
15 import java.net.URL JavaDoc;
16 import java.net.URLConnection JavaDoc;
17
18 import org.mmbase.security.SecurityException;
19 import org.mmbase.security.MMBaseCopConfig;
20 import org.mmbase.util.*;
21 import org.mmbase.util.logging.*;
22 import org.mmbase.util.xml.DocumentReader;
23 import org.w3c.dom.*;
24 import org.xml.sax.InputSource JavaDoc;
25
26
27 /**
28  * Provides the static utility methods to authenticate by class. Default a file
29  * security/<classauthentication.xml> is used for this. If using the wrapper authentication,
30  * its configuration file, contains this configuration.
31  *
32  * @author Michiel Meeuwissen
33  * @version $Id: ClassAuthentication.java,v 1.13 2006/07/14 08:16:49 michiel Exp $
34  * @see ClassAuthenticationWrapper
35  * @since MMBase-1.8
36  */

37 public class ClassAuthentication {
38     private static final Logger log = Logging.getLoggerInstance(ClassAuthentication.class);
39
40     public static final String JavaDoc PUBLIC_ID_CLASSSECURITY_1_0 = "-//MMBase//DTD classsecurity config 1.0//EN";
41     public static final String JavaDoc DTD_CLASSSECURITY_1_0 = "classsecurity_1_0.dtd";
42     static {
43         XMLEntityResolver.registerPublicID(PUBLIC_ID_CLASSSECURITY_1_0, DTD_CLASSSECURITY_1_0, ClassAuthentication.class);
44     }
45     private static List authenticatedClasses = null;
46
47
48     static ResourceWatcher watcher = null;
49
50     /**
51      * Stop watchin the config file, if there is watched one. This is needed when security
52      * configuration switched to ClassAuthenticationWrapper (which will not happen very often).
53      */

54
55     static void stopWatching() {
56         if (watcher != null) {
57             watcher.exit();
58         }
59     }
60
61     private ClassAuthentication() {
62         //Static Utility class
63
}
64
65     /**
66      * Reads the configuration file and instantiates and loads the wrapped Authentication.
67      */

68     protected static synchronized void load(String JavaDoc configFile) throws SecurityException JavaDoc {
69         List resourceList = MMBaseCopConfig.securityLoader.getResourceList(configFile);
70         log.info("Loading " + configFile + "( " + resourceList + ")");
71         authenticatedClasses = new ArrayList();
72         ListIterator it = resourceList.listIterator();
73         while (it.hasNext()) it.next();
74         while (it.hasPrevious()) {
75             URL JavaDoc u = (URL JavaDoc) it.previous();
76             try {
77                 URLConnection JavaDoc con = u.openConnection();
78                 if (! con.getDoInput()) continue;
79                 InputSource JavaDoc in = new InputSource JavaDoc(con.getInputStream());
80                 Document document = DocumentReader.getDocumentBuilder(true, // validate aggresively, because no further error-handling will be done
81
new XMLErrorHandler(false, 0), // don't log, throw exception if not valid, otherwise big chance on NPE and so on
82
new XMLEntityResolver(true, ClassAuthentication.class) // validate
83
).parse(in);
84
85                 NodeList authenticates = document.getElementsByTagName("authenticate");
86
87                 for (int i = 0; i < authenticates.getLength(); i ++) {
88                     Node node = authenticates.item(i);
89                     String JavaDoc clazz = node.getAttributes().getNamedItem("class").getNodeValue();
90                     String JavaDoc method = node.getAttributes().getNamedItem("method").getNodeValue();
91                     Node property = node.getFirstChild();
92                     Map map = new HashMap();
93                     while (property != null) {
94                         if (property instanceof Element && property.getNodeName().equals("property")) {
95                             String JavaDoc name = property.getAttributes().getNamedItem("name").getNodeValue();
96                             String JavaDoc value = property.getAttributes().getNamedItem("value").getNodeValue();
97                             map.put(name, value);
98                         }
99                         property = property.getNextSibling();
100                     }
101                     authenticatedClasses.add(new Login(Pattern.compile(clazz), method, Collections.unmodifiableMap(map)));
102                 }
103             } catch (Exception JavaDoc e) {
104                 log.error(u + " " + e.getMessage(), e);
105             }
106         }
107
108         { // last fall back, everybody may get the 'anonymous' cloud.
109
Map map = new HashMap();
110             map.put("rank", "anonymous");
111             authenticatedClasses.add(new Login(Pattern.compile(".*"), "class", Collections.unmodifiableMap(map)));
112         }
113
114         log.service("Class authentication: " + authenticatedClasses);
115
116     }
117
118
119     /**
120      * Checks wether the (indirectly) calling class is authenticated by the
121      * ClassAuthenticationWrapper (using a stack trace). This method can be called from an
122      * Authentication implementation, e.g. to implement the 'class' application itself (if the
123      * authentication implementation does understand the concept itself, then passwords can be
124      * avoided in the wrappers' configuration file).
125      *
126      * @param application Only checks this 'authentication application'. Can be <code>null</code> to
127      * check for every application.
128      * @return A Login object if yes, <code>null</code> if not.
129      */

130     public static Login classCheck(String JavaDoc application) {
131         if (authenticatedClasses == null) {
132             synchronized(ClassAuthentication.class) { // if load is running this locks
133
if (authenticatedClasses == null) { // if locked, load was running and this now skips, so load is not called twice.
134
String JavaDoc configFile = "classauthentication.xml";
135                     load(configFile);
136                     watcher = new ResourceWatcher(MMBaseCopConfig.securityLoader) {
137                             public void onChange(String JavaDoc resource) {
138                                 load(resource);
139                             }
140                         };
141                     watcher.add(configFile);
142                     watcher.start();
143                 }
144             }
145         }
146         if (log.isDebugEnabled()) {
147             log.trace("Class authenticating (" + authenticatedClasses + ")");
148         }
149         Throwable JavaDoc t = new Throwable JavaDoc();
150         StackTraceElement JavaDoc[] stack = t.getStackTrace();
151
152         Iterator i = authenticatedClasses.iterator();
153
154         while(i.hasNext()) {
155             Login n = (Login) i.next();
156             if (application == null || application.equals(n.application)) {
157                 Pattern JavaDoc p = n.classPattern;
158                 for (int j = 0; j < stack.length; j++) {
159                     String JavaDoc className = stack[j].getClassName();
160                     if (className.startsWith("org.mmbase.security.")) continue;
161                     if (className.startsWith("org.mmbase.bridge.implementation.")) continue;
162                     log.trace("Checking " + className);
163                     if (p.matcher(className).matches()) {
164                         if (log.isDebugEnabled()) {
165                             log.debug("" + className + " matches! ->" + n + " " + n.getMap());
166                         }
167                         return n;
168                     }
169                 }
170             }
171         }
172         if (log.isDebugEnabled()) {
173             log.debug("Failed to authenticate " + Arrays.asList(stack) + " with " + authenticatedClasses);
174         }
175         return null;
176     }
177
178     /**
179      * A structure to hold the login information.
180      */

181     public static class Login {
182         Pattern JavaDoc classPattern;
183         String JavaDoc application;
184         Map map;
185         Login(Pattern JavaDoc p , String JavaDoc a, Map m) {
186             classPattern = p;
187             application = a;
188             map = m;
189         }
190
191         public Map getMap() {
192             return map;
193         }
194         public String JavaDoc toString() {
195             return classPattern.pattern() + (application.equals("class") ? "" : ": " + application);
196         }
197     }
198
199 }
200
Popular Tags