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.BusinessDAO;
30  import org.waarp.openr66.dao.DAOFactory;
31  import org.waarp.openr66.dao.exception.DAOConnectionException;
32  import org.waarp.openr66.dao.exception.DAONoDataException;
33  import org.waarp.openr66.pojo.Business;
34  import org.waarp.openr66.protocol.http.restv2.converters.HostConfigConverter;
35  import org.waarp.openr66.protocol.http.restv2.errors.RestErrorException;
36  import org.waarp.openr66.protocol.http.restv2.utils.JsonUtils;
37  import org.waarp.openr66.protocol.utils.Version;
38  
39  import javax.ws.rs.Consumes;
40  import javax.ws.rs.DELETE;
41  import javax.ws.rs.GET;
42  import javax.ws.rs.InternalServerErrorException;
43  import javax.ws.rs.OPTIONS;
44  import javax.ws.rs.POST;
45  import javax.ws.rs.PUT;
46  import javax.ws.rs.Path;
47  import java.util.ArrayList;
48  import java.util.List;
49  
50  import static io.netty.handler.codec.http.HttpResponseStatus.*;
51  import static javax.ws.rs.core.HttpHeaders.*;
52  import static javax.ws.rs.core.MediaType.*;
53  import static org.waarp.common.role.RoleDefault.ROLE.*;
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   * host configuration REST entry
60   * point.
61   */
62  @Path(CONFIG_HANDLER_URI)
63  public class HostConfigHandler 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 HostConfigHandler(final byte crud) {
88      super(crud);
89    }
90  
91    /**
92     * Method called to retrieve a host's configuration entry in the database.
93     *
94     * @param request the HttpRequest made on the resource
95     * @param responder the HttpResponder which sends the reply to the
96     *     request
97     */
98    @GET
99    @Consumes(WILDCARD)
100   @RequiredRole(READONLY)
101   public final void getConfig(final HttpRequest request,
102                               final HttpResponder responder) {
103     BusinessDAO businessDAO = null;
104     try {
105       businessDAO = DAO_FACTORY.getBusinessDAO(true);
106       final String host = serverName();
107       final Business business = businessDAO.select(host);
108       if (business != null) {
109         final ObjectNode responseObject =
110             HostConfigConverter.businessToNode(business);
111         responseObject.put("versionR66", Version.ID);
112         responseObject.put("versionBin",
113                            org.waarp.common.utility.Version.fullIdentifier());
114         final String responseText = JsonUtils.nodeToString(responseObject);
115         responder.sendJson(OK, responseText);
116       } else {
117         responder.sendStatus(NOT_FOUND);
118       }
119     } catch (final DAOConnectionException e) {
120       throw new InternalServerErrorException(e);
121     } catch (final DAONoDataException e) {
122       responder.sendStatus(NOT_FOUND);
123     } finally {
124       DAOFactory.closeDAO(businessDAO);
125     }
126   }
127 
128   /**
129    * Method called to initialize a host's configuration database entry if none
130    * already exists.
131    *
132    * @param request the HttpRequest made on the resource
133    * @param responder the HttpResponder which sends the reply to the
134    *     request
135    */
136   @POST
137   @Consumes(APPLICATION_FORM_URLENCODED)
138   @RequiredRole(CONFIGADMIN)
139   public final void initializeConfig(final HttpRequest request,
140                                      final HttpResponder responder) {
141     BusinessDAO businessDAO = null;
142     try {
143       businessDAO = DAO_FACTORY.getBusinessDAO(false);
144 
145       if (!businessDAO.exist(serverName())) {
146         final ObjectNode requestObject = JsonUtils.deserializeRequest(request);
147         checkSanity(requestObject);
148         final Business config =
149             HostConfigConverter.nodeToNewBusiness(requestObject);
150         businessDAO.insert(config);
151 
152         final ObjectNode responseObject =
153             HostConfigConverter.businessToNode(config);
154         final String responseText = JsonUtils.nodeToString(responseObject);
155         responder.sendJson(CREATED, responseText);
156       } else {
157         throw new RestErrorException(ALREADY_EXISTING(serverName()));
158       }
159     } catch (final DAOConnectionException e) {
160       throw new InternalServerErrorException(e);
161     } finally {
162       DAOFactory.closeDAO(businessDAO);
163     }
164   }
165 
166   /**
167    * Method called to update a host's configuration in the database if it
168    * exists.
169    *
170    * @param request the HttpRequest made on the resource
171    * @param responder the HttpResponder which sends the reply to the
172    *     request
173    */
174   @PUT
175   @Consumes(APPLICATION_JSON)
176   @RequiredRole(CONFIGADMIN)
177   public final void updateConfig(final HttpRequest request,
178                                  final HttpResponder responder) {
179     BusinessDAO businessDAO = null;
180 
181     try {
182       businessDAO = DAO_FACTORY.getBusinessDAO(false);
183 
184       if (!businessDAO.exist(serverName())) {
185         responder.sendStatus(NOT_FOUND);
186       }
187 
188       final ObjectNode requestObject = JsonUtils.deserializeRequest(request);
189       checkSanity(requestObject);
190       final Business oldConfig = businessDAO.select(serverName());
191       final Business newConfig =
192           HostConfigConverter.nodeToUpdatedBusiness(requestObject, oldConfig);
193       businessDAO.update(newConfig);
194 
195       final ObjectNode responseObject =
196           HostConfigConverter.businessToNode(newConfig);
197       final String responseText = JsonUtils.nodeToString(responseObject);
198       responder.sendJson(CREATED, responseText);
199     } catch (final DAOConnectionException e) {
200       throw new InternalServerErrorException(e);
201     } catch (final DAONoDataException e) {
202       responder.sendStatus(NOT_FOUND);
203     } finally {
204       DAOFactory.closeDAO(businessDAO);
205     }
206   }
207 
208   /**
209    * Method called to delete the current host's configuration entry in the database.
210    *
211    * @param request the HttpRequest made on the resource
212    * @param responder the HttpResponder which sends the reply to the
213    *     request
214    */
215   @DELETE
216   @Consumes(WILDCARD)
217   @RequiredRole(CONFIGADMIN)
218   public final void deleteConfig(final HttpRequest request,
219                                  final HttpResponder responder) {
220     BusinessDAO businessDAO = null;
221     try {
222       businessDAO = DAO_FACTORY.getBusinessDAO(false);
223       if (businessDAO.exist(serverName())) {
224         businessDAO.delete(businessDAO.select(serverName()));
225         responder.sendStatus(NO_CONTENT);
226       } else {
227         responder.sendStatus(NOT_FOUND);
228       }
229     } catch (final DAOConnectionException e) {
230       throw new InternalServerErrorException(e);
231     } catch (final DAONoDataException e) {
232       responder.sendStatus(NOT_FOUND);
233     } finally {
234       DAOFactory.closeDAO(businessDAO);
235     }
236   }
237 
238   /**
239    * Method called to get a list of all allowed HTTP methods on this entry
240    * point. The HTTP methods are sent as
241    * an array in the reply's headers.
242    *
243    * @param request the HttpRequest made on the resource
244    * @param responder the HttpResponder which sends the reply to the
245    *     request
246    */
247   @OPTIONS
248   @Consumes(WILDCARD)
249   @RequiredRole(NOACCESS)
250   public final void options(final HttpRequest request,
251                             final HttpResponder responder) {
252     responder.sendStatus(OK, OPTIONS_HEADERS);
253   }
254 }