public TimeStampedMessage receive() {
		// check if file is modified
		File file = new File(configurationFileName);

		@SuppressWarnings("unused")
		TimerTask task = new FileModified(file) {
			protected void onChange(File file) {
				// code the action on a change
				/* read from dropbox folder */
				configurationFileReader.parseFile(configurationFileName);
				ruleChecker.setSendRules(configurationFileReader.getSendRules());
				ruleChecker.setReceiveRules(configurationFileReader.getReceiveRules());
				textArea.append("The file " + file.getName() + " is changed\n");
			}
		};

		/*
		 * Check delayedMessageBuffer, if not empty, directly get one message
		 * and return it
		 */
		if (!delayedMessageBuffer.isEmpty()) {
			return delayedMessageBuffer.poll();
		}

		TimeStampedMessage message = null;
		while (true) {
			/* Get a message from receive buffer */
			while (receiveBuffer.isEmpty()) {
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
				}
			}
			message = receiveBuffer.poll();

			/* Check receive rule */
			TimeStampedMessage toReturnMessage = ruleChecker.checkReceiveRule(message, delayedMessageBuffer);
			if (toReturnMessage != null) {
				message = toReturnMessage;
				break;
			} else {
				// Drop. But still increment local clock
				clockService.incrementTimeStamp();
			}
		}
        
        // LC2(b) & VC4: On receiving a message. Update local clock = max(local time, message's time)
        clockService.incrementTimeStamp(message);
        
        // Re-assign the message's timestamp with the updated local one
		message.setTimeStamp(ClockFactory.getTimeStamp());

		// Log
		try {
			loggerOut.writeObject(message);
			textArea.append("Logged the receive event.");
		} catch (Exception e) {
			e.printStackTrace();
			textArea.append("Couldn't log the event.");
		}

		return message;
	}