View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.openr66.protocol.http.rest.handler;
21  
22  import com.fasterxml.jackson.databind.node.ArrayNode;
23  import com.fasterxml.jackson.databind.node.ObjectNode;
24  import io.netty.handler.codec.http.HttpResponseStatus;
25  import org.waarp.common.database.data.AbstractDbData;
26  import org.waarp.common.exception.InvalidArgumentException;
27  import org.waarp.common.json.JsonHandler;
28  import org.waarp.common.logging.WaarpLogger;
29  import org.waarp.common.logging.WaarpLoggerFactory;
30  import org.waarp.common.utility.WaarpShutdownHook;
31  import org.waarp.common.utility.WaarpStringUtils;
32  import org.waarp.gateway.kernel.exception.HttpIncorrectRequestException;
33  import org.waarp.gateway.kernel.exception.HttpInvalidAuthenticationException;
34  import org.waarp.gateway.kernel.rest.DataModelRestMethodHandler.COMMAND_TYPE;
35  import org.waarp.gateway.kernel.rest.HttpRestHandler;
36  import org.waarp.gateway.kernel.rest.HttpRestHandler.METHOD;
37  import org.waarp.gateway.kernel.rest.RestArgument;
38  import org.waarp.gateway.kernel.rest.RestConfiguration;
39  import org.waarp.openr66.protocol.configuration.Configuration;
40  import org.waarp.openr66.protocol.configuration.Messages;
41  import org.waarp.openr66.protocol.exception.OpenR66ProtocolBusinessException;
42  import org.waarp.openr66.protocol.exception.OpenR66ProtocolNotAuthenticatedException;
43  import org.waarp.openr66.protocol.exception.OpenR66ProtocolPacketException;
44  import org.waarp.openr66.protocol.exception.OpenR66ProtocolShutdownException;
45  import org.waarp.openr66.protocol.http.rest.HttpRestR66Handler;
46  import org.waarp.openr66.protocol.http.rest.HttpRestR66Handler.RESTHANDLERS;
47  import org.waarp.openr66.protocol.localhandler.ServerActions;
48  import org.waarp.openr66.protocol.localhandler.packet.json.JsonPacket;
49  import org.waarp.openr66.protocol.localhandler.packet.json.ShutdownOrBlockJsonPacket;
50  import org.waarp.openr66.protocol.utils.ChannelUtils;
51  
52  /**
53   * Server Http REST interface: http://host/server?... +
54   * ShutdownOrBlockJsonPacket as PUT or no Json body but
55   * GET to get Current Status in Json
56   */
57  public class HttpRestServerR66Handler extends HttpRestAbstractR66Handler {
58  
59    public static final String BASEURI = "server";
60    /**
61     * Internal Logger
62     */
63    private static final WaarpLogger logger =
64        WaarpLoggerFactory.getLogger(HttpRestServerR66Handler.class);
65  
66    public HttpRestServerR66Handler(final RestConfiguration config,
67                                    final METHOD... methods) {
68      super(BASEURI, config, METHOD.OPTIONS);
69      setIntersectionMethods(methods, METHOD.GET, METHOD.PUT);
70    }
71  
72    @Override
73    public final void endParsingRequest(final HttpRestHandler handler,
74                                        final RestArgument arguments,
75                                        final RestArgument result,
76                                        final Object body)
77        throws HttpIncorrectRequestException, HttpInvalidAuthenticationException {
78      try {
79        HttpRestV1Utils.checkSanity(arguments);
80      } catch (final InvalidArgumentException e) {
81        throw new HttpIncorrectRequestException("Issue on values", e);
82      }
83      logger.debug("debug: {} ### {}", arguments, result);
84      if (body != null) {
85        logger.debug("Obj: {}", body);
86      }
87      handler.setWillClose(false);
88      final ServerActions serverHandler =
89          ((HttpRestR66Handler) handler).getServerHandler();
90      if (arguments.getMethod() == METHOD.GET) {
91        // status Json
92        result.setCommand(ACTIONS_TYPE.GetStatus.name());
93        Configuration.configuration.getMonitoring().run(0, true);
94        final ObjectNode node =
95            Configuration.configuration.getMonitoring().exportAsJson(true);
96        result.setDetail("Current Waarp R66 status");
97        result.addResult(node);
98        setOk(handler, result, null, HttpResponseStatus.OK);
99        return;
100     }
101     // now action according to body
102     final JsonPacket json = (JsonPacket) body;
103     if (json == null) {
104       result.setDetail("not enough information");
105       setError(handler, result, HttpResponseStatus.BAD_REQUEST);
106       return;
107     }
108     result.getAnswer()
109           .put(AbstractDbData.JSON_MODEL, RESTHANDLERS.Server.name());
110     try {
111       if (json instanceof ShutdownOrBlockJsonPacket) {//
112         final ShutdownOrBlockJsonPacket node = (ShutdownOrBlockJsonPacket) json;
113         result.setCommand(ACTIONS_TYPE.ShutdownOrBlock.name());
114         final byte[] key = node.getKey();
115         if (node.isShutdownOrBlock()) {
116           // Shutdown
117           serverHandler.shutdown(key, node.isRestartOrBlock());
118           result.setDetail("Shutdown on going");
119         } else {
120           // Block
121           serverHandler.blockRequest(key, node.isRestartOrBlock());
122           node.setComment(
123               (node.isRestartOrBlock()? "Block" : "Unblock") + " new request");
124           result.setDetail(
125               (node.isRestartOrBlock()? "Block" : "Unblock") + " new request");
126         }
127         setOk(handler, result, json, HttpResponseStatus.OK);
128       } else {
129         logger.info("Validation is ignored: {}", json);
130         result.setDetail("Unknown command");
131         setError(handler, result, json, HttpResponseStatus.PRECONDITION_FAILED);
132       }
133     } catch (final OpenR66ProtocolNotAuthenticatedException e) {
134       throw new HttpInvalidAuthenticationException(e);
135     } catch (final OpenR66ProtocolBusinessException e) {
136       throw new HttpIncorrectRequestException(e);
137     } catch (final OpenR66ProtocolShutdownException e) {
138       result.setDetail("Shutdown on going");
139       setOk(handler, result, json, HttpResponseStatus.OK);
140       WaarpShutdownHook.shutdownWillStart();
141       logger.warn(Messages.getString("LocalServerHandler.0") + //$NON-NLS-1$
142                   serverHandler.getSession().getAuth().getUser());
143       // dont'close, thread will do
144       ChannelUtils.startShutdown();
145     }
146   }
147 
148   @Override
149   protected final ArrayNode getDetailedAllow() {
150     final ArrayNode node = JsonHandler.createArrayNode();
151 
152     if (methods.contains(METHOD.PUT)) {
153       final ShutdownOrBlockJsonPacket node3 = new ShutdownOrBlockJsonPacket();
154       node3.setComment("Shutdown Or Block request (PUT)");
155       node3.setKey("Key".getBytes(WaarpStringUtils.UTF8));
156       final ObjectNode node2;
157       final ArrayNode node1 = JsonHandler.createArrayNode();
158       try {
159         node1.add(node3.createObjectNode());
160         node2 = RestArgument.fillDetailedAllow(METHOD.PUT, path,
161                                                ACTIONS_TYPE.ShutdownOrBlock.name(),
162                                                node3.createObjectNode(), node1);
163         node.add(node2);
164       } catch (final OpenR66ProtocolPacketException ignored) {
165         // ignore
166       }
167     }
168     if (methods.contains(METHOD.GET)) {
169       final ArrayNode node1 = JsonHandler.createArrayNode();
170       node1.add(Configuration.configuration.getMonitoring().exportAsJson(true));
171       final ObjectNode node2 = RestArgument.fillDetailedAllow(METHOD.GET, path,
172                                                               ACTIONS_TYPE.GetStatus.name(),
173                                                               null, node1);
174       node.add(node2);
175     }
176 
177     final ObjectNode node2 =
178         RestArgument.fillDetailedAllow(METHOD.OPTIONS, path,
179                                        COMMAND_TYPE.OPTIONS.name(), null, null);
180     node.add(node2);
181 
182     return node;
183   }
184 }