View Javadoc

1   /*
2    *  
3    *  Fosstrak LLRP Commander (www.fosstrak.org)
4    * 
5    *  Copyright (C) 2008 ETH Zurich
6    *
7    *  This program is free software: you can redistribute it and/or modify
8    *  it under the terms of the GNU General Public License as published by
9    *  the Free Software Foundation, either version 3 of the License, or
10   *  (at your option) any later version.
11   *
12   *  This program is distributed in the hope that it will be useful,
13   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   *  GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License
18   *  along with this program.  If not, see <http://www.gnu.org/licenses/> 
19   *
20   */
21  
22  package org.fosstrak.llrp.adaptor.config;
23  
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.FileNotFoundException;
27  import java.io.FileOutputStream;
28  import java.io.IOException;
29  import java.util.LinkedList;
30  import java.util.List;
31  import java.util.Properties;
32  
33  import org.apache.log4j.Logger;
34  import org.fosstrak.llrp.adaptor.AdaptorManagement;
35  import org.fosstrak.llrp.adaptor.exception.LLRPRuntimeException;
36  import org.fosstrak.llrp.adaptor.util.SortedProperties;
37  
38  /**
39   * The {@link ConfigurationLoader} acts as a gateway to the configuration file. it 
40   * tries to mask away the structure of the configuration file by providing 
41   * prototypes for the adaptors and their readers. it provides reading and writing 
42   * of configuration files.
43   * @author sawielan
44   *
45   */
46  public class ConfigurationLoader {
47  	/** the logger. */
48  	private static Logger log = Logger.getLogger(ConfigurationLoader.class);
49  	
50  	/** the properties read from file. */
51  	private Properties props = null; 
52  	
53  	
54  	/** strings to parse the configuration file. */
55  	private static final String CFG_SEPARATOR = ".";
56  	
57  	private static final String CFG_NBR_ADAPTORS = "numberOfAdaptors";
58  	private static final String CFG_ADAPTOR_PREFIX = "adaptor";
59  	private static final String CFG_ADAPTOR_NAME = "name";
60  	private static final String CFG_ADAPTOR_MODE = "local";
61  	private static final String CFG_ADAPTOR_IP = "ip";
62  	
63  	private static final String CFG_NBR_READERS = "numberOfReaders";
64  	private static final String CFG_READER_PREFIX = "reader";
65  	private static final String CFG_READER_NAME = "name";
66  	private static final String CFG_READER_IP = "ip";
67  	private static final String CFG_READER_PORT = "port";
68  	private static final String CFG_READER_INITIATION = "clientInitiated";
69  	private static final String CFG_READER_CONNECT_IMMEDIATELY = "connectImmediately";
70  	
71  	private List<AdaptorConfiguration> adaptorConfigurations = null;
72  	
73  	/**
74  	 * creates a configuration loader.
75  	 */
76  	public ConfigurationLoader() {
77  	}
78  	
79  	/**
80  	 * reads a configuration file and delivers the content in a prototype-form.
81  	 * @param propertiesFile the properties file to read.
82  	 * @return the prototypes holding the configuration.
83  	 * @throws LLRPRuntimeException whenever the configuration file could not be read.
84  	 */
85  	public List<AdaptorConfiguration> getConfiguration(String propertiesFile ) throws LLRPRuntimeException {
86  		
87  		props = new Properties();
88  		// try to load the properties file
89  		try {
90  			props.load(new FileInputStream(new File(propertiesFile)));
91  		} catch (FileNotFoundException e) {
92  			log.error("The configuration file " + propertiesFile + " was not found.");
93  			throw new LLRPRuntimeException(e.getMessage());
94  		} catch (IOException e) {
95  			log.error("There has been an IO Exception when reading the configuration file " + propertiesFile);
96  			throw new LLRPRuntimeException(e.getMessage());
97  		}	
98  		
99  		adaptorConfigurations = new LinkedList<AdaptorConfiguration>();
100 		
101 		int numAdaptors = Integer.parseInt(props.getProperty(CFG_NBR_ADAPTORS));
102 		// read the adaptor configuration
103 		log.info("loading adaptors from configuration file " + propertiesFile);
104 		
105 		// read all the adaptors.
106 		for (int i=0; i<numAdaptors; i++) {
107 			String adaptorPrefix = CFG_ADAPTOR_PREFIX + i + CFG_SEPARATOR;
108 			// get the adaptor name
109 			String adaptorName = props.getProperty(adaptorPrefix + CFG_ADAPTOR_NAME);
110 			boolean isLocal = Boolean.parseBoolean(props.getProperty(adaptorPrefix + CFG_ADAPTOR_MODE));
111 			String adaptorIP = props.getProperty(adaptorPrefix + CFG_ADAPTOR_IP, null);
112 			
113 			log.debug(String.format("read adaptor values: (name:%s, ip:%s, local:%b)", 
114 					adaptorName, adaptorIP, isLocal));
115 			
116 			adaptorConfigurations.add(new AdaptorConfiguration(adaptorName, adaptorIP, isLocal, adaptorPrefix));
117 		}
118 		
119 		getReaderPrototypes();
120 		log.debug("loaded configuration from file");
121 		return adaptorConfigurations;
122 	}
123 	
124 	/**
125 	 * reads the reader configurations from the config file.
126 	 */
127 	private void getReaderPrototypes() {
128 		for (AdaptorConfiguration adaptor : adaptorConfigurations) {
129 			if (adaptor.isLocal()) {
130 				List<ReaderConfiguration> readerConfigurations = new LinkedList<ReaderConfiguration>();
131 				
132 				// get the number of readers to create
133 				int numReaders = Integer.parseInt(props.getProperty(adaptor.getPrefix() + CFG_NBR_READERS));
134 				for (int j=0; j<numReaders; j++) {
135 					String readerPrefix = adaptor.getPrefix() + CFG_READER_PREFIX + j + CFG_SEPARATOR;
136 					
137 					String readerName = props.getProperty(readerPrefix + CFG_READER_NAME);
138 					String readerIp = props.getProperty(readerPrefix + CFG_READER_IP);
139 					int readerPort = Integer.parseInt(props.getProperty(readerPrefix + CFG_READER_PORT));
140 					boolean readerClientInitiated = Boolean.parseBoolean(props.getProperty(readerPrefix + CFG_READER_INITIATION));
141 					boolean connectImmediately = Boolean.parseBoolean(props.getProperty(readerPrefix + CFG_READER_CONNECT_IMMEDIATELY));
142 					
143 					readerConfigurations.add(new ReaderConfiguration(
144 							readerName, readerIp, readerPort, 
145 							readerClientInitiated, connectImmediately));
146 					
147 					log.debug(String.format("read reader values: (name:%s, ip:%s, port:%d, clientInitiatedConnection: %b, connectImmediately: %b)", 
148 							readerName, readerIp, readerPort, readerClientInitiated, connectImmediately));
149 					
150 					adaptor.setReaderConfigurations(readerConfigurations);
151 				}
152 			}
153 		}
154 	}
155 	
156 	/**
157 	 * writes the configuration given by a list of prototypes to the configuration file.
158 	 * @param configurations the prototypes to be written to the config-file.
159 	 * @param propertiesFile the properties file where to store.
160 	 * @throws LLRPRuntimeException whenever the file could not be written.
161 	 */
162 	public void writeConfiguration(List<AdaptorConfiguration> configurations, 
163 			String propertiesFile) throws LLRPRuntimeException {
164 		
165 		Properties props = new SortedProperties();
166 
167 		log.info("storing adaptors to configuration file " + propertiesFile);
168 		
169 		// write the number of adaptors to the properties
170 		log.debug(String.format("writing property/value (%s,%d)", 
171 				CFG_NBR_ADAPTORS,
172 				configurations.size()));
173 		props.setProperty(CFG_NBR_ADAPTORS, String.format("%s", configurations.size()));
174 		
175 		// the first adapter we write is the default adapter
176 		int defaultIndex = 0;
177 		for (AdaptorConfiguration cfg : configurations) {
178 			if (AdaptorManagement.DEFAULT_ADAPTOR_NAME.equals(cfg.getAdaptorName())) {
179 				break;
180 			}
181 			defaultIndex ++;
182 		}
183 		AdaptorConfiguration defaultCfg = configurations.remove(defaultIndex);
184 		writeAdapter(defaultCfg, props, 0);
185 		int i=1;
186 		for (AdaptorConfiguration adaptor : configurations) {
187 			writeAdapter(adaptor, props, i);
188 			i++;		
189 		}
190 		
191 		try {
192 			props.store(new FileOutputStream(new File(propertiesFile)), null);
193 		} catch (FileNotFoundException e) {
194 			log.error("The configuration file " + propertiesFile + " could not be written.");
195 			throw new LLRPRuntimeException(e.getMessage());
196 		} catch (IOException e) {
197 			log.error("There has been an IO Exception when writing the configuration file " + propertiesFile);
198 			throw new LLRPRuntimeException(e.getMessage());
199 		}
200 	}
201 
202 	/**
203 	 * writes the configuration of one adapter into the properties file.
204 	 * @param adaptor the adapter configuration to be written.
205 	 * @param props the properties file.
206 	 * @param i the index to use.
207 	 */
208 	private void writeAdapter(AdaptorConfiguration adaptor, Properties props, int i) {
209 		String adaptorPrefix = CFG_ADAPTOR_PREFIX + i + CFG_SEPARATOR;
210 		
211 		// write the adaptor name
212 		log.debug(String.format("writing property/value (%s,%s)", 
213 					adaptorPrefix + CFG_ADAPTOR_NAME,
214 					adaptor.getAdaptorName()));
215 		props.setProperty(adaptorPrefix + CFG_ADAPTOR_NAME, adaptor.getAdaptorName());
216 		
217 		boolean isLocal = false;
218 		if (adaptor.isLocal()) {
219 			isLocal = true;
220 		} else {
221 			log.debug(String.format("writing property/value (%s,%s)",
222 					adaptorPrefix + CFG_ADAPTOR_IP,
223 					adaptor.getIp()));
224 			props.setProperty(adaptorPrefix + CFG_ADAPTOR_IP, adaptor.getIp());
225 		}
226 		log.debug(String.format("writing property/value (%s,%b)",
227 				adaptorPrefix + CFG_ADAPTOR_MODE,
228 				isLocal));
229 		props.setProperty(adaptorPrefix + CFG_ADAPTOR_MODE, String.format("%b", isLocal));
230 		
231 		// now store the reader part
232 		if (isLocal) {
233 			// store the number of readers to create
234 			log.debug(String.format("writing property/value (%s,%s)",
235 					adaptorPrefix + CFG_NBR_READERS,
236 					adaptor.getReaderPrototypes().size()));
237 			props.setProperty(adaptorPrefix + CFG_NBR_READERS, String.format("%d", adaptor.getReaderPrototypes().size()));
238 			int j=0;
239 			for (ReaderConfiguration reader : adaptor.getReaderPrototypes()) {
240 				
241 				String readerPrefix = adaptorPrefix + CFG_READER_PREFIX + j + CFG_SEPARATOR;
242 				j++;
243 				
244 				log.debug(String.format("writing property/value (%s,%s)",
245 						readerPrefix + CFG_READER_NAME,
246 						reader.getReaderName()));
247 				props.setProperty(readerPrefix + CFG_READER_NAME, reader.getReaderName());
248 				
249 				log.debug(String.format("writing property/value (%s,%s)",
250 						readerPrefix + CFG_READER_IP,
251 						reader.getReaderIp()));
252 				props.setProperty(readerPrefix + CFG_READER_IP, reader.getReaderIp());
253 				
254 				log.debug(String.format("writing property/value (%s,%d)",
255 						readerPrefix + CFG_READER_PORT,
256 						reader.getReaderPort()));
257 				props.setProperty(readerPrefix + CFG_READER_PORT, String.format("%d", reader.getReaderPort()));
258 				
259 				log.debug(String.format("writing property/value (%s,%b)",
260 						readerPrefix + CFG_READER_INITIATION,
261 						reader.isReaderClientInitiated()));
262 				props.setProperty(readerPrefix + CFG_READER_INITIATION, String.format("%b", reader.isReaderClientInitiated()));
263 				
264 				log.debug(String.format("writing property/value (%s,%b)",
265 						readerPrefix + CFG_READER_CONNECT_IMMEDIATELY,
266 						true));
267 				props.setProperty(readerPrefix + CFG_READER_CONNECT_IMMEDIATELY, String.format("%b", reader.isConnectImmediately()));
268 			}
269 		}
270 	}
271 }