com.imaginary.home.cloud.api.call.RelayCall.java Source code

Java tutorial

Introduction

Here is the source code for com.imaginary.home.cloud.api.call.RelayCall.java

Source

/*
 * Copyright (C) 2013 George Reese
 *
 * 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 com.imaginary.home.cloud.api.call;

import com.imaginary.home.cloud.Configuration;
import com.imaginary.home.cloud.ControllerRelay;
import com.imaginary.home.cloud.PendingCommand;
import com.imaginary.home.cloud.device.Device;
import com.imaginary.home.cloud.Location;
import com.imaginary.home.cloud.api.APICall;
import com.imaginary.home.cloud.api.RestException;
import org.dasein.persist.PersistenceException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * [Class Documentation]
 * <p>Created by George Reese: 1/24/13 3:07 PM</p>
 *
 * @author George Reese
 */
public class RelayCall extends APICall {
    @Override
    public void post(@Nonnull String requestId, @Nullable String userId, @Nonnull String[] path,
            @Nonnull HttpServletRequest req, @Nonnull HttpServletResponse resp,
            @Nonnull Map<String, Object> headers, @Nonnull Map<String, Object> parameters)
            throws RestException, IOException {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream()));
            StringBuilder source = new StringBuilder();
            String line;

            while ((line = reader.readLine()) != null) {
                source.append(line);
                source.append(" ");
            }
            JSONObject object = new JSONObject(source.toString());

            if (!object.has("pairingCode") || object.isNull("pairingCode")) {
                throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.MISSING_PAIRING_CODE,
                        "Pairing code is missing");
            }
            String code = object.getString("pairingCode");

            if (code.equalsIgnoreCase("null")) {
                throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.MISSING_PAIRING_CODE,
                        "Pairing code is missing");
            }
            Location location = Location.findForPairing(code);

            if (location == null) {
                throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_PAIRING_CODE,
                        "Invalid pairing code; pairing did not occur");
            }
            String relayName;

            if (object.has("name") && !object.isNull("name")) {
                relayName = object.getString("name");
            } else {
                throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.MISSING_DATA,
                        "Missing relay name from JSON");
            }
            ControllerRelay relay = location.pair(code, relayName);

            if (relay == null) {
                throw new RestException(HttpServletResponse.SC_FORBIDDEN, RestException.PAIRING_FAILURE,
                        "Pairing failed due to an invalid pairing code or expired pairing code");
            }
            HashMap<String, Object> json = new HashMap<String, Object>();

            json.put("apiKeyId", relay.getControllerRelayId());
            json.put("apiKeySecret", Configuration.decrypt(location.getLocationId(), relay.getApiKeySecret()));
            resp.setStatus(HttpServletResponse.SC_CREATED);
            resp.getWriter().println((new JSONObject(json)).toString());
            resp.getWriter().flush();
        } catch (JSONException e) {
            throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_JSON,
                    "Invalid JSON in body");
        } catch (PersistenceException e) {
            e.printStackTrace();
            throw new RestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, RestException.INTERNAL_ERROR,
                    "Internal database error");
        }
    }

    @Override
    public void put(@Nonnull String requestId, @Nullable String userId, @Nonnull String[] path,
            @Nonnull HttpServletRequest req, @Nonnull HttpServletResponse resp,
            @Nonnull Map<String, Object> headers, @Nonnull Map<String, Object> parameters)
            throws RestException, IOException {
        try {
            if (path.length < 2) {
                throw new RestException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, RestException.INVALID_OPERATION,
                        "No PUT on /relay");
            }
            ControllerRelay relay = ControllerRelay.getRelay(path[1]);

            if (relay == null) {
                throw new RestException(HttpServletResponse.SC_NOT_FOUND, RestException.NO_SUCH_OBJECT,
                        "Relay " + path[1] + " not found");
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream()));
            StringBuilder source = new StringBuilder();
            String line;

            while ((line = reader.readLine()) != null) {
                source.append(line);
                source.append(" ");
            }
            JSONObject object = new JSONObject(source.toString());
            String action;

            if (object.has("action") && !object.isNull("action")) {
                action = object.getString("action");
            } else {
                throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_ACTION,
                        "An invalid action was specified (or not specified) in the PUT");
            }
            if (action.equalsIgnoreCase("update")) {
                if (userId != null) {
                    throw new RestException(HttpServletResponse.SC_FORBIDDEN, RestException.USER_NOT_ALLOWED,
                            "This API call may be called only by controller relays");
                }
                update(relay, object, resp);
            } else if (action.equalsIgnoreCase("modify")) {
                if (object.has("relay")) {
                    object = object.getJSONObject("relay");
                } else {
                    object = null;
                }
                if (object == null) {
                    throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_PUT,
                            "No location was specified in the PUT");
                }
                String name;

                if (object.has("name") && !object.isNull("name")) {
                    name = object.getString("name");
                } else {
                    name = relay.getName();
                }
                relay.modify(name);
                resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
            } else {
                throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_ACTION,
                        "The action " + action + " is not a valid action.");
            }
        } catch (JSONException e) {
            throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_JSON,
                    "Invalid JSON in body");
        } catch (PersistenceException e) {
            e.printStackTrace();
            throw new RestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, RestException.INTERNAL_ERROR,
                    "Internal database error");
        }
    }

    private void update(ControllerRelay relay, JSONObject state, HttpServletResponse resp)
            throws RestException, IOException, JSONException {
        try {
            if (state.has("relay")) {
                JSONObject r = state.getJSONObject("relay");

                if (r.has("devices")) {
                    HashMap<String, Device> found = new HashMap<String, Device>();
                    JSONArray devices = r.getJSONArray("devices");

                    for (int i = 0; i < devices.length(); i++) {
                        JSONObject device = devices.getJSONObject(i);

                        if (!device.has("deviceId") || device.isNull("deviceId") || !device.has("deviceType")
                                || device.isNull("deviceType") || !device.has("systemId")
                                || device.isNull("systemId")) {
                            continue;
                        }
                        String id = device.getString("deviceId");
                        String t = device.getString("deviceType");
                        String systemId = device.getString("systemId");
                        Device d = Device.getDevice(t, relay, systemId, id);

                        if (d == null) {
                            d = Device.create(relay, t, device);
                        } else {
                            d.update(device);
                        }
                        found.put(d.getDeviceId(), d);
                    }
                    for (Device d : Device.findDevicesForRelay(relay)) {
                        if (!found.containsKey(d.getDeviceId())) {
                            d.remove();
                        }
                    }
                }
            }
            resp.addHeader("x-imaginary-has-commands", String.valueOf(PendingCommand.hasCommands(relay)));
            resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
        } catch (PersistenceException e) {
            throw new RestException(e);
        }
    }
}