gt: 		return validatePoint(id, xid, name, locator, null);
context: /*
      Mango - Open Source M2M - http://mango.serotoninsoftware.com
      Copyright (C) 2006-2011 Serotonin Software Technologies Inc.
      @author Matthew Lohbihler
      
      This program is free software: you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation, either version 3 of the License, or
      (at your option) any later version.
  
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package com.serotonin.mango.web.dwr;
  
  import java.io.File;
  import java.io.IOException;
  import java.lang.management.ManagementFactory;
  import java.net.InetAddress;
  import java.net.MalformedURLException;
  import java.nio.charset.IllegalCharsetNameException;
  import java.text.DateFormat;
  import java.text.DecimalFormat;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.TreeMap;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import java.util.regex.Pattern;
  
  import javax.management.MBeanAttributeInfo;
  import javax.management.MBeanServerConnection;
  import javax.management.ObjectName;
  import javax.management.RuntimeMBeanException;
  import javax.management.openmbean.CompositeData;
  import javax.management.remote.JMXConnector;
  import javax.management.remote.JMXConnectorFactory;
  import javax.management.remote.JMXServiceURL;
  import javax.script.ScriptException;
  
  import net.sf.mbus4j.Connection;
  import net.sf.mbus4j.MBusAddressing;
  import net.sf.mbus4j.TcpIpConnection;
  import net.sf.mbus4j.dataframes.MBusResponseFramesContainer;
  import net.sf.mbus4j.dataframes.UserDataResponse;
  import net.sf.mbus4j.dataframes.datablocks.DataBlock;
  import net.sf.openv4j.DataPoint;
  import net.sf.openv4j.Devices;
  import net.sf.openv4j.Group;
  import net.sf.openv4j.Protocol;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.jinterop.dcom.common.JISystem;
  
  import br.org.scadabr.OPCItem;
  import br.org.scadabr.OPCUtils;
  import br.org.scadabr.RealOPCMaster;
  import br.org.scadabr.vo.dataSource.alpha2.Alpha2DataSourceVO;
  import br.org.scadabr.vo.dataSource.alpha2.Alpha2PointLocatorVO;
  import br.org.scadabr.vo.dataSource.asciiFile.ASCIIFileDataSourceVO;
  import br.org.scadabr.vo.dataSource.asciiFile.ASCIIFilePointLocatorVO;
  import br.org.scadabr.vo.dataSource.asciiSerial.ASCIISerialDataSourceVO;
  import br.org.scadabr.vo.dataSource.asciiSerial.ASCIISerialPointLocatorVO;
  import br.org.scadabr.vo.dataSource.dnp3.Dnp3IpDataSourceVO;
  import br.org.scadabr.vo.dataSource.dnp3.Dnp3PointLocatorVO;
  import br.org.scadabr.vo.dataSource.dnp3.Dnp3SerialDataSourceVO;
  import br.org.scadabr.vo.dataSource.drStorageHt5b.DrStorageHt5bDataSourceVO;
  import br.org.scadabr.vo.dataSource.drStorageHt5b.DrStorageHt5bPointLocatorVO;
  import br.org.scadabr.vo.dataSource.iec101.IEC101EthernetDataSourceVO;
  import br.org.scadabr.vo.dataSource.iec101.IEC101PointLocatorVO;
  import br.org.scadabr.vo.dataSource.iec101.IEC101SerialDataSourceVO;
  import br.org.scadabr.vo.dataSource.nodaves7.NodaveS7DataSourceVO;
  import br.org.scadabr.vo.dataSource.nodaves7.NodaveS7PointLocatorVO;
  import br.org.scadabr.vo.dataSource.opc.OPCDataSourceVO;
  import br.org.scadabr.vo.dataSource.opc.OPCPointLocatorVO;
  import cc.radiuino.scadabr.vo.datasource.radiuino.RadiuinoDataSourceVO;
  import cc.radiuino.scadabr.vo.datasource.radiuino.RadiuinoPointLocatorVO;
  
  import com.dalsemi.onewire.OneWireException;
  import com.serotonin.bacnet4j.LocalDevice;
  import com.serotonin.bacnet4j.RemoteDevice;
  import com.serotonin.bacnet4j.type.constructed.Address;
  import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
  import com.serotonin.db.IntValuePair;
  import com.serotonin.io.StreamUtils;
  import org.scada_lts.modbus.SerialParameters;
  import com.serotonin.mango.Common;
  import com.serotonin.mango.DataTypes;
  import com.serotonin.mango.db.dao.DataPointDao;
  import com.serotonin.mango.db.dao.EventDao;
  import com.serotonin.mango.rt.RuntimeManager;
  import com.serotonin.mango.rt.dataImage.IDataPoint;
  import com.serotonin.mango.rt.dataImage.PointValueTime;
  import com.serotonin.mango.rt.dataImage.types.MangoValue;
  import com.serotonin.mango.rt.dataSource.DataSourceUtils;
  import com.serotonin.mango.rt.dataSource.ebro.EBI25Constants;
  import com.serotonin.mango.rt.dataSource.http.HttpReceiverData;
  import com.serotonin.mango.rt.dataSource.http.HttpRetrieverDataSourceRT;
  import com.serotonin.mango.rt.dataSource.meta.DataPointStateException;
  import com.serotonin.mango.rt.dataSource.meta.ResultTypeException;
  import com.serotonin.mango.rt.dataSource.meta.ScriptExecutor;
  import com.serotonin.mango.rt.dataSource.modbus.ModbusDataSource;
  import com.serotonin.mango.rt.dataSource.onewire.Network;
  import com.serotonin.mango.rt.dataSource.onewire.NetworkPath;
  import com.serotonin.mango.rt.dataSource.onewire.OneWireContainerInfo;
  import com.serotonin.mango.rt.dataSource.onewire.OneWireDataSourceRT;
  import com.serotonin.mango.rt.dataSource.pachube.PachubeDataSourceRT;
  import com.serotonin.mango.rt.dataSource.pachube.PachubeValue;
  import com.serotonin.mango.rt.dataSource.snmp.Version;
  import com.serotonin.mango.rt.dataSource.viconics.ViconicsDataSourceRT;
  import com.serotonin.mango.rt.event.EventInstance;
  import com.serotonin.mango.util.IntMessagePair;
  import com.serotonin.mango.vo.DataPointNameComparator;
  import com.serotonin.mango.vo.DataPointVO;
  import com.serotonin.mango.vo.User;
  import com.serotonin.mango.vo.dataSource.DataSourceVO;
  import com.serotonin.mango.vo.dataSource.PointLocatorVO;
  import com.serotonin.mango.vo.dataSource.bacnet.BACnetIPDataSourceVO;
  import com.serotonin.mango.vo.dataSource.bacnet.BACnetIPPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.ebro.EBI25DataSourceVO;
  import com.serotonin.mango.vo.dataSource.ebro.EBI25PointLocatorVO;
  import com.serotonin.mango.vo.dataSource.galil.GalilDataSourceVO;
  import com.serotonin.mango.vo.dataSource.galil.GalilPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.http.HttpImageDataSourceVO;
  import com.serotonin.mango.vo.dataSource.http.HttpImagePointLocatorVO;
  import com.serotonin.mango.vo.dataSource.http.HttpReceiverDataSourceVO;
  import com.serotonin.mango.vo.dataSource.http.HttpReceiverPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.http.HttpRetrieverDataSourceVO;
  import com.serotonin.mango.vo.dataSource.http.HttpRetrieverPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.internal.InternalDataSourceVO;
  import com.serotonin.mango.vo.dataSource.internal.InternalPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.jmx.JmxDataSourceVO;
  import com.serotonin.mango.vo.dataSource.jmx.JmxPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.mbus.MBusDataSourceVO;
  import com.serotonin.mango.vo.dataSource.mbus.MBusPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.mbus.MBusSearchByAddressing;
  import com.serotonin.mango.vo.dataSource.mbus.PrimaryAddressingSearch;
  import com.serotonin.mango.vo.dataSource.mbus.SecondaryAddressingSearch;
  import com.serotonin.mango.vo.dataSource.meta.MetaDataSourceVO;
  import com.serotonin.mango.vo.dataSource.meta.MetaPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.modbus.ModbusIpDataSourceVO;
  import com.serotonin.mango.vo.dataSource.modbus.ModbusIpDataSourceVO.TransportType;
  import com.serotonin.mango.vo.dataSource.modbus.ModbusPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.modbus.ModbusSerialDataSourceVO;
  import com.serotonin.mango.vo.dataSource.modbus.ModbusSerialDataSourceVO.EncodingType;
  import com.serotonin.mango.vo.dataSource.nmea.NmeaDataSourceVO;
  import com.serotonin.mango.vo.dataSource.nmea.NmeaPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.onewire.OneWireDataSourceVO;
  import com.serotonin.mango.vo.dataSource.onewire.OneWirePointLocatorVO;
  import com.serotonin.mango.vo.dataSource.openv4j.OpenV4JDataSourceVO;
  import com.serotonin.mango.vo.dataSource.openv4j.OpenV4JPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.pachube.PachubeDataSourceVO;
  import com.serotonin.mango.vo.dataSource.pachube.PachubePointLocatorVO;
  import com.serotonin.mango.vo.dataSource.persistent.PersistentDataSourceVO;
  import com.serotonin.mango.vo.dataSource.persistent.PersistentPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.pop3.Pop3DataSourceVO;
  import com.serotonin.mango.vo.dataSource.pop3.Pop3PointLocatorVO;
  import com.serotonin.mango.vo.dataSource.snmp.SnmpDataSourceVO;
  import com.serotonin.mango.vo.dataSource.snmp.SnmpPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.sql.SqlDataSourceVO;
  import com.serotonin.mango.vo.dataSource.sql.SqlPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.viconics.ViconicsDataSourceVO;
  import com.serotonin.mango.vo.dataSource.viconics.ViconicsPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.virtual.ChangeTypeVO;
  import com.serotonin.mango.vo.dataSource.virtual.VirtualDataSourceVO;
  import com.serotonin.mango.vo.dataSource.virtual.VirtualPointLocatorVO;
  import com.serotonin.mango.vo.dataSource.vmstat.VMStatDataSourceVO;
  import com.serotonin.mango.vo.dataSource.vmstat.VMStatPointLocatorVO;
  import com.serotonin.mango.vo.event.PointEventDetectorVO;
  import com.serotonin.mango.vo.permission.Permissions;
  import com.serotonin.mango.web.dwr.beans.BACnetDiscovery;
  import com.serotonin.mango.web.dwr.beans.BACnetObjectBean;
  import com.serotonin.mango.web.dwr.beans.DataPointDefaulter;
  import com.serotonin.mango.web.dwr.beans.EBI25InterfaceReader;
  import com.serotonin.mango.web.dwr.beans.EBI25InterfaceUpdater;
  import com.serotonin.mango.web.dwr.beans.EventInstanceBean;
  import com.serotonin.mango.web.dwr.beans.GalilCommandTester;
  import com.serotonin.mango.web.dwr.beans.HttpReceiverDataListener;
  import com.serotonin.mango.web.dwr.beans.MBusDiscovery;
  import com.serotonin.mango.web.dwr.beans.ModbusNodeScanListener;
  import com.serotonin.mango.web.dwr.beans.NmeaUtilListener;
  import com.serotonin.mango.web.dwr.beans.OpenV4JDataPointBean;
  import com.serotonin.mango.web.dwr.beans.OpenV4JDiscovery;
  import com.serotonin.mango.web.dwr.beans.OpenV4JProtocolBean;
  import com.serotonin.mango.web.dwr.beans.SnmpOidGet;
  import com.serotonin.mango.web.dwr.beans.SqlStatementTester;
  import com.serotonin.modbus4j.ModbusFactory;
  import com.serotonin.modbus4j.ModbusMaster;
  import com.serotonin.modbus4j.code.RegisterRange;
  import com.serotonin.modbus4j.exception.ErrorResponseException;
  import com.serotonin.modbus4j.exception.ModbusIdException;
  import com.serotonin.modbus4j.exception.ModbusInitException;
  import com.serotonin.modbus4j.exception.ModbusTransportException;
  import com.serotonin.modbus4j.ip.IpParameters;
  import com.serotonin.modbus4j.locator.BaseLocator;
  import com.serotonin.modbus4j.msg.ModbusRequest;
  import com.serotonin.modbus4j.msg.ReadResponse;
  import com.serotonin.modbus4j.serial.SerialPortWrapper;
  import com.serotonin.util.IpAddressUtils;
  import com.serotonin.util.StringUtils;
  import com.serotonin.viconics.RequestFailureException;
  import com.serotonin.viconics.ViconicsDevice;
  import com.serotonin.viconics.ViconicsNetwork;
  import com.serotonin.viconics.ViconicsTransportException;
  import com.serotonin.viconics.msg.NetworkIdentifyRequest;
  import com.serotonin.viconics.msg.NetworkIdentifyResponse;
  import com.serotonin.web.dwr.DwrResponseI18n;
  import com.serotonin.web.dwr.MethodFilter;
  import com.serotonin.web.i18n.LocalizableException;
  import com.serotonin.web.i18n.LocalizableMessage;
  import com.serotonin.web.taglib.DateFunctions;
  
  /**
   * @author Matthew Lohbihler
   */
  public class DataSourceEditDwr extends DataSourceListDwr {
  	private static final Log LOG = LogFactory.getLog(DataSourceEditDwr.class);
  
  	//
  	//
  	// Common methods
  	//
  	@MethodFilter
  	public DwrResponseI18n editInit() {
  		DwrResponseI18n response = new DwrResponseI18n();
  		response.addData("points", getPoints());
  		response.addData("alarms", getAlarms());
  		return response;
  	}
  
  	private DwrResponseI18n tryDataSourceSave(DataSourceVO<?> ds) {
  		DwrResponseI18n response = new DwrResponseI18n();
  
  		ds.validate(response);
  
  		if (!response.getHasMessages()) {
  			LOG.debug("Trying to save datasource " + ds.getName());
  			Common.ctx.getRuntimeManager().saveDataSource(ds);
  			response.addData("id", ds.getId());
  			LOG.debug("Response: " + response.toString());
  		}
  
  		return response;
  	}
  
  	@MethodFilter
  	public void cancelTestingUtility() {
  		Common.getUser().cancelTestingUtility();
  	}
  
  	@MethodFilter
  	public List<DataPointVO> enableAllPoints() {
  		User user = Common.getUser();
  		if (user == null)
  			return null;
  
  		DataSourceVO<?> ds = user.getEditDataSource();
  		if (ds.getId() == Common.NEW_ID)
  			return null;
  
  		List<DataPointVO> points = new DataPointDao().getDataPoints(ds.getId(),
  				DataPointNameComparator.instance);
  		for (DataPointVO dataPointVO : points) {
  			if (!dataPointVO.isEnabled()) {
  				Permissions.ensureDataSourcePermission(Common.getUser(),
  						dataPointVO.getDataSourceId());
  
  				RuntimeManager runtimeManager = Common.ctx.getRuntimeManager();
  				dataPointVO.setEnabled(true);
  				runtimeManager.saveDataPoint(dataPointVO);
  			}
  		}
  		return points;
  	}
  
  	@MethodFilter
  	public List<DataPointVO> getPoints() {
  		User user = Common.getUser();
  		if (user == null)
  			return null;
  
  		DataSourceVO<?> ds = user.getEditDataSource();
  		if (ds.getId() == Common.NEW_ID)
  			return null;
  
  		List<DataPointVO> points = new DataPointDao().getDataPoints(ds.getId(),
  				DataPointNameComparator.instance);
  		return points;
  	}
  
  	@MethodFilter
  	public DataPointVO getPoint(int pointId) {
  		return getPoint(pointId, null);
  	}
  
  	private DataPointVO getPoint(int pointId, DataPointDefaulter defaulter) {
  		DataSourceVO<?> ds = Common.getUser().getEditDataSource();
  
  		DataPointVO dp;
  		if (pointId == Common.NEW_ID) {
  			dp = new DataPointVO();
  			dp.setXid(new DataPointDao().generateUniqueXid());
  			dp.setDataSourceId(ds.getId());
  			dp.setPointLocator(ds.createPointLocator());
  			dp.setEventDetectors(new ArrayList<PointEventDetectorVO>(0));
  			if (defaulter != null)
  				defaulter.setDefaultValues(dp);
  		} else {
  			dp = new DataPointDao().getDataPoint(pointId);
  			if (dp != null && dp.getDataSourceId() != ds.getId())
  				throw new RuntimeException("Data source id mismatch");
  		}
  
  		return dp;
  	}
  
  	private DwrResponseI18n validatePoint(int id, String xid, String name,
  			PointLocatorVO locator, DataPointDefaulter defaulter) {
  		DwrResponseI18n response = new DwrResponseI18n();
  
  		DataPointVO dp = getPoint(id, defaulter);
  		dp.setXid(xid);
  		dp.setName(name);
  		dp.setPointLocator(locator);
  
  		if (StringUtils.isEmpty(xid))
  			response.addContextualMessage("xid", "validate.required");
  		else if (!new DataPointDao().isXidUnique(xid, id))
  			response.addContextualMessage("xid", "validate.xidUsed");
  		else if (StringUtils.isLengthGreaterThan(xid, 50))
  			response.addContextualMessage("xid", "validate.notLongerThan", 50);
  
  		if (StringUtils.isEmpty(name))
  			response.addContextualMessage("name", "dsEdit.validate.required");
  
  		locator.validate(response);
  
  		if (!response.getHasMessages()) {
  			Common.ctx.getRuntimeManager().saveDataPoint(dp);
  			response.addData("id", dp.getId());
  			response.addData("points", getPoints());
  		}
  
  		return response;
  	}
  
  	@MethodFilter
  	public List<DataPointVO> deletePoint(int id) {
  		DataPointVO dp = getPoint(id, null);
  		if (dp != null)
  			Common.ctx.getRuntimeManager().deleteDataPoint(dp);
  
  		return getPoints();
  	}
  
  	@MethodFilter
  	public Map<String, Object> toggleEditDataSource() {
  		DataSourceVO<?> ds = Common.getUser().getEditDataSource();
  		return super.toggleDataSource(ds.getId());
  	}
  
  	@MethodFilter
  	public DwrResponseI18n togglePoint(int dataPointId) {
  		DwrResponseI18n response = super.toggleDataPoint(dataPointId);
  		response.addData("points", getPoints());
  		return response;
  	}
  
  	@MethodFilter
  	public List<EventInstanceBean> getAlarms() {
  		DataSourceVO<?> ds = Common.getUser().getEditDataSource();
  		List<EventInstance> events = new EventDao()
  				.getPendingEventsForDataSource(ds.getId(), Common.getUser()
  						.getId());
  		List<EventInstanceBean> beans = new ArrayList<EventInstanceBean>();
  		if (events != null) {
  			for (EventInstance event : events)
  				beans.add(new EventInstanceBean(event.isActive(), event
  						.getAlarmLevel(), DateFunctions.getTime(event
  						.getActiveTimestamp()), getMessage(event.getMessage())));
  		}
  		return beans;
  	}
  
  	@MethodFilter
  	public void updateEventAlarmLevel(int eventId, int alarmLevel) {
  		DataSourceVO<?> ds = Common.getUser().getEditDataSource();
  		ds.setAlarmLevel(eventId, alarmLevel);
  	}
  
  	//
  	//
  	// Virtual stuff
  	//
  	@MethodFilter
  	public DwrResponseI18n saveVirtualDataSource(String name, String xid,
  			int updatePeriods, int updatePeriodType) {
  		VirtualDataSourceVO ds = (VirtualDataSourceVO) Common.getUser()
  				.getEditDataSource();
  
  		ds.setXid(xid);
  		ds.setName(name);
  		ds.setUpdatePeriods(updatePeriods);
  		ds.setUpdatePeriodType(updatePeriodType);
  
  		return tryDataSourceSave(ds);
  	}
  
  	@MethodFilter
  	public IntMessagePair[] getChangeTypes(int dataTypeId) {
  		return ChangeTypeVO.getChangeTypes(dataTypeId);
  	}
  
  	@MethodFilter
  	public DwrResponseI18n saveVirtualPointLocator(int id, String xid,
  			String name, VirtualPointLocatorVO locator) {
  		return validatePoint(id, xid, name, locator, null);
  	}
  
  	//
  	//
  	// Modbus common stuff
  	//
  	@MethodFilter
  	public Map<String, Object> modbusScanUpdate() {
  		Map<String, Object> result = new HashMap<String, Object>();
  		ModbusNodeScanListener scan = Common.getUser().getTestingUtility(
  				ModbusNodeScanListener.class);
  		if (scan == null)
  			return null;
  
  		result.put("nodes", scan.getNodesFound());
  		result.put("message", scan.getMessage());
  		result.put("finished", scan.isFinished());
  
  		return result;
  	}
  
  	@MethodFilter
  	public DwrResponseI18n saveModbusPointLocator(int id, String xid,
  			String name, ModbusPointLocatorVO locator) {
  		return validatePoint(id, xid, name, locator, null);
  	}
  
  	private void testModbusPointLocator(ModbusMaster modbusMaster,
  			ModbusPointLocatorVO locator, boolean serial,
  			DwrResponseI18n response) {
  		locator.validate(response);
  		if (response.getHasMessages())
  			return;
  
  		try {
  			BaseLocator<?> bl = ModbusDataSource.createModbusLocator(locator);
  			modbusMaster.init();
  			Object result = modbusMaster.getValue(bl);
  			response.addData("result", new LocalizableMessage(
  					"dsEdit.modbus.locatorTest.result", result));
  		} catch (ModbusInitException e) {
  			if (serial)
  				response.addMessage(new LocalizableMessage(
  						"dsEdit.modbus.locatorTestIp.startError", e
  								.getMessage()));
  			else
  				response.addMessage(new LocalizableMessage(
  						"dsEdit.modbus.locatorTestSerial.startError", e
  								.getMessage()));
  		} catch (ErrorResponseException e) {
  			response.addMessage(new LocalizableMessage("common.default", e
  					.getErrorResponse().getExceptionMessage()));
  		} catch (ModbusTransportException e) {
  			response.addMessage(ModbusDataSource.localExceptionMessage(e));
  		} catch (IllegalCharsetNameException e) {
  			response.addMessage(new LocalizableMessage(
  					"validate.invalidCharset"));
  		} finally {
  			modbusMaster.destroy();
  		}
  	}
  
  	private void testModbusData(ModbusMaster modbusMaster, int slaveId,
  			int range, int offset, int length, boolean serial,
  			DwrResponseI18n response) {
  		boolean binary = range == RegisterRange.COIL_STATUS
  				|| range == RegisterRange.INPUT_STATUS;
  		if (length > modbusMaster.getMaxReadCount(range))
  			length = modbusMaster.getMaxReadCount(range);
  		if (offset + length > 65536)
  			length = 65536 - offset;
  		response.addData("length", length);
  
  		try {
  			ModbusRequest mreq = new ModbusFactory().createReadRequest(slaveId,
  					range, offset, length);
  
  			modbusMaster.init();
  			ReadResponse mres = (ReadResponse) modbusMaster.send(mreq);
  			if (mres.isException())
  				response.addMessage(new LocalizableMessage("common.default",
  						mres.getExceptionMessage()));
  			else {
  				List<String> results = new ArrayList<String>();
  				if (binary) {
  					boolean[] data = mres.getBooleanData();
  					for (int i = 0; i < length; i++)
  						results.add(Integer.toString(offset + i) + " ==> "
  								+ Boolean.toString(data[i]));
  				} else {
  					short[] data = mres.getShortData();
  					for (int i = 0; i < length; i++)
  						results.add(Integer.toString(offset + i) + " ==> "
  								+ StreamUtils.toHex(data[i]));
  				}
  				response.addData("results", results);
  			}
  		} catch (ModbusIdException e) {
  			response.addMessage(ModbusDataSource.localExceptionMessage(e));
  		} catch (ModbusInitException e) {
  			if (serial)
  				response.addMessage(new LocalizableMessage(
  						"dsEdit.modbus.locatorTestIp.startError", e
  								.getMessage()));
  			else
  				response.addMessage(new LocalizableMessage(
  						"dsEdit.modbus.locatorTestSerial.startError", e
  								.getMessage()));
  		} catch (ModbusTransportException e) {
  			response.addMessage(ModbusDataSource.localExceptionMessage(e));
  		} finally {
  			modbusMaster.destroy();
  		}
  	}
  
  	//
  	//
  	// Modbus serial stuff
  	//
  	@MethodFilter
  	public DwrResponseI18n saveModbusSerialDataSource(String name, String xid,
  			int updatePeriods, int updatePeriodType, boolean quantize,
  			int timeout, int retries, boolean contiguousBatches,
  			boolean createSlaveMonitorPoints, int maxReadBitCount,
  			int maxReadRegisterCount, int maxWriteRegisterCount,
  			String commPortId, int baudRate, int flowControlIn,
  			int flowControlOut, int dataBits, int stopBits, int parity,
  			String encoding, boolean echo, int concurrency) {
  		ModbusSerialDataSourceVO ds = (ModbusSerialDataSourceVO) Common
  				.getUser().getEditDataSource();
  
  		ds.setXid(xid);
  		ds.setName(name);
  		ds.setUpdatePeriods(updatePeriods);
  		ds.setUpdatePeriodType(updatePeriodType);
  		ds.setQuantize(quantize);
  		ds.setTimeout(timeout);
  		ds.setRetries(retries);
  		ds.setContiguousBatches(contiguousBatches);
  		ds.setCreateSlaveMonitorPoints(createSlaveMonitorPoints);
  		ds.setMaxReadBitCount(maxReadBitCount);
  		ds.setMaxReadRegisterCount(maxReadRegisterCount);
  		ds.setMaxWriteRegisterCount(maxWriteRegisterCount);
  		ds.setCommPortId(commPortId);
  		ds.setBaudRate(baudRate);
  		ds.setFlowControlIn(flowControlIn);
  		ds.setFlowControlOut(flowControlOut);
  		ds.setDataBits(dataBits);
  		ds.setStopBits(stopBits);
  		ds.setParity(parity);
  		ds.setEncodingStr(encoding);
  		ds.setEcho(echo);
  		ds.setConcurrency(concurrency);
  
  		return tryDataSourceSave(ds);
  	}
  
  	@MethodFilter
  	public String modbusSerialScan(int timeout, int retries, String commPortId,
  			int baudRate, int flowControlIn, int flowControlOut, int dataBits,
  			int stopBits, int parity, String encoding, int concurrency) {
  		ModbusMaster modbusMaster;
  		try {
  			modbusMaster = createModbusSerialMaster(timeout, retries,
  					commPortId, baudRate, flowControlIn, flowControlOut,
  					dataBits, stopBits, parity, encoding, concurrency);
  		} catch (Exception e) {
  			return getMessage("dsEdit.modbus.scanError");
  		}
  		ModbusNodeScanListener scan = new ModbusNodeScanListener(
  				getResourceBundle(), modbusMaster, true);
  		Common.getUser().setTestingUtility(scan);
  		return null;
  	}
  
  	@MethodFilter
  	public DwrResponseI18n testModbusSerialLocator(int timeout, int retries,
  			String commPortId, int baudRate, int flowControlIn,
  			int flowControlOut, int dataBits, int stopBits, int parity,
  			String encoding, int concurrency, ModbusPointLocatorVO locator) {
  		DwrResponseI18n response = new DwrResponseI18n();
  		ModbusMaster modbusMaster;
  		try {
  			modbusMaster = createModbusSerialMaster(timeout, retries,
  					commPortId, baudRate, flowControlIn, flowControlOut,
  					dataBits, stopBits, parity, encoding, concurrency);
  			testModbusPointLocator(modbusMaster, locator, true, response);
  		} catch (Exception e) {
  			response.addMessage(new LocalizableMessage(
  					"dsEdit.modbus.scanError"));
  		}
  		return response;
  	}
  
  	@MethodFilter
  	public DwrResponseI18n testModbusSerialData(int timeout, int retries,
  			String commPortId, int baudRate, int flowControlIn,
  			int flowControlOut, int dataBits, int stopBits, int parity,
  			String encoding, int concurrency, int slaveId, int range,
  			int offset, int length) {
  		DwrResponseI18n response = new DwrResponseI18n();
  		ModbusMaster modbusMaster;
  		try {
  			modbusMaster = createModbusSerialMaster(timeout, retries,
  					commPortId, baudRate, flowControlIn, flowControlOut,
  					dataBits, stopBits, parity, encoding, concurrency);
  			testModbusData(modbusMaster, slaveId, range, offset, length, true,
  					response);
  		} catch (Exception e) {
  			response.addMessage(new LocalizableMessage(
  					"dsEdit.modbus.scanError"));
  		}
  		return response;
  	}
  
  	private ModbusMaster createModbusSerialMaster(int timeout, int retries,
  			String commPortId, int baudRate, int flowControlIn,
  			int flowControlOut, int dataBits, int stopBits, int parity,
  			String encoding, int concurrency) throws Exception {
  		User user = Common.getUser();
  		Permissions.ensureDataSourcePermission(user);
  
  		if (StringUtils.isEmpty(commPortId))
  			throw new Exception();
  
  		SerialParameters params = new SerialParameters();
  		params.setCommPortId(commPortId);
  		params.setPortOwnerName("Mango Modbus Serial Data Source Scan");
  		params.setBaudRate(baudRate);
  		params.setFlowControlIn(flowControlIn);
  		params.setFlowControlOut(flowControlOut);
  		params.setDataBits(dataBits);
  		params.setStopBits(stopBits);
  		params.setParity(parity);
  
  		EncodingType encodingType = EncodingType.valueOf(encoding);
  
  		ModbusMaster modbusMaster;
  		if (encodingType == EncodingType.ASCII)
  			modbusMaster = new ModbusFactory().createAsciiMaster(params);
  		else
  			modbusMaster = new ModbusFactory().createRtuMaster(params);
  		modbusMaster.setTimeout(timeout);
  		modbusMaster.setRetries(retries);
  
  		return modbusMaster;
  	}
  
  	//
  	//
  	// Modbus IP stuff
  	//
  	@MethodFilter
  	public DwrResponseI18n saveModbusIpDataSource(String name, String xid,
  			int updatePeriods, int updatePeriodType, boolean quantize,
  			int timeout, int retries, boolean contiguousBatches,
  			boolean createSlaveMonitorPoints, int maxReadBitCount,
  			int maxReadRegisterCount, int maxWriteRegisterCount,
  			String transportType, String host, int port, boolean encapsulated,
  			boolean createSocketMonitorPoint) {
  		ModbusIpDataSourceVO ds = (ModbusIpDataSourceVO) Common.getUser()
  				.getEditDataSource();
  
  		ds.setXid(xid);
  		ds.setName(name);
  		ds.setUpdatePeriods(updatePeriods);
  		ds.setUpdatePeriodType(updatePeriodType);
  		ds.setQuantize(quantize);
  		ds.setTimeout(timeout);
  		ds.setRetries(retries);
  		ds.setContiguousBatches(contiguousBatches);
  		ds.setCreateSlaveMonitorPoints(createSlaveMonitorPoints);
  		ds.setMaxReadBitCount(maxReadBitCount);
  		ds.setMaxReadRegisterCount(maxReadRegisterCount);
  		ds.setMaxWriteRegisterCount(maxWriteRegisterCount);
  		ds.setTransportTypeStr(transportType);
  		ds.setHost(host);
  		ds.setPort(port);
  		ds.setEncapsulated(encapsulated);
  		ds.setCreateSocketMonitorPoint(createSocketMonitorPoint);
  
  		return tryDataSourceSave(ds);
  	}
  
  	@MethodFilter
  	public String modbusIpScan(int timeout, int retries, String transport,
  			String host, int port, boolean encapsulated) {
  		ModbusMaster modbusMaster = createModbusIpMaster(timeout, retries,
  				transport, host, port, encapsulated);
  		ModbusNodeScanListener scan = new ModbusNodeScanListener(
  				getResourceBundle(), modbusMaster, false);
  		Common.getUser().setTestingUtility(scan);
  		return null;
  	}
  
  	@MethodFilter
  	public DwrResponseI18n testModbusIpLocator(int timeout, int retries,
  			String transport, String host, int port, boolean encapsulated,
  			ModbusPointLocatorVO locator) {
  		DwrResponseI18n response = new DwrResponseI18n();
  		ModbusMaster modbusMaster = createModbusIpMaster(timeout, retries,
  				transport, host, port, encapsulated);
  		testModbusPointLocator(modbusMaster, locator, false, response);
  		return response;
  	}
  
  	@MethodFilter
  	public DwrResponseI18n testModbusIpData(int timeout, int retries,
  			String transport, String host, int port, boolean encapsulated,
  			int slaveId, int range, int offset, int length) {
  		DwrResponseI18n response = new DwrResponseI18n();
  		ModbusMaster modbusMaster = createModbusIpMaster(timeout, retries,
  				transport, host, port, encapsulated);
  		testModbusData(modbusMaster, slaveId, range, offset, length, false,
  				response);
  		return response;
  	}
  
  	private ModbusMaster createModbusIpMaster(int timeout, int retries,
  			String transport, String host, int port, boolean encapsulated) {
  		User user = Common.getUser();
  		Permissions.ensureDataSourcePermission(user);
  
  		IpParameters params = new IpParameters();
  		params.setHost(host);
  		params.setPort(port);
  		params.setEncapsulated(encapsulated);
  
  		TransportType transportType = TransportType.valueOf(transport);
  
  		ModbusMaster modbusMaster;
  		if (transportType == TransportType.TCP_LISTENER)
  			modbusMaster = new ModbusFactory().createTcpListener(params);
  		else if (transportType == TransportType.UDP)
  			modbusMaster = new ModbusFactory().createUdpMaster(params);
  		else
  			modbusMaster = new ModbusFactory().createTcpMaster(params,
  					transportType == TransportType.TCP_KEEP_ALIVE);
  		modbusMaster.setTimeout(timeout);
  		modbusMaster.setRetries(retries);
  
  		return modbusMaster;
  	}
  
  	//
  	//
  	// SNMP stuff
  	//
  	@MethodFilter
  	public DwrResponseI18n saveSnmpDataSource(String name, String xid,
  			int updatePeriods, int updatePeriodType, String host, int port,
  			int snmpVersion, String community, String securityName,
  			String authProtocol, String authPassphrase, String privProtocol,
  			String privPassphrase, String engineId, String contextEngineId,
  			String contextName, int retries, int timeout, int trapPort,
  			String localAddress) {
  		SnmpDataSourceVO ds = (SnmpDataSourceVO) Common.getUser()
  				.getEditDataSource();
  
  		ds.setXid(xid);
  		ds.setName(name);
  		ds.setUpdatePeriods(updatePeriods);
  		ds.setUpdatePeriodType(updatePeriodType);
  		ds.setHost(host);
  		ds.setPort(port);
  		ds.setSnmpVersion(snmpVersion);
  		ds.setCommunity(community);
  		ds.setSecurityName(securityName);
  		ds.setAuthProtocol(authProtocol);
  		ds.setAuthPassphrase(authPassphrase);
  		ds.setPrivProtocol(privProtocol);
  		ds.setPrivPassphrase(privPassphrase);
  		ds.setEngineId(engineId);
  		ds.setContextEngineId(contextEngineId);
  		ds.setContextName(contextName);
  		ds.setRetries(retries);
  		ds.setTimeout(timeout);
  		ds.setTrapPort(trapPort);
  		ds.setLocalAddress(localAddress);
  
  		return tryDataSourceSave(ds);
  	}
  
  	@MethodFilter
  	public DwrResponseI18n saveSnmpPointLocator(int id, String xid,
  			String name, SnmpPointLocatorVO locator) {
  		return validatePoint(id, xid, name, locator, null);
  	}
  
  	@MethodFilter
  	public void snmpGetOid(String oid, String host, int port, int snmpVersion,
  			String community, String securityName, String authProtocol,
  			String authPassphrase, String privProtocol, String privPassphrase,
  			String engineId, String contextEngineId, String contextName,
  			int retries, int timeout) {
  		User user = Common.getUser();
  		Permissions.ensureDataSourcePermission(user);
  
  		Version version = Version.getVersion(snmpVersion, community,
  				securityName, authProtocol, authPassphrase, privProtocol,
  				privPassphrase, engineId, contextEngineId, contextName);
  		user.setTestingUtility(new SnmpOidGet(getResourceBundle(), host, port,
  				version, oid, retries, timeout));
  	}
  
  	@MethodFilter
  	public String snmpGetOidUpdate() {
  		SnmpOidGet snmpOidGet = Common.getUser().getTestingUtility(
  				SnmpOidGet.class);
  		if (snmpOidGet == null)
  			return null;
  		return snmpOidGet.getResult();
  	}
  
  	//
  	//
  	// SQL stuff
  	//
  	@MethodFilter
  	public DwrResponseI18n saveSqlDataSource(String name, String xid,
  			int updatePeriods, int updatePeriodType, String driverClassname,
  			String connectionUrl, String username, String password,
  			String selectStatement, boolean rowBasedQuery) {
  		SqlDataSourceVO ds = (SqlDataSourceVO) Common.getUser()
  				.getEditDataSource();
  
  		ds.setXid(xid);
  		ds.setName(name);
  		ds.setUpdatePeriods(updatePeriods);
  		ds.setUpdatePeriodType(updatePeriodType);
  		ds.setDriverClassname(driverClassname);
  		ds.setConnectionUrl(connectionUrl);
  		ds.setUsername(username);
  		ds.setPassword(password);
  		ds.setSelectStatement(selectStatement);
  		ds.setRowBasedQuery(rowBasedQuery);
  
  		return tryDataSourceSave(ds);
  	}
  
  	@MethodFilter
  	public DwrResponseI18n saveSqlPointLocator(int id, String xid, String name,
  			SqlPointLocatorVO locator) {
  		return validatePoint(id, xid, name, locator, null);
  	}
  
  	@MethodFilter
  	public void sqlTestStatement(String driverClassname, String connectionUrl,
  			String username, String password, String selectStatement,
  			boolean rowBasedQuery) {
  		User user = Common.getUser();
  		Permissions.ensureDataSourcePermission(user);
  		user.setTestingUtility(new SqlStatementTester(getResourceBundle(),
  				driverClassname, connectionUrl, username, password,
  				selectStatement, rowBasedQuery));
  	}
  
  	@MethodFilter
  	public Map<String, Object> sqlTestStatementUpdate() {
  		Map<String, Object> result = new HashMap<String, Object>();
  		SqlStatementTester statementTester = Common.getUser()
  				.getTestingUtility(SqlStatementTester.class);
  		if (statementTester == null)
  			return null;
  		if (!statementTester.isDone())
  			return null;
  
  		if (statementTester.getErrorMessage() != null)
  			result.put("error", statementTester.getErrorMessage());
  		else
  			result.put("resultTable", statementTester.getResultTable());
  		return result;
  	}
  
  	//
  	//
  	// HTTP receiver stuff
  	//
  	@MethodFilter
  	public DwrResponseI18n saveHttpReceiverDataSource(String name, String xid,
  			String[] ipWhiteList, String[] deviceIdWhiteList) {
  		HttpReceiverDataSourceVO ds = (HttpReceiverDataSourceVO) Common
  				.getUser().getEditDataSource();
  
  		ds.setXid(xid);
  		ds.setName(name);
  		ds.setIpWhiteList(ipWhiteList);
  		ds.setDeviceIdWhiteList(deviceIdWhiteList);
  
  		return tryDataSourceSave(ds);
  	}
  
  	@MethodFilter
  	public DwrResponseI18n saveHttpReceiverPointLocator(int id, String xid,
  			String name, HttpReceiverPointLocatorVO locator) {
  