From 4f496c84bc50cb2eb1e9093c6aaa2a88fe9821d0 Mon Sep 17 00:00:00 2001 From: Predix Robot Date: Tue, 22 Aug 2017 15:22:16 -0700 Subject: [PATCH] Release 1.0.2 --- OSS_NOTICE_kit_service_V1.0.pdf | Bin 0 -> 184223 bytes config/application-template.properties | 50 ++++ config/application.properties | 41 +-- config/kit-service-tinfoil-swagger.json | 12 + manifest.yml | 1 + manifest.yml.template | 5 + pom.xml | 17 +- .../solsvc/kitservice/boot/Application.java | 3 + .../kitservice/boot/AuthenticationFilter.java | 7 +- .../solsvc/kitservice/boot/EventError.java | 6 + .../kitservice/boot/utils/CSVWriter.java | 178 +++++++++++++ .../kitservice/boot/utils/FdhUtils.java | 53 +++- .../kitservice/controller/KitController.java | 188 +++++++++++--- .../error/DeviceRegistrationError.java | 1 - .../kitservice/manager/DeviceManager.java | 235 ++++++++++++++---- .../manager/GroupManagementService.java | 190 +++++++------- .../model/{KitGroup.java => DeviceGroup.java} | 17 +- .../solsvc/kitservice/model/GeoLocation.java | 69 +++++ .../kitservice/model/RegisterDevice.java | 116 +++++++-- .../solsvc/kitservice/model/UserGroup.java | 20 +- .../validator/RegisterDeviceValidation.java | 17 +- .../META-INF/application-security.xml | 2 +- src/main/resources/application.properties | 7 +- .../service/AbstractBaseControllerIT.java | 4 +- .../solsvc/service/KitControllerIT.java | 223 +++++++++++------ 25 files changed, 1133 insertions(+), 329 deletions(-) create mode 100644 OSS_NOTICE_kit_service_V1.0.pdf create mode 100644 config/application-template.properties create mode 100644 src/main/java/com/ge/predix/solsvc/kitservice/boot/utils/CSVWriter.java rename src/main/java/com/ge/predix/solsvc/kitservice/model/{KitGroup.java => DeviceGroup.java} (80%) create mode 100644 src/main/java/com/ge/predix/solsvc/kitservice/model/GeoLocation.java diff --git a/OSS_NOTICE_kit_service_V1.0.pdf b/OSS_NOTICE_kit_service_V1.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5930c871740604dbad8a255c0ee8487d959d79e5 GIT binary patch literal 184223 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 Mil1LmONr`#01-I|_y7O^ literal 0 HcmV?d00001 diff --git a/config/application-template.properties b/config/application-template.properties new file mode 100644 index 0000000..9e81b94 --- /dev/null +++ b/config/application-template.properties @@ -0,0 +1,50 @@ +#properties for running locally or for unit tests +logging.level.root=INFO +logging.level.org.springframework=INFO +logging.level.org.springframework.security=INFO +logging.level.com.ge.predix.solsvc.kitservice=DEBUG +#/config/application.properties are local ovverrides to src/main/resources(aka classpath)/application.properties +server.port=9092 + +spring.profiles.active=local,asset + +#if you are behind a corporate proxy/firewall and want to access Predix Cloud +#predix.oauth.proxyHost =put.your.proxyHost.here +#predix.oauth.proxyPort=put.your.proxyPort.here + +#OAuth - please see predix-rest-client src/main/java/com/ge/predix/solsvc/restclient/config/OauthRestConfig.java for more info on oauth properties +predix.oauth.issuerId.url=put.your.uaa.issuerId.here +#you may put client:secret as unencoded cleartext by setting predix.oauth.clientIdEncode=true +predix.oauth.clientId=you.should.base64encode(put.your.clientId:put.your.clientSecret separated by a colon) +#for debugging purposes, set to a high value +predix.rest.defaultSocketTimeout=500000 + +springfox.documentation.swagger.v2.path=/ +java.docs.url=https://predixdev.github.io/kit-service +accessTokenEndpointUrl=${predix.oauth.issuerId.url} + +#asset - get from VCAP env vars by binding an application to your asset instance e.g. cf bind-service +#asset - see asset-bootstrap - src/main/java/com/ge/predix/solsvc/bootstrap/ams/common/AssetRestConfig.java for more info on asset properties +predix.asset.restHost=put.your.Asset.service.instance.host.here +predix.asset.zoneid=put.your.Asset.service.instance.zoneId.here + +#timeseries - get from VCAP env vars by binding an application to your timeseries instance e.g. cf bind-service +#timeseries - see timeseries-bootstrap - src/main/java/com/ge/predix/solsvc/timeseries/bootstrap/config/TimeseriesRestConfig.java for more info on timeseries properties +predix.timeseries.queryUrl=https://put.your.timeseries.service.instance.name.query.url.here/v1/datapoints +predix.timeseries.zoneid=put.your.TS.service.instance.zoneId.here +predix.timeseries.websocket.uri=wss://put.your.timeseries.ingest.uri.here/v1/stream/messages +#websocket for timeseries - get from VCAP env vars by binding an application to your timeseries instance e.g. cf bind-service +#websocket for timeseries - see websocket-client - src/main/java/com/ge/predix/solsvc/websocket/config/IWebSocketConfig.java for more info on websocket properties +predix.timeseries.websocket.pool.maxIdle=5 +predix.timeseries.websocket.pool.maxActive=5 +predix.timeseries.websocket.pool.maxWait=8000 + +#endpoints.beans.enabled=true +#endpoints.info.enabled=true + +register.device.deactivation=60 + +kit.webapp.url=https://put.your.kit-cloud-webapp-link +kit.device.credentials=you.should.device.clientid.base64encode(put.your.clientId:put.your.clientSecret separated by a colon) +kit.device.artifactory.url=https://your.artifactory.username:your.artifactory.ApiKey@artifactory.predix.io/artifactory/PREDIX-EXT/predix-kit-rpm/ + diff --git a/config/application.properties b/config/application.properties index 720fd86..9e81b94 100644 --- a/config/application.properties +++ b/config/application.properties @@ -8,11 +8,14 @@ server.port=9092 spring.profiles.active=local,asset -predix.oauth.proxyHost=sjc1intproxy01.crd.ge.com -predix.oauth.proxyPort=8080 - -predix.oauth.issuerId.url=https://92c10ab6-9ed3-4daf-a1b7-b71207885eb1.predix-uaa-training.run.aws-usw02-pr.ice.predix.io/oauth/token -predix.oauth.clientId=app_client_id:secret +#if you are behind a corporate proxy/firewall and want to access Predix Cloud +#predix.oauth.proxyHost =put.your.proxyHost.here +#predix.oauth.proxyPort=put.your.proxyPort.here + +#OAuth - please see predix-rest-client src/main/java/com/ge/predix/solsvc/restclient/config/OauthRestConfig.java for more info on oauth properties +predix.oauth.issuerId.url=put.your.uaa.issuerId.here +#you may put client:secret as unencoded cleartext by setting predix.oauth.clientIdEncode=true +predix.oauth.clientId=you.should.base64encode(put.your.clientId:put.your.clientSecret separated by a colon) #for debugging purposes, set to a high value predix.rest.defaultSocketTimeout=500000 @@ -20,22 +23,28 @@ springfox.documentation.swagger.v2.path=/ java.docs.url=https://predixdev.github.io/kit-service accessTokenEndpointUrl=${predix.oauth.issuerId.url} -predix.asset.restHost=predix-asset.run.aws-usw02-pr.ice.predix.io -predix.asset.zoneid=67e1d772-4ed8-4ae7-bf26-1b4351f64cd0 - -#timeseries details -predix.timeseries.queryUrl=https://time-series-store-predix.run.aws-usw02-pr.ice.predix.io/v1/datapoints -predix.timeseries.zoneid=743e1d4a-e546-4e77-a22c-f775ecf85288 -predix.timeseries.websocket.uri=wss://gateway-predix-data-services.run.aws-usw02-pr.ice.predix.io/v1/stream/messages +#asset - get from VCAP env vars by binding an application to your asset instance e.g. cf bind-service +#asset - see asset-bootstrap - src/main/java/com/ge/predix/solsvc/bootstrap/ams/common/AssetRestConfig.java for more info on asset properties +predix.asset.restHost=put.your.Asset.service.instance.host.here +predix.asset.zoneid=put.your.Asset.service.instance.zoneId.here + +#timeseries - get from VCAP env vars by binding an application to your timeseries instance e.g. cf bind-service +#timeseries - see timeseries-bootstrap - src/main/java/com/ge/predix/solsvc/timeseries/bootstrap/config/TimeseriesRestConfig.java for more info on timeseries properties +predix.timeseries.queryUrl=https://put.your.timeseries.service.instance.name.query.url.here/v1/datapoints +predix.timeseries.zoneid=put.your.TS.service.instance.zoneId.here +predix.timeseries.websocket.uri=wss://put.your.timeseries.ingest.uri.here/v1/stream/messages +#websocket for timeseries - get from VCAP env vars by binding an application to your timeseries instance e.g. cf bind-service +#websocket for timeseries - see websocket-client - src/main/java/com/ge/predix/solsvc/websocket/config/IWebSocketConfig.java for more info on websocket properties predix.timeseries.websocket.pool.maxIdle=5 predix.timeseries.websocket.pool.maxActive=5 predix.timeseries.websocket.pool.maxWait=8000 -endpoints.beans.enabled=true -endpoints.info.enabled=true +#endpoints.beans.enabled=true +#endpoints.info.enabled=true register.device.deactivation=60 -kit.webapp.url=https://kit-cloud-poc.run.aws-usw02-pr.ice.predix.io -kit.device.credentials=ZGV2aWNlX2NsaWVudF9pZDpzZWNyZXQ= +kit.webapp.url=https://put.your.kit-cloud-webapp-link +kit.device.credentials=you.should.device.clientid.base64encode(put.your.clientId:put.your.clientSecret separated by a colon) +kit.device.artifactory.url=https://your.artifactory.username:your.artifactory.ApiKey@artifactory.predix.io/artifactory/PREDIX-EXT/predix-kit-rpm/ diff --git a/config/kit-service-tinfoil-swagger.json b/config/kit-service-tinfoil-swagger.json index 7d48963..cf3ddbe 100644 --- a/config/kit-service-tinfoil-swagger.json +++ b/config/kit-service-tinfoil-swagger.json @@ -39,6 +39,9 @@ } } }, + "400": { + "description": "Bad Request" + }, "401": { "description": "Unauthorized" }, @@ -83,6 +86,9 @@ "201": { "description": "Created" }, + "400": { + "description": "Bad Request" + }, "401": { "description": "Unauthorized" }, @@ -122,6 +128,9 @@ "type": "object" } }, + "400": { + "description": "Bad Request" + }, "401": { "description": "Unauthorized" }, @@ -170,6 +179,9 @@ "201": { "description": "Created" }, + "400": { + "description": "Bad Request" + }, "401": { "description": "Unauthorized" }, diff --git a/manifest.yml b/manifest.yml index 808f4c4..3d793cf 100644 --- a/manifest.yml +++ b/manifest.yml @@ -24,3 +24,4 @@ env: logging_level_root: INFO logging_level_org_springframework: INFO logging_level_com_ge_predix_solsvc: DEBUG + diff --git a/manifest.yml.template b/manifest.yml.template index 677e3fe..3d793cf 100644 --- a/manifest.yml.template +++ b/manifest.yml.template @@ -20,3 +20,8 @@ env: KIT_CLOUD_APP_URL : {kitCloudUrl} JAVA_DOCS_URL : https://predixdev.github.io/kit-service kit_device_credentials : {deviceEncodedClient} + #logging - see application-cloud.properties + logging_level_root: INFO + logging_level_org_springframework: INFO + logging_level_com_ge_predix_solsvc: DEBUG + diff --git a/pom.xml b/pom.xml index e0c4a50..8b5519c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.ge.predix.solsvc kit-service - 1.0.1 + 1.0.2 org.springframework.boot @@ -116,7 +116,11 @@ groovy ${groovy.version} - + + org.apache.commons + commons-csv + 1.0 + joda-time @@ -135,6 +139,15 @@ springfox-swagger-ui ${springfox.version} + + org.apache.ant + ant + 1.9.3 + + + org.apache.activemq + activemq-client + diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/boot/Application.java b/src/main/java/com/ge/predix/solsvc/kitservice/boot/Application.java index 557fe2d..f56cefe 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/boot/Application.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/boot/Application.java @@ -74,6 +74,9 @@ public class Application @SuppressWarnings("unused") private static ApplicationContext context; + /** + * + */ static String[] profiles ; @SuppressWarnings("javadoc") diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/boot/AuthenticationFilter.java b/src/main/java/com/ge/predix/solsvc/kitservice/boot/AuthenticationFilter.java index 99e0f45..208a03c 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/boot/AuthenticationFilter.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/boot/AuthenticationFilter.java @@ -25,7 +25,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.collections.CollectionUtils; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.jwt.Jwt; import org.springframework.security.jwt.JwtHelper; @@ -127,15 +126,17 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) } } + request.setAttribute("userToken", accessToken); //$NON-NLS-1$ + request.setAttribute("isAdmin", foundScope); //$NON-NLS-1$ - if ( !foundScope ) + /* if ( !foundScope ) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); throw new InsufficientAuthenticationException( "Authorization header does not have the required scope to access the resource"); //$NON-NLS-1$ - } + }*/ // setting security Context chain.doFilter(req, res); diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/boot/EventError.java b/src/main/java/com/ge/predix/solsvc/kitservice/boot/EventError.java index 2e9c6ea..b6d84ac 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/boot/EventError.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/boot/EventError.java @@ -39,6 +39,11 @@ public class EventError * timeStamp */ String timeStamp; + + /** + * code + */ + String code; /** * @param status @@ -51,6 +56,7 @@ public EventError(int status, Map errorAttributes) this.status = status; this.error = (String) errorAttributes.get("error"); //$NON-NLS-1$ this.message = (String) errorAttributes.get("message"); //$NON-NLS-1$ + this.code = (String) errorAttributes.get("code"); //$NON-NLS-1$ if(! StringUtils.isEmpty(errorAttributes.get("timestamp"))) {//$NON-NLS-1$ this.timeStamp = errorAttributes.get("timestamp").toString(); //$NON-NLS-1$ } diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/boot/utils/CSVWriter.java b/src/main/java/com/ge/predix/solsvc/kitservice/boot/utils/CSVWriter.java new file mode 100644 index 0000000..ee9823f --- /dev/null +++ b/src/main/java/com/ge/predix/solsvc/kitservice/boot/utils/CSVWriter.java @@ -0,0 +1,178 @@ +package com.ge.predix.solsvc.kitservice.boot.utils; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import javax.annotation.PostConstruct; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import com.ge.predix.entity.asset.AssetTag; +import com.ge.predix.solsvc.kitservice.model.RegisterDevice; + +/** + * + * @author 212546387 - + */ +@Component +public class CSVWriter { + + //Delimiter used in CSV file + private String NEW_LINE_SEPARATOR = "\n"; //$NON-NLS-1$ + + @Value("${kit.device.export.asset.properties}") + private String assetProperties; + + @Value("${kit.device.export.assettag.properties}") + private String assetTagProperties; + + @Value("${kit.device.export.assettag.timeseriesdatasource.properties}") + private String assetTagTimeSeriesDataSourceProperties; + + + private Object [] FILE_HEADER_ASSET = {"uri", //$NON-NLS-1$ + "userGroup", //$NON-NLS-1$ + "latitude", //$NON-NLS-1$ + "longitude", //$NON-NLS-1$ + "updateDate", //$NON-NLS-1$ + "expirationDate", //$NON-NLS-1$ + "deviceType", //$NON-NLS-1$ + "deviceName", //$NON-NLS-1$ + "deviceGroup", //$NON-NLS-1$ + "deviceAddress", //$NON-NLS-1$ + "createdDate", //$NON-NLS-1$ + "activationDate"}; //$NON-NLS-1$ + private Object [] FILE_HEADER_TAG = {"deviceURI", //$NON-NLS-1$ + "tagUri", //$NON-NLS-1$ + "label", //$NON-NLS-1$ + "isKpi", //$NON-NLS-1$ + "unit", //$NON-NLS-1$ + "hiQualityThreshold", //$NON-NLS-1$ + "hiAlarmThreshold", //$NON-NLS-1$ + "loAlarmThreshold", //$NON-NLS-1$ + "loQualityThreshold", //$NON-NLS-1$ + "lastCalibrated", //$NON-NLS-1$ + "locationUUID", //$NON-NLS-1$ + "alertStatusUri"}; //$NON-NLS-1$ + + /** + * - + */ + @PostConstruct + public void activate() { + this.FILE_HEADER_ASSET = this.assetProperties.replaceAll(", ", ",").split(","); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + this.FILE_HEADER_TAG = this.assetTagProperties.replaceAll(", ", ",").split(","); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + /** + * @param devices - + * @return - + * @throws IOException - + */ + public String getAssetCSV(List devices) { + + SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a"); //$NON-NLS-1$ + StringWriter deviceWriter = new StringWriter(); + CSVFormat csvFileFormatDevice = CSVFormat.DEFAULT.withRecordSeparator(this.NEW_LINE_SEPARATOR); + try (CSVPrinter assetPrinter = new CSVPrinter(deviceWriter,csvFileFormatDevice);){ + assetPrinter.printRecord(this.FILE_HEADER_ASSET); + for (RegisterDevice device:devices) { + List record = new ArrayList(); + for (Object key:this.FILE_HEADER_ASSET) { + if ("latitude".equals(key.toString()) || "longitude".equals(key.toString()) || PropertyUtils.isReadable(device, key.toString())) { //$NON-NLS-1$ //$NON-NLS-2$ + try { + switch(key.toString()) { + case "updateDate" : //$NON-NLS-1$ + case "expirationDate" : //$NON-NLS-1$ + case "createdDate" : //$NON-NLS-1$ + case "activationDate" : //$NON-NLS-1$ + record.add(sdf.format(new Date(Long.valueOf(PropertyUtils.getProperty(device, key.toString()).toString())))); + break; + case "latitude": //$NON-NLS-1$ + record.add(device.getGeoLocation().getLatitude()); + break; + case "longitude": //$NON-NLS-1$ + record.add(device.getGeoLocation().getLongitude()); + break; + default: + record.add(PropertyUtils.getProperty(device, key.toString()).toString()); + } + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException("Exception when reading Device",e); //$NON-NLS-1$ + } + } + } + assetPrinter.printRecord(record); + + } + } catch (IOException e) { + throw new RuntimeException("Exception when creating csv file for Device ",e); //$NON-NLS-1$ + } + + + StringWriter tagWriter = new StringWriter(); + CSVFormat csvFileFormatTag = CSVFormat.DEFAULT.withRecordSeparator(this.NEW_LINE_SEPARATOR); + try (CSVPrinter tagPrinter = new CSVPrinter(tagWriter,csvFileFormatTag);){ + tagPrinter.printRecord(this.FILE_HEADER_TAG); + for (RegisterDevice device:devices) { + for (AssetTag tag:device.getTags()) { + List record = new ArrayList(); + record.add(device.getUri()); + for (Object key:this.FILE_HEADER_TAG) { + if ("tag".equals(key.toString()) || PropertyUtils.isReadable(tag, key.toString())) { //$NON-NLS-1$ + try { + switch(key.toString()) { + case "tag" : //$NON-NLS-1$ + record.add(tag.getTimeseriesDatasource().getTag()); + break; + default: + Object value = PropertyUtils.getProperty(tag, key.toString()); + if (value != null) { + record.add(value.toString()); + }else{ + record.add(""); //$NON-NLS-1$ + } + } + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException("Exception when reading AssetTag",e); //$NON-NLS-1$ + } + } + } + tagPrinter.printRecord(record); + } + } + } catch (IOException e) { + throw new RuntimeException("Exception when creating csv file for Asset Tags",e); //$NON-NLS-1$ + } + + + String zipFileName = "AssetModel.zip"; //$NON-NLS-1$ + try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFileName));){ + + zos.putNextEntry(new ZipEntry("Asset.csv")); //$NON-NLS-1$ + byte[] data = deviceWriter.toString().getBytes(); + zos.write(data, 0, data.length); + zos.closeEntry(); + + zos.putNextEntry(new ZipEntry("AssetTag.csv")); //$NON-NLS-1$ + data = tagWriter.toString().getBytes(); + zos.write(data, 0, data.length); + zos.closeEntry(); + + } catch (IOException e) { + throw new RuntimeException("Exception when creating Zip file",e); //$NON-NLS-1$ + } + return "AssetModel.zip"; //$NON-NLS-1$ + } +} diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/boot/utils/FdhUtils.java b/src/main/java/com/ge/predix/solsvc/kitservice/boot/utils/FdhUtils.java index 6f5a189..920390d 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/boot/utils/FdhUtils.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/boot/utils/FdhUtils.java @@ -10,6 +10,9 @@ package com.ge.predix.solsvc.kitservice.boot.utils; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + import org.apache.commons.lang3.StringUtils; import com.ge.predix.entity.assetfilter.AssetFilter; @@ -87,9 +90,10 @@ private static PutFieldDataCriteria getFieldCriteria(String dataString) * @param userId - * @param deviceAddress - * @return - + * @throws UnsupportedEncodingException - */ public static GetFieldDataRequest createGetUserDeviceRequest(String filterFieldValue, String expectedDataType, String userId, - String deviceAddress) + String deviceAddress) throws UnsupportedEncodingException { GetFieldDataRequest getFieldDataRequest = new GetFieldDataRequest(); @@ -110,9 +114,11 @@ public static GetFieldDataRequest createGetUserDeviceRequest(String filterFieldV assetFilter.setFilterString("deviceAddress="+deviceAddress); //$NON-NLS-1$ } else if(StringUtils.isEmpty(deviceAddress)) { - assetFilter.setFilterString("userId="+userId); //$NON-NLS-1$ + String encodedUrl = URLEncoder.encode("uaaUsers="+userId+"> getDevices(HttpServletRequest request,@SuppressWarnings({ - "javadoc", "unused" + @SuppressWarnings({ "unused", "resource" }) + @RequestMapping(value = "/device", method = RequestMethod.GET, + produces={MediaType.APPLICATION_JSON_VALUE,MediaType.APPLICATION_XHTML_XML_VALUE} + ) + public ResponseEntity getDevices(HttpServletRequest request,@SuppressWarnings({ + "javadoc" }) @RequestHeader("Authorization") String authorization) { + List devices = null; String userId = getUserId(request); - List devices = this.getDeviceManager().getDevices(userId); + Boolean isAdmin = (Boolean) request.getAttribute("isAdmin"); //$NON-NLS-1$ + + if(isAdmin) { + devices = this.getDeviceManager().getAllAdminDevices(); + }else { + devices = this.getDeviceManager().getDevices(userId); + } + String contentType = request.getHeader("Content-Type"); //$NON-NLS-1$ + + if (contentType != null && MediaType.APPLICATION_OCTET_STREAM_VALUE.equals(contentType)) { + String fileName = this.csvWriter.getAssetCSV(devices); + File file = new File(fileName); + InputStreamResource resource; + try { + resource = new InputStreamResource(new FileInputStream(file)); + return ResponseEntity.ok() + .contentLength(file.length()) + .contentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM_VALUE)) + .header("content-disposition", "attachment;filename="+fileName) //$NON-NLS-1$ //$NON-NLS-2$ + .body(resource); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } return new ResponseEntity>(devices, HttpStatus.OK); } @@ -89,13 +125,13 @@ public ResponseEntity> getDevices(HttpServletRequest reques * @return - */ @SuppressWarnings("unused") - @RequestMapping(value = "/device/register", method = RequestMethod.POST) + @RequestMapping(value = "/device/register", method = RequestMethod.POST) public ResponseEntity registerDevice(@RequestBody RegisterDevice device, HttpServletRequest request, BindingResult result,@SuppressWarnings("javadoc") @RequestHeader("Authorization") String authorization) { String userId = getUserId(request); log.info("Calling registerKit for user " + userId); //$NON-NLS-1$ - device.setUserId(userId); + // validation RegisterDeviceValidation validation = new RegisterDeviceValidation(); @@ -106,25 +142,37 @@ public ResponseEntity registerDevice(@RequestBody RegisterDevice device, Http return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); } // continue to register device - RegisterDevice originalDevice = this.getDeviceManager().getDevice("device", userId, device.getDeviceAddress());//$NON-NLS-1$ + // RegisterDevice originalDevice = this.getDeviceManager().getDevice("device", userId, device.getDeviceAddress());//$NON-NLS-1$ + // removing the user check adding check per deviceIdentifer + RegisterDevice originalDevice = this.getDeviceManager().getDevice("device", null, device.getDeviceAddress());//$NON-NLS-1$ try { if ( originalDevice == null ) { // device not found. register it. log.info("Registrating device with address " + device.getDeviceAddress()); //$NON-NLS-1$ - this.getDeviceManager().registerDevice(device); + this.getDeviceManager().registerDevice(device,userId); } else { - device = originalDevice; - // check device expiry - this.getDeviceManager().checkDeviceExpiry(originalDevice); + log.info("This is a registered device with address " + device.getDeviceAddress()); //$NON-NLS-1$ + // this try-catch to check expire + try { + // check device expire + this.getDeviceManager().checkDeviceExpiry(originalDevice); + } + catch (DeviceRegistrationError e) + { + List errors = setErrors(e, HttpStatus.BAD_REQUEST.value(),DEVICE_EXPIRY_ERROR); + return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); + } + this.getDeviceManager().updateDevice(device, originalDevice,userId); + } } catch (DeviceRegistrationError e) { - List errors = setErrors(e, HttpStatus.BAD_REQUEST.value()); + List errors = setErrors(e, HttpStatus.BAD_REQUEST.value(),DEVICE_REGISTRATION_ERROR); return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); } // setting config @@ -172,7 +220,7 @@ private List setObjectErrors(List errors, int status) { Map errorAttributes = new HashMap(); errorAttributes.put("error", error.getObjectName()); //$NON-NLS-1$ - errorAttributes.put("message", error.getDefaultMessage());//$NON-NLS-1$ //$NON-NLS-2$ + errorAttributes.put("message", error.getDefaultMessage());//$NON-NLS-1$ EventError eventError = new EventError(status, errorAttributes); eventErrors.add(eventError); @@ -200,7 +248,7 @@ public ResponseEntity updateRegisterDevice(@PathVariable String deviceId,@Req log.info("Calling registerKit for user " + userId); //$NON-NLS-1$ List errors = new ArrayList(); - if(!RegisterDeviceValidation.validate(deviceId, Pattern.compile(RegisterDeviceValidation.DEVICE_NAME_PATTERN))) { //$NON-NLS-1$ + if(!RegisterDeviceValidation.validate(deviceId, Pattern.compile(RegisterDeviceValidation.DEVICE_NAME_PATTERN))) { ObjectError error = new ObjectError("deviceId", "Device id should match ^[A-Za-z0-9-]*"); //$NON-NLS-1$//$NON-NLS-2$ errors.add(error); } @@ -215,7 +263,7 @@ public ResponseEntity updateRegisterDevice(@PathVariable String deviceId,@Req List eventErrors = setObjectErrors(errors, HttpStatus.BAD_REQUEST.value()); return new ResponseEntity<>(eventErrors, HttpStatus.BAD_REQUEST); } - device.setUserId(userId); + device.setDeviceAddress(deviceId); @@ -240,12 +288,12 @@ public ResponseEntity updateRegisterDevice(@PathVariable String deviceId,@Req } try { - this.getDeviceManager().updateDevice(device, originalDevice); + this.getDeviceManager().updateDevice(device, originalDevice,userId); } catch (DeviceRegistrationError e) { - List eventErrors = setErrors(e, HttpStatus.BAD_REQUEST.value()); + List eventErrors = setErrors(e, HttpStatus.BAD_REQUEST.value(),DEVICE_REGISTRATION_ERROR); return new ResponseEntity<>(eventErrors, HttpStatus.BAD_REQUEST); } return this.getDevice(deviceId, request, authorization); @@ -257,13 +305,15 @@ public ResponseEntity updateRegisterDevice(@PathVariable String deviceId,@Req * @param badRequest * @return - */ - private List setErrors(DeviceRegistrationError e, int status) + @SuppressWarnings("unused") + private List setErrors(DeviceRegistrationError e, int status , int errorCode) { List eventErrors = new ArrayList(); Map errorAttributes = new HashMap(); errorAttributes.put("error", e.getMessage()); //$NON-NLS-1$ errorAttributes.put("message", e.getMessage());//$NON-NLS-1$ - EventError eventError = new EventError(status, errorAttributes); + errorAttributes.put("code",String.valueOf(errorCode));//$NON-NLS-1$ + EventError eventError = new EventError(errorCode, errorAttributes); eventErrors.add(eventError); return eventErrors; @@ -297,14 +347,15 @@ private String getUserId(HttpServletRequest request) * @param echo - * @return - */ - @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET) + @SuppressWarnings("resource") + @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET) public ResponseEntity getDevice(@PathVariable String deviceId, HttpServletRequest request, @RequestHeader("Authorization") String authorization) { String userId = getUserId(request); List errors = new ArrayList(); - if(!RegisterDeviceValidation.validate(deviceId, Pattern.compile(RegisterDeviceValidation.DEVICE_NAME_PATTERN))) { //$NON-NLS-1$ + if(!RegisterDeviceValidation.validate(deviceId, Pattern.compile(RegisterDeviceValidation.DEVICE_NAME_PATTERN))) { ObjectError error = new ObjectError("deviceId", "Device id should match ^[A-Za-z0-9-]*"); //$NON-NLS-1$//$NON-NLS-2$ errors.add(error); } @@ -334,11 +385,90 @@ public ResponseEntity getDevice(@PathVariable String deviceId, HttpServletReq } catch (DeviceRegistrationError e) { - List eventErrors = setErrors(e, HttpStatus.BAD_REQUEST.value()); + List eventErrors = setErrors(e, HttpStatus.BAD_REQUEST.value(),DEVICE_EXPIRY_ERROR); return new ResponseEntity<>(eventErrors, HttpStatus.BAD_REQUEST); } - device.setDeviceConfig(this.getDeviceManager().getDeviceConfig()); - return new ResponseEntity(device, HttpStatus.OK); + String contentType = request.getHeader("Content-Type"); //$NON-NLS-1$ + if (contentType == null + || (!MediaType.APPLICATION_OCTET_STREAM_VALUE.equals(contentType) + && !MediaType.APPLICATION_ATOM_XML_VALUE.equals(contentType))) { + device.setDeviceConfig(this.getDeviceManager().getDeviceConfig()); + } + + if (contentType != null && MediaType.APPLICATION_OCTET_STREAM_VALUE.equals(contentType)) { + List devices = new ArrayList(); + devices.add(device); + String fileName = this.csvWriter.getAssetCSV(devices); + File file = new File(fileName); + InputStreamResource resource; + try { + resource = new InputStreamResource(new FileInputStream(file)); + return ResponseEntity.ok() + .contentLength(file.length()) + .contentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM_VALUE)) + .header("content-disposition", "attachment;filename="+fileName) //$NON-NLS-1$ //$NON-NLS-2$ + .body(resource); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }finally { + file.delete(); + } + return null; + } + return new ResponseEntity(device, HttpStatus.OK); + } + + + /** + * This method resets the Device settings. + * @param deviceId - + * @param device - + * @param request - + * @param result - + * @param authorization - + * @return - + */ + @RequestMapping(value = "/device/reset/{deviceId}", method = RequestMethod.PUT) + public ResponseEntity resetRegisterDevice(@PathVariable String deviceId, HttpServletRequest request, + @RequestHeader("Authorization") String authorization) + { + String userId = getUserId(request); + + List errors = new ArrayList(); + if(!RegisterDeviceValidation.validate(deviceId, Pattern.compile(RegisterDeviceValidation.DEVICE_NAME_PATTERN))) { + ObjectError error = new ObjectError("deviceId", "Device id should match ^[A-Za-z0-9-]*"); //$NON-NLS-1$//$NON-NLS-2$ + errors.add(error); + } + + if( RegisterDeviceValidation.DEVICE_ADDRESS_LENGTH <= deviceId.length()){ + ObjectError error = new ObjectError("deviceId", "DeviceId is limited to max 75"); //$NON-NLS-1$//$NON-NLS-2$ + errors.add(error); + } + + if ( CollectionUtils.isNotEmpty(errors)) + { + List eventErrors = setObjectErrors(errors, HttpStatus.BAD_REQUEST.value()); + return new ResponseEntity<>(eventErrors, HttpStatus.BAD_REQUEST); + } + // continue with get + + RegisterDevice device = this.getDeviceManager().getDevice(deviceId, userId); + + // check device activation + try + { + Boolean isAdmin = (Boolean) request.getAttribute("isAdmin"); //$NON-NLS-1$ + this.getDeviceManager().resetDevice(device,isAdmin,userId); + } + catch (DeviceRegistrationError e) + { + List eventErrors = setErrors(e, HttpStatus.BAD_REQUEST.value(),DEVICE_RESET_ERROR); + return new ResponseEntity<>(eventErrors, HttpStatus.BAD_REQUEST); + } + + return new ResponseEntity<>(null, HttpStatus.OK); + } diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/error/DeviceRegistrationError.java b/src/main/java/com/ge/predix/solsvc/kitservice/error/DeviceRegistrationError.java index 6bd815a..6124ea0 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/error/DeviceRegistrationError.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/error/DeviceRegistrationError.java @@ -41,7 +41,6 @@ public DeviceRegistrationError(String message, Throwable cause, boolean enableSu boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); - // TODO Auto-generated constructor stub } /** diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/manager/DeviceManager.java b/src/main/java/com/ge/predix/solsvc/kitservice/manager/DeviceManager.java index 1d58cb8..6c9190b 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/manager/DeviceManager.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/manager/DeviceManager.java @@ -12,19 +12,20 @@ import java.io.File; import java.io.IOException; -import java.nio.charset.Charset; +import java.io.UnsupportedEncodingException; import java.time.Instant; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.text.StrSubstitutor; +import org.apache.commons.lang.time.DateUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; @@ -51,6 +52,7 @@ import com.ge.predix.solsvc.fdh.handler.PutDataHandler; import com.ge.predix.solsvc.kitservice.boot.utils.FdhUtils; import com.ge.predix.solsvc.kitservice.error.DeviceRegistrationError; +import com.ge.predix.solsvc.kitservice.model.DeviceGroup; import com.ge.predix.solsvc.kitservice.model.RegisterDevice; import com.ge.predix.solsvc.kitservice.model.UserGroup; import com.ge.predix.solsvc.restclient.config.IOauthRestConfig; @@ -66,7 +68,7 @@ public class DeviceManager extends BaseManager { private static final Logger log = LoggerFactory.getLogger(DeviceManager.class); private static final String DEVICE = "device"; //$NON-NLS-1$ - private static final String GROUP = "group"; //$NON-NLS-1$ + private static final String DEVICEGROUP = "deviceGroup"; //$NON-NLS-1$ @Autowired @@ -102,6 +104,11 @@ public class DeviceManager extends BaseManager @Value("${kit.device.credentials:null}") String deviceCredentials; + @SuppressWarnings("javadoc") + @Value("${kit.device.artifactory.url:null}") + String artifactoryConfigUrl; + + /** @@ -120,14 +127,15 @@ public RegisterDevice getDevice(String deviceIdentifier, String userId) /** * Registers a device * @param device - + * @param userId - * @return RegisterDevice * @throws DeviceRegistrationError - */ - public RegisterDevice registerDevice(RegisterDevice device) throws DeviceRegistrationError + public RegisterDevice registerDevice(RegisterDevice device, String userId) throws DeviceRegistrationError { // reactivation TBD - log.info("Calling registerDevice for device="+device.getUri()+" User = "+device.getUserId()); //$NON-NLS-1$ //$NON-NLS-2$ - return createorUpdateDevice(device); + log.info("Calling registerDevice for device="+device.getUri()+" User = "+userId); //$NON-NLS-1$ //$NON-NLS-2$ + return createorUpdateDevice(device,userId); } @@ -136,11 +144,11 @@ public RegisterDevice registerDevice(RegisterDevice device) throws DeviceRegistr * @return RegisterDevice * @throws DeviceRegistrationError */ - private RegisterDevice createorUpdateDevice(RegisterDevice device) throws DeviceRegistrationError + private RegisterDevice createorUpdateDevice(RegisterDevice device, String userId) throws DeviceRegistrationError { List
    headers = getServiceHeaders(); - log.debug("In here to get Service Headers "+this.jsonMapper.toJson(device)); + // log.debug("In here to get Service Headers "+this.jsonMapper.toJson(device)); if(StringUtils.isEmpty(device.getUri())){ device.setUri("/"+DEVICE+"/"+device.getDeviceAddress()); //$NON-NLS-1$ //$NON-NLS-2$ } @@ -156,9 +164,11 @@ private RegisterDevice createorUpdateDevice(RegisterDevice device) throws Device device.setActivationDate(String.valueOf(Instant.now().toEpochMilli())); } - if(!StringUtils.isEmpty(device.getGroupRef()) && !device.getGroupRef().startsWith("/group")){ //$NON-NLS-1$ - String groupRef= device.getGroupRef(); - device.setGroupRef("/"+GROUP+"/"+groupRef); //$NON-NLS-1$ //$NON-NLS-2$ + if(!StringUtils.isEmpty(device.getDeviceGroup()) && !device.getDeviceGroup().toLowerCase().startsWith("/devicegroup")){ //$NON-NLS-1$ + String groupRef= device.getDeviceGroup(); + device.setDeviceGroup("/"+DEVICEGROUP+"/"+groupRef); //$NON-NLS-1$ //$NON-NLS-2$ + } else if (!StringUtils.isEmpty(device.getDeviceGroup()) && device.getDeviceGroup().contains("group")) { //$NON-NLS-1$ + device.getDeviceGroup().replaceFirst("group", DEVICEGROUP); //$NON-NLS-1$ } @@ -166,13 +176,41 @@ private RegisterDevice createorUpdateDevice(RegisterDevice device) throws Device List tags = getDefaultTags(device.getDeviceAddress()); device.setTags(new HashSet(tags)); - // User and user group - UserGroup userGroup = this.groupManagementService.getOrCreateUserGroup(headers,device.getUserId()); - String userGroupString = this.groupManagementService.getUserGroupString(userGroup); - String group = this.groupManagementService.getOrCreateGroup(headers,userGroup.getUri(),device.getGroupRef()); + // User and user group , device group + //1. Check if the userGroup exists for the device + //2. if userGroup, then add userId to users only, if not both places owner and users + //3. add this new userGroup to list of device-group. userGroup list. + //4. check if the deviceGroup name exists if yes use it add userGroup to the list + //5 .update the device with deviceGroup and userGroup. - log.debug("With group"+group + "userGroup" + userGroupString); //$NON-NLS-1$ //$NON-NLS-2$ + UserGroup userGroup = null; + if(!StringUtils.isEmpty(device.getUserGroup())) { + userGroup = this.groupManagementService.getUserGroup(device.getUserGroup(),headers); + } + if( userGroup !=null ) { + // this means that user group found adding the user to this user group + userGroup.getUaaUsers().add(userId); + userGroup.setUpdatedDate(String.valueOf(Instant.now().toEpochMilli())); + } else { + // user group not found creating a new userGroup adding user as a owner + userGroup = this.groupManagementService.createUserGroup(userId); + } + device.setUserGroup(userGroup.getUri()); + //****END user group setup + DeviceGroup deviceGroup = null; + if(!StringUtils.isEmpty(device.getDeviceGroup())) { + deviceGroup = this.groupManagementService.getDeviceGroup(headers,device.getDeviceGroup()); + } + if( deviceGroup == null ){ + // this means that device group not ** found adding the user to this user group + deviceGroup = this.groupManagementService.createDeviceGroup(device.getDeviceGroup(),userGroup.getUri()); + } + + + String userGroupString = this.groupManagementService.getUserGroupString(userGroup); + String group = this.groupManagementService.getDeviceGroupString(deviceGroup); + log.debug("With devicegroup"+deviceGroup.getUri() + "userGroup" + userGroupString); //$NON-NLS-1$ //$NON-NLS-2$ List kitModels = new ArrayList<>(); kitModels.add(device); @@ -183,8 +221,7 @@ private RegisterDevice createorUpdateDevice(RegisterDevice device) throws Device log.debug(this.jsonMapper.toJson(result)); if ( !CollectionUtils.isEmpty(result.getErrorEvent()) ) { - log.info("Error: registering/Updating Device"); //$NON-NLS-1$ - //TBD: do something + log.error("Error: registering/Updating Device for With devicegroup"+deviceGroup.getUri() + "userGroup" + userGroupString +" for User with Id" + userId); //$NON-NLS-1$ //$NON-NLS-2$ throw new DeviceRegistrationError(result.getErrorEvent().get(0)); } return device; @@ -197,14 +234,34 @@ private RegisterDevice createorUpdateDevice(RegisterDevice device) throws Device */ private RegisterDevice getDeviceInfoFromData(Data predixString) { + RegisterDevice device = null; PredixString data = (PredixString) predixString; String deviceString = StringEscapeUtils.unescapeJava(data.getString()); deviceString = deviceString.substring(1, deviceString.length() - 1); deviceString = deviceString.substring(0, deviceString.length()); List registeredDevice = this.jsonMapper.fromJsonArray("["+deviceString+"]", RegisterDevice.class); //$NON-NLS-1$ //$NON-NLS-2$ - if(CollectionUtils.isNotEmpty(registeredDevice)) - return registeredDevice.get(0); - return null; + if(CollectionUtils.isNotEmpty(registeredDevice)) { + device = registeredDevice.get(0); + if(device.getActivationDate() == null ) { + device.setExpirationDate(calculateExpiryDate(String.valueOf(Instant.now().toEpochMilli()))); + } else { + device.setExpirationDate(calculateExpiryDate(device.getActivationDate())); + } + } + + return device; + } + + /** + * + * @param activatationDate + * @return - + */ + private String calculateExpiryDate(String activatationDate) { + Date date = new Date(); + date.setTime(Long.valueOf(activatationDate)); + Date expiry = DateUtils.addDays(date, Integer.valueOf(this.deactivationPeriod)); + return String.valueOf(expiry.getTime()); } @@ -242,6 +299,7 @@ private List
    getServiceHeaders() public List getDevices(String userId) { log.info("Calling get All Device for"); //$NON-NLS-1$ + return getDevice(userId); } @@ -257,14 +315,23 @@ public List getDevice(String userId) log.info("Calling getDevice"); //$NON-NLS-1$ List devices= new ArrayList (); List
    headers = getServiceHeaders(); - GetFieldDataRequest request = FdhUtils.createGetUserDeviceRequest("/"+DEVICE, "PredixString",userId,null); //$NON-NLS-1$ //$NON-NLS-2$ - List fieldDatas= getFieldDataResult(request,headers); - - if(CollectionUtils.isNotEmpty(fieldDatas)) { - for(FieldData fieldData:fieldDatas){ - devices.add( getDeviceInfoFromData(fieldData.getData())); + GetFieldDataRequest request; + try + { + request = FdhUtils.createGetUserDeviceRequest("/"+DEVICE, "PredixString",userId,null); //$NON-NLS-1$//$NON-NLS-2$ + List fieldDatas= getFieldDataResult(request,headers); + + if(CollectionUtils.isNotEmpty(fieldDatas)) { + for(FieldData fieldData:fieldDatas){ + devices.add( getDeviceInfoFromData(fieldData.getData())); + } } + } + catch (UnsupportedEncodingException e) + { + log.info("Error with decoding the String Asset filter "+e.toString(),e); //$NON-NLS-1$ + } return devices; } @@ -284,12 +351,24 @@ public RegisterDevice getDevice(String deviceIdentifier, String userId, String d log.info("Calling getDevice by user and device address"); //$NON-NLS-1$ RegisterDevice device =null; List
    headers = getServiceHeaders(); - GetFieldDataRequest request = FdhUtils.createGetUserDeviceRequest(deviceIdentifier, "PredixString",userId,deviceAddress); //$NON-NLS-1$ - List fieldData = getFieldDataResult(request,headers); - if(CollectionUtils.isNotEmpty(fieldData)) { - return getDeviceInfoFromData(fieldData.get(0).getData()); + GetFieldDataRequest request; + try + { + request = FdhUtils.createGetUserDeviceRequest(deviceIdentifier, "PredixString",userId,deviceAddress);//$NON-NLS-1$ + List fieldData = getFieldDataResult(request,headers); + if(CollectionUtils.isNotEmpty(fieldData)) { + device = getDeviceInfoFromData(fieldData.get(0).getData()); + } } + catch (UnsupportedEncodingException e) + { + + log.info("Error with decoding the String Asset filter "+e.toString(),e); //$NON-NLS-1$ + + } + return device; + } @@ -345,6 +424,7 @@ public Map getDeviceConfig() deviceConfig.put("predixTimeSeriesZoneid", this.timeseriesConfig.getZoneId()); deviceConfig.put("deviceDeactivationPeriod", this.deactivationPeriod); deviceConfig.put("cloudApplicationUrl", this.kitApplicationUrl); + deviceConfig.put("artifactoryConfigUrl", this.artifactoryConfigUrl); return deviceConfig; } @@ -353,23 +433,32 @@ public Map getDeviceConfig() /** * @param device - * @param originalDevice - + * @param userId - * @throws DeviceRegistrationError - */ - public void updateDevice(RegisterDevice device, RegisterDevice originalDevice) throws DeviceRegistrationError + public void updateDevice(RegisterDevice device, RegisterDevice originalDevice , String userId) throws DeviceRegistrationError { - log.info("Calling updateDevice for device="+device.getUri()+" User = "+device.getUserId()); //$NON-NLS-1$ //$NON-NLS-2$ + log.info("Calling updateDevice for device="+originalDevice.getUri()+" User = "+userId); //$NON-NLS-1$ //$NON-NLS-2$ if(StringUtils.isNotEmpty(device.getDeviceName()) && ! originalDevice.getDeviceName().equalsIgnoreCase(device.getDeviceName())) { originalDevice.setDeviceName(device.getDeviceName()); } - if(StringUtils.isNotEmpty(device.getGroupRef()) && ! originalDevice.getGroupRef().equalsIgnoreCase(device.getGroupRef())) { - originalDevice.setGroupRef(device.getGroupRef()); + if(StringUtils.isNotEmpty(device.getDeviceGroup()) && ! originalDevice.getDeviceGroup().equalsIgnoreCase(device.getDeviceGroup())) { + originalDevice.setDeviceGroup(device.getDeviceGroup()); } if(CollectionUtils.isNotEmpty(device.getTags())) { originalDevice.getTags().addAll(device.getTags()); } + if(device.getGeoLocation() !=null && StringUtils.isNotEmpty(device.getGeoLocation().getLatitude())) { + originalDevice.getGeoLocation().setLatitude(device.getGeoLocation().getLatitude()); + } + if(device.getGeoLocation() !=null && StringUtils.isNotEmpty(device.getGeoLocation().getLongitude())) { + originalDevice.getGeoLocation().setLongitude(device.getGeoLocation().getLongitude()); + } + + originalDevice.setUpdateDate(String.valueOf(Instant.now().toEpochMilli())); - this.createorUpdateDevice(originalDevice); + this.createorUpdateDevice(originalDevice,userId); } /** @@ -378,19 +467,67 @@ public void updateDevice(RegisterDevice device, RegisterDevice originalDevice) t */ public void checkDeviceExpiry(RegisterDevice device) throws DeviceRegistrationError { - Long currentTime = Instant.now().toEpochMilli(); - //Date currentDate = new Date(currentTime); - Long activationTime = Long.valueOf(device.getActivationDate()); - // Date activationDate = new Date(activationTime); - - DateTime currentDate = new DateTime(currentTime); - DateTime activationDate = new DateTime(activationTime); - - int days = Days.daysBetween(currentDate, activationDate).getDays(); - - if(Math.abs(days) > Integer.valueOf(this.deactivationPeriod)){ - throw new DeviceRegistrationError("Device has past its activation period."); //$NON-NLS-1$ - } + Long currentTime = Instant.now().toEpochMilli(); + //Date currentDate = new Date(currentTime); + Long activationTime = Long.valueOf(device.getActivationDate()); + // Date activationDate = new Date(activationTime); + + DateTime currentDate = new DateTime(currentTime); + DateTime activationDate = new DateTime(activationTime); + + int days = Days.daysBetween(currentDate, activationDate).getDays(); + + if(Math.abs(days) > Integer.valueOf(this.deactivationPeriod)){ + throw new DeviceRegistrationError("Device has past its activation period."); //$NON-NLS-1$ + } + } + + /** + * @param device - + * @param isAdmin - + * @param userid - + * @throws DeviceRegistrationError - + */ + public void resetDevice(RegisterDevice device, Boolean isAdmin, String userid) throws DeviceRegistrationError + { + if(isAdmin) { + log.info("DeviceManager: admin access... resetting device"+device.getUri()); //$NON-NLS-1$ + device.setUpdateDate(String.valueOf(Instant.now().toEpochMilli())); + device.setActivationDate(device.getUpdateDate()); + createorUpdateDevice(device,userid); + } + + } + + /** + * - + * @return - + */ + public List getAllAdminDevices() + { + log.info("Calling getAdminDevice"); //$NON-NLS-1$ + List devices= new ArrayList (); + List
    headers = getServiceHeaders(); + GetFieldDataRequest request; + try + { + request = FdhUtils.createGetAdminDeviceRequest("/"+DEVICE, "PredixString"); //$NON-NLS-1$//$NON-NLS-2$ + List fieldDatas= getFieldDataResult(request,headers); + + if(CollectionUtils.isNotEmpty(fieldDatas)) { + for(FieldData fieldData:fieldDatas){ + devices.add( getDeviceInfoFromData(fieldData.getData())); + } + } + + } + catch (UnsupportedEncodingException e) + { + log.info("Error with decoding the String Asset filter "+e.toString(),e); //$NON-NLS-1$ + } + + return devices; + } } diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/manager/GroupManagementService.java b/src/main/java/com/ge/predix/solsvc/kitservice/manager/GroupManagementService.java index f4a862c..d3210d5 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/manager/GroupManagementService.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/manager/GroupManagementService.java @@ -7,7 +7,7 @@ * with the terms and conditions stipulated in the agreement/contract * under which the software has been supplied. */ - + package com.ge.predix.solsvc.kitservice.manager; import java.time.Instant; @@ -28,7 +28,7 @@ import com.ge.predix.entity.fielddata.PredixString; import com.ge.predix.entity.getfielddata.GetFieldDataRequest; import com.ge.predix.solsvc.kitservice.boot.utils.FdhUtils; -import com.ge.predix.solsvc.kitservice.model.KitGroup; +import com.ge.predix.solsvc.kitservice.model.DeviceGroup; import com.ge.predix.solsvc.kitservice.model.UserGroup; /** @@ -38,22 +38,23 @@ @Component public class GroupManagementService extends BaseManager { - private static final Logger log = LoggerFactory.getLogger(GroupManagementService.class); - private static final String USER_GROUP = "user-group"; //$NON-NLS-1$ - - + private static final Logger log = LoggerFactory.getLogger(GroupManagementService.class); + private static final String USERGROUP = "userGroup"; //$NON-NLS-1$ + /** * @param headers - * @param userId - * @return - */ - public UserGroup getUserGroup(List
    headers, String userId) + public UserGroup getUserGroupbyUserId(List
    headers, String userId) { UserGroup userGroup = null; - if(StringUtils.isNotEmpty(userId)){ - GetFieldDataRequest request = FdhUtils.createGetUserGroupRequest("/"+USER_GROUP, "PredixString",userId); //$NON-NLS-1$ //$NON-NLS-2$ - List fieldData = getFieldDataResult(request,headers); - if(CollectionUtils.isEmpty(fieldData)) { + if ( StringUtils.isNotEmpty(userId) ) + { + GetFieldDataRequest request = FdhUtils.createGetUserGroupRequest("/" + USERGROUP, "PredixString", userId); //$NON-NLS-1$ //$NON-NLS-2$ + List fieldData = getFieldDataResult(request, headers); + if ( CollectionUtils.isEmpty(fieldData) ) + { return null; } Data predixString = fieldData.get(0).getData(); @@ -61,120 +62,111 @@ public UserGroup getUserGroup(List
    headers, String userId) String deviceString = StringEscapeUtils.unescapeJava(data.getString()); deviceString = deviceString.substring(1, deviceString.length() - 1); deviceString = deviceString.substring(0, deviceString.length()); - List userGroups = this.jsonMapper.fromJsonArray("["+deviceString+"]", UserGroup.class); //$NON-NLS-1$ //$NON-NLS-2$ - if(CollectionUtils.isNotEmpty(userGroups)) - userGroup = userGroups.get(0); + List userGroups = this.jsonMapper.fromJsonArray("[" + deviceString + "]", UserGroup.class); //$NON-NLS-1$ //$NON-NLS-2$ + if ( CollectionUtils.isNotEmpty(userGroups) ) userGroup = userGroups.get(0); return userGroup; - + } return userGroup; } + /** * @param headers - - * @param userGroupRef - - * @param groupRef - + * @param deviceGroup - * @param userId - * @return - */ - - public String getOrCreateGroup(List
    headers, String userGroupRef, String groupRef) + public UserGroup createUserGroup(String userId) { - - KitGroup group = getGroup(headers,groupRef); - if( group == null) { - group = createGroup(groupRef,userGroupRef); - } - group.getGroupRef().add(userGroupRef); - - List kitModels = new ArrayList<>(); - kitModels.add(group); - return this.jsonMapper.toJson(kitModels); - + + UserGroup userGroup = new UserGroup(); + userGroup.setUri("/" + USERGROUP + "/" + UUID.randomUUID().toString()); //$NON-NLS-1$ //$NON-NLS-2$ + userGroup.getUaaOwners().add(userId); + userGroup.getUaaUsers().add(userId); + userGroup.setCreatedDate(String.valueOf(Instant.now().toEpochMilli())); + return userGroup; + } - + /** + * @param userGroupUri - * @param headers - - * @param groupRef - + * @param deviceGroup - * @param userId - * @return - */ - public UserGroup getOrCreateUserGroup(List
    headers, String userId) + public UserGroup getUserGroup(String userGroupUri, List
    headers) { - - UserGroup userGroup = getUserGroup(headers,userId); - if(userGroup == null) { - userGroup = createUserGroup(userId); - } - else { - userGroup.getUsers().add(userId); - userGroup.setUpdatedDate(String.valueOf(Instant.now().toEpochMilli())); + + UserGroup userGroup = null; + + GetFieldDataRequest request = FdhUtils.createGetUserGroupRequest(userGroupUri, "PredixString", null); //$NON-NLS-1$ + List fieldData = getFieldDataResult(request, headers); + if ( CollectionUtils.isEmpty(fieldData) ) + { + return null; } + Data predixString = fieldData.get(0).getData(); + PredixString data = (PredixString) predixString; + String deviceString = StringEscapeUtils.unescapeJava(data.getString()); + deviceString = deviceString.substring(1, deviceString.length() - 1); + deviceString = deviceString.substring(0, deviceString.length()); + List userGroups = this.jsonMapper.fromJsonArray("[" + deviceString + "]", UserGroup.class); //$NON-NLS-1$ //$NON-NLS-2$ + if ( CollectionUtils.isNotEmpty(userGroups) ) userGroup = userGroups.get(0); return userGroup; - - + } - + /** * * @param userGroup - * @return - */ - public String getUserGroupString(final UserGroup userGroup) { + public String getUserGroupString(final UserGroup userGroup) + { ArrayList kitModels = new ArrayList<>(); - kitModels.add(userGroup); + kitModels.add(userGroup); return this.jsonMapper.toJson(kitModels); } - /** - * @param groupRef - * @param userId - * @return - - */ - private UserGroup createUserGroup(String userId) + /** + * + * @param deviceGroupRef - + * @param userGroupRef - + * @return - + */ + DeviceGroup createDeviceGroup(String deviceGroupRef, String userGroupRef) { - UserGroup userGroup = new UserGroup(); - userGroup.setUri("/"+USER_GROUP+"/"+UUID.randomUUID().toString()); //$NON-NLS-1$ //$NON-NLS-2$ - userGroup.getOwners().add(userId); - userGroup.getUsers().add(userId); - userGroup.setCreatedDate(String.valueOf(Instant.now().toEpochMilli())); - return userGroup; - - } - - - /** - * - * @param groupRef - * @return - - */ - private KitGroup createGroup(String groupRef,String userGroupRef) - { - KitGroup group = new KitGroup(); - group.setUri(groupRef); + DeviceGroup group = new DeviceGroup(); + group.setUri(deviceGroupRef); group.setCreatedate(String.valueOf(Instant.now().toEpochMilli())); - group.setDescription(groupRef); - String[] parts = groupRef.split("/"); //$NON-NLS-1$ - if(parts.length > 0 ){ - group.setName(parts[parts.length-1]); + group.setDescription(deviceGroupRef); + String[] parts = deviceGroupRef.split("/"); //$NON-NLS-1$ + if ( parts.length > 0 ) + { + group.setName(parts[parts.length - 1]); } - group.getGroupRef().add(userGroupRef); + group.getUserGroup().add(userGroupRef); return group; } - /** - * @param headers - * @param groupRef - * @return - - */ - private KitGroup getGroup(List
    headers, String groupRef) + /** + * + * @param headers - + * @param deviceGroupRef - + * @return - + */ + DeviceGroup getDeviceGroup(List
    headers, String deviceGroupRef) { - log.info("Calling getGroup for "+groupRef); //$NON-NLS-1$ - KitGroup group = null; - if(StringUtils.isNotEmpty(groupRef)){ - GetFieldDataRequest request = FdhUtils.createGetGroupRequest(groupRef, "PredixString"); //$NON-NLS-1$ - List fieldData = getFieldDataResult(request,headers); - if(CollectionUtils.isEmpty(fieldData)) { + log.info("Calling deviceGroupRef for " + deviceGroupRef); //$NON-NLS-1$ + DeviceGroup group = null; + if ( StringUtils.isNotEmpty(deviceGroupRef) ) + { + GetFieldDataRequest request = FdhUtils.createGetGroupRequest(deviceGroupRef, "PredixString"); //$NON-NLS-1$ + List fieldData = getFieldDataResult(request, headers); + if ( CollectionUtils.isEmpty(fieldData) ) + { return null; } Data predixString = fieldData.get(0).getData(); @@ -182,15 +174,25 @@ private KitGroup getGroup(List
    headers, String groupRef) String deviceString = StringEscapeUtils.unescapeJava(data.getString()); deviceString = deviceString.substring(1, deviceString.length() - 1); deviceString = deviceString.substring(0, deviceString.length()); - List groups = this.jsonMapper.fromJsonArray("["+deviceString+"]", KitGroup.class); //$NON-NLS-1$ //$NON-NLS-2$ - if(CollectionUtils.isNotEmpty(groups)) - group = groups.get(0); + List groups = this.jsonMapper.fromJsonArray("[" + deviceString + "]", DeviceGroup.class); //$NON-NLS-1$ //$NON-NLS-2$ + if ( CollectionUtils.isNotEmpty(groups) ) group = groups.get(0); return group; - + } return group; - - + } +/** + * @param deviceGroup - + * @return - + */ +public String getDeviceGroupString(DeviceGroup deviceGroup) +{ + List kitModels = new ArrayList<>(); + kitModels.add(deviceGroup); + return this.jsonMapper.toJson(kitModels); +} + + } diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/model/KitGroup.java b/src/main/java/com/ge/predix/solsvc/kitservice/model/DeviceGroup.java similarity index 80% rename from src/main/java/com/ge/predix/solsvc/kitservice/model/KitGroup.java rename to src/main/java/com/ge/predix/solsvc/kitservice/model/DeviceGroup.java index bb60fc2..fb12891 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/model/KitGroup.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/model/DeviceGroup.java @@ -23,27 +23,28 @@ * * @author 212421693 - */ -public class KitGroup extends Group +public class DeviceGroup extends Group { /** * */ - Set groupRef = new HashSet(); + Set userGroup = new HashSet(); + /** - * @return the groupRef + * @return the userGroupRef */ - public Set getGroupRef() + public Set getUserGroup() { - return this.groupRef; + return this.userGroup; } /** - * @param groupRef the groupRef to set + * @param userGroupRef the userGroupRef to set */ - public void setGroupRef(Set groupRef) + public void setUserGroup(Set userGroupRef) { - this.groupRef = groupRef; + this.userGroup = userGroupRef; } /* (non-Javadoc) diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/model/GeoLocation.java b/src/main/java/com/ge/predix/solsvc/kitservice/model/GeoLocation.java new file mode 100644 index 0000000..423b330 --- /dev/null +++ b/src/main/java/com/ge/predix/solsvc/kitservice/model/GeoLocation.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017 General Electric Company. All rights reserved. + * + * The copyright to the computer software herein is the property of + * General Electric Company. The software may be used and/or copied only + * with the written permission of General Electric Company or in accordance + * with the terms and conditions stipulated in the agreement/contract + * under which the software has been supplied. + */ + +package com.ge.predix.solsvc.kitservice.model; + +import java.io.Serializable; + +/** + * + * @author 212421693 - + */ +public class GeoLocation implements Serializable +{ + + /** + * + */ + private static final long serialVersionUID = -3350292912815020657L; + /** + * + */ + String latitude; + + /** + * + */ + String longitude; + + /** + * @return the latitude + */ + public String getLatitude() + { + return this.latitude; + } + + /** + * @param latitude the latitude to set + */ + public void setLatitude(String latitude) + { + this.latitude = latitude; + } + + /** + * @return the longitude + */ + public String getLongitude() + { + return this.longitude; + } + + /** + * @param longitude the longitude to set + */ + public void setLongitude(String longitude) + { + this.longitude = longitude; + } + + +} diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/model/RegisterDevice.java b/src/main/java/com/ge/predix/solsvc/kitservice/model/RegisterDevice.java index 30e7a6a..822361b 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/model/RegisterDevice.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/model/RegisterDevice.java @@ -14,16 +14,16 @@ import java.util.Map; import java.util.Set; -import javax.validation.constraints.Pattern; +import javax.xml.bind.annotation.XmlRootElement; import com.ge.predix.entity.asset.AssetTag; -import com.ge.predix.solsvc.bootstrap.ams.dto.Tag; /** * * @author 212421693 - */ +@XmlRootElement(name="device") public class RegisterDevice { /** @@ -55,14 +55,22 @@ public RegisterDevice() * */ String activationDate; + /** * */ - String groupRef; + String expirationDate; /** * */ - private String userId; + + String deviceGroup; + + /** + * + */ + String userGroup; + /** * */ @@ -73,6 +81,30 @@ public RegisterDevice() */ String updateDate; + /** + * + */ + String ipAddress; + + /** + * + */ + private GeoLocation geoLocation = new GeoLocation(); + + /** + * @return the ipAddress + */ + public String getIpAddress() + { + return this.ipAddress; + } + /** + * @param ipAddress the ipAddress to set + */ + public void setIpAddress(String ipAddress) + { + this.ipAddress = ipAddress; + } /** * */ @@ -149,19 +181,34 @@ public void setActivationDate(String activationDate) { this.activationDate = activationDate; } + /** - * @return the groupRef + * @return the deviceGroupRef */ - public String getGroupRef() + public String getDeviceGroup() { - return this.groupRef; + return this.deviceGroup; } /** - * @param groupRef the groupRef to set + * @param deviceGroupRef the deviceGroupRef to set */ - public void setGroupRef(String groupRef) + public void setDeviceGroup(String deviceGroupRef) { - this.groupRef = groupRef; + this.deviceGroup = deviceGroupRef; + } + /** + * @return the userGroupRef + */ + public String getUserGroup() + { + return this.userGroup; + } + /** + * @param userGroupRef the userGroupRef to set + */ + public void setUserGroup(String userGroupRef) + { + this.userGroup = userGroupRef; } /** * @return the createdDate @@ -191,31 +238,18 @@ public void setTags(Set tags) { this.tags = tags; } - /** - * @return the userId - */ - public String getUserId() - { - return this.userId; - } - /** - * @param userId the userId to set - */ - public void setUserId(String userId) - { - this.userId = userId; - } + /** * @return the deviceConfig */ - public Map getDeviceConfig() + public Map getDeviceConfig() { return this.deviceConfig; } /** * @param deviceConfig the deviceConfig to set */ - public void setDeviceConfig(Map deviceConfig) + public void setDeviceConfig(Map deviceConfig) { this.deviceConfig = deviceConfig; } @@ -233,6 +267,36 @@ public void setUpdateDate(String updateDate) { this.updateDate = updateDate; } + + /** + * + * @return - + */ + public String getExpirationDate() { + return this.expirationDate; + } + + /** + * + * @param expirationDate - + */ + public void setExpirationDate(String expirationDate) { + this.expirationDate = expirationDate; + } + /** + * @return the geLocation + */ + public GeoLocation getGeoLocation() + { + return this.geoLocation; + } + /** + * @param geLocation the geLocation to set + */ + public void setGeoLocation(GeoLocation geLocation) + { + this.geoLocation = geLocation; + } } diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/model/UserGroup.java b/src/main/java/com/ge/predix/solsvc/kitservice/model/UserGroup.java index 320dc99..dc3f383 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/model/UserGroup.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/model/UserGroup.java @@ -25,11 +25,11 @@ public class UserGroup /** * */ - Set users = new HashSet(); + Set uaaUsers = new HashSet(); /** * */ - Set owners = new HashSet(); + Set uaaOwners = new HashSet(); /** * @@ -56,30 +56,30 @@ public void setUri(String uri) /** * @return the users */ - public Set getUsers() + public Set getUaaUsers() { - return this.users; + return this.uaaUsers; } /** * @param users the users to set */ - public void setUsers(Set users) + public void setUaaUsers(Set users) { - this.users = users; + this.uaaUsers = users; } /** * @return the owners */ - public Set getOwners() + public Set getUaaOwners() { - return this.owners; + return this.uaaOwners; } /** * @param owners the owners to set */ - public void setOwners(Set owners) + public void setUaaOwners(Set owners) { - this.owners = owners; + this.uaaOwners = owners; } /** diff --git a/src/main/java/com/ge/predix/solsvc/kitservice/validator/RegisterDeviceValidation.java b/src/main/java/com/ge/predix/solsvc/kitservice/validator/RegisterDeviceValidation.java index f5a94b5..7a63285 100644 --- a/src/main/java/com/ge/predix/solsvc/kitservice/validator/RegisterDeviceValidation.java +++ b/src/main/java/com/ge/predix/solsvc/kitservice/validator/RegisterDeviceValidation.java @@ -13,6 +13,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.springframework.util.StringUtils; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; @@ -73,8 +74,7 @@ public void validate(Object target, Errors errors) ValidationUtils.rejectIfEmptyOrWhitespace(errors, "deviceName", "field.required"); //$NON-NLS-1$//$NON-NLS-2$ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "deviceAddress", "field.required"); //$NON-NLS-1$//$NON-NLS-2$ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "deviceType", "field.required"); //$NON-NLS-1$//$NON-NLS-2$ - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userId", "field.required"); //$NON-NLS-1$//$NON-NLS-2$ - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "groupRef", "field.required"); //$NON-NLS-1$//$NON-NLS-2$ + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "deviceGroup", "field.required"); //$NON-NLS-1$//$NON-NLS-2$ if(!validate(device.getDeviceName() , this.pattern)){ @@ -86,14 +86,14 @@ public void validate(Object target, Errors errors) if(!validate(device.getDeviceType(),this.deviceTypePattern)){ errors.rejectValue("DeviceType", "Device Type should match ^[A-Za-z0-9]*"); //$NON-NLS-1$//$NON-NLS-2$ } - if(!validate(device.getGroupRef(),this.groupRefPattern)){ - errors.rejectValue("GroupRef", "GroupRef should match ^[A-Za-z0-9-/]*"); //$NON-NLS-1$//$NON-NLS-2$ + if(!validate(device.getDeviceGroup(),this.groupRefPattern)){ + errors.rejectValue("GroupRef", "DeviceGroupRef should match ^[A-Za-z0-9-/]*"); //$NON-NLS-1$//$NON-NLS-2$ } - if(DEVICE_NAME_LENGTH <= device.getDeviceName().length() ){ + if( StringUtils.isEmpty(device.getDeviceName()) || DEVICE_NAME_LENGTH <= device.getDeviceName().length() ){ errors.rejectValue("DeviceName", "Device Name is limited to max 50"); //$NON-NLS-1$//$NON-NLS-2$ } - if( DEVICE_ADDRESS_LENGTH <= device.getDeviceAddress().length()){ + if( StringUtils.isEmpty(device.getDeviceAddress()) || DEVICE_ADDRESS_LENGTH <= device.getDeviceAddress().length()){ errors.rejectValue("DeviceAddress", "Device Address is limited to max 75"); //$NON-NLS-1$//$NON-NLS-2$ } } @@ -101,11 +101,14 @@ public void validate(Object target, Errors errors) /** * @param deviceName - - * @param pattern + * @param pattern - * @return - */ public static boolean validate(String deviceName, Pattern pattern) { + if(StringUtils.isEmpty(deviceName) ){ + return false; + } Matcher matcher = pattern.matcher(deviceName); return matcher.matches(); } diff --git a/src/main/resources/META-INF/application-security.xml b/src/main/resources/META-INF/application-security.xml index 3fc7224..24ac3d5 100644 --- a/src/main/resources/META-INF/application-security.xml +++ b/src/main/resources/META-INF/application-security.xml @@ -47,7 +47,7 @@ tokens in requests --> - + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 7f654b3..0674911 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -21,4 +21,9 @@ register.device.deactivation=${registration_deactivation} #view in cloud application kit.webapp.url=${KIT_CLOUD_APP_URL} -kit.device.credentials=${kit_device_credentials} \ No newline at end of file +kit.device.credentials=${kit_device_credentials} + +kit.device.artifactory.url=https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_APIKEY}@artifactory.predix.io/artifactory/PREDIX-EXT/com/ge/predix/solsvc/predixkit/ + +kit.device.export.asset.properties=uri, userGroup, latitude, longitude, updateDate, expirationDate, deviceType, deviceName, deviceGroup, deviceAddress, createdDate, activationDate +kit.device.export.assettag.properties=deviceURI, tagUri, label, isKpi, unit, hiQualityThreshold, hiAlarmThreshold, loAlarmThreshold, loQualityThreshold, lastCalibrated, locationUUID, alertStatusUri, tag \ No newline at end of file diff --git a/src/test/java/com/ge/predix/solsvc/service/AbstractBaseControllerIT.java b/src/test/java/com/ge/predix/solsvc/service/AbstractBaseControllerIT.java index bc08941..62e403d 100644 --- a/src/test/java/com/ge/predix/solsvc/service/AbstractBaseControllerIT.java +++ b/src/test/java/com/ge/predix/solsvc/service/AbstractBaseControllerIT.java @@ -28,5 +28,7 @@ @IntegrationTest({"server.port=9092"}) public abstract class AbstractBaseControllerIT { - + /* + * + */ } diff --git a/src/test/java/com/ge/predix/solsvc/service/KitControllerIT.java b/src/test/java/com/ge/predix/solsvc/service/KitControllerIT.java index e29e7b0..9cd67ba 100644 --- a/src/test/java/com/ge/predix/solsvc/service/KitControllerIT.java +++ b/src/test/java/com/ge/predix/solsvc/service/KitControllerIT.java @@ -46,6 +46,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.ge.predix.solsvc.ext.util.JsonMapper; +import com.ge.predix.solsvc.kitservice.model.GeoLocation; import com.ge.predix.solsvc.kitservice.model.RegisterDevice; import com.ge.predix.solsvc.restclient.config.IOauthRestConfig; import com.ge.predix.solsvc.restclient.impl.RestClient; @@ -92,34 +93,32 @@ public void setUp() /** * @throws Exception - */ - @SuppressWarnings("nls") @Test public void registerDeviceWithAuthenticationError() throws Exception { - this.base = new URL("http://localhost:" + this.localServerPort + "/device/register"); + this.base = new URL("http://localhost:" + this.localServerPort + "/device/register"); //$NON-NLS-1$ //$NON-NLS-2$ ResponseEntity response = this.template.getForEntity(this.base.toString(), String.class); - assertThat(response.getBody(), containsString("unauthorized")); + assertThat(response.getBody(), containsString("unauthorized")); //$NON-NLS-1$ } /** * @throws Exception - */ - @SuppressWarnings("nls") @Test public void registerDevice() throws Exception { - String url = "http://localhost:" + this.localServerPort + "/device/register"; + String url = "http://localhost:" + this.localServerPort + "/device/register"; //$NON-NLS-1$ //$NON-NLS-2$ RegisterDevice device = getRegisterDevice(); String req = this.jsonMapper.toJson(device); - log.debug("Register Device Json req is " + this.jsonMapper.toJson(device)); + log.debug("Register Device Json req is " + this.jsonMapper.toJson(device)); //$NON-NLS-1$ List
    headers = new ArrayList
    (); - String userToken = getUserToken("app_user_1", "app_user_1"); - headers.add(new BasicHeader("Authorization", userToken)); - headers.add(new BasicHeader("Content-Type", "application/json")); + String userToken = getUserToken("app_user_1", "app_user_1"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ CloseableHttpResponse response = null; try @@ -127,11 +126,13 @@ public void registerDevice() response = this.restClient.post(url, req, headers, this.restConfig.getDefaultConnectionTimeout(), this.restConfig.getDefaultSocketTimeout()); Assert.assertNotNull(response); - Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); + Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); //$NON-NLS-1$ String body = EntityUtils.toString(response.getEntity()); - assertThat(body, containsString("uri")); + assertThat(body, containsString("uri")); //$NON-NLS-1$ RegisterDevice registeredDevice = this.objectMapper.readValue(body, RegisterDevice.class); assertTrue(registeredDevice.getUri() != null); + String kitDeviceUrl = (String) registeredDevice.getDeviceConfig().get("artifactoryConfigUrl"); //$NON-NLS-1$ + assertTrue(kitDeviceUrl != null && kitDeviceUrl.startsWith("https")); //$NON-NLS-1$ } finally @@ -143,25 +144,24 @@ public void registerDevice() /** * @throws Exception - */ - @SuppressWarnings("nls") @Test public void updateDevice() throws Exception { List
    headers = new ArrayList
    (); - String userToken = getUserToken("app_user_1", "app_user_1"); - headers.add(new BasicHeader("Authorization", userToken)); - headers.add(new BasicHeader("Content-Type", "application/json")); + String userToken = getUserToken("app_user_1", "app_user_1"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ RegisterDevice device = getRegisterDevice(); String url = "http://localhost:" + this.localServerPort + "/device/" + device.getDeviceAddress(); //$NON-NLS-1$//$NON-NLS-2$ RegisterDevice updateDevice = getRegisterDevicebyId(headers,url); - updateDevice.setDeviceName("UpdateDevice-Test"); + updateDevice.setDeviceName("UpdateDevice-Test"); //$NON-NLS-1$ String req = this.jsonMapper.toJson(updateDevice); - log.debug("update Device Json req is " + this.jsonMapper.toJson(updateDevice)); + log.debug("update Device Json req is " + this.jsonMapper.toJson(updateDevice)); //$NON-NLS-1$ CloseableHttpResponse response = null; try @@ -169,7 +169,7 @@ public void updateDevice() response = this.restClient.put(url, req, headers, this.restConfig.getDefaultConnectionTimeout(), this.restConfig.getDefaultSocketTimeout()); Assert.assertNotNull(response); - Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); + Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); //$NON-NLS-1$ RegisterDevice newUpdatedDevice = getRegisterDevicebyId(headers,url); Assert.assertTrue(newUpdatedDevice.getDeviceName().equalsIgnoreCase(updateDevice.getDeviceName())); @@ -218,23 +218,22 @@ private RegisterDevice getRegisterDevicebyId(List
    headers , String url ) /** * @throws Exception - */ - @SuppressWarnings("nls") @Test public void registerDeviceValidationFailure() throws Exception { - String url = "http://localhost:" + this.localServerPort + "/device/register"; + String url = "http://localhost:" + this.localServerPort + "/device/register"; //$NON-NLS-1$ //$NON-NLS-2$ RegisterDevice device = getRegisterDevice(); // device.setUserId(""); //device.setDeviceAddress(""); - device.setDeviceName("!!!!"); + device.setDeviceName("!!!!"); //$NON-NLS-1$ String req = this.jsonMapper.toJson(device); - log.debug("Register Device Json req is " + this.jsonMapper.toJson(device)); + log.debug("Register Device Json req is " + this.jsonMapper.toJson(device)); //$NON-NLS-1$ List
    headers = new ArrayList
    (); - String userToken = getUserToken("app_user_1", "app_user_1"); - headers.add(new BasicHeader("Authorization", userToken)); - headers.add(new BasicHeader("Content-Type", "application/json")); + String userToken = getUserToken("app_user_1", "app_user_1"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ CloseableHttpResponse response = null; try @@ -242,9 +241,9 @@ public void registerDeviceValidationFailure() response = this.restClient.post(url, req, headers, this.restConfig.getDefaultConnectionTimeout(), this.restConfig.getDefaultSocketTimeout()); Assert.assertNotNull(response); - Assert.assertTrue(response.toString().contains("HTTP/1.1 400")); + Assert.assertTrue(response.toString().contains("HTTP/1.1 400")); //$NON-NLS-1$ String body = EntityUtils.toString(response.getEntity()); - assertThat(body, containsString("error")); + assertThat(body, containsString("error")); //$NON-NLS-1$ } finally @@ -257,25 +256,24 @@ public void registerDeviceValidationFailure() * * @throws Exception - */ - @SuppressWarnings("nls") @Test public void getDevice() throws Exception { RegisterDevice device = getRegisterDevice(); - String url = "http://localhost:" + this.localServerPort + "/device/" + device.getDeviceAddress(); + String url = "http://localhost:" + this.localServerPort + "/device/" + device.getDeviceAddress(); //$NON-NLS-1$ //$NON-NLS-2$ List
    headers = new ArrayList
    (); - String userToken = getUserToken("app_user_1", "app_user_1"); - headers.add(new BasicHeader("Authorization", userToken)); - headers.add(new BasicHeader("Content-Type", "application/json")); + String userToken = getUserToken("app_user_1", "app_user_1"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ CloseableHttpResponse response = null; try { response = this.restClient.get(url, headers); Assert.assertNotNull(response); - Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); String body = EntityUtils.toString(response.getEntity()); + Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); //$NON-NLS-1$ // assertThat(body, containsString("uri")); RegisterDevice registeredDevice = this.objectMapper.readValue(body, RegisterDevice.class); assertTrue(registeredDevice.getUri() != null); @@ -291,25 +289,24 @@ public void getDevice() * * @throws Exception - */ - @SuppressWarnings("nls") @Test public void getDeviceValidation() throws Exception { - String url = "http://localhost:" + this.localServerPort + "/device/tinfoil_0481%29"; + String url = "http://localhost:" + this.localServerPort + "/device/tinfoil_0481%29"; //$NON-NLS-1$ //$NON-NLS-2$ List
    headers = new ArrayList
    (); - String userToken = getUserToken("app_user_1", "app_user_1"); - headers.add(new BasicHeader("Authorization", userToken)); - headers.add(new BasicHeader("Content-Type", "application/json")); + String userToken = getUserToken("app_user_1", "app_user_1"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ CloseableHttpResponse response = null; try { response = this.restClient.get(url, headers); Assert.assertNotNull(response); - Assert.assertTrue(response.toString().contains("HTTP/1.1 400")); + Assert.assertTrue(response.toString().contains("HTTP/1.1 400")); //$NON-NLS-1$ String body = EntityUtils.toString(response.getEntity()); - assertThat(body, containsString("error")); + assertThat(body, containsString("error")); //$NON-NLS-1$ } finally @@ -322,27 +319,27 @@ public void getDeviceValidation() * * @throws Exception - */ - @SuppressWarnings("nls") - @Test + @SuppressWarnings({ "unchecked" }) +@Test public void getAllDevice() throws Exception { - String url = "http://localhost:" + this.localServerPort + "/device/"; + String url = "http://localhost:" + this.localServerPort + "/device/"; //$NON-NLS-1$ //$NON-NLS-2$ List
    headers = new ArrayList
    (); - String userToken = getUserToken("app_user_1", "app_user_1"); - headers.add(new BasicHeader("Authorization", userToken)); - headers.add(new BasicHeader("Content-Type", "application/json")); + String userToken = getUserToken("app_user_1", "app_user_1"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ CloseableHttpResponse response = null; try { response = this.restClient.get(url, headers); Assert.assertNotNull(response); - Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); + Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); //$NON-NLS-1$ String body = EntityUtils.toString(response.getEntity()); List registeredDevices = this.objectMapper.readValue(body, ArrayList.class); assertTrue(registeredDevices != null); - assertTrue(registeredDevices.size() > 1); + assertTrue(registeredDevices.size() > 0); } finally @@ -356,28 +353,28 @@ public void getAllDevice() * @throws Exception - */ @SuppressWarnings({ - "nls", "resource" + "resource" }) - @Test + @Test public void checkDeviceActivationExpiry() throws Exception { - String url = "http://localhost:" + this.localServerPort + "/device/register"; + String url = "http://localhost:" + this.localServerPort + "/device/register"; //$NON-NLS-1$ //$NON-NLS-2$ RegisterDevice device = getRegisterDevice(); - device.setUri("/device/testexpiry"); - device.setGroupRef("/group/testexpiry"); - device.setDeviceName("TEST-EXPIRY"); - device.setDeviceAddress("TEST-EXPIRY"); + device.setUri("/device/testexpiry"); //$NON-NLS-1$ + device.setDeviceGroup("/deviceGroup/testexpiry"); //$NON-NLS-1$ + device.setDeviceName("TEST-EXPIRY"); //$NON-NLS-1$ + device.setDeviceAddress("testexpiry"); //$NON-NLS-1$ DateTime lastWeek = new DateTime().minusDays(60+1); device.setActivationDate(String.valueOf(lastWeek.getMillis())); String req = this.jsonMapper.toJson(device); - log.debug("Register Device Json req is " + this.jsonMapper.toJson(device)); + log.debug("Register Device Json req is " + this.jsonMapper.toJson(device)); //$NON-NLS-1$ List
    headers = new ArrayList
    (); - String userToken = getUserToken("app_user_1", "app_user_1"); - System.out.println("user token" +userToken); - headers.add(new BasicHeader("Authorization", userToken)); - headers.add(new BasicHeader("Content-Type", "application/json")); + String userToken = getUserToken("app_user_1", "app_user_1"); //$NON-NLS-1$ //$NON-NLS-2$ + + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ CloseableHttpResponse response = null; try @@ -385,13 +382,12 @@ public void checkDeviceActivationExpiry() response = this.restClient.post(url, req, headers, this.restConfig.getDefaultConnectionTimeout(), this.restConfig.getDefaultSocketTimeout()); Assert.assertNotNull(response); - System.out.println("in here "+response.toString()); // first time response is 200OK, next time its a validation failure due to expire time check - Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK") || (response.toString().contains("400 Bad Request") )); - String geturl = "http://localhost:" + this.localServerPort + "/device/"+device.getDeviceAddress(); + Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK") || (response.toString().contains("400 Bad Request") )); //$NON-NLS-1$ //$NON-NLS-2$ + String geturl = "http://localhost:" + this.localServerPort + "/device/"+device.getDeviceAddress(); //$NON-NLS-1$ //$NON-NLS-2$ response = this.restClient.get(geturl, headers); String body = EntityUtils.toString(response.getEntity()); - assertThat(body, containsString("Device has past its activation period.")); + assertThat(body, containsString("Device has past its activation period.")); //$NON-NLS-1$ } finally @@ -407,14 +403,19 @@ private RegisterDevice getRegisterDevice() { RegisterDevice device = new RegisterDevice(); // device.setUri("/device/test-guid"); //$NON-NLS-1$ + device.setActivationDate("1496181827187"); //$NON-NLS-1$ device.setActivationDate(String.valueOf(Instant.now().toEpochMilli())); // device.setCreatedDate(String.valueOf(Instant.now().toEpochMilli())); - device.setDeviceName("NUC-124-test-2"); //$NON-NLS-1$ - device.setDeviceAddress("NUC-124-test-2"); //$NON-NLS-1$ + device.setDeviceName("NUC-WR-IDP-E799-2"); //$NON-NLS-1$ + device.setDeviceAddress("WR-IDP-E799"); //$NON-NLS-1$ device.setDeviceType("NUC"); //$NON-NLS-1$ - device.setGroupRef("/group/testcompany-2"); //$NON-NLS-1$ + device.setDeviceGroup("/deviceGroup/testcompany-2"); //$NON-NLS-1$ // device.setUserId("bd9f70a3-8aaa-490b-b2a8-91ba59e58f0f"); //$NON-NLS-1$ device.setUri("/device/" + device.getDeviceAddress()); //$NON-NLS-1$ + GeoLocation geoLocation = new GeoLocation(); + geoLocation.setLatitude("51.5033640"); //$NON-NLS-1$ + geoLocation.setLongitude("-0.1276250"); //$NON-NLS-1$ + device.setGeoLocation(geoLocation); return device; } @@ -433,14 +434,14 @@ private String getUserToken(String username, String password) resourceDetails.setAccessTokenUri(url); - String[] clientIds = this.restConfig.getOauthClientId().split(":"); + String[] clientIds = this.restConfig.getOauthClientId().split(":"); //$NON-NLS-1$ resourceDetails.setClientId(clientIds[0]); resourceDetails.setClientSecret(clientIds[1]); OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails); OAuth2AccessToken token = restTemplate.getAccessToken(); - return token.getTokenType() + " " + token.getValue(); + return token.getTokenType() + " " + token.getValue(); //$NON-NLS-1$ } @@ -453,29 +454,31 @@ private String getClientToken(String clientId, String secret) clientCreds.setClientSecret(secret); OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(clientCreds); OAuth2AccessToken token = restTemplate.getAccessToken(); - return token.getTokenType() + " " + token.getValue(); + return token.getTokenType() + " " + token.getValue(); //$NON-NLS-1$ } - @SuppressWarnings("nls") + /** + * @throws Exception - + */ @Test public void getMachineDevice() throws Exception { RegisterDevice device = getRegisterDevice(); - String url = "http://localhost:" + this.localServerPort + "/device/" + device.getDeviceAddress(); + String url = "http://localhost:" + this.localServerPort + "/device/" + device.getDeviceAddress(); //$NON-NLS-1$ //$NON-NLS-2$ List
    headers = new ArrayList
    (); - String clientToken = getClientToken("device_client_id", "secret"); - headers.add(new BasicHeader("Authorization", clientToken)); - headers.add(new BasicHeader("Content-Type", "application/json")); + String clientToken = getClientToken("device_client_id", "secret"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", clientToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ CloseableHttpResponse response = null; try { response = this.restClient.get(url, headers); Assert.assertNotNull(response); - Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); + Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); //$NON-NLS-1$ String body = EntityUtils.toString(response.getEntity()); // assertThat(body, containsString("uri")); RegisterDevice registeredDevice = this.objectMapper.readValue(body, RegisterDevice.class); @@ -487,5 +490,73 @@ public void getMachineDevice() if ( response != null ) response.close(); } } + + + /** + * @throws Exception - + */ + @Test + public void resetDevice() + throws Exception + { + List
    headers = new ArrayList
    (); String userToken = getUserToken("app_user_1", "app_user_1"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ + + RegisterDevice device = getRegisterDevice(); + String url = "http://localhost:" + this.localServerPort + "/device/reset/" + device.getDeviceAddress(); //$NON-NLS-1$//$NON-NLS-2$ + + CloseableHttpResponse response = null; + try + { + response = this.restClient.put(url, "", headers, this.restConfig.getDefaultConnectionTimeout(), //$NON-NLS-1$ + this.restConfig.getDefaultSocketTimeout()); + Assert.assertNotNull(response); + Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); //$NON-NLS-1$ + String getUrl = "http://localhost:" + this.localServerPort + "/device/" + device.getDeviceAddress(); //$NON-NLS-1$//$NON-NLS-2$ + RegisterDevice newUpdatedDevice = getRegisterDevicebyId(headers,getUrl); + Assert.assertTrue(org.apache.commons.lang.StringUtils.equalsIgnoreCase(newUpdatedDevice.getActivationDate(), newUpdatedDevice.getUpdateDate())); + } + finally + { + if ( response != null ) response.close(); + } + } + + + /** + * + * @throws Exception - + */ + @SuppressWarnings({ "unchecked" }) + @Test + public void getAdminDevice() + throws Exception + { + + String url = "http://localhost:" + this.localServerPort + "/device/"; //$NON-NLS-1$ //$NON-NLS-2$ + List
    headers = new ArrayList
    (); + String userToken = getUserToken("app_admin_1", "secret"); //$NON-NLS-1$ //$NON-NLS-2$ + headers.add(new BasicHeader("Authorization", userToken)); //$NON-NLS-1$ + headers.add(new BasicHeader("Content-Type", "application/json")); //$NON-NLS-1$ //$NON-NLS-2$ + + CloseableHttpResponse response = null; + try + { + response = this.restClient.get(url, headers); + Assert.assertNotNull(response); + Assert.assertTrue(response.toString().contains("HTTP/1.1 200 OK")); //$NON-NLS-1$ + String body = EntityUtils.toString(response.getEntity()); + List registeredDevices = this.objectMapper.readValue(body, ArrayList.class); + assertTrue(registeredDevices != null); + assertTrue(registeredDevices.size() > 0); + + } + finally + { + if ( response != null ) response.close(); + } + } + }