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.commander;
23  
24  import java.io.BufferedReader;
25  import java.io.ByteArrayInputStream;
26  import java.io.File;
27  import java.io.FileInputStream;
28  import java.io.InputStream;
29  import java.io.InputStreamReader;
30  import java.io.StringReader;
31  import java.lang.reflect.Method;
32  import java.util.ArrayList;
33  import java.util.HashMap;
34  import java.util.Map;
35  
36  import org.apache.log4j.Logger;
37  import org.eclipse.core.resources.IFile;
38  import org.eclipse.core.resources.IFolder;
39  import org.eclipse.core.resources.IProject;
40  import org.eclipse.core.resources.IResource;
41  import org.eclipse.core.resources.IWorkspaceRoot;
42  import org.eclipse.core.resources.ResourcesPlugin;
43  import org.eclipse.core.runtime.CoreException;
44  import org.eclipse.core.runtime.IStatus;
45  import org.eclipse.core.runtime.Status;
46  import org.eclipse.jface.dialogs.ErrorDialog;
47  import org.eclipse.jface.preference.IPreferenceStore;
48  import org.eclipse.jface.resource.ImageDescriptor;
49  import org.eclipse.swt.graphics.Image;
50  import org.eclipse.ui.IFileEditorInput;
51  import org.eclipse.ui.IWorkbench;
52  import org.eclipse.ui.IWorkbenchPage;
53  import org.eclipse.ui.PlatformUI;
54  import org.eclipse.ui.ide.IDE;
55  import org.fosstrak.llrp.adaptor.AdaptorManagement;
56  import org.fosstrak.llrp.adaptor.exception.LLRPRuntimeException;
57  import org.fosstrak.llrp.client.LLRPExceptionHandlerTypeMap;
58  import org.fosstrak.llrp.client.LLRPMessageItem;
59  import org.fosstrak.llrp.client.MessageHandler;
60  import org.fosstrak.llrp.client.ROAccessReportsRepository;
61  import org.fosstrak.llrp.client.Repository;
62  import org.fosstrak.llrp.client.RepositoryFactory;
63  import org.fosstrak.llrp.client.repository.sql.DerbyRepository;
64  import org.fosstrak.llrp.commander.preferences.PreferenceConstants;
65  import org.fosstrak.llrp.commander.repository.MessageModel;
66  import org.fosstrak.llrp.commander.util.LLRP;
67  import org.fosstrak.llrp.commander.util.MessageBoxRefresh;
68  import org.fosstrak.llrp.commander.util.Utility;
69  import org.fosstrak.llrp.commander.views.MessageboxView;
70  import org.fosstrak.llrp.commander.views.ReaderExplorerView;
71  import org.jdom.Document;
72  import org.llrp.ltk.exceptions.InvalidLLRPMessageException;
73  import org.llrp.ltk.generated.LLRPMessageFactory;
74  import org.llrp.ltk.generated.messages.RO_ACCESS_REPORT;
75  import org.llrp.ltk.generated.parameters.LLRPStatus;
76  import org.llrp.ltk.types.LLRPMessage;
77  
78  /**
79   * This single access point for lower level resources, like Reader and Messages, from
80   * the GUI side. The class apply the <strong>Singleton</strong> pattern.
81   *
82   * @author Haoning Zhang
83   * @author sawielan
84   * @version 1.0
85   */
86  public class ResourceCenter {
87  
88  	/**
89  	 * Maximal message retrieval number
90  	 */
91  	public final static int GET_MAX_MESSAGES = 25;
92  	
93  	/**
94  	 * Default Eclipse Project for storing editable messages
95  	 */
96  	public final static String DEFAULT_ECLIPSE_PROJECT = "LLRP_CMDR";
97  	
98  	/**
99  	 * Default reader configuration file name
100 	 */
101 	public final static String DEFAULT_READER_DEF_FILENAME = "readers.xml";
102 	
103 	/**
104 	 * Pre-built folder, for opened incoming messages
105 	 */
106 	public final static String REPO_SUBFOLDER = "Temporary";
107 	
108 	/**
109 	 * Pre-built folder, for editable outgoing messages
110 	 */
111 	public final static String DRAFT_SUBFOLDER = "Draft";
112 	
113 	/**
114 	 * Pre-built folder, for messages template (samples)
115 	 */
116 	public final static String SAMPLE_SUBFOLDER = "Sample";
117 	
118 	/** folder storing the configuration files. */
119 	public final static String CONFIG_SUBFOLDER = "cfg";
120 	
121 	/** the name of the configuration file for the reader configuration. */
122 	public final static String RDR_CFG_FILE = "rdrCfg.properties";
123 	
124 	public final static String DB_SUBFOLDER = "db"; 
125 	
126 	private static ResourceCenter instance;
127 	
128 	private Repository repo;
129 	
130 	private static Logger log = Logger.getLogger(ResourceCenter.class);
131 	
132 	private MessageModel messageModel;
133 	
134 	private String eclipseProjectName;
135 	
136 	private String readerDefinitionFilename;
137 	
138 	private ExceptionHandler exceptionHandler;
139 	
140 	private HashMap<String, String> readerConfigMap;
141 	
142 	private HashMap<String, String> readerROSpecMap;
143 	
144 	private ReaderExplorerView readerExplorerView;
145 	
146 	/**
147 	 * Only store meta data, without XML content, to save the memory
148 	 */
149 	private ArrayList<LLRPMessageItem> messageList;
150 	
151 	/** the worker thread that refreshes the message box periodically. */
152 	private MessageBoxRefresh messageBoxRefresh = null;
153 	
154 	/** flags whether the adaptor management has been initialized or not. */
155 	private boolean adapterMgmtInitialized = false;
156 	
157 	// flags, whether the RO_ACCESS_REPORTS logging facility has been initialized.
158 	private boolean roAccessReportsLogginInitialized = false;
159 	
160 	/** use an image cache in order not to recreate images over and over again.*/
161 	private Map<String, Image> imageCache = new HashMap<String, Image> ();
162 	
163     /**
164      * Private Constructor, internally called.
165      */
166 	private ResourceCenter() {
167 
168 		// load class LLRP
169 		LLRP.getLlrpDefintion();
170 			
171 		setEclipseProjectName(DEFAULT_ECLIPSE_PROJECT);
172 		setReaderDefinitionFilename(DEFAULT_READER_DEF_FILENAME);
173 		
174 		messageList = new ArrayList<LLRPMessageItem>();
175 		
176 		messageModel = new MessageModel();
177 		
178 		readerConfigMap = new HashMap<String, String>();
179 		readerROSpecMap = new HashMap<String, String>();
180 	}
181 	
182 	/**
183 	 * helper to initialize the adaptor management at the right moment.
184 	 */
185 	public void initializeAdaptorMgmt() {
186 		if (adapterMgmtInitialized) {
187 			log.info("adaptor management already initialized");
188 			return;
189 		}
190 		
191 		IProject project = getEclipseProject();
192 		// refresh the workspace...
193 		try {
194 			project.refreshLocal(IResource.DEPTH_INFINITE, null);
195 		} catch (CoreException e1) {
196 			e1.printStackTrace();
197 		}
198 		
199 		// check if the configuration folder exists.
200 		IFolder configFolder = project.getFolder(
201 				ResourceCenter.CONFIG_SUBFOLDER);
202 		if (!configFolder.exists()) {
203 			try {
204 				log.info("create new config folder...");
205 				configFolder.create(true, true, null);
206 				log.info("created config folder.");
207 			} catch (Exception e) {
208 				e.printStackTrace();
209 			}
210 		}
211 		
212 		// check if the reader configuration exists.
213 		IFile cfg = configFolder.getFile(
214 				ResourceCenter.RDR_CFG_FILE
215 				);
216 		
217 		if (cfg.exists()) {
218 			log.info("found configuration file - good.");
219 		} else {
220 			log.info("reader configuration file missing. create new...");
221 			String defaultCFG = Utility.findWithFullPath(
222 					"/readerDefaultConfig.properties");
223 			
224 			try {
225 				// copy the file
226 				InputStream in = new FileInputStream(new File(defaultCFG));					
227 				cfg.create(in, false, null);
228 				in.close();
229 				
230 			} catch (Exception e) {
231 				e.printStackTrace();
232 			}
233 		}
234 		// create our message handler
235 		MessageHandler handler = new MessageHandler() {
236 
237 			public void handle(String adapter, String reader, LLRPMessage msg) {
238 				LLRPMessageItem item = new LLRPMessageItem();
239 				item.setAdapter(adapter);
240 				item.setReader(reader);
241 				
242 				String msgName = msg.getName();
243 				item.setMessageType(msgName);
244 				
245 				// if the message contains a "LLRPStatus" parameter, set the status code (otherwise use empty string)
246 				String statusCode = "";
247 				try {
248 					Method getLLRPStatusMethod = msg.getClass().getMethod("getLLRPStatus", new Class[0]);
249 					LLRPStatus status = (LLRPStatus) getLLRPStatusMethod.invoke(msg, new Object[0]);
250 					statusCode = status.getStatusCode().toString();
251 				} catch (Exception e) {
252 					// do nothing
253 				} 
254 				item.setStatusCode(statusCode);
255 				
256 				// store the xml string to the repository
257 				try {
258 					item.setContent(msg.toXMLString());
259 				} catch (InvalidLLRPMessageException e) {
260 					e.printStackTrace();
261 				}
262 				
263 				try {
264 					getRepository().put(item);
265 				} catch (Exception e) {
266 					// repository might be null
267 					e.printStackTrace();
268 				}
269 				
270 				// add the message to the meta data list.
271 				addToMessageMetadataList(item);
272 				
273 				if (item.getMessageType().equals("GET_READER_CONFIG_RESPONSE")) {
274 					ResourceCenter.getInstance().addReaderConfig(
275 							item.getAdapter(), 
276 							item.getReader(), 
277 							item.getId());
278 				}
279 				
280 				if (item.getMessageType().equals("GET_ROSPECS_RESPONSE")) {
281 					ResourceCenter.getInstance().addReaderROSpec(
282 							item.getAdapter(), 
283 							item.getReader(), 
284 							item.getId());
285 				}
286 			}
287 		};
288 		
289 		AdaptorManagement.getInstance().registerFullHandler(handler);
290 		IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
291 		String readConfig = myWorkspaceRoot.getLocation().toString() + 
292 				cfg.getFullPath().toString();
293 		
294 		String storeConfig = readConfig;
295 		boolean commitChanges = true;
296 		try {
297 			AdaptorManagement.getInstance().initialize(
298 					readConfig, storeConfig, commitChanges, null, null);
299 		} catch (LLRPRuntimeException e) {
300 			e.printStackTrace();
301 		}
302 		
303 		adapterMgmtInitialized = true;
304 	}	
305 	
306 	/**
307 	 * initialize the RO_ACCESS_REPORTS logging facility. This initializer 
308 	 * should be called once. Basically it registers the repository on the 
309 	 * adapter management to be notified about new RO_ACCESS_REPORTS.
310 	 */
311 	public void initializeROAccessReportsLogging() {
312 		if (roAccessReportsLogginInitialized) return;
313 		
314 		// get a handle of the repository.
315 		ROAccessReportsRepository r = getRepository().getROAccessRepository();
316 		if ((null != r) && (r instanceof MessageHandler)) {
317 			log.debug("initializing RO_ACCESS_REPORTS logging facility.");			
318 			AdaptorManagement.getInstance().registerPartialHandler(
319 					(MessageHandler)r, RO_ACCESS_REPORT.class);
320 		}
321 		roAccessReportsLogginInitialized = true;
322 	}
323 	
324 	/**
325 	 * Get the Message model
326 	 * 
327 	 * @return Message Model
328 	 */
329 	public MessageModel getMessageModel() {
330 		return messageModel;
331 	}
332 	
333     /**
334      * Return the only instance of this class, call the Constructor in its first call.
335      *
336      */
337 	public static ResourceCenter getInstance() {
338 		if (null == instance) {
339 			instance = new ResourceCenter();
340 		}
341 		return instance;
342 	}
343 	
344 	/**
345 	 * Add LLRP Message Item to Repository and Content Provider.
346 	 * 
347 	 * @param aNewMessage Incoming LLRP Message
348 	 */
349 	public void addMessage(LLRPMessageItem aNewMessage) {
350 		if (null == aNewMessage) {
351 			return;
352 		}
353 		
354 		//Add the Repository
355 		repo.put(aNewMessage);
356 	}
357 	
358 	/**
359 	 * Get the message meta data list.
360 	 * 
361 	 * @return Message meta data list 
362 	 */
363 	public ArrayList<LLRPMessageItem> getMessageMetadataList() {
364 		return messageList;
365 	}
366 	
367 	/**
368 	 * Add new message meta data item into list
369 	 * @param aNewMessage New message meta data item
370 	 */
371 	public void addToMessageMetadataList(LLRPMessageItem aNewMessage) {
372 		//Remove XML Content to save the memory, then put into the 1st place of the list
373 		aNewMessage.setContent("");
374 		messageList.add(aNewMessage);
375 		
376 		// flag the refresher to refresh the messagebox 
377 		if (messageBoxRefresh != null) {
378 			messageBoxRefresh.setDirty();
379 		}
380 	}
381 	
382 	/**
383 	 * Clear all data in meta data list
384 	 */
385 	public void clearMessageMetadataList() {
386 		messageList.clear();
387 	}
388 	
389 	/**
390 	 * Get LLRP XML content by Message ID
391 	 * @param aMsgId Message ID
392 	 * @return LLRP XML Content
393 	 */
394 	public String getMessageContent(String aMsgId) {
395 		
396 		if (null == aMsgId) {
397 			return null;
398 		}
399 		
400 		LLRPMessageItem msg = repo.get(aMsgId);
401 		
402 		return msg.getContent().equals("") ? null : msg.getContent();
403 	}
404 	
405 	/**
406 	 * allows to set a new repository.
407 	 * @param repo the new repository.
408 	 * @return the old repository.
409 	 */
410 	public Repository setRepository(Repository repo) {
411 		Repository old = this.repo;
412 		this.repo = repo;
413 		return old;
414 	}
415 	
416 	/**
417 	 * Get the Repository interface.
418 	 * 
419 	 * @return Repository interface
420 	 */
421 	public Repository getRepository() {
422 		if (repo == null) {
423 			
424 			log.debug("open/create new repository");
425 			IProject project = getEclipseProject();
426 			// refresh the workspace...
427 			try {
428 				project.refreshLocal(IResource.DEPTH_INFINITE, null);
429 			} catch (CoreException e1) {
430 				e1.printStackTrace();
431 			}
432 			
433 			IWorkspaceRoot myWorkspaceRoot = 
434 				ResourcesPlugin.getWorkspace().getRoot();
435 			IFolder dbFolder = project.getFolder(
436 					ResourceCenter.DB_SUBFOLDER);
437 			
438 			String dbLocation = myWorkspaceRoot.getLocation().toString() + 
439 					dbFolder.getFullPath().toString() + "/";
440 			
441 			log.info("using db location: " + dbLocation);
442 			IPreferenceStore store = LLRPPlugin.getDefault().getPreferenceStore();
443 			boolean internalDB = store.getBoolean(
444 					PreferenceConstants.P_USE_INTERNAL_DB);
445 			
446 			repo = null;
447 			boolean wipeRO = store.getBoolean(
448 					PreferenceConstants.P_WIPE_RO_ACCESS_REPORTS_ON_STARTUP);
449 			boolean wipe = store.getBoolean(
450 					PreferenceConstants.P_WIPE_DB_ON_STARTUP
451 					);
452 			boolean logRO = store.getBoolean(
453 					PreferenceConstants.P_LOG_RO_ACCESS_REPORTS
454 					);
455 			Map<String, String> args = new HashMap<String, String> ();
456 			args.put(RepositoryFactory.ARG_WIPE_DB, 
457 					String.format("%b", wipe));
458 			args.put(RepositoryFactory.ARG_WIPE_RO_ACCESS_REPORTS_DB, 
459 					String.format("%b", wipeRO));
460 			args.put(RepositoryFactory.ARG_LOG_RO_ACCESS_REPORT, 
461 					String.format("%b", logRO));
462 			if (!internalDB) {
463 				// obtain the user name, password and JDBC connector URL from the 
464 				// eclipse preference store.
465 				args.put(RepositoryFactory.ARG_USERNAME,
466 						store.getString(PreferenceConstants.P_EXT_DB_USERNAME));
467 				args.put(RepositoryFactory.ARG_PASSWRD,
468 						store.getString(PreferenceConstants.P_EXT_DB_PWD));
469 				args.put(RepositoryFactory.ARG_JDBC_STRING,
470 						store.getString(PreferenceConstants.P_EXT_DB_JDBC));
471 				args.put(RepositoryFactory.ARG_DB_CLASSNAME,
472 						store.getString(PreferenceConstants.P_EXT_DB_IMPLEMENTOR));
473 				
474 				try {
475 					repo = RepositoryFactory.create(args);
476 					
477 				} catch (Exception e) {
478 					log.error("Could not invoke the repository, using fallback");
479 					e.printStackTrace();
480 					IStatus status = new Status(
481 							IStatus.WARNING, LLRPPlugin.PLUGIN_ID, 
482 							"LLRP Repository Warning.", e);
483 					ErrorDialog.openError(
484 							LLRPPlugin.getDefault().getWorkbench()
485 								.getDisplay().getActiveShell(),
486 							"Could not open Repository - Using fallback.", 
487 							e.getMessage(), status);
488 				}
489 			}
490 			if (internalDB || (null == repo)) {
491 				log.debug("Starting internal Derby database.");
492 				args.put(DerbyRepository.ARG_REPO_LOCATION, dbLocation);
493 				args.put(RepositoryFactory.ARG_USERNAME, "");
494 				args.put(RepositoryFactory.ARG_PASSWRD, "");
495 				args.put(RepositoryFactory.ARG_JDBC_STRING, "");
496 				repo = new DerbyRepository();
497 				try {
498 					repo.initialize(args);
499 				} catch (LLRPRuntimeException e) {
500 					e.printStackTrace();
501 					IStatus status = new Status(
502 							IStatus.WARNING, LLRPPlugin.PLUGIN_ID,
503 							"LLRP Repository Warning.", e);
504 					ErrorDialog.openError(
505 							LLRPPlugin.getDefault().getWorkbench()
506 								.getDisplay().getActiveShell(),
507 							"Could not open Default/Fallback repository " + 
508 							"LLRP Commander cannot continue properly!", 
509 							e.getMessage(), status);
510 				}
511 			}
512 		}
513 		return repo;
514 	}
515 	
516 	/**
517 	 * @return true if RO_ACCESS_REPORTS shall be logged, false otherwise.
518 	 */
519 	public boolean isLogROAccessReports() {
520 		IPreferenceStore store = LLRPPlugin.getDefault().getPreferenceStore();
521 		return store.getBoolean(PreferenceConstants.P_LOG_RO_ACCESS_REPORTS);
522 	}
523 	
524 	/**
525 	 * Get Eclipse Project Name
526 	 * @return Eclipse Project Name
527 	 */
528 	public String getEclipseProjectName() {
529 		return eclipseProjectName;
530 	}
531 	
532 	/**
533 	 * Set Eclipse Project Name
534 	 * @param aName Eclipse Project Name
535 	 */
536 	public void setEclipseProjectName(String aName) {
537 		eclipseProjectName = aName;
538 	}
539 	
540 	/**
541 	 * Get Eclipse <code>IProject</code> instance
542 	 * @return Eclipse IProject instance
543 	 */
544 	public IProject getEclipseProject() {
545 		IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
546 		IProject myWebProject = myWorkspaceRoot.getProject(getEclipseProjectName());
547 		
548 		if (!myWebProject.exists()) {
549 			log.info("Project " + getEclipseProjectName() + " doesn't exists!");
550 			return null;
551 		}
552 		
553 		try {
554 			if (myWebProject.exists() && !myWebProject.isOpen()) {
555 				myWebProject.open(null);
556 			}
557 		} catch (CoreException ce) {
558 			log.debug("could not open project " + ce.getMessage());
559 		}
560 		
561 		return myWebProject;
562 	}
563 	
564 	/**
565 	 * Get current editing file name
566 	 * @return Current editing file name
567 	 */
568 	public String getCurrentFileName() {
569 		
570 		IWorkbench workbench = PlatformUI.getWorkbench();
571 		IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage();
572 		String fileName = page.getActiveEditor().getEditorInput().getName();
573 		
574 		return fileName;
575 	}
576 	
577 	/**
578 	 * Get current editing XML content
579 	 * @return Current editing XML content
580 	 */
581 	public String getCurrentFile() {
582 		
583 		IWorkbench workbench = PlatformUI.getWorkbench();
584 		IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage();
585 		IFileEditorInput input = (IFileEditorInput) page.getActiveEditor().getEditorInput();
586 		
587 		StringBuffer aXMLContent = new StringBuffer();
588 		
589 		try {
590 			InputStream is = input.getFile().getContents();
591 			BufferedReader reader = new BufferedReader(
592 					new InputStreamReader(is));
593 
594 			String line;
595 			while ((line = reader.readLine()) != null) {
596 				aXMLContent.append(line);
597 			}
598 
599 			reader.close();
600 			
601 		} catch (Exception e) {
602 			e.printStackTrace();
603 		}
604 		
605 		return aXMLContent.toString();
606 	}
607 	
608 	/**
609 	 * Helper function. Generate <code>LLRPMessage</code> instance
610 	 * by XML content.
611 	 * If the exchange by LTKJava hold errors, return null.
612 	 * 
613 	 * @param aXMLFileContent XML file content
614 	 * @return LLRPMessage instance.
615 	 */
616 	public LLRPMessage generateLLRPMessage(String aXMLFileContent) {
617 		
618 		LLRPMessage message = null;
619 		
620 		log.info("Start generating LLRPMessage...");
621 		
622 		try {
623 			Document doc = new org.jdom.input.SAXBuilder()
624 					.build(new StringReader(aXMLFileContent));
625 			
626 			message = LLRPMessageFactory.createLLRPMessage(doc);
627 
628 		} catch (Exception e) {
629 			e.printStackTrace();
630 		}
631 		
632 		log.info("LLRPMessage successfully generated.");
633 		
634 		return message;
635 	}
636 	
637 	/**
638 	 * Send LLRP Message.
639 	 * 
640 	 * @param aAdapterName Adapter Logical Name
641 	 * @param aReaderName Reader Logical Name
642 	 * @param aMessage LLRPMessage instance
643 	 * @param aComment User Input Comments
644 	 */
645 	public void sendMessage(String aAdapterName, String aReaderName, LLRPMessage aMessage, String aComment) {
646 		try {
647 			String msgName = aMessage.getName();
648 			
649 			LLRPMessageItem  item = new LLRPMessageItem();
650 			item.setMark(LLRPMessageItem.MARK_OUTGOING);
651 			item.setAdapter(aAdapterName);
652 			item.setReader(aReaderName);
653 			item.setContent(aMessage.toXMLString());
654 			item.setMessageType(msgName);
655 			item.setComment(aComment);
656 			
657 			this.addMessage(item);
658 			
659 			AdaptorManagement.getInstance().enqueueLLRPMessage(aAdapterName, aReaderName, aMessage);
660 						
661 		} catch (LLRPRuntimeException e) {
662 			e.printStackTrace();
663 		} catch (InvalidLLRPMessageException ive) {
664 			ive.printStackTrace();
665 		}
666 	}
667 	
668 	/**
669 	 * Disconnect all readers.
670 	 */
671 	public void disconnectAllReaders() {
672 		log.info("Disconnecting all readers...");
673 		AdaptorManagement.getInstance().disconnectReaders();
674 		
675 		AdaptorManagement.getInstance().shutdown();
676 	}
677 
678 	/**
679 	 * Get Reader definition filename
680 	 * @return Reader definition filename
681 	 */
682 	public String getReaderDefinitionFilename() {
683 		return readerDefinitionFilename;
684 	}
685 
686 	/**
687 	 * Set Reader definition filename
688 	 * @param aReaderDefinitionFilename Reader definition filename
689 	 */
690 	public void setReaderDefinitionFilename(String aReaderDefinitionFilename) {
691 		readerDefinitionFilename = aReaderDefinitionFilename;
692 	}
693 		
694 	/**
695 	 * Get <code>Image</code> from icon folder
696 	 * @param aFilename Image filename
697 	 * @return Image instance
698 	 */
699 	public Image getImage(String aFilename) {
700 		synchronized (imageCache) {
701 			if (imageCache.containsKey(aFilename)) {
702 				return imageCache.get(aFilename);
703 			}
704 			log.debug("Generate Image:" + "icons/" + aFilename);
705 			Image img = LLRPPlugin.getImageDescriptor("icons/" + aFilename).createImage();
706 			imageCache.put(aFilename, img);
707 			return img;
708 		}
709 	}
710 	
711 	/**
712 	 * Get <code>ImageDescriptor</code> from icon folder
713 	 * @param aFilename Image filename
714 	 * @return ImageDescriptor instance
715 	 */
716 	public ImageDescriptor getImageDescriptor(String aFilename) {
717 		log.debug("Generate ImageDescriptor:" + "icons/" + aFilename);
718 		return LLRPPlugin.getImageDescriptor("icons/" + aFilename);
719 	}
720 	
721 	public void setExceptionHandler(ExceptionHandler aHandler) {
722 		exceptionHandler = aHandler;
723 		AdaptorManagement.getInstance().setExceptionHandler(aHandler);
724 	}
725 	
726 	public void postExceptionToGUI(LLRPExceptionHandlerTypeMap aExceptionType, String aAdapter, String aReader) {
727 		if (null == exceptionHandler) {
728 			return;
729 		}
730 		
731 		exceptionHandler.postExceptionToGUI(aExceptionType, null, aAdapter, aReader);
732 		
733 	}
734 	
735 	/**
736 	 * set the message box view in the message box refresh thread. If the 
737 	 * refresh thread is not started yet, a new instance is generated and the 
738 	 * thread is started, otherwise the new message box view is registered on 
739 	 * the running thread.
740 	 * @param aMessagebox the message box to be set.
741 	 */
742 	public void setMessageboxView(MessageboxView aMessagebox) {
743 		if (messageBoxRefresh == null) {
744 			messageBoxRefresh = new MessageBoxRefresh(aMessagebox);
745 			new Thread(messageBoxRefresh).start();
746 		} else {
747 			messageBoxRefresh.setMessageBox(aMessagebox);
748 		}
749 	}
750 
751 	/**
752 	 * @param readerExplorerView the readerExplorerView to set
753 	 */
754 	public void setReaderExplorerView(ReaderExplorerView readerExplorerView) {
755 		this.readerExplorerView = readerExplorerView;
756 	}
757 
758 
759 	/**
760 	 * @return the readerExplorerView
761 	 */
762 	public ReaderExplorerView getReaderExplorerView() {
763 		return readerExplorerView;
764 	}
765 	
766 	public void addReaderConfig(String aAdapterName, String aReaderName, String aMessageID) {
767 		readerConfigMap.put(aAdapterName + aReaderName, aMessageID);
768 	}
769 	
770 	public void removeReaderConfig(String aAdapterName, String aReaderName) {
771 		readerConfigMap.remove(aAdapterName + aReaderName);
772 	}
773 	
774 	public String getReaderConfigMsgId(String aAdapterName, String aReaderName) {
775 		String result = readerConfigMap.get(aAdapterName + aReaderName);
776 		return result;
777 	}
778 	
779 	public void addReaderROSpec(String aAdapterName, String aReaderName, String aMessageID) {
780 		readerROSpecMap.put(aAdapterName + aReaderName, aMessageID);
781 	}
782 	
783 	public void removeReaderROSpec(String aAdapterName, String aReaderName) {
784 		readerROSpecMap.remove(aAdapterName + aReaderName);
785 	}
786 	
787 	public String getReaderROSpecMsgId(String aAdapterName, String aReaderName) {
788 		String result = readerROSpecMap.get(aAdapterName + aReaderName);
789 		return result;
790 	}
791 	
792 	public boolean existReaderConfig(String aAdapterName, String aReaderName) {
793 		String result = getReaderConfigMsgId(aAdapterName, aReaderName);
794 		return (null == result) ? false : true;
795 	}
796 	
797 	public boolean existReaderROSpec(String aAdapterName, String aReaderName) {
798 		String result = getReaderROSpecMsgId(aAdapterName, aReaderName);
799 		return (null == result) ? false : true;
800 	}
801 	
802 	/**
803 	 * writes a chunk of data to a folder within a requested file.
804 	 * @param folder the folder where to write to. if null uses "temporary".
805 	 * @param fileName the file name where to write to. if null, abort.
806 	 * @param msg the data chunk to be written.
807 	 * @return the file handle interface of the written file.
808 	 * @throws Exception when there is a problem.
809 	 */
810 	public IFile writeMessageToFile(String folder, 
811 			String fileName, String msg) throws Exception {
812 		
813 		if (null == folder) folder = ResourceCenter.REPO_SUBFOLDER;
814 		if (null == msg) return null;
815 		
816 		if (null == fileName) fileName = String.format(
817 				"%d.csv", System.currentTimeMillis());
818 		
819 		IProject project = getEclipseProject();
820 		
821 		// open if necessary
822 		if (project.exists() && !project.isOpen())
823 			project.open(null);
824 		
825 		IFolder repoFolder = project.getFolder(folder);
826 		if (!repoFolder.exists()) {
827 			repoFolder.create(true, true, null);
828 		}
829 		IFile msgFile = repoFolder.getFile(fileName);
830 		
831 		if (!msgFile.exists()) {
832 			InputStream is = 
833 				new ByteArrayInputStream(msg.getBytes());
834 			msgFile.create(is, false, null);
835 		}
836 		return msgFile;
837 	}
838 	
839 	/**
840 	 * writes the content of the given id into a temporary file.
841 	 * @param aMsgId the message id to write to file.
842 	 */
843 	public void writeMessageToFile(String aMsgId) {
844 		
845 		if (null == aMsgId) {
846 			log.warn("Message is null!");
847 			return;
848 		}
849 		
850 		String content = getMessageContent(aMsgId);
851 		
852 		try {IFile msgFile = writeMessageToFile(
853 					ResourceCenter.REPO_SUBFOLDER, aMsgId + ".llrp", content);
854 			// Open new file in editor
855 			IWorkbench workbench = PlatformUI.getWorkbench();
856 			IWorkbenchPage page = 
857 				workbench.getActiveWorkbenchWindow().getActivePage();
858 			
859 			IDE.openEditor(page, msgFile, 
860 					"org.fosstrak.llrp.commander.editors.LLRPEditor", true);
861 		} catch (Exception e) {
862 			e.printStackTrace();
863 		}
864 	}
865 	
866 	/**
867 	 * tear down the resource center.
868 	 */
869 	public void close() {
870 		log.info("Closing Database...");
871 		ResourceCenter.getInstance().getRepository().close();
872 		log.info("Undefine all readers...");
873 		ResourceCenter.getInstance().disconnectAllReaders();
874 		log.info("stopping message box refresher...");
875 		messageBoxRefresh.stop();
876 	}
877 
878 	/**
879 	 * @return the messageBoxRefresh
880 	 */
881 	public MessageBoxRefresh getMessageBoxRefresh() {
882 		return messageBoxRefresh;
883 	}
884 }