View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Chris Henson <chenson42@users.sourceforge.net>,
5    *               Keith Naas <knaas@users.sourceforge.net>
6    *
7    * This library is free software; you can redistribute it and/or
8    * modify it under the terms of the GNU Lesser General Public
9    * License as published by the Free Software Foundation; either
10   * version 3 of the License, or (at your option) any later version.
11   *
12   * This library is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this library; if not, see
19   * <http://www.gnu.org/licenses/>.
20   */
21  
22  package org.jumpmind.symmetric.web;
23  
24  import java.io.IOException;
25  
26  import javax.servlet.FilterChain;
27  import javax.servlet.ServletException;
28  import javax.servlet.ServletRequest;
29  import javax.servlet.ServletResponse;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import org.apache.commons.lang.StringUtils;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.jumpmind.symmetric.transport.IConcurrentConnectionManager;
37  import org.jumpmind.symmetric.transport.IConcurrentConnectionManager.ReservationType;
38  
39  /***
40   * Configured within symmetric-web.xml
41   */
42  public class NodeConcurrencyFilter extends AbstractFilter {
43  
44      private final static Log logger = LogFactory.getLog(NodeConcurrencyFilter.class);
45  
46      private IConcurrentConnectionManager concurrentConnectionManager;
47  
48      private String reservationUriPattern;
49  
50      @Override
51      public boolean isContainerCompatible() {
52          return true;
53      }
54  
55      public void doFilter(final ServletRequest req, final ServletResponse resp, final FilterChain chain)
56              throws IOException, ServletException {
57  
58          HttpServletRequest httpRequest = (HttpServletRequest) req;
59          String poolId = httpRequest.getRequestURI();
60          String nodeId = StringUtils.trimToNull(req.getParameter(WebConstants.NODE_ID));
61          String method = httpRequest.getMethod();
62  
63          if (method.equals("HEAD") && matchesUriPattern(normalizeRequestUri(httpRequest), reservationUriPattern)) {
64              // I read here
65              // http://java.sun.com/j2se/1.5.0/docs/guide/net/http-keepalive.html
66              // that keepalive likes to
67              // have a known content length. I also read that HEAD is better if
68              // no content is going to be returned.
69              resp.setContentLength(0);
70              if (!concurrentConnectionManager.reserveConnection(nodeId, poolId, ReservationType.SOFT)) {
71                  sendError(resp, HttpServletResponse.SC_SERVICE_UNAVAILABLE);
72              }
73          } else if (concurrentConnectionManager.reserveConnection(nodeId, poolId, ReservationType.HARD)) {
74              try {
75                  chain.doFilter(req, resp);
76              } finally {
77                  concurrentConnectionManager.releaseConnection(nodeId, poolId);
78              }
79          } else {
80              sendError(resp, HttpServletResponse.SC_SERVICE_UNAVAILABLE);
81          }
82      }
83  
84      @Override
85      protected Log getLogger() {
86          return logger;
87      }
88  
89      public void setConcurrentConnectionManager(IConcurrentConnectionManager concurrentConnectionManager) {
90          this.concurrentConnectionManager = concurrentConnectionManager;
91      }
92  
93      public void setReservationUriPattern(String reservationUriPattern) {
94          this.reservationUriPattern = reservationUriPattern;
95      }
96  }