/* * Copyright 2011-16 Fraunhofer ISE * * This file is part of OpenMUC. * For more information visit http://www.openmuc.org * * OpenMUC 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. * * OpenMUC 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 OpenMUC. If not, see <http://www.gnu.org/licenses/>. * */ package org.openmuc.framework.server.restws.servlets; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.openmuc.framework.config.ArgumentSyntaxException; import org.openmuc.framework.config.ChannelConfig; import org.openmuc.framework.config.ConfigService; import org.openmuc.framework.config.ConfigWriteException; import org.openmuc.framework.config.DeviceConfig; import org.openmuc.framework.config.DeviceScanInfo; import org.openmuc.framework.config.DriverConfig; import org.openmuc.framework.config.DriverInfo; import org.openmuc.framework.config.DriverNotAvailableException; import org.openmuc.framework.config.IdCollisionException; import org.openmuc.framework.config.RootConfig; import org.openmuc.framework.config.ScanException; import org.openmuc.framework.config.ScanInterruptedException; import org.openmuc.framework.dataaccess.Channel; import org.openmuc.framework.dataaccess.DataAccessService; import org.openmuc.framework.lib.json.Const; import org.openmuc.framework.lib.json.FromJson; import org.openmuc.framework.lib.json.ToJson; import org.openmuc.framework.lib.json.exceptions.MissingJsonObjectException; import org.openmuc.framework.lib.json.exceptions.RestConfigIsNotCorrectException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; public class DriverResourceServlet extends GenericServlet { private static final long serialVersionUID = -2223282905555493215L; private final static Logger logger = LoggerFactory.getLogger(DriverResourceServlet.class); private DataAccessService dataAccess; private ConfigService configService; private RootConfig rootConfig; private DeviceScanListenerImplementation scanListener = new DeviceScanListenerImplementation(); @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); String[] pathAndQueryString = checkIfItIsACorrectRest(request, response, logger); if (pathAndQueryString != null) { setConfigAccess(); String pathInfo = pathAndQueryString[ServletLib.PATH_ARRAY_NR]; List<String> driversList = new ArrayList<>(); Collection<DriverConfig> driverConfigList = rootConfig.getDrivers(); for (DriverConfig drv : driverConfigList) { driversList.add(drv.getId()); } ToJson json = new ToJson(); if (pathInfo.equals("/")) { json.addStringList(Const.DRIVERS, driversList); } else { String[] pathInfoArray = ServletLib.getPathInfoArray(pathInfo); String driverID = pathInfoArray[0].replace("/", ""); List<Channel> driverChannelsList; List<String> driverDevicesList = new ArrayList<>(); if (driversList.contains(driverID)) { Collection<ChannelConfig> channelConfigList = new ArrayList<>(); Collection<DeviceConfig> deviceConfigList; DriverConfig drv = rootConfig.getDriver(driverID); deviceConfigList = drv.getDevices(); setDriverDevicesListAndChannelConfigList(driverDevicesList, channelConfigList, deviceConfigList); driverChannelsList = getDriverChannelList(channelConfigList); response.setStatus(HttpServletResponse.SC_OK); boolean driverIsRunning = configService.getIdsOfRunningDrivers().contains(driverID); if (pathInfoArray.length > 1) { if (pathInfoArray[1].equalsIgnoreCase(Const.CHANNELS)) { json.addChannelList(driverChannelsList); json.addBoolean(Const.RUNNING, driverIsRunning); } else if (pathInfoArray[1].equalsIgnoreCase(Const.RUNNING)) { json.addBoolean(Const.RUNNING, driverIsRunning); } else if (pathInfoArray[1].equalsIgnoreCase(Const.INFOS)) { DriverInfo driverInfo; try { driverInfo = configService.getDriverInfo(driverID); json.addDriverInfo(driverInfo); } catch (DriverNotAvailableException e) { throw new IOException(e); } } else if (pathInfoArray[1].equalsIgnoreCase(Const.DEVICES)) { json.addStringList(Const.DEVICES, driverDevicesList); json.addBoolean(Const.RUNNING, driverIsRunning); } else if (pathInfoArray[1].equalsIgnoreCase(Const.SCAN)) { List<DeviceScanInfo> deviceScanInfoList = new ArrayList<>(); scanListener = new DeviceScanListenerImplementation(deviceScanInfoList); String settings = request.getParameter(Const.SETTINGS); deviceScanInfoList = scanForAllDrivers(driverID, settings, scanListener, response); json.addDeviceScanInfoList(deviceScanInfoList); } else if (pathInfoArray[1].equalsIgnoreCase(Const.SCAN_PROGRESS_INFO)) { json.addDeviceScanProgressInfo(scanListener.getRestScanProgressInfo()); } else if (pathInfoArray[1].equalsIgnoreCase(Const.CONFIGS) && pathInfoArray.length == 2) { doGetConfigs(json, driverID, response); } else if (pathInfoArray[1].equalsIgnoreCase(Const.CONFIGS) && pathInfoArray.length == 3) { doGetConfigField(json, driverID, pathInfoArray[2], response); } else { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest path is not available.", " Path Info = ", request.getPathInfo()); } } else if (pathInfoArray.length == 1) { json.addChannelRecordList(driverChannelsList); json.addBoolean(Const.RUNNING, driverIsRunning); } else { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest path is not available.", " Path Info = ", request.getPathInfo()); } } else { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest driver is not available.", " driverID = ", driverID); } } sendJson(json, response); } } @Override public void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); String[] pathAndQueryString = checkIfItIsACorrectRest(request, response, logger); if (pathAndQueryString != null) { setConfigAccess(); String pathInfo = pathAndQueryString[ServletLib.PATH_ARRAY_NR]; String[] pathInfoArray = ServletLib.getPathInfoArray(pathInfo); String driverID = pathInfoArray[0].replace("/", ""); String json = ServletLib.getJsonText(request); if (pathInfoArray.length < 1) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest path is not available.", " Rest Path = ", request.getPathInfo()); } else { DriverConfig driverConfig = rootConfig.getDriver(driverID); if (driverConfig != null && pathInfoArray.length == 2 && pathInfoArray[1].equalsIgnoreCase(Const.CONFIGS)) { setAndWriteDriverConfig(driverID, response, json, true); } else if (driverConfig != null && pathInfoArray.length == 2 && pathInfoArray[1].equalsIgnoreCase(Const.SCAN_INTERRUPT)) { interruptScanProcess(driverID, response, json); } else { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest path is not available.", " Rest Path = ", request.getPathInfo()); } } } } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); String[] pathAndQueryString = checkIfItIsACorrectRest(request, response, logger); if (pathAndQueryString != null) { setConfigAccess(); String pathInfo = pathAndQueryString[ServletLib.PATH_ARRAY_NR]; String[] pathInfoArray = ServletLib.getPathInfoArray(pathInfo); String driverID = pathInfoArray[0].replace("/", ""); String json = ServletLib.getJsonText(request); if (pathInfoArray.length != 1) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest path is not available.", " Rest Path = ", request.getPathInfo()); } else { try { rootConfig.addDriver(driverID); configService.setConfig(rootConfig); configService.writeConfigToFile(); setAndWriteDriverConfig(driverID, response, json, false); } catch (IdCollisionException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_CONFLICT, logger, "Driver \"" + driverID + "\" already exist"); } catch (ConfigWriteException e) { ServletLib.sendHTTPErrorAndLogErr(response, HttpServletResponse.SC_CONFLICT, logger, "Could not write driver \"", driverID, "\"."); e.printStackTrace(); } } } } @Override public void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); String[] pathAndQueryString = checkIfItIsACorrectRest(request, response, logger); if (pathAndQueryString != null) { setConfigAccess(); String pathInfo = pathAndQueryString[0]; String driverID = null; String[] pathInfoArray = ServletLib.getPathInfoArray(pathInfo); driverID = pathInfoArray[0].replace("/", ""); DriverConfig driverConfig = rootConfig.getDriver(driverID); if (pathInfoArray.length != 1) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest path is not available", " Path Info = ", request.getPathInfo()); } else if (driverConfig == null) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Driver \"" + driverID + "\" does not exist."); } else { try { driverConfig.delete(); configService.setConfig(rootConfig); configService.writeConfigToFile(); if (rootConfig.getDriver(driverID) == null) { response.setStatus(HttpServletResponse.SC_OK); } else { ServletLib.sendHTTPErrorAndLogErr(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, logger, "Not able to delete driver ", driverID); } } catch (ConfigWriteException e) { ServletLib.sendHTTPErrorAndLogErr(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, logger, "Not able to write into config."); e.printStackTrace(); } } } } private boolean setAndWriteDriverConfig(String driverID, HttpServletResponse response, String json, boolean isHTTPPut) { boolean ok = false; try { DriverConfig driverConfig = rootConfig.getDriver(driverID); if (driverConfig != null) { try { FromJson fromJson = new FromJson(json); fromJson.setDriverConfig(driverConfig, driverID); } catch (IdCollisionException e) { } configService.setConfig(rootConfig); configService.writeConfigToFile(); response.setStatus(HttpServletResponse.SC_OK); ok = true; } else { ServletLib.sendHTTPErrorAndLogErr(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, logger, "Not able to access to driver ", driverID); } } catch (JsonSyntaxException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_CONFLICT, logger, "JSON syntax is wrong."); } catch (MissingJsonObjectException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, e.getMessage()); } catch (ConfigWriteException e) { ServletLib.sendHTTPErrorAndLogErr(response, HttpServletResponse.SC_CONFLICT, logger, "Could not write driver \"", driverID, "\"."); e.printStackTrace(); } catch (RestConfigIsNotCorrectException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_ACCEPTABLE, logger, "Not correct formed driver config json.", " JSON = ", json); } catch (IllegalStateException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_CONFLICT, logger, e.getMessage()); } return ok; } private void doGetConfigs(ToJson json, String drvId, HttpServletResponse response) throws IOException { DriverConfig driverConfig = rootConfig.getDriver(drvId); if (driverConfig != null) { json.addDriverConfig(driverConfig); } else { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest driver is not available.", " driverID = ", drvId); } } private void doGetConfigField(ToJson json, String drvId, String configField, HttpServletResponse response) throws IOException { DriverConfig driverConfig = rootConfig.getDriver(drvId); if (driverConfig != null) { JsonObject jsoConfigAll = ToJson.getDriverConfigAsJsonObject(driverConfig); if (jsoConfigAll == null) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Could not find JSON object \"configs\""); } else { JsonElement jseConfigField = jsoConfigAll.get(configField); if (jseConfigField == null) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest config field is not available.", " configField = ", configField); } else { JsonObject jso = new JsonObject(); jso.add(configField, jseConfigField); json.addJsonObject(Const.CONFIGS, jso); } } } else { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest driver is not available.", " driverID = ", drvId); } } private void interruptScanProcess(String driverID, HttpServletResponse response, String json) { try { configService.interruptDeviceScan(driverID); response.setStatus(HttpServletResponse.SC_OK); } catch (UnsupportedOperationException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, logger, "Driver does not support scan interrupting.", " driverID = ", driverID); } catch (DriverNotAvailableException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest driver is not available.", " driverID = ", driverID); } } private List<DeviceScanInfo> scanForAllDrivers(String driverID, String settings, DeviceScanListenerImplementation scanListener, HttpServletResponse response) { List<DeviceScanInfo> scannedDevicesList = new ArrayList<>(); try { configService.scanForDevices(driverID, settings, scanListener); scannedDevicesList = scanListener.getScannedDevicesList(); } catch (UnsupportedOperationException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, logger, "Driver does not support scanning.", " driverID = ", driverID); } catch (DriverNotAvailableException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest driver is not available.", " driverID = ", driverID); } return scannedDevicesList; } private List<DeviceScanInfo> scanForAllDrivers(String driverID, String settings, HttpServletResponse response) { List<DeviceScanInfo> scannedDevicesList = new ArrayList<>(); try { scannedDevicesList = configService.scanForDevices(driverID, settings); } catch (UnsupportedOperationException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, logger, "Driver does not support scanning.", " driverID = ", driverID); } catch (DriverNotAvailableException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_FOUND, logger, "Requested rest driver is not available.", " driverID = ", driverID); } catch (ArgumentSyntaxException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_NOT_ACCEPTABLE, logger, "Argument syntax was wrong.", " driverID = ", driverID, " Settings = ", settings); } catch (ScanException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, logger, "Error while scan driver devices", " driverID = ", driverID, " Settings = ", settings); } catch (ScanInterruptedException e) { ServletLib.sendHTTPErrorAndLogDebug(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, logger, "Scan interrupt occured", " driverID = ", driverID, " Settings = ", settings); } return scannedDevicesList; } private List<Channel> getDriverChannelList(Collection<ChannelConfig> channelConfig) { List<Channel> driverChannels = new ArrayList<>(); for (ChannelConfig chCf : channelConfig) { driverChannels.add(dataAccess.getChannel(chCf.getId())); } return driverChannels; } private void setDriverDevicesListAndChannelConfigList(List<String> driverDevices, Collection<ChannelConfig> channelConfig, Collection<DeviceConfig> deviceConfig) { for (DeviceConfig dvCf : deviceConfig) { driverDevices.add(dvCf.getId()); channelConfig.addAll(dvCf.getChannels()); } } private void setConfigAccess() { this.dataAccess = handleDataAccessService(null); this.configService = handleConfigService(null); this.rootConfig = handleRootConfig(null); } }