View Javadoc

1   package org.naftulin.configmgr.parsers;
2   
3   import java.io.BufferedInputStream;
4   import java.io.BufferedReader;
5   import java.io.IOException;
6   import java.io.InputStream;
7   import java.io.InputStreamReader;
8   import java.io.Reader;
9   import java.io.StringReader;
10  import java.net.URL;
11  import java.util.HashMap;
12  import java.util.Map;
13  import java.util.regex.Matcher;
14  import java.util.regex.Pattern;
15  
16  import org.apache.commons.digester.Digester;
17  import org.apache.commons.digester.xmlrules.DigesterLoader;
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.log4j.Logger;
20  import org.naftulin.configmgr.ConfigurationManagementEntry;
21  import org.naftulin.configmgr.ConfigurationManagementEntryImpl;
22  import org.naftulin.configmgr.ConfigurationManagerException;
23  import org.naftulin.configmgr.ConfigurationType;
24  import org.naftulin.configmgr.content.MasterRecordImpl;
25  import org.xml.sax.SAXException;
26  
27  /***
28   * Parses master configuration file to create a configuration entry.
29   * 
30   * @author Henry Naftulin
31   * @version 1.0
32   */
33  public class MasterRecordParser extends AbstractConfigEntryParser {
34  	private static final long serialVersionUID = 1L;
35  	private static final String MASTER_RECORD_RULES_XML = "master-record-rules.xml";
36  	private static final Logger log = Logger.getLogger(MasterRecordParser.class);
37  	
38  	/***
39  	 * Retrurns a configuration managment entry by reading the master record file passed in, and storing it's content.
40  	 * @param key the key configuration entry will be assigned
41  	 * @param fileUrl the file URL to be parsed.
42  	 * @return a configuration managment with content of master configuration file.
43  	 * @throws ConfigurationManagerException if an error occurs while parsing an entry.
44  	 */
45  	public ConfigurationManagementEntry getConfigurationManagementEntry(final String key, 
46  			final URL fileUrl) throws ConfigurationManagerException {
47  		validateParameters(key, fileUrl);
48  		
49  		final String fileName = fileUrl.getFile();
50  		String content = null;
51  		ConfigurationManagementEntry entry = null;
52  		try {
53  			final InputStream stream = fileUrl.openStream();
54  			log.debug("reading master record configuration from file " + fileName);
55  			content = readStreamContentAsString(stream);
56  			log.debug("master record configuration is " + content);
57  			
58  		} catch (IOException e) {
59  			log.warn("Error while reading log4j file", e);
60  			throw new ConfigurationManagerException("Error while reading log4j file",e);
61  		}		
62  		entry = new ConfigurationManagementEntryImpl(key, fileName , content, this, ConfigurationType.MASTER_RECORD);
63  		log.info("configured entry " + entry);		
64  		return entry;
65  	}
66  
67  	private void validateParameters(final String key, final URL fileUrl)
68  			throws ConfigurationManagerException {
69  		if (fileUrl == null) {
70  			throw new ConfigurationManagerException("file URL is null");
71  		}
72  		if (fileUrl.getFile() == null) {
73  			throw new ConfigurationManagerException("file name passed in the URL " + fileUrl + " is null");
74  		}
75  		if (key == null) { 
76  			throw new ConfigurationManagerException("key is null");
77  		}
78  	}
79  	
80  	/***
81  	 * Returns a string representation of this parser.
82  	 * @return a string representation of this parser.
83  	 */
84  	public String toString() {
85  		return "master record parser";
86  	}
87  
88  	/***
89  	 * Returns master record based on the configuration file passed in. Parses the passed in file based
90  	 * on the digester rules defined in MASTER_RECORD_RULES_XML and
91  	 * uses commons digester to create master record object based on it.
92  	 * @param fileName xml file that describe the configuration.
93  	 * @return master record.
94  	 * @exception ConfigurationManagerException if a master record cannot be parsed.
95  	 */
96  	public MasterRecordImpl digestMasterRecord(final String fileName) throws ConfigurationManagerException{
97  		MasterRecordImpl masterRecord = null;
98  		final Digester masterRecordDigester = getDigester();
99  		if (masterRecordDigester == null) {
100 			throw new ConfigurationManagerException("Major error: could not create a digester from  " + MASTER_RECORD_RULES_XML + " file with rules to parse master record. Make sure all jars that configuration manager depends on are present.");
101 		}
102 		log.debug("loaded rules to read master record");
103 		//masterRecordDigester.push(masterRecord);
104 		try {
105 			log.debug("loading master record file " + fileName);
106 			final URL masterRecordXml = MasterRecordParser.class.getClassLoader().getResource(fileName);
107 			if (masterRecordXml == null) {
108 				throw new ConfigurationManagerException("Could not read master record from file " + fileName + ". Please check whether this file exists and you have read permissions to read it."); 
109 			}
110 			
111 			final Reader preprocessedStream = preprocessConfigurationFile(masterRecordXml);
112 			
113 			masterRecord = (MasterRecordImpl) masterRecordDigester.parse(preprocessedStream);
114 			if (masterRecord == null) {
115 				throw new ConfigurationManagerException("Could not parse master record from file " + fileName + " based on rules file " + MASTER_RECORD_RULES_XML + ". Master record is null. Please check these files to make sure they are valid");
116 			}
117 			masterRecord.setFileName(fileName);
118 		} catch (IOException e) {
119 			throw new ConfigurationManagerException("Could not read master record from file " + fileName + " and rules file " + MASTER_RECORD_RULES_XML + ". Please check whether these files exist and you have read permissions to read them.", e);
120 		} catch (SAXException e) {
121 			throw new ConfigurationManagerException("Could not parse master record from file " + fileName + " and rules file " + MASTER_RECORD_RULES_XML + ". Please check whether these files are valid xml files.", e);
122 		}
123 		log.info("master record parsed " + masterRecord);
124 		return masterRecord;
125 	}
126 
127 	private Reader preprocessConfigurationFile(final URL masterRecordXml) throws IOException {
128 		final BufferedReader readStream = new BufferedReader(new InputStreamReader(masterRecordXml.openStream()));
129 		final StringBuffer sb = new StringBuffer();
130 		String line;
131 		while((line=readStream.readLine()) != null) {
132 			sb.append(line);
133 		}
134 		
135 		final String fileContent = sb.toString();
136 		final String modifiedFileContent = doSubstitutions(fileContent);
137 		
138 		final Reader preprocessedFile = new StringReader(modifiedFileContent);
139 		return preprocessedFile;
140 	}
141 
142 	String doSubstitutions(final String fileContent) {
143 		String modifiedFileContent = fileContent;
144 		
145 		final Pattern environmentVarPattern = Pattern.compile("//?//S+//?");
146 		final Matcher environmentVarMatcher = environmentVarPattern.matcher(fileContent);
147 		//Map<String, String> environmentVarValue= new HashMap<String, String>();
148 		String environmentVar = null;
149 		String value = null;
150 		while(environmentVarMatcher.find()) {
151 			String environmentVarWithMarkers = environmentVarMatcher.group();
152 			if (environmentVarWithMarkers.length()>2) {
153 				environmentVar = environmentVarWithMarkers.substring(1, environmentVarWithMarkers.length()-1);
154 				value = getEnvironmentVarValue(environmentVar);
155 				modifiedFileContent = StringUtils.replace(modifiedFileContent, environmentVarWithMarkers, value);				
156 			}
157 		}
158 		return modifiedFileContent;
159 	}
160 
161 	String getEnvironmentVarValue(final String environmentVar) {
162 		String value = System.getProperty(environmentVar);
163 		
164 		if (value == null) {
165 			value = System.getenv(environmentVar);
166 		}
167 		
168 		if (value == null) {
169 			value = "";
170 		}
171 		return value;
172 	}
173 
174 	public Digester getDigester() throws ConfigurationManagerException {
175 		URL rules = MasterRecordParser.class.getResource(MASTER_RECORD_RULES_XML);
176 		if (rules == null) {
177 			throw new ConfigurationManagerException("Major error: could not find " + MASTER_RECORD_RULES_XML + " file with rules to parse master record. Please get a configuration manager distribution.");
178 		}
179 		log.debug("about to load rules to read master record");
180 		Digester masterRecordDigester = DigesterLoader.createDigester(rules);
181 		return masterRecordDigester;
182 	}
183 	
184 }