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  
21  package org.waarp.openr66.protocol.http.restv2.dbhandlers;
22  
23  import com.fasterxml.jackson.databind.node.ObjectNode;
24  import io.cdap.http.HttpResponder;
25  import io.netty.handler.codec.http.DefaultHttpHeaders;
26  import io.netty.handler.codec.http.HttpHeaders;
27  import io.netty.handler.codec.http.HttpMethod;
28  import io.netty.handler.codec.http.HttpRequest;
29  import org.waarp.openr66.dao.DAOFactory;
30  import org.waarp.openr66.dao.LimitDAO;
31  import org.waarp.openr66.dao.exception.DAOConnectionException;
32  import org.waarp.openr66.dao.exception.DAONoDataException;
33  import org.waarp.openr66.pojo.Limit;
34  import org.waarp.openr66.protocol.http.restv2.converters.LimitsConverter;
35  import org.waarp.openr66.protocol.http.restv2.errors.RestErrorException;
36  import org.waarp.openr66.protocol.http.restv2.utils.JsonUtils;
37  
38  import javax.ws.rs.Consumes;
39  import javax.ws.rs.DELETE;
40  import javax.ws.rs.GET;
41  import javax.ws.rs.InternalServerErrorException;
42  import javax.ws.rs.OPTIONS;
43  import javax.ws.rs.POST;
44  import javax.ws.rs.PUT;
45  import javax.ws.rs.Path;
46  import java.util.ArrayList;
47  import java.util.List;
48  
49  import static io.netty.handler.codec.http.HttpResponseStatus.*;
50  import static javax.ws.rs.core.HttpHeaders.*;
51  import static javax.ws.rs.core.MediaType.*;
52  import static org.waarp.common.role.RoleDefault.ROLE.*;
53  import static org.waarp.openr66.protocol.configuration.Configuration.*;
54  import static org.waarp.openr66.protocol.http.restv2.RestConstants.*;
55  import static org.waarp.openr66.protocol.http.restv2.errors.RestErrors.*;
56  
57  /**
58   * This is the {@link AbstractRestDbHandler} handling all requests made on the
59   * bandwidth limits REST entry
60   * point.
61   */
62  @Path(LIMITS_HANDLER_URI)
63  public class LimitsHandler extends AbstractRestDbHandler {
64  
65    /**
66     * The content of the 'Allow' header sent when an 'OPTIONS' request is made
67     * on the handler.
68     */
69    private static final HttpHeaders OPTIONS_HEADERS;
70  
71    static {
72      OPTIONS_HEADERS = new DefaultHttpHeaders();
73      final List<HttpMethod> allow = new ArrayList<HttpMethod>();
74      allow.add(HttpMethod.GET);
75      allow.add(HttpMethod.POST);
76      allow.add(HttpMethod.PUT);
77      allow.add(HttpMethod.DELETE);
78      allow.add(HttpMethod.OPTIONS);
79      OPTIONS_HEADERS.add(ALLOW, allow);
80    }
81  
82    /**
83     * Initializes the handler with the given CRUD mask.
84     *
85     * @param crud the CRUD mask for this handler
86     */
87    public LimitsHandler(final byte crud) {
88      super(crud);
89    }
90  
91    /**
92     * Method called to obtain a description of the host's current bandwidth
93     * limits.
94     *
95     * @param request the HttpRequest made on the resource
96     * @param responder the HttpResponder which sends the reply to the
97     *     request
98     */
99    @GET
100   @Consumes(WILDCARD)
101   @RequiredRole(LIMIT)
102   public final void getLimits(final HttpRequest request,
103                               final HttpResponder responder) {
104     LimitDAO limitDAO = null;
105     try {
106       limitDAO = DAO_FACTORY.getLimitDAO(true);
107       final String host = serverName();
108       if (limitDAO.exist(host)) {
109         final Limit limits = limitDAO.select(host);
110         final ObjectNode responseObject = LimitsConverter.limitToNode(limits);
111         final String responseText = JsonUtils.nodeToString(responseObject);
112         responder.sendJson(OK, responseText);
113       } else {
114         responder.sendStatus(NOT_FOUND);
115       }
116     } catch (final DAOConnectionException e) {
117       throw new InternalServerErrorException(e);
118     } catch (final DAONoDataException e) {
119       responder.sendStatus(NOT_FOUND);
120     } finally {
121       DAOFactory.closeDAO(limitDAO);
122     }
123   }
124 
125   /**
126    * Method called to initiate the entry for this host in the bandwidth limits
127    * database. If the host already has
128    * limits set in its configuration, they will be replaced by these new
129    * ones.
130    *
131    * @param request the HttpRequest made on the resource
132    * @param responder the HttpResponder which sends the reply to the
133    *     request
134    */
135   @POST
136   @Consumes(APPLICATION_JSON)
137   @RequiredRole(READONLY)
138   public final void initializeLimits(final HttpRequest request,
139                                      final HttpResponder responder) {
140     LimitDAO limitDAO = null;
141     try {
142       limitDAO = DAO_FACTORY.getLimitDAO(false);
143 
144       if (!limitDAO.exist(serverName())) {
145         final ObjectNode requestObject = JsonUtils.deserializeRequest(request);
146         checkSanity(requestObject);
147         final Limit limits = LimitsConverter.nodeToNewLimit(requestObject);
148         limitDAO.insert(limits);
149 
150         configuration.changeNetworkLimit(limits.getReadGlobalLimit(),
151                                          limits.getWriteGlobalLimit(),
152                                          limits.getReadSessionLimit(),
153                                          limits.getWriteSessionLimit(),
154                                          limits.getDelayLimit());
155 
156         final ObjectNode responseObject = LimitsConverter.limitToNode(limits);
157         final String responseText = JsonUtils.nodeToString(responseObject);
158         responder.sendJson(CREATED, responseText);
159       } else {
160         throw new RestErrorException(ALREADY_EXISTING(serverName()));
161       }
162     } catch (final DAOConnectionException e) {
163       throw new InternalServerErrorException(e);
164     } finally {
165       DAOFactory.closeDAO(limitDAO);
166     }
167   }
168 
169   /**
170    * Method called to update this host's bandwidth limits in the database and
171    * configuration.
172    *
173    * @param request the HttpRequest made on the resource
174    * @param responder the HttpResponder which sends the reply to the
175    *     request
176    */
177   @PUT
178   @Consumes(APPLICATION_JSON)
179   @RequiredRole(LIMIT)
180   public final void updateLimits(final HttpRequest request,
181                                  final HttpResponder responder) {
182     LimitDAO limitDAO = null;
183     try {
184       limitDAO = DAO_FACTORY.getLimitDAO(false);
185 
186       if (!limitDAO.exist(serverName())) {
187         responder.sendStatus(NOT_FOUND);
188         return;
189       }
190 
191       final ObjectNode requestObject = JsonUtils.deserializeRequest(request);
192       checkSanity(requestObject);
193       final Limit oldLimits = limitDAO.select(serverName());
194       final Limit newLimits =
195           LimitsConverter.nodeToUpdatedLimit(requestObject, oldLimits);
196 
197       limitDAO.update(newLimits);
198 
199       configuration.changeNetworkLimit(newLimits.getReadGlobalLimit(),
200                                        newLimits.getWriteGlobalLimit(),
201                                        newLimits.getReadSessionLimit(),
202                                        newLimits.getWriteSessionLimit(),
203                                        newLimits.getDelayLimit());
204 
205       final ObjectNode responseObject = LimitsConverter.limitToNode(newLimits);
206       final String responseText = JsonUtils.nodeToString(responseObject);
207       responder.sendJson(CREATED, responseText);
208 
209     } catch (final DAOConnectionException e) {
210       throw new InternalServerErrorException(e);
211     } catch (final DAONoDataException e) {
212       responder.sendStatus(NOT_FOUND);
213     } finally {
214       DAOFactory.closeDAO(limitDAO);
215     }
216   }
217 
218   /**
219    * Method called to remove any bandwidth limits in place on this host. Also
220    * removes any limits set in the
221    * configuration.
222    *
223    * @param request the HttpRequest made on the resource
224    * @param responder the HttpResponder which sends the reply to the
225    *     request
226    */
227   @DELETE
228   @Consumes(WILDCARD)
229   @RequiredRole(LIMIT)
230   public final void deleteLimits(final HttpRequest request,
231                                  final HttpResponder responder) {
232     LimitDAO limitDAO = null;
233     try {
234       limitDAO = DAO_FACTORY.getLimitDAO(false);
235 
236       if (limitDAO.exist(serverName())) {
237         limitDAO.delete(limitDAO.select(serverName()));
238         configuration.changeNetworkLimit(0, 0, 0, 0, 0);
239         responder.sendStatus(NO_CONTENT);
240       } else {
241         responder.sendStatus(NOT_FOUND);
242       }
243     } catch (final DAOConnectionException e) {
244       throw new InternalServerErrorException(e);
245     } catch (final DAONoDataException e) {
246       responder.sendStatus(NOT_FOUND);
247     } finally {
248       DAOFactory.closeDAO(limitDAO);
249     }
250   }
251 
252   /**
253    * Method called to get a list of all allowed HTTP methods on this entry
254    * point. The HTTP methods are sent as
255    * an array in the reply's headers.
256    *
257    * @param request the HttpRequest made on the resource
258    * @param responder the HttpResponder which sends the reply to the
259    *     request
260    */
261   @OPTIONS
262   @Consumes(WILDCARD)
263   @RequiredRole(NOACCESS)
264   public final void options(final HttpRequest request,
265                             final HttpResponder responder) {
266     responder.sendStatus(OK, OPTIONS_HEADERS);
267   }
268 }