1
2
3
4
5
6
7 package gov.bnl.gums.configuration;
8
9 import gov.bnl.gums.GUMS;
10 import gov.bnl.gums.GridUser;
11 import gov.bnl.gums.SiteUser;
12 import gov.bnl.gums.account.AccountMapper;
13 import gov.bnl.gums.account.ManualAccountMapper;
14 import gov.bnl.gums.admin.CertCache;
15 import gov.bnl.gums.groupToAccount.GroupToAccountMapping;
16 import gov.bnl.gums.hostToGroup.CertificateHostToGroupMapping;
17 import gov.bnl.gums.hostToGroup.HostToGroupMapping;
18 import gov.bnl.gums.userGroup.UserGroup;
19 import gov.bnl.gums.userGroup.VOMSUserGroup;
20 import gov.bnl.gums.userGroup.ManualUserGroup;
21 import gov.bnl.gums.util.StringUtil;
22 import gov.bnl.gums.util.URIToolkit;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.io.OutputStream;
29 import java.io.PrintStream;
30 import java.net.MalformedURLException;
31 import java.net.URL;
32 import java.util.*;
33 import java.util.jar.JarFile;
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36
37 import javax.xml.parsers.DocumentBuilder;
38 import javax.xml.parsers.DocumentBuilderFactory;
39 import javax.xml.parsers.ParserConfigurationException;
40 import javax.xml.transform.Source;
41 import javax.xml.transform.Transformer;
42 import javax.xml.transform.TransformerFactory;
43 import javax.xml.transform.sax.SAXSource;
44 import javax.xml.transform.stream.StreamResult;
45 import javax.xml.transform.stream.StreamSource;
46
47 import org.xml.sax.ErrorHandler;
48 import org.xml.sax.InputSource;
49 import org.xml.sax.SAXParseException;
50 import org.xml.sax.SAXException;
51 import org.xml.sax.XMLReader;
52 import org.xml.sax.helpers.XMLReaderFactory;
53 import org.apache.commons.beanutils.MethodUtils;
54 import org.apache.commons.digester.*;
55 import org.apache.log4j.Logger;
56
57
58
59
60
61
62
63 public class ConfigurationToolkit {
64
65
66
67
68
69 public class SimpleErrorHandler implements ErrorHandler {
70 public String error = null;
71
72 public void error(SAXParseException exception) {
73 log.error(exception.getMessage());
74 adminLog.error(exception.getMessage());
75 error = exception.getMessage();
76 }
77
78 public void fatalError(SAXParseException exception) {
79 log.fatal(exception.getMessage());
80 adminLog.fatal(exception.getMessage());
81 error = exception.getMessage();
82 }
83
84 public void warning(SAXParseException exception) {
85 log.warn(exception.getMessage());
86 adminLog.warn(exception.getMessage());
87 }
88 }
89
90 private static class ConfElementRule extends Rule {
91 public void begin(String str, String str1, org.xml.sax.Attributes attributes) throws java.lang.Exception {
92 Object configElement = getDigester().peek();
93 for (int i = 0; i < attributes.getLength(); i++) {
94 String attribute = attributes.getQName(i);
95 String value = attributes.getValue(i);
96 String setMethod = "set" + attribute.substring(0, 1).toUpperCase() + attribute.substring(1);
97 try {
98 try {
99
100 MethodUtils.invokeMethod(configElement, setMethod, value);
101 } catch (NoSuchMethodException e) {
102 if (value.length()==0)
103
104 continue;
105
106 Boolean boolVal;
107 try {
108 boolVal = new Boolean(value);
109 MethodUtils.invokeMethod(configElement, setMethod, boolVal);
110 }
111 catch (Exception e2) {
112 throw new NoSuchMethodException();
113 }
114 }
115 } catch (NoSuchMethodException e) {
116
117 try {
118 StringTokenizer tokens = new StringTokenizer(value, ",");
119 while (tokens.hasMoreTokens()) {
120 value = tokens.nextToken().trim();
121 String addMethod = "add" + attribute.substring(0, 1).toUpperCase() + attribute.substring(1, attribute.length() - 1);
122 MethodUtils.invokeMethod(configElement, addMethod, value);
123 }
124 } catch (NoSuchMethodException e1) {
125 throw new NoSuchMethodException("Could not find setter function for "+attribute);
126 }
127 }
128 }
129 }
130 }
131 static public String testHostDN = "/DC=com/DC=example/OU=Services/CN=example.site.com";
132 static public Pattern testHostDNPattern = (Pattern) Pattern.compile(testHostDN);
133 static public String testUserDN = "/DC=com/DC=example/OU=People/CN=Example User 12345";
134 static private Logger adminLog = Logger.getLogger(GUMS.gumsAdminLogName);
135 static private Logger log = Logger.getLogger(ConfigurationToolkit.class);
136 static private String schemaPath = null;
137 static private String templateSchemaPath = null;
138 static private String transformDir = null;
139 static String gumsJarPath = null;
140 static public Set<Class<ConfigElement>> userGroupSet = null;
141 static public Set<Class<ConfigElement>> accountMapperSet = null;
142 static public Set<Class<ConfigElement>> groupToAccountSet = null;
143 static public Set<Class<ConfigElement>> hostToGroupSet = null;
144
145 static {
146 String resourceDir = null;
147 try {
148 resourceDir = CertCache.getResourceDir();
149 } catch (Exception e) {
150
151 URL resource = new ConfigurationToolkit().getClass().getClassLoader().getResource("gums.config");
152 if (resource == null) {
153 String temp = System.getProperty("user.dir");
154 if (temp.endsWith("/WEB-INF/scripts"))
155 resourceDir = temp + "/..";
156 }
157
158 if (resource != null)
159 resourceDir = resource.getPath().replace("/gums.config", "");
160 }
161 if (resourceDir != null) {
162 schemaPath = resourceDir + "/gums.config.schema";
163 templateSchemaPath = resourceDir + "/gums.config.template.schema";
164 transformDir = resourceDir + "/";
165 }
166 String[] classPaths = System.getProperty("java.class.path").split(File.pathSeparator);
167 for (int i=0; i<classPaths.length; i++) {
168 if (classPaths[i].contains("gums-core") && classPaths[i].contains(".jar")) {
169 gumsJarPath = classPaths[i];
170 break;
171 }
172 }
173 try {
174 userGroupSet = findClasses(Thread.currentThread().getContextClassLoader(), null, Collections.singleton("gov.bnl.gums.userGroup"), gumsJarPath!=null?Collections.singleton(gumsJarPath):null);
175 userGroupSet.remove(UserGroup.class);
176 accountMapperSet = findClasses(Thread.currentThread().getContextClassLoader(), null, Collections.singleton("gov.bnl.gums.account"), gumsJarPath!=null?Collections.singleton(gumsJarPath):null);
177 accountMapperSet.remove(AccountMapper.class);
178 groupToAccountSet = findClasses(Thread.currentThread().getContextClassLoader(), null, Collections.singleton("gov.bnl.gums.groupToAccount"), gumsJarPath!=null?Collections.singleton(gumsJarPath):null);
179 hostToGroupSet = findClasses(Thread.currentThread().getContextClassLoader(), null, Collections.singleton("gov.bnl.gums.hostToGroup"), gumsJarPath!=null?Collections.singleton(gumsJarPath):null);
180 hostToGroupSet.remove(HostToGroupMapping.class);
181 } catch (ClassNotFoundException e) {
182 log.fatal(e);
183 throw new RuntimeException(e.getMessage());
184 }
185 }
186
187 static public Configuration do1_1_to_1_4Transform(String configText,
188 String transformPath) {
189 try {
190 log.trace("Transforming configuration file using transform '" + transformPath);
191
192 File configFileTemp = File.createTempFile("gums", "config");
193
194 XMLReader reader = XMLReaderFactory.createXMLReader();
195 Source source = new SAXSource(reader, new InputSource(new ByteArrayInputStream(configText.getBytes())));
196
197 StreamResult result = new StreamResult(configFileTemp);
198 Source style = new StreamSource(transformPath);
199
200 TransformerFactory transFactory = TransformerFactory.newInstance();
201 Transformer trans = transFactory.newTransformer(style);
202
203 trans.transform(source, result);
204
205
206
207 Digester digester = ConfigurationToolkit.retrieveDigester();
208 Configuration configuration = new Configuration(true);
209 digester.push(configuration);
210 digester.parse("file://" + configFileTemp.getAbsolutePath());
211
212 configFileTemp.delete();
213
214
215 Iterator<String> it = new ArrayList<String>(configuration.getAccountMappers().keySet()).iterator();
216 while (it.hasNext()) {
217 String name = it.next();
218 String origName = new String(name);
219 if (name.indexOf("://") != -1) {
220 name = name.replaceAll(".*://", "");
221 name = name.replaceAll(".*/dc=", "");
222 name = name.replaceAll("dc=", "");
223 name = name.toLowerCase();
224 if (configuration.getAccountMapper(name) != null) {
225 int count = 1;
226 while (configuration.getAccountMapper(name + Integer.toString(count)) != null)
227 count++;
228 name += Integer.toString(count);
229 }
230 AccountMapper accountMapper = configuration.getAccountMapper(origName);
231 if (accountMapper != null) {
232 accountMapper.setName(name);
233 configuration.removeAccountMapper(origName, false);
234 configuration.addAccountMapper(accountMapper);
235 Iterator<GroupToAccountMapping> it2 = configuration.getGroupToAccountMappings().values().iterator();
236 while (it2.hasNext()) {
237 GroupToAccountMapping groupToAccountMapping = it2.next();
238 List<String> accountMappers = StringUtil.toList(groupToAccountMapping.getAccountMappers());
239 Iterator<String> it3 = accountMappers.iterator();
240 int index = 0;
241 while (it3.hasNext()) {
242 String str = it3.next();
243 if (str.equals(origName)) {
244 groupToAccountMapping.removeAccountMapper(index);
245 groupToAccountMapping.addAccountMapper(index, name);
246 it3 = accountMappers.iterator();
247 index = 0;
248 } else
249 index++;
250 }
251 }
252 }
253 }
254 }
255
256 if (configuration.getUserGroup("osg") != null) {
257
258 configuration.setSource("OSG");
259 configuration.setIsTemplate(true);
260 }
261
262 return configuration;
263 } catch (Exception e) {
264 String message = "Could not convert older version of gums.config";
265 log.error(message, e);
266 adminLog.error(message);
267 throw new RuntimeException(message);
268 }
269 }
270
271 static public Configuration do1_3_to_1_4Transform(String configText) {
272 try {
273 configText = configText.replaceAll("\n", " ");
274
275
276 Map<String, String> vsMap = new HashMap<String, String>();
277 String vomsServerName = null;
278 String vomsUrl = null;
279 int i = configText.indexOf("<vomsServers", 0) + 1;
280 while (i != -1) {
281 if ((i = configText.indexOf("<vomsServer", i)) != -1) {
282 int j = -1;
283 if ((j = configText.indexOf("name", i)) != -1) {
284 int startingIndex = -1, endingIndex = -1;
285 for (; j < configText.length() && configText.charAt(j) != '\n'; j++) {
286 if (configText.charAt(j) == '\'' || configText.charAt(j) == '"') {
287 startingIndex = j + 1;
288 break;
289 }
290 }
291 j++;
292 for (; j < configText.length() && configText.charAt(j) != '\n'; j++) {
293 if (configText.charAt(j) == '\'' || configText.charAt(j) == '"') {
294 endingIndex = j;
295 break;
296 }
297 }
298 if (startingIndex != -1 && endingIndex != -1)
299 vomsServerName = configText.substring(startingIndex, endingIndex);
300 }
301 if ((j = configText.indexOf("baseUrl", i)) != -1) {
302 int startingIndex = -1, endingIndex = -1;
303 for (; j < configText.length() && configText.charAt(j) != '\n'; j++) {
304 if (configText.charAt(j) == '\'' || configText.charAt(j) == '"') {
305 startingIndex = j + 1;
306 break;
307 }
308 }
309 j++;
310 for (; j < configText.length() && configText.charAt(j) != '\n'; j++) {
311 if (configText.charAt(j) == '\'' || configText.charAt(j) == '"') {
312 endingIndex = j;
313 break;
314 }
315 }
316 if (startingIndex != -1 && endingIndex != -1)
317 vomsUrl = configText.substring(startingIndex, endingIndex);
318 }
319 i++;
320 }
321 if (vomsServerName != null && vomsUrl != null) {
322 vsMap.put(vomsServerName, vomsUrl);
323 vomsServerName = null;
324 vomsUrl = null;
325 }
326 }
327
328
329 Map<String, String> ugMap = new HashMap<String, String>();
330 String userGroupName = null;
331 String vomsServer = null;
332 i = configText.indexOf("<vomsUserGroups", 0) + 1;
333 while (i != -1) {
334 if ((i = configText.indexOf("<vomsUserGroup", i)) != -1) {
335 int j = -1;
336 if ((j = configText.indexOf("name", i)) != -1) {
337 int startingIndex = -1, endingIndex = -1;
338 for (; j < configText.length() && configText.charAt(j) != '\n'; j++) {
339 if (configText.charAt(j) == '\'' || configText.charAt(j) == '"') {
340 startingIndex = j + 1;
341 break;
342 }
343 }
344 j++;
345 for (; j < configText.length() && configText.charAt(j) != '\n'; j++) {
346 if (configText.charAt(j) == '\'' || configText.charAt(j) == '"') {
347 endingIndex = j;
348 break;
349 }
350 }
351 if (startingIndex != -1 && endingIndex != -1)
352 userGroupName = configText.substring(startingIndex, endingIndex);
353 }
354 if ((j = configText.indexOf("vomsServer", i)) != -1) {
355 int startingIndex = -1, endingIndex = -1;
356 for (; j < configText.length() && configText.charAt(j) != '\n'; j++) {
357 if (configText.charAt(j) == '\'' || configText.charAt(j) == '"') {
358 startingIndex = j + 1;
359 break;
360 }
361 }
362 j++;
363 for (; j < configText.length() && configText.charAt(j) != '\n'; j++) {
364 if (configText.charAt(j) == '\'' || configText.charAt(j) == '"') {
365 endingIndex = j;
366 break;
367 }
368 }
369 if (startingIndex != -1 && endingIndex != -1)
370 vomsServer = configText.substring(startingIndex, endingIndex);
371 }
372 i++;
373 }
374 if (userGroupName != null && vomsServer != null) {
375 ugMap.put(userGroupName, vomsServer);
376 userGroupName = null;
377 vomsServer = null;
378 }
379 }
380
381
382 String sslKey = "";
383 Pattern p = Pattern.compile(".*sslKey[\\s]*=[\\s]*['|\"](.*?)['|\"].*");
384 Matcher m = p.matcher(configText);
385 if (m.matches())
386 sslKey = m.group(1);
387 String sslCertfile = "";
388 p = Pattern.compile(".*sslCertfile[\\s]*=[\\s]*['|\"](.*?)['|\"].*");
389 m = p.matcher(configText);
390 if (m.matches())
391 sslCertfile = m.group(1);
392 String sslCaFiles = "";
393 p = Pattern.compile(".*sslCAFiles[\\s]*=[\\s]*['|\"](.*?)['|\"].*");
394 m = p.matcher(configText);
395 if (m.matches())
396 sslCaFiles = m.group(1);
397 String sslKeyPasswd = "";
398 p = Pattern.compile(".*sslKeyPasswd[\\s]*=[\\s]*['|\"](.*?)['|\"].*");
399 m = p.matcher(configText);
400 if (m.matches())
401 sslKeyPasswd = m.group(1);
402
403
404 configText = configText.replaceAll("<vomsServers>.*</vomsServers>", "");
405 configText = configText.replaceAll("remainderUrl", "vomsServerUrls");
406 configText = configText.replaceAll("vomsServer=['|\"].*?['|\"]", "");
407 configText = configText.replaceAll("persistenceFactory=['|\"].*?['|\"]", "");
408 configText = configText.replaceAll("<hostToGroupMapping[\\s]", "<certificateHostToGroupMapping");
409
410
411 Configuration configuration = new Configuration();
412 Digester digester = retrieveDigester();
413 digester.push(configuration);
414 digester.parse(new ByteArrayInputStream(configText.getBytes()));
415
416
417 configuration.setSslKey(sslKey);
418 configuration.setSslCertfile(sslCertfile);
419 configuration.setSslCAFiles(sslCaFiles);
420 configuration.setSslKeyPasswd(sslKeyPasswd);
421
422
423 for (UserGroup u : configuration.getUserGroups().values()) {
424 if (u instanceof VOMSUserGroup) {
425 VOMSUserGroup vug = (VOMSUserGroup) u;
426 String remainderUrl = vug.getVomsServerUrls();
427 String temp = ugMap.get(vug.getName());
428 if (temp != null) {
429 String baseUrl = vsMap.get(temp);
430 vug.setVomsServerUrls(baseUrl + remainderUrl);
431 }
432 }
433 }
434
435 return configuration;
436 } catch (Exception e) {
437 String message = "Could not convert older version of gums.config";
438 log.error(message, e);
439 adminLog.error(message);
440 throw new RuntimeException(message);
441 }
442 }
443
444 public static Set<Class<ConfigElement>> getConfigElementTypes(Class<?> configElementClass) {
445 if (configElementClass.equals(AccountMapper.class))
446 return accountMapperSet;
447 else if (configElementClass.equals(UserGroup.class))
448 return userGroupSet;
449 else if (configElementClass.equals(GroupToAccountMapping.class))
450 return groupToAccountSet;
451 else if (configElementClass.equals(HostToGroupMapping.class))
452 return hostToGroupSet;
453 else
454 assert(false);
455 return null;
456 }
457
458 static public void insertTest(Configuration configuration) {
459
460 ManualUserGroup manualUserGroup;
461 UserGroup userGroup = (ManualUserGroup) configuration.getUserGroup("_test");
462 if (userGroup != null && userGroup instanceof ManualUserGroup)
463 manualUserGroup = (ManualUserGroup) userGroup;
464 else {
465 String name = "_test";
466 while (configuration.getUserGroup(name) != null)
467 name = name + "_";
468 manualUserGroup = new ManualUserGroup(configuration, name);
469 }
470 GridUser testUser = new GridUser(testUserDN);
471 if (!manualUserGroup.isMember(testUser))
472 manualUserGroup.addMember(testUser);
473
474
475 ManualAccountMapper manualAccountMapper;
476 AccountMapper accountMapper = configuration.getAccountMapper("_test");
477 if (accountMapper != null && accountMapper instanceof ManualAccountMapper)
478 manualAccountMapper = (ManualAccountMapper) accountMapper;
479 else {
480 String name = "_test";
481 while (configuration.getAccountMapper(name) != null)
482 name = name + "_";
483 manualAccountMapper = new ManualAccountMapper(configuration, name);
484 }
485 if (manualAccountMapper.mapDn(testUser.getDn(), false) == null)
486 manualAccountMapper.createMapping(testUser.getDn(),
487 new SiteUser("test"));
488
489
490 GroupToAccountMapping g2AMapping = configuration.getGroupToAccountMapping("_test");
491 if (g2AMapping == null) {
492 g2AMapping = new GroupToAccountMapping(configuration, "_test");
493 g2AMapping.setName("_test");
494 }
495 if (!StringUtil.toList(g2AMapping.getUserGroups()).contains(manualUserGroup.getName()))
496 g2AMapping.addUserGroup(manualUserGroup.getName());
497 if (!StringUtil.toList(g2AMapping.getAccountMappers()).contains(manualAccountMapper.getName()))
498 g2AMapping.addAccountMapper(manualAccountMapper.getName());
499
500
501 HostToGroupMapping h2GMapping = configuration.getHostToGroupMapping(testHostDN);
502 if (h2GMapping == null) {
503 h2GMapping = new CertificateHostToGroupMapping(configuration);
504 ((CertificateHostToGroupMapping) h2GMapping).setDn(testHostDN);
505 }
506 if (!StringUtil.toList(h2GMapping.getGroupToAccountMappings()).contains(g2AMapping.getName()))
507 h2GMapping.addGroupToAccountMapping(g2AMapping.getName());
508 }
509
510 public static void main(String args[]) {
511 if (args.length != 1) {
512 System.out.println("Must specify arguments: {configuration path}");
513 return;
514 }
515
516
517
518 PrintStream errStreamOriginal = System.err;
519 System.setErr(new PrintStream(new OutputStream() {
520 public void write(int b) {
521 }
522 }));
523 PrintStream outStreamOriginal = System.out;
524 System.setOut(new PrintStream(new OutputStream() {
525 public void write(int b) {
526 }
527 }));
528
529 try {
530 FileInputStream fileInputStream = new FileInputStream(args[0]);
531 try {
532 StringBuffer configBuffer = new StringBuffer();
533 int ch;
534 while ((ch = fileInputStream.read()) != -1)
535 configBuffer.append((char) ch);
536 ConfigurationToolkit.parseConfiguration(
537 configBuffer.toString(), false);
538 } finally {
539 fileInputStream.close();
540 }
541 } catch (Exception e) {
542 System.setErr(errStreamOriginal);
543 System.setOut(outStreamOriginal);
544 System.out.println("Configuration is NOT valid:");
545 System.out.println(e.getMessage());
546 System.exit(1);
547 }
548
549 System.setErr(errStreamOriginal);
550 System.setOut(outStreamOriginal);
551
552 System.out.println("Configuration is valid");
553 }
554
555
556
557
558
559
560
561
562
563 public static Configuration metaParse(ByteArrayInputStream inputStream)
564 throws IOException, SAXException {
565 Digester digester = new Digester();
566 digester.setValidating(false);
567 digester.addObjectCreate("gums", Configuration.class);
568 digester.addSetProperties("gums");
569 digester.parse(inputStream);
570 Configuration conf = (Configuration) digester.getRoot();
571 conf.setMetaOnly(true);
572 return conf;
573 }
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588 public static Configuration parseConfiguration(String configText,
589 boolean insertTest) throws ParserConfigurationException,
590 IOException, SAXException, ClassNotFoundException {
591
592
593 Configuration configuration = metaParse(new ByteArrayInputStream(
594 configText.getBytes()));
595 boolean isTemplate = configuration.isTemplate();
596 if (!configuration.versionWasSet)
597 configuration.setVersion("1.1");
598 if (configuration.getVersion().startsWith(GUMS.getMajorMinorVersion())) {
599
600 log.trace("Loading configuration");
601 validate(configText, isTemplate);
602 configuration = new Configuration();
603 Digester digester = retrieveDigester();
604 digester.push(configuration);
605 digester.parse(new ByteArrayInputStream(configText.getBytes()));
606 } else {
607
608 if (configuration.getVersion().equals("1.1")) {
609 configuration = do1_1_to_1_4Transform(configuration.isMetaOnly() ? configText : configuration.toXml(), transformDir + "gums.config.transform1_1-1_4");
610 configuration.setSource("OSG");
611 } else if (configuration.getVersion().equals("1.3")) {
612 log.trace("Loading configuration");
613 configuration = do1_3_to_1_4Transform(configuration.isMetaOnly() ? configText : configuration.toXml());
614 } else {
615 String message = "Cannot parse configurations with version '" + configuration.getVersion() + "'";
616 adminLog.error(message);
617 throw new RuntimeException(message);
618 }
619
620 configuration.setVersion(GUMS.getMajorMinorVersion());
621 }
622
623 return configuration;
624 }
625
626 static public Configuration parseConfigurationTemplates(String uris,
627 String tempFile) throws Exception {
628 Configuration conf = null;
629 StringTokenizer st = new StringTokenizer(uris, ",");
630 while (st.hasMoreTokens()) {
631 String uri = st.nextToken().trim();
632 String configText = URIToolkit.parseUri(uri, tempFile);
633 if (conf == null) {
634 conf = parseConfiguration(configText, false);
635 if (!conf.isTemplate())
636 throw new RuntimeException(uri
637 + " is not a configuration template");
638 } else {
639 Configuration tempConf = parseConfiguration(configText, false);
640 if (!tempConf.isTemplate())
641 throw new RuntimeException(uri
642 + " is not a configuration template");
643 conf.mergeConfigurationTemplate(tempConf, null, false);
644 }
645 }
646
647
648 if (tempFile != null) {
649 File tempDir = new File(new File(tempFile).getParent());
650 String[] tempFiles = tempDir.list();
651 for (String tfName : tempFiles) {
652 File tf = new File(tfName);
653 Calendar cal = Calendar.getInstance();
654 cal.add(Calendar.HOUR, -1);
655 if (new Date(tf.lastModified()).before(cal.getTime()))
656 tf.delete();
657 }
658 }
659
660 return conf;
661 }
662
663
664
665
666 public static Digester retrieveDigester() throws ClassNotFoundException,
667 IOException {
668 Digester digester = new Digester();
669 digester.setValidating(false);
670
671 digester.addSetProperties("gums");
672
673 addRules(digester, userGroupSet, "gums/userGroups", "addUserGroup");
674 addRules(digester, accountMapperSet, "gums/accountMappers", "addAccountMapper");
675 addRules(digester, groupToAccountSet, "gums/groupToAccountMappings", "addGroupToAccountMapping");
676 addRules(digester, hostToGroupSet, "gums/hostToGroupMappings", "addHostToGroupMapping");
677
678 return digester;
679 }
680
681
682
683
684
685
686
687
688
689
690 public static void validate(String configText, boolean isTemplate)
691 throws ParserConfigurationException, SAXException, IOException {
692 System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
693 "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
694 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
695 log.trace("DocumentBuilderFactory: " + factory.getClass().getName());
696
697 factory.setNamespaceAware(true);
698 factory.setValidating(true);
699 factory.setAttribute(
700 "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
701 "http://www.w3.org/2001/XMLSchema");
702 if (isTemplate)
703 factory.setAttribute(
704 "http://java.sun.com/xml/jaxp/properties/schemaSource",
705 "file:" + templateSchemaPath);
706 else
707 factory.setAttribute(
708 "http://java.sun.com/xml/jaxp/properties/schemaSource",
709 "file:" + schemaPath);
710
711 DocumentBuilder builder = factory.newDocumentBuilder();
712 SimpleErrorHandler errorHandler = new ConfigurationToolkit().new SimpleErrorHandler();
713 builder.setErrorHandler(errorHandler);
714
715 builder.parse(new ByteArrayInputStream(configText.getBytes()));
716
717 if (errorHandler.error != null)
718 throw new ParserConfigurationException(errorHandler.error);
719 }
720
721 @SuppressWarnings("unchecked")
722 protected static void addRules(Digester digester, Set<Class<ConfigElement>> configElementMap, String xmlGroup, String addMethodName) throws ClassNotFoundException, IOException {
723 for (Class c: configElementMap) {
724 char[] xmlElementName = c.getSimpleName().replace("VOMS", "voms").replace("LDAP", "ldap").toCharArray();
725 xmlElementName[0] = Character.toLowerCase(xmlElementName[0]);
726 String xmlPattern = xmlGroup + "/" + new String(xmlElementName);
727 digester.addObjectCreate(xmlPattern, c);
728 digester.addRule(xmlPattern, new ConfElementRule());
729 digester.addSetNext(xmlPattern, addMethodName, c.getName());
730 }
731 }
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751 @SuppressWarnings("unchecked")
752 protected static Set<Class<ConfigElement>> findClasses(ClassLoader classLoader,
753 Set<String> interfaceFilter, Set<String> packageFilter,
754 Set<String> jarFilter) throws ClassNotFoundException {
755 Map<String, Set<Class<ConfigElement>>> classTable = new HashMap();
756 Object[] classPaths;
757 try {
758
759 classPaths = ((java.net.URLClassLoader) classLoader).getURLs();
760 if (classPaths.length<=1)
761
762 classPaths = System.getProperty("java.class.path", "").split(File.pathSeparator);
763 } catch (ClassCastException cce) {
764
765 classPaths = System.getProperty("java.class.path", "").split(File.pathSeparator);
766 }
767
768 for (int h = 0; h < classPaths.length; h++) {
769 Enumeration files = null;
770 JarFile module = null;
771
772 File classPath = new File((URL.class).isInstance(classPaths[h]) ? ((URL) classPaths[h]).getFile() : classPaths[h].toString());
773 if (classPath.isDirectory() && jarFilter == null) {
774 List<String> dirListing = new ArrayList();
775
776 recursivelyListDir(dirListing, classPath, new StringBuffer());
777
778 files = Collections.enumeration(dirListing);
779 } else if (classPath.getName().endsWith(".jar")) {
780
781 if (jarFilter != null && !jarFilter.contains(classPath.getName())) {
782 continue;
783 }
784 try {
785
786
787 module = new JarFile(classPath);
788 } catch (MalformedURLException mue) {
789 throw new ClassNotFoundException("Bad classpath. Error: "
790 + mue.getMessage());
791 } catch (IOException io) {
792 throw new ClassNotFoundException(
793 "jar file '"
794 + classPath.getName()
795 + "' could not be instantiate from file path. Error: "
796 + io.getMessage());
797 }
798
799 files = module.entries();
800 }
801
802
803 while (files != null && files.hasMoreElements()) {
804
805 String fileName = files.nextElement().toString();
806
807 if (fileName.endsWith(".class")) {
808
809 String className = fileName.replaceAll("/", ".").substring(0, fileName.length() - 6);
810
811
812
813
814 if (packageFilter != null && !packageFilter.contains(className.substring(0, className.lastIndexOf(".")))) {
815 continue;
816 }
817
818 Class theClass = null;
819 try {
820 theClass = Class.forName(className, false, classLoader);
821 } catch (NoClassDefFoundError e) {
822 log.trace("Skipping class '" + className + "' for reason " + e.getMessage());
823 continue;
824 }
825
826 if (theClass.isInterface()) {
827 continue;
828 }
829
830 Class[] classInterfaces = theClass.getInterfaces();
831
832
833
834 String interfaceName = null;
835 for (int i = 0; i < classInterfaces.length
836 || (i == 0 && interfaceFilter == null); i++) {
837 if (i < classInterfaces.length) {
838 interfaceName = classInterfaces[i].getName();
839
840 if (interfaceFilter != null
841 && !interfaceFilter.contains(interfaceName)) {
842 continue;
843 }
844 }
845
846 if (classTable.containsKey(interfaceName)) {
847
848
849 classTable.get(interfaceName).add(theClass);
850 } else {
851
852
853 Set<Class<ConfigElement>> allClasses = new HashSet();
854 allClasses.add(theClass);
855 classTable.put(interfaceName, allClasses);
856 }
857 }
858
859 }
860 }
861
862
863 if (module != null) {
864 try {
865 module.close();
866 } catch (IOException ioe) {
867 throw new ClassNotFoundException("The module jar file '"
868 + classPath.getName()
869 + "' could not be closed. Error: "
870 + ioe.getMessage());
871 }
872 }
873
874 }
875
876 return classTable.values().iterator().next();
877 }
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892 protected static void recursivelyListDir(List<String> dirListing, File dir,
893 StringBuffer relativePath) {
894 int prevLen;
895
896
897 if (dir.isDirectory()) {
898
899 File[] files = dir.listFiles();
900
901 for (int i = 0; i < files.length; i++) {
902
903 prevLen = relativePath.length();
904
905
906 recursivelyListDir(dirListing, files[i], relativePath.append(
907 prevLen == 0 ? "" : "/").append(files[i].getName()));
908
909 relativePath.delete(prevLen, relativePath.length());
910 }
911 } else {
912
913
914 dirListing.add(relativePath.toString());
915 }
916 }
917
918 }