1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.user2;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.net.URI;
24 import java.net.URISyntaxException;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28
29 import javax.xml.transform.Source;
30 import javax.xml.transform.TransformerException;
31
32 import org.apache.logging.log4j.LogManager;
33 import org.apache.logging.log4j.Logger;
34 import org.jdom2.Document;
35 import org.jdom2.Element;
36 import org.jdom2.JDOMException;
37 import org.jdom2.Namespace;
38 import org.jdom2.transform.JDOMSource;
39 import org.mycore.common.MCRException;
40 import org.mycore.common.config.MCRConfiguration2;
41 import org.mycore.common.content.MCRFileContent;
42 import org.mycore.common.content.MCRSourceContent;
43 import org.mycore.common.xml.MCRXMLParserFactory;
44 import org.xml.sax.SAXException;
45
46
47
48
49
50
51
52
53
54 public class MCRRealmFactory {
55
56 static final String RESOURCE_REALMS_URI = "resource:realms.xml";
57
58 static final String REALMS_URI_CFG_KEY = MCRUser2Constants.CONFIG_PREFIX + "Realms.URI";
59
60 private static final Logger LOGGER = LogManager.getLogger(MCRRealm.class);
61
62 private static final int REFRESH_DELAY = 5000;
63
64 private static long lastModified = 0;
65
66
67 private static HashMap<String, MCRRealm> realmsMap = new HashMap<>();
68
69 private static HashMap<String, MCRUserAttributeMapper> attributeMapper = new HashMap<>();
70
71
72 private static List<MCRRealm> realmsList = new ArrayList<>();
73
74
75 private static MCRRealm localRealm;
76
77 private static URI realmsURI;
78
79 private static File realmsFile;
80
81 private static long lastChecked;
82
83 private static Document realmsDocument;
84
85 static {
86 String dataDirProperty = "MCR.datadir";
87 String dataDir = MCRConfiguration2.getString(dataDirProperty).orElse(null);
88 if (dataDir == null) {
89 LOGGER.warn("{} is undefined.", dataDirProperty);
90 try {
91 realmsURI = new URI(MCRConfiguration2.getString(REALMS_URI_CFG_KEY).orElse(RESOURCE_REALMS_URI));
92 } catch (URISyntaxException e) {
93 throw new MCRException(e);
94 }
95 } else {
96 File dataDirFile = new File(dataDir);
97 String realmsCfg = MCRConfiguration2.getString(REALMS_URI_CFG_KEY)
98 .orElse(dataDirFile.toURI() + "realms.xml");
99 try {
100 realmsURI = new URI(realmsCfg);
101 LOGGER.info("Using realms defined in {}", realmsURI);
102 if ("file".equals(realmsURI.getScheme())) {
103 realmsFile = new File(realmsURI);
104 LOGGER.info("Loading realms from file: {}", realmsFile);
105 } else {
106 LOGGER.info("Try loading realms with URIResolver for scheme {}", realmsURI);
107 }
108 } catch (URISyntaxException e) {
109 throw new MCRException(e);
110 }
111 }
112 loadRealms();
113 }
114
115
116
117
118 private static void loadRealms() {
119 Element root;
120 try {
121 root = getRealms().getRootElement();
122 } catch (SAXException | JDOMException | TransformerException | IOException e) {
123 throw new MCRException("Could not load realms from URI: " + realmsURI);
124 }
125 String localRealmID = root.getAttributeValue("local");
126 HashMap<String, MCRRealm> realmsMap = new HashMap<>();
127
128 HashMap<String, MCRUserAttributeMapper> attributeMapper = new HashMap<>();
129
130 List<MCRRealm> realmsList = new ArrayList<>();
131
132 List<Element> realms = root.getChildren("realm");
133 for (Element child : realms) {
134 String id = child.getAttributeValue("id");
135 MCRRealm realm = new MCRRealm(id);
136
137 List<Element> labels = child.getChildren("label");
138 for (Element label : labels) {
139 String text = label.getTextTrim();
140 String lang = label.getAttributeValue("lang", Namespace.XML_NAMESPACE);
141 realm.setLabel(lang, text);
142 }
143
144 realm.setPasswordChangeURL(child.getChildTextTrim("passwordChangeURL"));
145 Element login = child.getChild("login");
146 if (login != null) {
147 realm.setLoginURL(login.getAttributeValue("url"));
148 realm.setRedirectParameter(login.getAttributeValue("redirectParameter"));
149 realm.setRealmParameter(login.getAttributeValue("realmParameter"));
150 }
151 Element createElement = child.getChild("create");
152 if (createElement != null) {
153 realm.setCreateURL(createElement.getAttributeValue("url"));
154 }
155
156 attributeMapper.put(id, MCRUserAttributeMapper.instance(child));
157
158 realmsMap.put(id, realm);
159 realmsList.add(realm);
160 if (localRealmID.equals(id)) {
161 localRealm = realm;
162 }
163 }
164 MCRRealmFactory.realmsDocument = root.getDocument();
165 MCRRealmFactory.realmsMap = realmsMap;
166 MCRRealmFactory.realmsList = realmsList;
167 MCRRealmFactory.attributeMapper = attributeMapper;
168 }
169
170 private static Document getRealms() throws JDOMException, TransformerException, SAXException, IOException {
171 if (realmsFile == null) {
172 return MCRSourceContent.getInstance(realmsURI.toASCIIString()).asXML();
173 }
174 if (!realmsFile.exists() || realmsFile.length() == 0) {
175 LOGGER.info("Creating {}...", realmsFile.getAbsolutePath());
176 MCRSourceContent realmsContent = MCRSourceContent.getInstance(RESOURCE_REALMS_URI);
177 realmsContent.sendTo(realmsFile);
178 }
179 updateLastModified();
180 return MCRXMLParserFactory.getNonValidatingParser().parseXML(new MCRFileContent(realmsFile));
181 }
182
183
184
185
186
187
188
189 public static MCRRealm getRealm(String id) {
190 reInitIfNeeded();
191 return realmsMap.get(id);
192 }
193
194 public static MCRUserAttributeMapper getAttributeMapper(String id) {
195 reInitIfNeeded();
196 return attributeMapper.get(id);
197 }
198
199
200
201
202
203
204 public static List<MCRRealm> listRealms() {
205 reInitIfNeeded();
206 return realmsList;
207 }
208
209
210
211
212 public static Document getRealmsDocument() {
213 reInitIfNeeded();
214 return realmsDocument.clone();
215 }
216
217
218
219
220 static Source getRealmsSource() {
221 reInitIfNeeded();
222 return new JDOMSource(realmsDocument);
223 }
224
225
226
227
228
229
230 public static MCRRealm getLocalRealm() {
231 reInitIfNeeded();
232 return localRealm;
233 }
234
235 private static boolean reloadingRequired() {
236 boolean reloading = false;
237
238 long now = System.currentTimeMillis();
239
240 if (now > lastChecked + REFRESH_DELAY) {
241 lastChecked = now;
242 if (hasChanged()) {
243 reloading = true;
244 }
245 }
246
247 return reloading;
248 }
249
250 private static boolean hasChanged() {
251 if (realmsFile == null || !realmsFile.exists()) {
252 return false;
253 }
254 return realmsFile.lastModified() > lastModified;
255 }
256
257 private static void updateLastModified() {
258 if (realmsFile == null || !realmsFile.exists()) {
259 return;
260 }
261 lastModified = realmsFile.lastModified();
262 }
263
264 private static void reInitIfNeeded() {
265 if (reloadingRequired()) {
266 loadRealms();
267 }
268 }
269
270 }