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.Filter;
31  import org.waarp.openr66.dao.HostDAO;
32  import org.waarp.openr66.dao.TransferDAO;
33  import org.waarp.openr66.dao.exception.DAOConnectionException;
34  import org.waarp.openr66.dao.exception.DAONoDataException;
35  import org.waarp.openr66.database.data.DbTaskRunner.Columns;
36  import org.waarp.openr66.pojo.Host;
37  import org.waarp.openr66.protocol.configuration.Configuration;
38  import org.waarp.openr66.protocol.http.restv2.converters.HostConverter;
39  import org.waarp.openr66.protocol.http.restv2.utils.JsonUtils;
40  
41  import javax.ws.rs.Consumes;
42  import javax.ws.rs.DELETE;
43  import javax.ws.rs.GET;
44  import javax.ws.rs.InternalServerErrorException;
45  import javax.ws.rs.OPTIONS;
46  import javax.ws.rs.PUT;
47  import javax.ws.rs.Path;
48  import javax.ws.rs.PathParam;
49  import java.util.ArrayList;
50  import java.util.List;
51  
52  import static io.netty.handler.codec.http.HttpResponseStatus.*;
53  import static javax.ws.rs.core.HttpHeaders.*;
54  import static javax.ws.rs.core.MediaType.*;
55  import static org.waarp.common.role.RoleDefault.ROLE.HOST;
56  import static org.waarp.common.role.RoleDefault.ROLE.*;
57  import static org.waarp.openr66.protocol.http.restv2.RestConstants.*;
58  
59  /**
60   * This is the {@link AbstractRestDbHandler} handling all requests made on the
61   * single host REST entry point.
62   */
63  @Path(HOST_ID_HANDLER_URI)
64  public class HostIdHandler extends AbstractRestDbHandler {
65  
66    /**
67     * The content of the 'Allow' header sent when an 'OPTIONS' request is made
68     * on the handler.
69     */
70    private static final HttpHeaders OPTIONS_HEADERS;
71  
72    static {
73      OPTIONS_HEADERS = new DefaultHttpHeaders();
74      final List<HttpMethod> allow = new ArrayList<HttpMethod>();
75      allow.add(HttpMethod.GET);
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 HostIdHandler(final byte crud) {
88      super(crud);
89    }
90  
91    /**
92     * Method called to retrieve a host entry from the database with the id in
93     * the request URI.
94     *
95     * @param request the HttpRequest made on the resource
96     * @param responder the HttpResponder which sends the reply to the
97     *     request
98     * @param id the requested host's name
99     */
100   @GET
101   @Consumes(WILDCARD)
102   @RequiredRole(READONLY)
103   public final void getHost(final HttpRequest request,
104                             final HttpResponder responder,
105                             @PathParam(URI_ID) final String id) {
106     checkSanity(id);
107     HostDAO hostDAO = null;
108     try {
109       hostDAO = DAO_FACTORY.getHostDAO(true);
110       final Host host = hostDAO.select(id);
111       if (host == null) {
112         responder.sendStatus(NOT_FOUND);
113         return;
114       }
115       final ObjectNode responseObject = HostConverter.hostToNode(host);
116       final String responseText = JsonUtils.nodeToString(responseObject);
117       responder.sendJson(OK, responseText);
118     } catch (final DAOConnectionException e) {
119       throw new InternalServerErrorException(e);
120     } catch (final DAONoDataException e) {
121       responder.sendStatus(NOT_FOUND);
122     } finally {
123       DAOFactory.closeDAO(hostDAO);
124     }
125   }
126 
127   /**
128    * Method called to update the host entry with the given id. The entry is
129    * replaced by the one in the request's
130    * body.
131    *
132    * @param request the HttpRequest made on the resource
133    * @param responder the HttpResponder which sends the reply to the
134    *     request
135    * @param id the requested host's name
136    */
137   @PUT
138   @Consumes(APPLICATION_JSON)
139   @RequiredRole(HOST)
140   public final void updateHost(final HttpRequest request,
141                                final HttpResponder responder,
142                                @PathParam(URI_ID) final String id) {
143     checkSanity(id);
144     HostDAO hostDAO = null;
145     try {
146       hostDAO = DAO_FACTORY.getHostDAO(false);
147       final Host oldHost = hostDAO.select(id);
148 
149       if (oldHost == null) {
150         responder.sendStatus(NOT_FOUND);
151         return;
152       }
153 
154       final ObjectNode requestObject = JsonUtils.deserializeRequest(request);
155       checkSanity(requestObject);
156       final Host newHost =
157           HostConverter.nodeToUpdatedHost(requestObject, oldHost);
158 
159       hostDAO.update(newHost);
160 
161       final ObjectNode responseObject = HostConverter.hostToNode(newHost);
162       final String responseText = JsonUtils.nodeToString(responseObject);
163       responder.sendJson(CREATED, responseText);
164 
165     } catch (final DAOConnectionException e) {
166       throw new InternalServerErrorException(e);
167     } catch (final DAONoDataException e) {
168       responder.sendStatus(NOT_FOUND);
169     } finally {
170       DAOFactory.closeDAO(hostDAO);
171     }
172   }
173 
174   /**
175    * Method called to delete a host entry from the database.
176    * Note that if the host is used in any related Transfers, or if the host
177    * is the current host, the delete
178    * cannot be achieved and NOT_FOUND will be returned.
179    *
180    * @param request the HttpRequest made on the resource
181    * @param responder the HttpResponder which sends the reply to the
182    *     request
183    * @param id the requested host's name
184    */
185   @DELETE
186   @Consumes(WILDCARD)
187   @RequiredRole(HOST)
188   public final void deleteHost(final HttpRequest request,
189                                final HttpResponder responder,
190                                @PathParam(URI_ID) final String id) {
191     checkSanity(id);
192     HostDAO hostDAO = null;
193     try {
194       hostDAO = DAO_FACTORY.getHostDAO(false);
195       final Host host = hostDAO.select(id);
196       if (host == null) {
197         responder.sendStatus(NOT_FOUND);
198       } else {
199         if (Configuration.configuration.getHostId().equals(id) ||
200             Configuration.configuration.getHostSslId().equals(id)) {
201           responder.sendStatus(NOT_FOUND);
202         } else {
203           TransferDAO transferDAO = null;
204           try {
205             transferDAO = DAO_FACTORY.getTransferDAO();
206             final List<Filter> filters = new ArrayList<Filter>();
207             Filter filter = new Filter(Columns.REQUESTED.name(), "=", id);
208             filters.add(filter);
209             long nb = transferDAO.count(filters);
210             filters.clear();
211             filter = new Filter(Columns.REQUESTER.name(), "=", id);
212             filters.add(filter);
213             nb += transferDAO.count(filters);
214             if (nb > 0) {
215               responder.sendStatus(NOT_FOUND);
216             }
217           } catch (final DAOConnectionException e) {
218             throw new InternalServerErrorException(e);
219           } finally {
220             DAOFactory.closeDAO(transferDAO);
221           }
222         }
223         hostDAO.delete(host);
224         responder.sendStatus(NO_CONTENT);
225       }
226     } catch (final DAOConnectionException e) {
227       throw new InternalServerErrorException(e);
228     } catch (final DAONoDataException e) {
229       responder.sendStatus(NOT_FOUND);
230     } finally {
231       DAOFactory.closeDAO(hostDAO);
232     }
233   }
234 
235   /**
236    * Method called to get a list of all allowed HTTP methods on this entry
237    * point. The HTTP methods are sent as
238    * an array in the reply's headers.
239    *
240    * @param request the HttpRequest made on the resource
241    * @param responder the HttpResponder which sends the reply to the
242    *     request
243    * @param id the requested host's name
244    */
245   @OPTIONS
246   @Consumes(WILDCARD)
247   @RequiredRole(NOACCESS)
248   public final void options(final HttpRequest request,
249                             final HttpResponder responder,
250                             @PathParam(URI_ID) final String id) {
251     checkSanity(id);
252     responder.sendStatus(OK, OPTIONS_HEADERS);
253   }
254 }