Java tutorial
/* * Copyright 2016 Brigham Young University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.byu.mpn.rest; import com.amazonaws.services.sns.model.InvalidParameterException; import edu.byu.mpn.da.interfaces.DeviceDao; import edu.byu.mpn.domain.Device; import edu.byu.mpn.helpers.ResponseMessage; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import javax.ws.rs.*; import javax.ws.rs.core.Response; import java.util.Date; /** * Created by cwoodfie on 4/5/16. */ @Service @Produces("application/json") @Consumes("application/json") @Path("/v1/devices") public class DeviceController extends BaseController { private static final Logger LOG = LogManager.getLogger(DeviceController.class); public static final String EX_OUT_OF_DATE = "The resource you passed in is out of date. Please refresh your device info and try again."; public static final String EX_EMPTY_REQUEST = "No request body provided."; public static final String EX_MISSING_ID = "The id of the device must be included in the request body."; public static final String EX_ID_CONFLICT = "The id in the url does not match the id included in the device."; public static final String EX_PERSONID_MISSING = "The request body must include a personId."; public static final String EX_TOKEN_MISSING = "The request body must include a valid token"; public static final String EX_NACHO_DEVICE = "The device you are trying to access is registered to somebody else."; public static final String EX_NACHO_PERSONID = "The personId included in the device does not match the logged in user. Please use your own personId and try again."; public static final String EX_MISSING_PARAMETER_FORMAT = "The device passed in was missing the %s parameter"; public static final String EX_UNSUPPORTED_PLATFORM = "Mobile Push Notifications have not been implemented for your device platform. \"Android\" and \"Apple\" are currently the only valid platforms."; private DeviceDao deviceDao; private String applePlatformApplicationArn; private String androidPlatformApplicationArn; private String topicArn; private String testTopicArn; @Autowired public void setDeviceDao(DeviceDao deviceDao) { this.deviceDao = deviceDao; } @Autowired public void setApplePlatformApplicationArn( @Qualifier("applePlatformApplicationArn") String applePlatformApplicationArn) { this.applePlatformApplicationArn = applePlatformApplicationArn; } @Autowired public void setAndroidPlatformApplicationArn( @Qualifier("androidPlatformApplicationArn") String androidPlatformApplicationArn) { this.androidPlatformApplicationArn = androidPlatformApplicationArn; } @Autowired public void setTopicArn(@Qualifier("topicArn") String topicArn) { this.topicArn = topicArn; } @Autowired public void setTestTopicArn(@Qualifier("testTopicArn") String testTopicArn) { this.testTopicArn = testTopicArn; } @GET public Response getAllDevices(@QueryParam("personId") @DefaultValue("") final String personId) { LOG.info("/v1/devices GET"); if (personId.isEmpty()) { return Response.status(Response.Status.OK).entity(deviceDao.getAllDevices()).build(); } else { return Response.status(Response.Status.OK).entity(deviceDao.getAllDevicesByPersonId(personId)).build(); } } @Path("/{id}") @GET public Response getDeviceById(@PathParam("id") Integer id, @DefaultValue("") @QueryParam("proxyId") String proxyId) { LOG.info("/v1/devices/{id} GET"); Device device = deviceDao.getDeviceById(id); if (device == null) { return Response.status(Response.Status.NOT_FOUND).build(); } else if (device.getPersonId() != null && !device.getPersonId().equals(getPersonId(proxyId))) { return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_DEVICE)).build(); } return Response.status(Response.Status.OK).entity(device).build(); } @POST public Response createDevice(@DefaultValue("") @QueryParam("proxyId") String proxyId, @DefaultValue("false") @QueryParam("testTopic") boolean testTopic, Device device) { LOG.info("/v1/devices POST"); Response errorResponse = validateCreateDevice(device, proxyId); if (errorResponse != null) { return errorResponse; } // Checks whether device already exists Device deviceByToken = deviceDao.getDeviceByTokenAndPlatform(device.getToken(), device.getDevicePlatform()); if (deviceByToken != null) { if (device.getPersonId().equals(deviceByToken.getPersonId())) { return Response.status(Response.Status.OK).entity(deviceByToken).build(); } else { return Response.status(Response.Status.FORBIDDEN).entity(EX_NACHO_DEVICE).build(); } } device.setDateRegistered(new Date()); final String platformApplicationArn = APPLE.equals(device.getDevicePlatform()) ? applePlatformApplicationArn : androidPlatformApplicationArn; try { device.setEndpointArn( mpnClient.createPlatformEndpoint(device.getToken(), platformApplicationArn).getEndpointArn()); device.setSubscriptionArn(mpnClient.subscribeDevice(device.getEndpointArn(), topicArn, device.getPersonId(), device.getDeviceName()).getSubscriptionArn()); if (testTopic) { mpnClient.subscribeDevice(device.getEndpointArn(), testTopicArn, device.getPersonId(), device.getDeviceName()); } } catch (InvalidParameterException e) { LOG.error(e.getMessage(), e); return Response.status(Response.Status.BAD_REQUEST).entity(new ResponseMessage(e.getMessage())).build(); } deviceDao.saveOrUpdateDevice(device, getLoggedInPersonId()); return Response.status(Response.Status.CREATED).entity(device).build(); } private Response validateCreateDevice(Device device, String proxyId) { String missingParameter = null; if (device == null) { return Response.status(Response.Status.BAD_REQUEST).entity(new ResponseMessage(EX_EMPTY_REQUEST)) .build(); } else if (device.getDeviceId() == null || device.getDeviceId().isEmpty()) { missingParameter = "deviceId"; } else if (device.getPersonId() == null || device.getPersonId().isEmpty()) { missingParameter = "personId"; } else if (device.getToken() == null || device.getToken().isEmpty()) { missingParameter = "token"; } else if (device.getDeviceName() == null || device.getDeviceName().isEmpty()) { missingParameter = "deviceName"; } else if (device.getDevicePlatform() == null || device.getDevicePlatform().isEmpty()) { missingParameter = "devicePlatform"; } if (missingParameter != null) { return Response.status(Response.Status.BAD_REQUEST) .entity(new ResponseMessage(String.format(EX_MISSING_PARAMETER_FORMAT, missingParameter))) .build(); } else if (!device.getPersonId().equals(getPersonId(proxyId))) { return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_PERSONID)) .build(); } else if (!isValidDevicePlatform(device.getDevicePlatform())) { return Response.status(501).entity(new ResponseMessage(EX_UNSUPPORTED_PLATFORM)).build(); } return null; } private boolean isValidDevicePlatform(String devicePlatform) { return ANDROID.equals(devicePlatform) || APPLE.equals(devicePlatform); } @Path("/{id}") @PUT public Response updateDevice(@PathParam("id") Integer id, @DefaultValue("") @QueryParam("proxyId") String proxyId, Device device) { LOG.info("/v1/devices/{id} PUT"); Response errorResponse = validateUpdateDevice(id, device, proxyId); if (errorResponse != null) { return errorResponse; } Device currentDevice = deviceDao.getDeviceById(id); // If deviceId or deviceName are included in the request body, update them in the database currentDevice .setDeviceId(device.getDeviceId() == null ? currentDevice.getDeviceId() : device.getDeviceId()); currentDevice.setDeviceName( device.getDeviceName() == null ? currentDevice.getDeviceName() : device.getDeviceName()); if (currentDevice.getPersonId() == null) { // If device is being registered, set new dateRegistered currentDevice.setDateRegistered(new Date()); currentDevice.setPersonId(device.getPersonId()); currentDevice.setSubscriptionArn(mpnClient.subscribeDevice(currentDevice.getEndpointArn(), topicArn, currentDevice.getPersonId(), currentDevice.getDeviceName()).getSubscriptionArn()); } if (!currentDevice.getToken().equals(device.getToken())) { currentDevice.setToken(device.getToken()); try { mpnClient.updatePlatformEndpoint(currentDevice.getToken(), currentDevice.getEndpointArn()); } catch (InvalidParameterException e) { LOG.error(e.getMessage(), e); return Response.status(Response.Status.BAD_REQUEST).entity(new ResponseMessage(e.getMessage())) .build(); } } deviceDao.saveOrUpdateDevice(currentDevice, getLoggedInPersonId()); return Response.status(Response.Status.OK).entity(currentDevice).build(); } private Response validateUpdateDevice(Integer id, Device device, String proxyId) { String errorMessage = null; if (device == null) { errorMessage = EX_EMPTY_REQUEST; } else if (device.getId() == null) { errorMessage = EX_MISSING_ID; } else if (!id.equals(device.getId())) { errorMessage = EX_ID_CONFLICT; } else if (device.getPersonId() == null || device.getPersonId().isEmpty()) { errorMessage = EX_PERSONID_MISSING; } else if (device.getToken() == null || device.getToken().isEmpty()) { errorMessage = EX_TOKEN_MISSING; } if (errorMessage != null) { return Response.status(Response.Status.BAD_REQUEST).entity(new ResponseMessage(errorMessage)).build(); } Device oldDevice = deviceDao.getDeviceById(id); if (oldDevice == null) { return Response.status(Response.Status.NOT_FOUND).build(); } else if (!device.getPersonId().equals(getPersonId(proxyId))) { return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_PERSONID)) .build(); } else if (!(device.getPersonId().equals(oldDevice.getPersonId()) || oldDevice.getPersonId() == null || oldDevice.getPersonId().isEmpty())) { return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_DEVICE)).build(); } return null; } @Path("/{id}") @DELETE public Response unregisterDevice(@PathParam("id") Integer id, @DefaultValue("") @QueryParam("proxyId") String proxyId) { LOG.info("/v1/devices/{id} DELETE"); Device device = deviceDao.getDeviceById(id); if (device == null) { return Response.status(Response.Status.NOT_FOUND).build(); } else if (device.getPersonId() == null) { // The device is already unregistered, so return success return Response.status(Response.Status.OK).entity(device).build(); } else if (!device.getPersonId().equals(getPersonId(proxyId))) { // The authenticated user does not match the devices registered owner return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_DEVICE)).build(); } device.setPersonId(null); mpnClient.unsubscribeDevice(device.getEndpointArn(), device.getSubscriptionArn()); device.setSubscriptionArn(null); deviceDao.saveOrUpdateDevice(device, getLoggedInPersonId()); return Response.status(Response.Status.OK).entity(device).build(); } }