1 package com.atlassian.seraph.service;
2
3 import com.atlassian.seraph.SecurityService;
4 import com.atlassian.seraph.config.SecurityConfig;
5 import com.atlassian.seraph.util.CachedPathMapper;
6 import com.atlassian.seraph.util.XMLUtils;
7
8 import org.apache.log4j.Category;
9 import org.w3c.dom.Document;
10 import org.w3c.dom.Element;
11 import org.w3c.dom.NodeList;
12
13 import com.opensymphony.util.ClassLoaderUtil;
14
15 import java.net.URL;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.StringTokenizer;
23 import java.util.concurrent.ConcurrentHashMap;
24
25 import javax.servlet.http.HttpServletRequest;
26 import javax.xml.parsers.DocumentBuilderFactory;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class PathService implements SecurityService
51 {
52 private static final Category log = Category.getInstance(PathService.class);
53 static String CONFIG_FILE_PARAM_KEY = "config.file";
54
55 String configFileLocation = "seraph-paths.xml";
56
57
58 private final CachedPathMapper pathMapper = new CachedPathMapper();
59
60
61 private final Map<String, String[]> paths = new ConcurrentHashMap<String, String[]>();
62
63
64
65
66 public void init(final Map<String, String> params, final SecurityConfig config)
67 {
68 if (params.get(CONFIG_FILE_PARAM_KEY) != null)
69 {
70 configFileLocation = params.get(CONFIG_FILE_PARAM_KEY);
71 }
72
73 configurePathMapper();
74 }
75
76
77
78
79 private void configurePathMapper()
80 {
81 try
82 {
83 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
84 URL fileUrl = ClassLoaderUtil.getResource(configFileLocation, this.getClass());
85
86 if (fileUrl == null)
87 {
88 fileUrl = ClassLoaderUtil.getResource("/" + configFileLocation, this.getClass());
89 }
90
91 if (fileUrl == null)
92 {
93 return;
94 }
95
96
97 final Document doc = factory.newDocumentBuilder().parse(fileUrl.toString());
98
99
100 final Element root = doc.getDocumentElement();
101 final NodeList pathNodes = root.getElementsByTagName("path");
102
103 final Map<String, String> pathMaps = new HashMap<String, String>();
104
105 for (int i = 0; i < pathNodes.getLength(); i++)
106 {
107 final Element path = (Element) pathNodes.item(i);
108
109 final String pathName = path.getAttribute("name");
110 final String roleNames = XMLUtils.getContainedText(path, "role-name");
111 final String urlPattern = XMLUtils.getContainedText(path, "url-pattern");
112
113 if ((roleNames != null) && (urlPattern != null))
114 {
115 final String[] rolesArr = parseRoles(roleNames);
116 paths.put(pathName, rolesArr);
117 pathMaps.put(pathName, urlPattern);
118 }
119 }
120 pathMapper.set(pathMaps);
121 }
122 catch (final Exception ex)
123 {
124 log.error(ex);
125 }
126 }
127
128 protected String[] parseRoles(final String roleNames)
129 {
130 final StringTokenizer st = new StringTokenizer(roleNames, ",; \t\n", false);
131 final String[] roles = new String[st.countTokens()];
132 int i = 0;
133 while (st.hasMoreTokens())
134 {
135 roles[i] = st.nextToken();
136 i++;
137 }
138 return roles;
139 }
140
141 public void destroy()
142 {}
143
144 public Set<String> getRequiredRoles(final HttpServletRequest request)
145 {
146 final String servletPath = request.getServletPath();
147 return getRequiredRoles(servletPath);
148 }
149
150 public Set<String> getRequiredRoles(final String servletPath)
151 {
152 final Set<String> requiredRoles = new HashSet<String>();
153
154
155 final Collection<String> constraintMatches = pathMapper.getAll(servletPath);
156
157 if (constraintMatches == null)
158 {
159 throw new RuntimeException("No constraints matched for path " + servletPath);
160 }
161 for (final String constraint : constraintMatches)
162 {
163 final String[] rolesForPath = paths.get(constraint);
164 for (int i = 0; i < rolesForPath.length; i++)
165 {
166 if (!requiredRoles.contains(rolesForPath[i]))
167 {
168 requiredRoles.add(rolesForPath[i]);
169 }
170 }
171 }
172 return Collections.unmodifiableSet(requiredRoles);
173 }
174 }