/******************************************************************************* * Copyright (c) 2015 Sierra Wireless and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.html. * * Contributors: * Sierra Wireless - initial API and implementation *******************************************************************************/ package org.eclipse.leshan.server.bootstrap.demo.servlet; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.eclipse.leshan.server.bootstrap.BootstrapConfig; import org.eclipse.leshan.server.bootstrap.demo.BootstrapStoreImpl; import org.eclipse.leshan.server.bootstrap.demo.ConfigurationChecker.ConfigurationException; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import com.google.gson.JsonSyntaxException; /** * Servlet for REST API in charge of adding bootstrap information to the bootstrap server. */ @SuppressWarnings("serial") public class BootstrapServlet extends HttpServlet { private static class SignedByteUnsignedByteAdapter implements JsonSerializer<Byte>, JsonDeserializer<Byte> { @Override public Byte deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return json.getAsByte(); } @Override public JsonElement serialize(Byte src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive((int) src & 0xff); } } private final BootstrapStoreImpl bsStore; private final Gson gson; public BootstrapServlet(BootstrapStoreImpl bsStore) { this.bsStore = bsStore; this.gson = new GsonBuilder().registerTypeHierarchyAdapter(Byte.class, new SignedByteUnsignedByteAdapter()) .create(); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getPathInfo() != null) { sendError(resp, HttpServletResponse.SC_NOT_FOUND, "bad URL"); return; } resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType("application/json"); resp.getOutputStream().write(gson.toJson(bsStore.getBootstrapConfigs()).getBytes(StandardCharsets.UTF_8)); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getPathInfo() == null) { // we need the endpoint in the URL sendError(resp, HttpServletResponse.SC_BAD_REQUEST, "endpoint name should be specified in the URL"); return; } String[] path = StringUtils.split(req.getPathInfo(), '/'); // endPoint if (path.length != 1) { sendError(resp, HttpServletResponse.SC_BAD_REQUEST, "endpoint name should be specified in the URL, nothing more"); return; } String endpoint = path[0]; try { BootstrapConfig cfg = gson.fromJson(new InputStreamReader(req.getInputStream()), BootstrapConfig.class); if (cfg == null) { sendError(resp, HttpServletResponse.SC_BAD_REQUEST, "no content"); } else { bsStore.addConfig(endpoint, cfg); resp.setStatus(HttpServletResponse.SC_OK); } } catch (JsonSyntaxException | ConfigurationException e) { sendError(resp, HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); } } @Override protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getPathInfo() == null) { // we need the endpoint in the URL sendError(resp, HttpServletResponse.SC_BAD_REQUEST, "endpoint name should be specified in the URL"); return; } String[] path = StringUtils.split(req.getPathInfo(), '/'); // endPoint if (path.length != 1) { sendError(resp, HttpServletResponse.SC_BAD_REQUEST, "endpoint name should be specified in the URL, nothing more"); return; } String endpoint = path[0]; if (bsStore.deleteConfig(endpoint)) { resp.setStatus(HttpServletResponse.SC_NO_CONTENT); } else { sendError(resp, HttpServletResponse.SC_NOT_FOUND, "no config for " + endpoint); } } private void sendError(HttpServletResponse resp, int statusCode, String errorMessage) throws IOException { resp.setStatus(statusCode); resp.setContentType("text/plain; charset=UTF-8"); if (errorMessage != null) resp.getOutputStream().write(errorMessage.getBytes(StandardCharsets.UTF_8)); } }