View Javadoc

1   /*
2    * ConfigurationToolkit.java
3    *
4    * Created on June 4, 2004, 10:51 AM
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.account.AccountMapper;
12  import gov.bnl.gums.account.AccountPoolMapper;
13  import gov.bnl.gums.account.GecosAccountMapper;
14  import gov.bnl.gums.account.GecosLdapAccountMapper;
15  import gov.bnl.gums.account.LdapAccountMapper;
16  import gov.bnl.gums.account.GecosNisAccountMapper;
17  import gov.bnl.gums.account.GroupAccountMapper;
18  import gov.bnl.gums.account.ManualAccountMapper;
19  import gov.bnl.gums.admin.CertCache;
20  import gov.bnl.gums.groupToAccount.GroupToAccountMapping;
21  import gov.bnl.gums.hostToGroup.CertificateHostToGroupMapping;
22  import gov.bnl.gums.hostToGroup.HostToGroupMapping;
23  import gov.bnl.gums.persistence.HibernatePersistenceFactory;
24  import gov.bnl.gums.persistence.LDAPPersistenceFactory;
25  import gov.bnl.gums.persistence.LocalPersistenceFactory;
26  import gov.bnl.gums.persistence.PersistenceFactory;
27  import gov.bnl.gums.userGroup.LDAPUserGroup;
28  import gov.bnl.gums.userGroup.ManualUserGroup;
29  import gov.bnl.gums.userGroup.UserGroup;
30  import gov.bnl.gums.userGroup.VOMSUserGroup;
31  import gov.bnl.gums.userGroup.VomsServer;
32  
33  import java.io.ByteArrayInputStream;
34  import java.io.File;
35  import java.io.FileInputStream;
36  import java.io.IOException;
37  import java.io.InputStream;
38  import java.io.StringBufferInputStream;
39  import java.net.URL;
40  import java.util.*;
41  
42  import javax.xml.parsers.DocumentBuilder;
43  import javax.xml.parsers.DocumentBuilderFactory;
44  import javax.xml.parsers.ParserConfigurationException;
45  import javax.xml.transform.Source;
46  import javax.xml.transform.Transformer;
47  import javax.xml.transform.TransformerFactory;
48  import javax.xml.transform.sax.SAXSource;
49  import javax.xml.transform.stream.StreamResult;
50  import javax.xml.transform.stream.StreamSource;
51  
52  import org.xml.sax.ErrorHandler;
53  import org.xml.sax.InputSource;
54  import org.xml.sax.SAXParseException;
55  import org.xml.sax.SAXException;
56  import org.xml.sax.XMLReader;
57  import org.xml.sax.helpers.XMLReaderFactory;
58  import org.apache.commons.beanutils.MethodUtils;
59  import org.apache.commons.digester.*;
60  import org.apache.log4j.Logger;
61  
62  /** 
63   * Contains the logic on how to parse an XML configuration file to create a
64   * correctly built Configuration object.
65   *
66   * @author Gabriele Carcassi, Jay Packard
67   */
68  public class ConfigurationToolkit {
69  	static private Logger log = Logger.getLogger(ConfigurationToolkit.class); 
70  	static private Logger adminLog = Logger.getLogger(GUMS.gumsAdminLogName);
71  	static String schemaPath;
72  	static String transformPath;
73  
74  	static
75  	{
76  		String configDir;
77  		try {
78  			configDir = CertCache.getResourceDir();
79  		}
80  		catch (Exception e) {
81  			URL resource = new ConfigurationToolkit().getClass().getClassLoader().getResource("gums.config");
82  			configDir = resource.getPath().replace("/gums.config", "");
83  		}
84  		schemaPath = configDir+"/gums.config.schema";
85  		transformPath = configDir+"/gums.config.transform";
86  	}
87  
88  	/**
89  	 * Simple error handler that logs errors
90  	 * 
91  	 * @author jpackard
92  	 */
93  	public class SimpleErrorHandler implements ErrorHandler {
94  		public String error = null;
95  
96  		public void error(SAXParseException exception) {
97  			log.error(exception.getMessage());
98  			adminLog.error(exception.getMessage());
99  			error = exception.getMessage();
100 		}
101 
102 		public void fatalError(SAXParseException exception) {
103 			log.fatal(exception.getMessage());
104 			adminLog.fatal(exception.getMessage());
105 			error = exception.getMessage();
106 		}
107 
108 		public void warning(SAXParseException exception) {
109 			log.warn(exception.getMessage());
110 			adminLog.warn(exception.getMessage());
111 		}
112 	}
113 
114 	// Rule for handling the list of accountMappers within a groupToAccountMapping
115 	private static class AccountMapperListRule extends Rule {
116 
117 		public void begin(String str, String str1, org.xml.sax.Attributes attributes) throws java.lang.Exception {
118 			if (attributes.getValue("accountMappers") != null) {
119 				Configuration conf = (Configuration) getDigester().getRoot();
120 				GroupToAccountMapping gTAMapping = (GroupToAccountMapping)getDigester().peek();
121 				StringTokenizer tokens = new StringTokenizer(attributes.getValue("accountMappers"), ",");
122 				while (tokens.hasMoreTokens()) {
123 					String accountMapperName = tokens.nextToken().trim();
124 					Object accountMapper = conf.getAccountMappers().get(accountMapperName);
125 					if (accountMapper == null) {
126 						throw new IllegalArgumentException("The accountMapper '" + accountMapperName + "' is used within a groupToAccountMapping, but it was not defined.");
127 					}
128 					MethodUtils.invokeMethod(gTAMapping, "addAccountMapper", accountMapperName);
129 				}
130 			}
131 		}
132 
133 	}
134 
135 	// Rule for handling the list of groupToAccountMappings within a hostToGroupMapping
136 	private static class GroupListRule extends Rule {
137 
138 		public void begin(String str, String str1, org.xml.sax.Attributes attributes) throws java.lang.Exception {
139 			if (attributes.getValue("groupToAccountMappings") != null) {
140 				Configuration conf = (Configuration) getDigester().getRoot();
141 				Object obj = getDigester().peek();
142 				StringTokenizer tokens = new StringTokenizer(attributes.getValue("groupToAccountMappings"), ",");
143 				while (tokens.hasMoreTokens()) {
144 					String groupToAccountMappingName = tokens.nextToken().trim();
145 					Object groupToAccountMapping = conf.getGroupToAccountMappings().get(groupToAccountMappingName);
146 					if (groupToAccountMapping == null) {
147 						throw new IllegalArgumentException("The groupToAccountMapping '" + groupToAccountMappingName + "' is used within a hostToGroupMapping, but it was not defined.");
148 					}
149 					MethodUtils.invokeMethod(obj, "addGroupToAccountMapping", groupToAccountMappingName);
150 				}
151 			}
152 		}
153 
154 	}    
155 
156 	// Simple override rule that ignores missing properties
157 	// and excludes given properties
158 	private static class PassRule extends SetPropertiesRule {
159 
160 		public PassRule(String [] excludes) {
161 			super(excludes, new String[]{});
162 			setIgnoreMissingProperty(false);
163 		}
164 
165 	}
166 
167 	// Rule for handling a reference to a persistent Factory
168 	private static class PersistenceFactoryRule extends Rule {
169 
170 		public void begin(String str, String str1, org.xml.sax.Attributes attributes) throws java.lang.Exception {
171 			if (attributes.getValue("persistenceFactory") != null) {
172 				Configuration conf = (Configuration) getDigester().getRoot();
173 				Object mapper = getDigester().peek();
174 				String persistenceFactoryName = attributes.getValue("persistenceFactory").trim();
175 				Object persistenceFactory = conf.getPersistenceFactories().get(persistenceFactoryName);
176 				if (persistenceFactory == null) {
177 					throw new IllegalArgumentException("The persistence factory '" + persistenceFactoryName + "' is used, but it was not defined.");
178 				}
179 				MethodUtils.invokeMethod(mapper, "setPersistenceFactory", new Object[] {persistenceFactoryName});
180 			}
181 		}
182 
183 	}
184 
185 	// Rule for distinguishing between 3rd party properties and GUMS properties
186 	private static class PersistencePropertiesRule extends Rule {
187 
188 		public void begin(String str, String str1, org.xml.sax.Attributes attributes) throws java.lang.Exception {
189 			Object digestor = getDigester().peek();
190 			Properties properties = new Properties();
191 			for (int nAtt = 0; nAtt < attributes.getLength(); nAtt++) {
192 				String name = attributes.getQName(nAtt);
193 				String value = attributes.getValue(nAtt);
194 				log.trace("Adding " + name + " " + value + " property");
195 				/*if (name.equals("name"))
196                     MethodUtils.invokeMethod(digestor, "setName", new Object[] {value});
197                 else if (name.equals("description"))
198                     MethodUtils.invokeMethod(digestor, "setDescription", new Object[] {value});
199                 else if (name.equals("synchGroups"))
200                     MethodUtils.invokeMethod(digestor, "setSynchGroups", new Object[] {new Boolean(value.equals("true"))});
201                 else if (name.equals("caCertFile"))
202                     MethodUtils.invokeMethod(digestor, "setCaCertFile", new Object[] {value});
203                 else if (name.equals("groupIdField"))
204                     MethodUtils.invokeMethod(digestor, "setGroupIdField", new Object[] {value});
205                 else if (name.equals("accountField"))
206                     MethodUtils.invokeMethod(digestor, "setAccountField", new Object[] {value});
207                 else if (name.equals("memberAccountField"))
208                     MethodUtils.invokeMethod(digestor, "setMemberAccountField", new Object[] {value});
209                 else if (name.equals("trustStorePassword"))
210                     MethodUtils.invokeMethod(digestor, "setTrustStorePassword", new Object[] {value});
211                 else if (!name.equals("className"))*/
212 				if (name.indexOf(".")!=-1)
213 					properties.setProperty(name, value);
214 			}
215 			MethodUtils.invokeMethod(digestor, "setProperties", properties);
216 		}
217 
218 	};
219 
220 	// Rule for handling the list of userGroups within a groupToAccountMapping
221 	private static class UserGroupListRule extends Rule {
222 
223 		public void begin(String str, String str1, org.xml.sax.Attributes attributes) throws java.lang.Exception {
224 			if (attributes.getValue("userGroups") != null) {
225 				Configuration conf = (Configuration) getDigester().getRoot();
226 				Object mapping = getDigester().peek();
227 				StringTokenizer tokens = new StringTokenizer(attributes.getValue("userGroups"), ",");
228 				while (tokens.hasMoreTokens()) {
229 					String userGroupName = tokens.nextToken().trim();
230 					Object userGroup = conf.getUserGroups().get(userGroupName);
231 					if (userGroup == null) {
232 						throw new IllegalArgumentException("The userGroup '" + userGroupName + "' is used within a groupToAccountMapping, but it was not defined.");
233 					}
234 					MethodUtils.invokeMethod(mapping, "addUserGroup", userGroupName);
235 				}
236 			}
237 		}
238 
239 	}
240 
241 	//  Rule for handling a reference to a VO
242 	private static class VomsServerRule extends Rule {
243 
244 		public void begin(String str, String str1, org.xml.sax.Attributes attributes) throws java.lang.Exception {
245 			if (attributes.getValue("vomsServer")!=null && !attributes.getValue("vomsServer").trim().equals("")) {
246 				Configuration conf = (Configuration) getDigester().getRoot();
247 				Object obj = getDigester().peek();
248 				String vomsServerName = attributes.getValue("vomsServer").trim();
249 				Object vomsServer = conf.getVomsServers().get(vomsServerName);
250 				if (vomsServer==null) {
251 					throw new IllegalArgumentException("The VOMS server '" + vomsServerName + "' is used, but it was not defined.");
252 				}
253 				MethodUtils.invokeMethod(obj, "setVomsServer", new Object[] {vomsServerName});
254 			}
255 		}
256 
257 	}          
258 
259 	/**
260 	 * Get the gums.config version for the given file
261 	 * 
262 	 * @param filename
263 	 * @return
264 	 * @throws IOException
265 	 * @throws SAXException
266 	 */
267 	public static String getVersion(String configText) throws IOException, SAXException {
268 		Digester digester = new Digester();
269 		digester.setValidating(false);
270 		digester.addObjectCreate("gums", Version.class);
271 		digester.addSetProperties("gums");
272 		log.trace("Loading the version from configuration");
273 		digester.parse(new ByteArrayInputStream(configText.getBytes()));
274 		String version = ((Version)digester.getRoot()).getVersion();
275 		log.trace("Loaded gums.config is version " + version );
276 		if (version == null)
277 			return "1.1";
278 		return version;
279 	}
280 
281 	/**
282 	 * @return a Digestor object for parsing gums.config
283 	 */
284 	public static Digester retrieveDigester() {
285 		Digester digester = new Digester();
286 		digester.setValidating(false);
287 
288 		digester.addSetProperties("gums");
289 
290 		digester.addObjectCreate("gums/persistenceFactories/hibernatePersistenceFactory", HibernatePersistenceFactory.class);
291 		digester.addSetProperties("gums/persistenceFactories/hibernatePersistenceFactory");
292 		digester.addRule("gums/persistenceFactories/hibernatePersistenceFactory", new PersistencePropertiesRule());
293 		digester.addSetNext("gums/persistenceFactories/hibernatePersistenceFactory", "addPersistenceFactory", "gov.bnl.gums.persistence.PersistenceFactory");
294 
295 		digester.addObjectCreate("gums/persistenceFactories/ldapPersistenceFactory", LDAPPersistenceFactory.class);
296 		digester.addSetProperties("gums/persistenceFactories/ldapPersistenceFactory");
297 		digester.addRule("gums/persistenceFactories/ldapPersistenceFactory", new PersistencePropertiesRule());
298 		digester.addSetNext("gums/persistenceFactories/ldapPersistenceFactory", "addPersistenceFactory", "gov.bnl.gums.persistence.PersistenceFactory");
299 
300 		digester.addObjectCreate("gums/persistenceFactories/localPersistenceFactory", LocalPersistenceFactory.class);
301 		digester.addSetProperties("gums/persistenceFactories/localPersistenceFactory");
302 		digester.addRule("gums/persistenceFactories/localPersistenceFactory", new PersistencePropertiesRule());
303 		digester.addSetNext("gums/persistenceFactories/localPersistenceFactory", "addPersistenceFactory", "gov.bnl.gums.persistence.PersistenceFactory");
304 
305 		digester.addObjectCreate("gums/vomsServers/vomsServer", VomsServer.class);
306 		digester.addSetProperties("gums/vomsServers/vomsServer");
307 		digester.addRule("gums/vomsServers/vomsServer", new PassRule(new String[] {"persistenceFactory"}));
308 		digester.addRule("gums/vomsServers/vomsServer", new PersistenceFactoryRule());
309 		digester.addSetNext("gums/vomsServers/vomsServer", "addVomsServer", "gov.bnl.gums.userGroup.VomsServer");
310 
311 		digester.addObjectCreate("gums/userGroups/ldapUserGroup", LDAPUserGroup.class);
312 		digester.addRule("gums/userGroups/ldapUserGroup", new PassRule(new String[] {"className", "persistenceFactory", "vomsServer"}));
313 		digester.addRule("gums/userGroups/ldapUserGroup", new PersistenceFactoryRule());
314 		digester.addRule("gums/userGroups/ldapUserGroup", new VomsServerRule());
315 		digester.addSetNext("gums/userGroups/ldapUserGroup", "addUserGroup", "gov.bnl.gums.userGroup.UserGroup");
316 
317 		digester.addObjectCreate("gums/userGroups/manualUserGroup", ManualUserGroup.class);
318 		digester.addRule("gums/userGroups/manualUserGroup", new PassRule(new String[] {"className", "persistenceFactory", "vomsServer"}));
319 		digester.addRule("gums/userGroups/manualUserGroup", new PersistenceFactoryRule());
320 		digester.addRule("gums/userGroups/manualUserGroup", new VomsServerRule());
321 		digester.addSetNext("gums/userGroups/manualUserGroup", "addUserGroup", "gov.bnl.gums.userGroup.UserGroup");
322 
323 		digester.addObjectCreate("gums/userGroups/vomsUserGroup", VOMSUserGroup.class);
324 		digester.addRule("gums/userGroups/vomsUserGroup", new PassRule(new String[] {"className", "persistenceFactory", "vomsServer"}));
325 		digester.addRule("gums/userGroups/vomsUserGroup", new PersistenceFactoryRule());
326 		digester.addRule("gums/userGroups/vomsUserGroup", new VomsServerRule());
327 		digester.addSetNext("gums/userGroups/vomsUserGroup", "addUserGroup", "gov.bnl.gums.userGroup.UserGroup");
328 
329 		digester.addObjectCreate("gums/accountMappers/accountPoolMapper", AccountPoolMapper.class);
330 		digester.addSetProperties("gums/accountMappers/accountPoolMapper");
331 		digester.addRule("gums/accountMappers/accountPoolMapper", new PersistenceFactoryRule());
332 		digester.addSetNext("gums/accountMappers/accountPoolMapper", "addAccountMapper", "gov.bnl.gums.account.AccountMapper");
333 
334 		digester.addObjectCreate("gums/accountMappers/gecosAccountMapper", GecosAccountMapper.class);
335 		digester.addSetProperties("gums/accountMappers/gecosAccountMapper");
336 		digester.addRule("gums/accountMappers/gecosAccountMapper", new PersistenceFactoryRule());
337 		digester.addSetNext("gums/accountMappers/gecosAccountMapper", "addAccountMapper", "gov.bnl.gums.account.AccountMapper");
338 
339 		digester.addObjectCreate("gums/accountMappers/gecosLdapAccountMapper", GecosLdapAccountMapper.class);
340 		digester.addSetProperties("gums/accountMappers/gecosLdapAccountMapper");
341 		digester.addSetNext("gums/accountMappers/gecosLdapAccountMapper", "addAccountMapper", "gov.bnl.gums.account.AccountMapper");
342 
343 		digester.addObjectCreate("gums/accountMappers/ldapAccountMapper", LdapAccountMapper.class);
344 		digester.addSetProperties("gums/accountMappers/ldapAccountMapper");
345 		digester.addSetNext("gums/accountMappers/ldapAccountMapper", "addAccountMapper", "gov.bnl.gums.account.AccountMapper");
346 
347 		digester.addObjectCreate("gums/accountMappers/gecosNisAccountMapper", GecosNisAccountMapper.class);
348 		digester.addSetProperties("gums/accountMappers/gecosNisAccountMapper");
349 		digester.addSetNext("gums/accountMappers/gecosNisAccountMapper", "addAccountMapper", "gov.bnl.gums.account.AccountMapper");
350 
351 		digester.addObjectCreate("gums/accountMappers/groupAccountMapper", GroupAccountMapper.class);
352 		digester.addSetProperties("gums/accountMappers/groupAccountMapper");
353 		digester.addSetNext("gums/accountMappers/groupAccountMapper", "addAccountMapper", "gov.bnl.gums.account.AccountMapper");
354 
355 		digester.addObjectCreate("gums/accountMappers/manualAccountMapper", ManualAccountMapper.class);
356 		digester.addSetProperties("gums/accountMappers/manualAccountMapper");
357 		digester.addRule("gums/accountMappers/manualAccountMapper", new PersistenceFactoryRule());
358 		digester.addSetNext("gums/accountMappers/manualAccountMapper", "addAccountMapper", "gov.bnl.gums.account.AccountMapper");
359 
360 		digester.addObjectCreate("gums/groupToAccountMappings/groupToAccountMapping", GroupToAccountMapping.class);
361 		digester.addSetProperties("gums/groupToAccountMappings/groupToAccountMapping");
362 		digester.addRule("gums/groupToAccountMappings/groupToAccountMapping", new PassRule(new String[] {"userGroups", "accountMappers"}));
363 		digester.addRule("gums/groupToAccountMappings/groupToAccountMapping", new UserGroupListRule());
364 		digester.addRule("gums/groupToAccountMappings/groupToAccountMapping", new AccountMapperListRule());
365 		digester.addSetNext("gums/groupToAccountMappings/groupToAccountMapping", "addGroupToAccountMapping", "gov.bnl.gums.groupToAccount.GroupToAccountMapping");
366 
367 		digester.addObjectCreate("gums/hostToGroupMappings/hostToGroupMapping", CertificateHostToGroupMapping.class);
368 		digester.addSetProperties("gums/hostToGroupMappings/hostToGroupMapping");
369 		digester.addRule("gums/hostToGroupMappings/hostToGroupMapping", new PassRule(new String[] {"groupToAccountMappings"}));
370 		digester.addRule("gums/hostToGroupMappings/hostToGroupMapping", new GroupListRule());
371 		digester.addSetNext("gums/hostToGroupMappings/hostToGroupMapping", "addHostToGroupMapping", "gov.bnl.gums.hostToGroup.HostToGroupMapping");
372 
373 		return digester;
374 	}
375 
376 	/**
377 	 * Validate gums.config given a config file and a schema file
378 	 * 
379 	 * @param configFile
380 	 * @param schemaFile
381 	 * @throws ParserConfigurationException
382 	 * @throws SAXException
383 	 * @throws IOException
384 	 */
385 	public static void validate(String configText) throws ParserConfigurationException, SAXException, IOException {
386 		System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
387 		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
388 		log.trace("DocumentBuilderFactory: "+ factory.getClass().getName());
389 
390 		factory.setNamespaceAware(true);
391 		factory.setValidating(true);
392 		factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
393 		factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", "file:"+schemaPath);
394 
395 		DocumentBuilder builder = factory.newDocumentBuilder();
396 		SimpleErrorHandler errorHandler = new ConfigurationToolkit().new SimpleErrorHandler();
397 		builder.setErrorHandler( errorHandler );
398 
399 		builder.parse(new ByteArrayInputStream(configText.getBytes()));
400 
401 		if (errorHandler.error != null)
402 			throw new ParserConfigurationException(errorHandler.error);
403 	}
404 
405 	/** new StringBufferInputStream(configText)
406 	 * Load gums.config
407 	 * 
408 	 * @param configFile
409 	 * @param configText
410 	 * @param schemaPath
411 	 * @return
412 	 * @throws ParserConfigurationException
413 	 * @throws IOException
414 	 * @throws SAXException
415 	 * 
416 	 * Either set configPath or configText
417 	 */
418 	public static synchronized Configuration parseConfiguration(String configText, boolean insertTest) throws ParserConfigurationException, IOException, SAXException {
419 		Configuration configuration;
420 		if (ConfigurationToolkit.getVersion(configText).equals("1.1")) {
421 			log.trace("Loading the configuration required configuration using schema '" + transformPath);
422 			configuration = doTransform(configText);
423 			if (insertTest)
424 				insertGipProbe(configuration);
425 		}
426 		else {
427 			log.trace("Loading the configuration using schema '" + schemaPath);
428 			configuration = new Configuration();
429 			validate(configText);
430 			Digester digester = retrieveDigester();
431 			digester.push(configuration);
432 			digester.parse(new ByteArrayInputStream(configText.getBytes()));
433 		}
434 
435 		// Make sure storeConfig is set in only one persistence factory
436 		Iterator it = configuration.getPersistenceFactories().values().iterator();
437 		int storeConfigCount = 0;
438 		while (it.hasNext()) {
439 			PersistenceFactory persFact = (PersistenceFactory)it.next();
440 			if (persFact.getStoreConfig())
441 				storeConfigCount++;
442 		}
443 		if (storeConfigCount>1)
444 			throw new RuntimeException("Only one persistence factory may be set to store the configuration");
445 
446 		if (insertTest) {
447 			// Add test user and test configuration
448 			Map userGroups = configuration.getUserGroups();
449 			it = userGroups.values().iterator();
450 			while (it.hasNext()) {
451 				UserGroup userGroup = (UserGroup)it.next();
452 				if (userGroup instanceof ManualUserGroup) {
453 					// Add test user to manual user group
454 					ManualUserGroup manualUserGroup = (ManualUserGroup)userGroup;
455 					String persFactory = manualUserGroup.getPersistenceFactory();
456 					GridUser testUser = new GridUser("/DC=com/DC=example/OU=People/CN=Example User 12345");
457 					if (!manualUserGroup.isInGroup(testUser))
458 						manualUserGroup.addMember(testUser);
459 
460 					// Add test account mapper
461 					ManualAccountMapper manualAccountMapper;
462 					AccountMapper accountMapper = configuration.getAccountMapper("_test");
463 					if (accountMapper != null && accountMapper instanceof ManualAccountMapper)
464 						manualAccountMapper = (ManualAccountMapper)accountMapper;
465 					else {
466 						String name = "_test";
467 						while (configuration.getAccountMapper(name)!=null)
468 							name = name + "_";
469 						manualAccountMapper = new ManualAccountMapper(configuration);
470 						manualAccountMapper.setName(name);
471 						manualAccountMapper.setPersistenceFactory(persFactory);
472 						configuration.addAccountMapper(manualAccountMapper);
473 					}
474 					if (!manualAccountMapper.getAccountMap().containsKey(testUser.getCertificateDN()))
475 						manualAccountMapper.addMapping(testUser.getCertificateDN(), "test");
476 
477 					// Add test groupToAccountMapping
478 					GroupToAccountMapping g2AMapping = configuration.getGroupToAccountMapping("_test");
479 					if (g2AMapping == null) {
480 						g2AMapping = new GroupToAccountMapping(configuration);
481 						g2AMapping.setName("_test");
482 						configuration.addGroupToAccountMapping(g2AMapping);
483 					}
484 					if (!g2AMapping.containsUserGroup(manualUserGroup.getName()))
485 						g2AMapping.addUserGroup(manualUserGroup.getName());
486 					if (!g2AMapping.containsAccountMapper(manualAccountMapper.getName()))
487 						g2AMapping.addAccountMapper(manualAccountMapper.getName());
488 
489 					// Add test hostToGroupMapping
490 					HostToGroupMapping h2GMapping = configuration.getHostToGroupMapping("/DC=com/DC=example/OU=Services/CN=example.site.com");
491 					if (h2GMapping == null) {
492 						h2GMapping = new CertificateHostToGroupMapping(configuration);
493 						((CertificateHostToGroupMapping)h2GMapping).setDn("/DC=com/DC=example/OU=Services/CN=example.site.com");
494 						configuration.addHostToGroupMapping(0, h2GMapping);
495 					}
496 					if (!h2GMapping.containsGroupToAccountMapping(g2AMapping.getName()))
497 						h2GMapping.addGroupToAccountMapping(g2AMapping.getName());
498 
499 					break;
500 				}
501 			}
502 		}
503 
504 		return configuration;
505 	}
506 
507 	static public Configuration doTransform(String configText) {
508 		log.trace("Transforming configuration file using transform '" + transformPath);
509 
510 		try {
511 			File configFileTemp = File.createTempFile("gums", "config");
512 
513 			XMLReader reader = XMLReaderFactory.createXMLReader();
514 			Source source = new SAXSource(reader, new InputSource(new ByteArrayInputStream(configText.getBytes())));
515 
516 			StreamResult result = new StreamResult(configFileTemp);
517 			Source style = new StreamSource(transformPath);
518 
519 			TransformerFactory transFactory = TransformerFactory.newInstance();
520 			Transformer trans = transFactory.newTransformer(style);
521 
522 			trans.transform(source, result);
523 
524 			// Reload it to get rid of duplicates that the transform couldn't handle
525 			// as well as to clean up the formatting
526 			Digester digester = ConfigurationToolkit.retrieveDigester();
527 			Configuration configuration = new Configuration(true);
528 			digester.push(configuration);
529 			digester.parse("file://"+configFileTemp.getAbsolutePath());
530 
531 			configFileTemp.delete();
532 
533 			// Clean up VOMS server names
534 			Iterator it = new ArrayList(configuration.getVomsServers().keySet()).iterator();
535 			while (it.hasNext()) {
536 				String name = (String)it.next();
537 				String origName = new String(name);
538 				if (name.startsWith("http")) {
539 					name = name.replaceAll("^http.*://","");
540 					name = name.replaceAll(".*/voms/","");
541 					name = name.replaceAll(".*/edg-voms-admin/","");
542 					name = name.replaceAll("[:|/].*","");
543 					name = name.toLowerCase();
544 					if (configuration.getVomsServer(name)!=null) {
545 						int count = 1;
546 						while (configuration.getVomsServer(name + Integer.toString(count)) != null) 
547 							count++;
548 						name += Integer.toString(count);
549 					}
550 					VomsServer vo = configuration.getVomsServer(origName);
551 					if (vo!=null) {
552 						vo.setName(name);
553 						configuration.removeVomsServer(origName);
554 						configuration.addVomsServer(vo);
555 						Iterator it2 = configuration.getUserGroups().values().iterator();
556 						while (it2.hasNext()) {
557 							UserGroup userGroup = (UserGroup)it2.next();
558 							if (userGroup instanceof VOMSUserGroup && ((VOMSUserGroup)userGroup).getVomsServer().equals(origName))
559 								((VOMSUserGroup)userGroup).setVomsServer(name);
560 						}
561 					}
562 				}
563 			}
564 
565 			// Clean up account mapper names
566 			it = new ArrayList(configuration.getAccountMappers().keySet()).iterator();
567 			while (it.hasNext()) {
568 				String name = (String)it.next();
569 				String origName = new String(name);
570 				if (name.indexOf("://")!=-1) {
571 					name = name.replaceAll(".*://","");
572 					name = name.replaceAll(".*/dc=","");
573 					name = name.replaceAll("dc=","");
574 					name = name.toLowerCase();
575 					if (configuration.getAccountMapper(name)!=null) {
576 						int count = 1;
577 						while (configuration.getAccountMapper(name + Integer.toString(count)) != null) 
578 							count++;
579 						name += Integer.toString(count);
580 					}
581 					AccountMapper accountMapper = configuration.getAccountMapper(origName);
582 					if (accountMapper!=null) {
583 						accountMapper.setName(name);
584 						configuration.removeAccountMapper(origName);
585 						configuration.addAccountMapper(accountMapper);
586 						Iterator it2 = configuration.getGroupToAccountMappings().values().iterator();
587 						while (it2.hasNext()) {
588 							GroupToAccountMapping groupToAccountMapping = (GroupToAccountMapping)it2.next();
589 							Iterator it3 = groupToAccountMapping.getAccountMappers().iterator();
590 							int index = 0;
591 							while (it3.hasNext()) {
592 								String str = (String)it3.next();
593 								if (str.equals(origName)) {
594 									groupToAccountMapping.getAccountMappers().remove(index);
595 									groupToAccountMapping.getAccountMappers().add(index, name);
596 									it3 = groupToAccountMapping.getAccountMappers().iterator();
597 									index = 0;
598 								}
599 								else
600 									index++;
601 							}
602 						}
603 					}
604 				}
605 			}
606 
607 			return configuration;
608 		} catch (Exception e) {
609 			String message = "Could not convert older version of gums.config";
610 			log.error(message, e);
611 			adminLog.error(message);
612 			throw new RuntimeException(message);	    	 
613 		} 
614 	}
615 
616 	static public void insertGipProbe(Configuration configuration) {
617 		try {
618 			// Insert GIP probe
619 			PersistenceFactory persistenceFactory = configuration.getPersistenceFactory("mysql");
620 			if (persistenceFactory==null && configuration.getPersistenceFactories().size()>0)
621 				persistenceFactory = (PersistenceFactory)configuration.getPersistenceFactories().values().iterator().next();
622 			if (persistenceFactory != null) {
623 
624 				// Add UserGroup
625 				UserGroup userGroup = configuration.getUserGroup("gums-test");
626 				if (userGroup==null || !(userGroup instanceof ManualUserGroup)) {
627 					int index = 1;
628 					while (configuration.getUserGroup("gums-test"+(index==1?"":Integer.toString(index)))!=null)
629 						index++;
630 					userGroup = new ManualUserGroup(configuration, "gums-test"+(index==1?"":Integer.toString(index)));
631 					userGroup.setDescription("Testing GUMS-status with GIP Probe");
632 					((ManualUserGroup)userGroup).setPersistenceFactory(persistenceFactory.getName());
633 					configuration.addUserGroup(userGroup);
634 				}
635 
636 				// Add member to usergroup's database
637 				GridUser user = new GridUser();
638 				user.setCertificateDN("/GIP-GUMS-Probe-Identity");
639 				if(((ManualUserGroup)userGroup).getMemberList().indexOf(user)==-1) {
640 					((ManualUserGroup)userGroup).addMember(user);
641 				}
642 
643 				// Add AccountMapper
644 				AccountMapper accountMapper = configuration.getAccountMapper("gums-test");
645 				if (accountMapper==null || !(accountMapper instanceof GroupAccountMapper) || !((GroupAccountMapper)accountMapper).getAccountName().equals("GumsTestUserMappingSuccessful")) {
646 					int index = 1;
647 					while (configuration.getAccountMapper("gums-test"+(index==1?"":Integer.toString(index)))!=null)
648 						index++;
649 					accountMapper = new GroupAccountMapper(configuration, "gums-test"+(index==1?"":Integer.toString(index)));
650 					accountMapper.setDescription("Testing GUMS-status with GIP Probe");
651 					((GroupAccountMapper)accountMapper).setAccountName("GumsTestUserMappingSuccessful");
652 					configuration.addAccountMapper(accountMapper);
653 				}
654 
655 				// Add GroupToAccountMapping
656 				GroupToAccountMapping g2aMapping = configuration.getGroupToAccountMapping("gums-test");
657 				if (g2aMapping==null) {
658 					int index = 1;
659 					while (configuration.getGroupToAccountMapping("gums-test"+(index==1?"":Integer.toString(index)))!=null)
660 						index++;
661 					g2aMapping = new GroupToAccountMapping(configuration, "gums-test"+(index==1?"":Integer.toString(index)));
662 					g2aMapping.setDescription("Testing GUMS-status with GIP Probe");
663 					configuration.addGroupToAccountMapping(g2aMapping);
664 				}
665 				if (g2aMapping.getAccountMappers().indexOf(accountMapper.getName())==-1)
666 					g2aMapping.addAccountMapper(accountMapper.getName());
667 				if (g2aMapping.getUserGroups().indexOf(userGroup.getName())==-1)
668 					g2aMapping.addUserGroup(userGroup.getName());     
669 
670 				// add or alter HostToGroupMapping
671 				String domainName = java.net.InetAddress.getLocalHost().getCanonicalHostName();
672 				if (domainName!=null && domainName.indexOf(".")!=-1)
673 					domainName = domainName.substring(domainName.indexOf("."),domainName.length());
674 				String cn = "*/?*" + (domainName!=null?domainName:".localdomain");
675 				List h2gMappings = configuration.getHostToGroupMappings();
676 				boolean foundCn = false;
677 				for (int i=0; i<h2gMappings.size(); i++) {
678 					// add groupToAccountMapping to each hostToGroupMapping
679 					HostToGroupMapping h2gMapping = (HostToGroupMapping)h2gMappings.get(i);
680 					h2gMapping.addGroupToAccountMapping(g2aMapping.getName()); 
681 					if (h2gMapping.getName().indexOf(cn)!=-1)
682 						foundCn = true;
683 				}
684 				if (!foundCn) {
685 					// create a new hostToGroupMapping
686 					HostToGroupMapping h2gMapping = new CertificateHostToGroupMapping(configuration);
687 					h2gMapping.setDescription("Testing GUMS-status with GIP Probe");
688 					((CertificateHostToGroupMapping)h2gMapping).setCn(cn);
689 					configuration.addHostToGroupMapping(h2gMapping);
690 					h2gMapping.addGroupToAccountMapping(g2aMapping.getName()); 
691 				}
692 			}
693 		} catch (Exception e) {
694 			String message = "Could not insert GIP probe";
695 			log.warn(message, e);
696 			adminLog.warn(message);
697 		} 
698 	}
699 
700 }