Revision 6669
Added by ben leinfelder about 13 years ago
lib/style/skins/dev/replControl.html | ||
---|---|---|
36 | 36 |
|
37 | 37 |
<FRAME SRC="replMain.html" BORDER=0 NAME="top"> |
38 | 38 |
|
39 |
<FRAME SRC="../../../servlet/replication?action=servercontrol&subaction=list"
|
|
39 |
<FRAME SRC="../../../admin?configureType=replication&action=servercontrol&subaction=list"
|
|
40 | 40 |
name="bottom"> |
41 | 41 |
|
42 | 42 |
</FRAMESET> |
lib/style/skins/dev/replMain.html | ||
---|---|---|
60 | 60 |
</tr> |
61 | 61 |
<tr> |
62 | 62 |
<td rowspan="2" width="50%"> |
63 |
<form action="../../../servlet/replication" method="POST" target="bottom"> |
|
63 |
<form action="../../../admin" method="POST" target="bottom"> |
|
64 |
<input type="hidden" name="configureType" value="replication"> |
|
64 | 65 |
<input type="radio" name="action" value="start">Start |
65 | 66 |
Delta T: <input value="172800000" size="15" name="rate"> milliseconds First Time <input value="10:00 PM" size="8" name="firsttime"> (The format should be 10:00 AM) <br> |
66 | 67 |
<input type="radio" name="action" value="stop">Stop <br><br> |
... | ... | |
76 | 77 |
</tr> |
77 | 78 |
<tr> |
78 | 79 |
<td rowspan="2" width="50%"> |
79 |
<form action="../../../servlet/replication" method="POST" target="bottom"> |
|
80 |
<input type="hidden" name="action" value="getall"> |
|
81 |
Get All - bring all updated documents from remote hosts to this server<br><br> |
|
82 |
|
|
80 |
<form action="../../../admin" method="POST" target="bottom"> |
|
81 |
<input type="hidden" name="action" value="getall"> |
|
82 |
<input type="hidden" name="configureType" value="replication"> |
|
83 |
Get All - bring all updated documents from remote hosts to this server |
|
84 |
<br> |
|
85 |
<br> |
|
83 | 86 |
<input type="submit" value="Submit" target="bottom"> |
84 | 87 |
</form> |
85 | 88 |
</td> |
... | ... | |
92 | 95 |
</tr> |
93 | 96 |
<tr> |
94 | 97 |
<td rowspan="2" width="50%"> |
95 |
<form action="../../../servlet/replication" method="POST" target="bottom"> |
|
98 |
<form action="../../../admin" method="POST" target="bottom"> |
|
99 |
<input type="hidden" name="configureType" value="replication"> |
|
96 | 100 |
<input type="hidden" name="action" value="servercontrol"> |
97 | 101 |
<input type="radio" name="subaction" value="delete"> Remove this server<br> |
98 | 102 |
<input type="radio" name="subaction" value="add"> Add this server<br> |
... | ... | |
109 | 113 |
</td> |
110 | 114 |
</tr> |
111 | 115 |
</table> |
112 |
<a href="../../../servlet/replication?action=servercontrol&subaction=list" target="bottom">
|
|
116 |
<a href="../../../admin?configureType=replication&action=servercontrol&subaction=list" target="bottom">
|
|
113 | 117 |
Refresh Server List</a> |
114 | 118 |
</body> |
115 | 119 |
</html> |
src/edu/ucsb/nceas/metacat/admin/ReplicationAdmin.java | ||
---|---|---|
1 |
/** |
|
2 |
* '$RCSfile$' |
|
3 |
* Purpose: A Class that implements database configuration methods |
|
4 |
* Copyright: 2008 Regents of the University of California and the |
|
5 |
* National Center for Ecological Analysis and Synthesis |
|
6 |
* Authors: Michael Daigle |
|
7 |
* |
|
8 |
* '$Author$' |
|
9 |
* '$Date$' |
|
10 |
* '$Revision$' |
|
11 |
* |
|
12 |
* This program is free software; you can redistribute it and/or modify |
|
13 |
* it under the terms of the GNU General Public License as published by |
|
14 |
* the Free Software Foundation; either version 2 of the License, or |
|
15 |
* (at your option) any later version. |
|
16 |
* |
|
17 |
* This program is distributed in the hope that it will be useful, |
|
18 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
19 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
20 |
* GNU General Public License for more details. |
|
21 |
* |
|
22 |
* You should have received a copy of the GNU General Public License |
|
23 |
* along with this program; if not, write to the Free Software |
|
24 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
25 |
*/ |
|
26 |
|
|
27 |
package edu.ucsb.nceas.metacat.admin; |
|
28 |
|
|
29 |
import java.io.IOException; |
|
30 |
import java.io.PrintWriter; |
|
31 |
import java.util.Enumeration; |
|
32 |
import java.util.Hashtable; |
|
33 |
import java.util.Vector; |
|
34 |
|
|
35 |
import javax.servlet.http.HttpServletRequest; |
|
36 |
import javax.servlet.http.HttpServletResponse; |
|
37 |
import javax.servlet.http.HttpSession; |
|
38 |
|
|
39 |
import org.apache.log4j.Logger; |
|
40 |
|
|
41 |
import edu.ucsb.nceas.metacat.replication.ReplicationService; |
|
42 |
import edu.ucsb.nceas.metacat.service.SessionService; |
|
43 |
import edu.ucsb.nceas.metacat.shared.MetacatUtilException; |
|
44 |
import edu.ucsb.nceas.metacat.shared.ServiceException; |
|
45 |
import edu.ucsb.nceas.metacat.util.AuthUtil; |
|
46 |
import edu.ucsb.nceas.metacat.util.SessionData; |
|
47 |
|
|
48 |
/** |
|
49 |
* Control the display of the database configuration page and the processing |
|
50 |
* of the configuration values. |
|
51 |
*/ |
|
52 |
public class ReplicationAdmin extends MetacatAdmin { |
|
53 |
|
|
54 |
private static ReplicationAdmin instance = null; |
|
55 |
private Logger logMetacat = Logger.getLogger(ReplicationAdmin.class); |
|
56 |
|
|
57 |
/** |
|
58 |
* private constructor since this is a singleton |
|
59 |
*/ |
|
60 |
private ReplicationAdmin() throws AdminException { |
|
61 |
|
|
62 |
} |
|
63 |
|
|
64 |
/** |
|
65 |
* Get the single instance of D1Admin. |
|
66 |
* |
|
67 |
* @return the single instance of D1Admin |
|
68 |
*/ |
|
69 |
public static ReplicationAdmin getInstance() throws AdminException { |
|
70 |
if (instance == null) { |
|
71 |
instance = new ReplicationAdmin(); |
|
72 |
} |
|
73 |
return instance; |
|
74 |
} |
|
75 |
|
|
76 |
/** |
|
77 |
* Handle configuration of replication -- pass through to the other handler |
|
78 |
* |
|
79 |
* @param request |
|
80 |
* the http request information |
|
81 |
* @param response |
|
82 |
* the http response to be sent back to the client |
|
83 |
* @throws ServiceException |
|
84 |
* @throws IOException |
|
85 |
* @throws MetacatUtilException |
|
86 |
*/ |
|
87 |
public void handleRequest(HttpServletRequest request, |
|
88 |
HttpServletResponse response) throws AdminException, ServiceException, IOException, MetacatUtilException { |
|
89 |
|
|
90 |
PrintWriter out = null; |
|
91 |
Hashtable<String, String[]> params = new Hashtable<String, String[]>(); |
|
92 |
Enumeration<String> paramlist = request.getParameterNames(); |
|
93 |
|
|
94 |
while (paramlist.hasMoreElements()) { |
|
95 |
String name = (String) paramlist.nextElement(); |
|
96 |
String[] value = request.getParameterValues(name); |
|
97 |
params.put(name, value); |
|
98 |
} |
|
99 |
|
|
100 |
String action = ""; |
|
101 |
if (!params.isEmpty() && params.get("action") != null) { |
|
102 |
action = ((String[]) params.get("action"))[0]; |
|
103 |
} |
|
104 |
String server = null; |
|
105 |
|
|
106 |
// start, stop, getall and servercontrol need to check if user is administrator |
|
107 |
HttpSession session = request.getSession(true); |
|
108 |
SessionData sessionData = null; |
|
109 |
String sessionId = ""; |
|
110 |
String username = ""; |
|
111 |
String[] groupnames = { "" }; |
|
112 |
|
|
113 |
if (params.containsKey("sessionid")) { |
|
114 |
sessionId = ((String[]) params.get("sessionid"))[0]; |
|
115 |
logMetacat.info("sessionid " + sessionId); |
|
116 |
if (SessionService.getInstance().isSessionRegistered(sessionId)) { |
|
117 |
logMetacat.info("Looking up id " + sessionId + " in registered sessions"); |
|
118 |
sessionData = SessionService.getInstance().getRegisteredSession(sessionId); |
|
119 |
} |
|
120 |
} |
|
121 |
if (sessionData == null) { |
|
122 |
sessionData = new SessionData(session.getId(), |
|
123 |
(String) session.getAttribute("username"), |
|
124 |
(String[]) session.getAttribute("groups"), |
|
125 |
(String) session.getAttribute("password"), |
|
126 |
(String) session.getAttribute("name")); |
|
127 |
} |
|
128 |
|
|
129 |
username = sessionData.getUserName(); |
|
130 |
logMetacat.warn("The user name from session is: " + username); |
|
131 |
groupnames = sessionData.getGroupNames(); |
|
132 |
if (!AuthUtil.isAdministrator(username, groupnames)) { |
|
133 |
String msg = "The user \"" + username |
|
134 |
+ "\" is not authorized for this action: " + action; |
|
135 |
out = response.getWriter(); |
|
136 |
out.print("<error>"); |
|
137 |
out.print(msg); |
|
138 |
out.print("</error>"); |
|
139 |
out.close(); |
|
140 |
logMetacat.warn(msg); |
|
141 |
return; |
|
142 |
} |
|
143 |
|
|
144 |
if (action.equals("stop")) { |
|
145 |
// stop the replication server |
|
146 |
ReplicationService.getInstance().stopReplication(); |
|
147 |
out = response.getWriter(); |
|
148 |
out.println("Replication Handler Stopped"); |
|
149 |
} else if (action.equals("start")) { |
|
150 |
ReplicationService.getInstance().startReplication(params); |
|
151 |
out = response.getWriter(); |
|
152 |
out.println("Replication Handler Started"); |
|
153 |
} else if (action.equals("getall")) { |
|
154 |
ReplicationService.getInstance().runOnce(); |
|
155 |
response.setContentType("text/html"); |
|
156 |
out = response.getWriter(); |
|
157 |
out.println("<html><body>\"Get All\" Done</body></html>"); |
|
158 |
} else if (action.equals("servercontrol")) { |
|
159 |
ReplicationService.handleServerControlRequest(params, response); |
|
160 |
} |
|
161 |
|
|
162 |
// Forward the request to the JSP page |
|
163 |
//RequestUtil.forwardRequest(request, response, "/admin/replControl.html", null); |
|
164 |
|
|
165 |
} |
|
166 |
|
|
167 |
/** |
|
168 |
* Validate the most important configuration options submitted by the user. |
|
169 |
* |
|
170 |
* @return a vector holding error message for any fields that fail |
|
171 |
* validation. |
|
172 |
*/ |
|
173 |
protected Vector<String> validateOptions(HttpServletRequest request) { |
|
174 |
Vector<String> errorVector = new Vector<String>(); |
|
175 |
|
|
176 |
// TODO MCD validate options. |
|
177 |
|
|
178 |
return errorVector; |
|
179 |
} |
|
180 |
} |
|
0 | 181 |
src/edu/ucsb/nceas/metacat/admin/MetacatAdminServlet.java | ||
---|---|---|
42 | 42 |
import edu.ucsb.nceas.metacat.properties.PropertyService; |
43 | 43 |
import edu.ucsb.nceas.metacat.service.SessionService; |
44 | 44 |
import edu.ucsb.nceas.metacat.shared.MetacatUtilException; |
45 |
import edu.ucsb.nceas.metacat.shared.ServiceException; |
|
45 | 46 |
import edu.ucsb.nceas.metacat.util.AuthUtil; |
46 | 47 |
import edu.ucsb.nceas.metacat.util.ConfigurationUtil; |
47 | 48 |
import edu.ucsb.nceas.metacat.util.RequestUtil; |
... | ... | |
185 | 186 |
// process dataone config |
186 | 187 |
D1Admin.getInstance().configureDataONE(request, response); |
187 | 188 |
return; |
189 |
} else if (action.equals("replication")) { |
|
190 |
// process replication config |
|
191 |
ReplicationAdmin.getInstance().handleRequest(request, response); |
|
192 |
return; |
|
188 | 193 |
} else { |
189 | 194 |
String errorMessage = "MetacatAdminServlet.handleGetOrPost - Invalid action in configuration request: " + action; |
190 | 195 |
logMetacat.error(errorMessage); |
... | ... | |
218 | 223 |
"MetacatAdminServlet.handleGetOrPost - Utility problem while handling request: " + ue.getMessage(); |
219 | 224 |
logMetacat.error(errorMessage); |
220 | 225 |
processingErrors.add(errorMessage); |
226 |
} catch (ServiceException e) { |
|
227 |
String errorMessage = |
|
228 |
"MetacatAdminServlet.handleGetOrPost - Service problem while handling request: " + e.getMessage(); |
|
229 |
logMetacat.error(errorMessage); |
|
230 |
processingErrors.add(errorMessage); |
|
221 | 231 |
} |
222 | 232 |
} |
223 | 233 |
} |
src/edu/ucsb/nceas/metacat/replication/ReplicationService.java | ||
---|---|---|
216 | 216 |
return; |
217 | 217 |
} |
218 | 218 |
|
219 |
protected void startReplication(Hashtable<String, String[]> params) throws ServiceException {
|
|
219 |
public void startReplication(Hashtable<String, String[]> params) throws ServiceException {
|
|
220 | 220 |
|
221 | 221 |
String firstTimeStr = ""; |
222 | 222 |
//start the replication server |
... | ... | |
291 | 291 |
* servercontrol delete server |
292 | 292 |
* servercontrol list |
293 | 293 |
*/ |
294 |
protected static void handleServerControlRequest(
|
|
294 |
public static void handleServerControlRequest(
|
|
295 | 295 |
Hashtable<String, String[]> params, HttpServletResponse response) { |
296 | 296 |
String subaction = ((String[]) params.get("subaction"))[0]; |
297 | 297 |
DBConnection dbConn = null; |
src/edu/ucsb/nceas/metacat/replication/ReplicationServlet.java | ||
---|---|---|
43 | 43 |
import javax.servlet.http.HttpServlet; |
44 | 44 |
import javax.servlet.http.HttpServletRequest; |
45 | 45 |
import javax.servlet.http.HttpServletResponse; |
46 |
import javax.servlet.http.HttpSession; |
|
47 | 46 |
|
48 | 47 |
import org.apache.log4j.Logger; |
49 | 48 |
import org.dataone.client.auth.CertificateManager; |
50 | 49 |
|
51 | 50 |
import edu.ucsb.nceas.metacat.service.ServiceService; |
52 |
import edu.ucsb.nceas.metacat.service.SessionService; |
|
53 |
import edu.ucsb.nceas.metacat.shared.MetacatUtilException; |
|
54 | 51 |
import edu.ucsb.nceas.metacat.shared.ServiceException; |
55 |
import edu.ucsb.nceas.metacat.util.AuthUtil; |
|
56 |
import edu.ucsb.nceas.metacat.util.SessionData; |
|
57 | 52 |
|
58 | 53 |
public class ReplicationServlet extends HttpServlet { |
59 | 54 |
|
... | ... | |
117 | 112 |
|
118 | 113 |
try { |
119 | 114 |
// check if the server is included in the list of replicated servers |
120 |
if (!action.equals("servercontrol") && !action.equals("stop") |
|
121 |
&& !action.equals("start") && !action.equals("getall")) { |
|
115 |
server = ((String[]) params.get("server"))[0]; |
|
122 | 116 |
|
123 |
server = ((String[]) params.get("server"))[0]; |
|
124 |
|
|
125 |
// verify the client certificate on the request |
|
126 |
boolean isValid = false; |
|
127 |
String msg = "Client certificate is invalid"; |
|
128 |
try { |
|
129 |
isValid = hasValidCertificate(request, server); |
|
130 |
} catch (Exception e) { |
|
131 |
msg = "Could not verify client certificate: " + e.getMessage(); |
|
132 |
logMetacat.error(msg, e); |
|
133 |
logReplication.error(msg, e); |
|
134 |
} |
|
135 |
if (!isValid) { |
|
136 |
// send message to response |
|
137 |
out = response.getWriter(); |
|
138 |
out.print("<error>"); |
|
139 |
out.print(msg); |
|
140 |
out.print("</error>"); |
|
141 |
out.close(); |
|
142 |
return; |
|
143 |
} |
|
144 |
|
|
145 |
if (ReplicationService.getServerCodeForServerName(server) == 0) { |
|
146 |
logReplication.debug("ReplicationServlet.handleGetOrPost - Action \"" + action + "\" rejected for server: " |
|
147 |
+ server); |
|
148 |
return; |
|
149 |
} else { |
|
150 |
logReplication.debug("ReplicationServlet.handleGetOrPost - Action \"" + action + "\" accepted for server: " |
|
151 |
+ server); |
|
152 |
} |
|
153 |
|
|
117 |
// verify the client certificate on the request |
|
118 |
boolean isValid = false; |
|
119 |
String msg = "Client certificate is invalid"; |
|
120 |
try { |
|
121 |
isValid = hasValidCertificate(request, server); |
|
122 |
} catch (Exception e) { |
|
123 |
msg = "Could not verify client certificate: " + e.getMessage(); |
|
124 |
logMetacat.error(msg, e); |
|
125 |
logReplication.error(msg, e); |
|
126 |
} |
|
127 |
if (!isValid) { |
|
128 |
// send message to response |
|
129 |
out = response.getWriter(); |
|
130 |
out.print("<error>"); |
|
131 |
out.print(msg); |
|
132 |
out.print("</error>"); |
|
133 |
out.close(); |
|
134 |
return; |
|
135 |
} |
|
136 |
|
|
137 |
// we passed the test, now continue |
|
138 |
if (ReplicationService.getServerCodeForServerName(server) == 0) { |
|
139 |
logReplication.debug("ReplicationServlet.handleGetOrPost - Action \"" + action + "\" rejected for server: " + server); |
|
140 |
return; |
|
154 | 141 |
} else { |
155 |
// start, stop, getall and servercontrol need to check if user is administor |
|
156 |
HttpSession sess = request.getSession(true); |
|
157 |
SessionData sessionData = null; |
|
158 |
String sess_id = ""; |
|
159 |
String username = ""; |
|
160 |
String[] groupnames = { "" }; |
|
161 |
|
|
162 |
if (params.containsKey("sessionid")) { |
|
163 |
sess_id = ((String[]) params.get("sessionid"))[0]; |
|
164 |
logReplication.info("ReplicationServlet.handleGetOrPost - in has sessionid " + sess_id); |
|
165 |
if (SessionService.getInstance().isSessionRegistered(sess_id)) { |
|
166 |
logReplication.info("ReplicationServlet.handleGetOrPost - find the id " + sess_id + " in hash table"); |
|
167 |
sessionData = SessionService.getInstance().getRegisteredSession(sess_id); |
|
168 |
} |
|
169 |
} |
|
170 |
if (sessionData == null) { |
|
171 |
sessionData = new SessionData(sess.getId(), |
|
172 |
(String) sess.getAttribute("username"), |
|
173 |
(String[]) sess.getAttribute("groups"), |
|
174 |
(String) sess.getAttribute("password"), |
|
175 |
(String) sess.getAttribute("name")); |
|
176 |
} |
|
177 |
|
|
178 |
username = sessionData.getUserName(); |
|
179 |
logReplication.warn("ReplicationServlet.handleGetOrPost - The user name from session is: " + username); |
|
180 |
groupnames = sessionData.getGroupNames(); |
|
181 |
if (!AuthUtil.isAdministrator(username, groupnames)) { |
|
182 |
out = response.getWriter(); |
|
183 |
out.print("<error>"); |
|
184 |
out.print("The user \"" + username |
|
185 |
+ "\" is not authorized for this action."); |
|
186 |
out.print("</error>"); |
|
187 |
out.close(); |
|
188 |
logReplication.warn("ReplicationServlet.handleGetOrPost - The user \"" + username |
|
189 |
+ "\" is not authorized for this action: " + action); |
|
190 |
return; |
|
191 |
} |
|
192 |
|
|
193 |
}// else |
|
194 |
|
|
142 |
logReplication.debug("ReplicationServlet.handleGetOrPost - Action \"" + action + "\" accepted for server: " + server); |
|
143 |
} |
|
144 |
|
|
145 |
// perform the correct action |
|
195 | 146 |
if (action.equals("readdata")) { |
196 | 147 |
OutputStream outStream = response.getOutputStream(); |
197 | 148 |
//to get the data file. |
... | ... | |
200 | 151 |
} else if (action.equals("forcereplicatedatafile")) { |
201 | 152 |
//read a specific docid from remote host, and store it into local host |
202 | 153 |
ReplicationService.handleForceReplicateDataFileRequest(params, request); |
203 |
} else if (action.equals("stop")) { |
|
204 |
// stop the replication server |
|
205 |
ReplicationService.getInstance().stopReplication(); |
|
206 |
out = response.getWriter(); |
|
207 |
out.println("Replication Handler Stopped"); |
|
208 |
} else if (action.equals("start")) { |
|
209 |
ReplicationService.getInstance().startReplication(params); |
|
210 |
out = response.getWriter(); |
|
211 |
out.println("Replication Handler Started"); |
|
212 |
} else if (action.equals("getall")) { |
|
213 |
ReplicationService.getInstance().runOnce(); |
|
214 |
response.setContentType("text/html"); |
|
215 |
out = response.getWriter(); |
|
216 |
out.println("<html><body>\"Get All\" Done</body></html>"); |
|
217 | 154 |
} else if (action.equals("forcereplicate")) { |
218 |
// read a specific docid from remote host, and store it into |
|
219 |
// local host |
|
220 |
ReplicationService.handleForceReplicateRequest(params, response, |
|
221 |
request); |
|
155 |
// read a specific docid from remote host, and store it into local host |
|
156 |
ReplicationService.handleForceReplicateRequest(params, response, request); |
|
222 | 157 |
} else if (action.equals("forcereplicatesystemmetadata")) { |
223 |
ReplicationService.handleForceReplicateSystemMetadataRequest(params, response, |
|
224 |
request); |
|
158 |
ReplicationService.handleForceReplicateSystemMetadataRequest(params, response, request); |
|
225 | 159 |
} else if (action.equals("forcereplicatedelete")) { |
226 |
// read a specific docid from remote host, and store it into |
|
227 |
// local host |
|
228 |
ReplicationService.handleForceReplicateDeleteRequest(params, |
|
229 |
response, request); |
|
160 |
// read a specific docid from remote host, and store it into local host |
|
161 |
ReplicationService.handleForceReplicateDeleteRequest(params, response, request); |
|
230 | 162 |
} else if (action.equals("update")) { |
231 | 163 |
// request an update list from the server |
232 | 164 |
ReplicationService.handleUpdateRequest(params, response); |
... | ... | |
245 | 177 |
ReplicationService.handleGetTimeRequest(params, response); |
246 | 178 |
} else if (action.equals("getcatalog")) { |
247 | 179 |
ReplicationService.handleGetCatalogRequest(params, response, true); |
248 |
} else if (action.equals("servercontrol")) { |
|
249 |
ReplicationService.handleServerControlRequest(params, response); |
|
250 | 180 |
} else if (action.equals("test")) { |
251 | 181 |
response.setContentType("text/html"); |
252 | 182 |
out = response.getWriter(); |
... | ... | |
256 | 186 |
} catch (ServiceException e) { |
257 | 187 |
logMetacat.error("ReplicationServlet.handleGetOrPost - " + ReplicationService.METACAT_REPL_ERROR_MSG); |
258 | 188 |
logReplication.error("ReplicationServlet.handleGetOrPost - Error in ReplicationServlet.handleGetOrPost: " + e.getMessage()); |
259 |
} catch (MetacatUtilException mue) { |
|
260 |
logMetacat.error("ReplicationServlet.handleGetOrPost - " + ReplicationService.METACAT_REPL_ERROR_MSG); |
|
261 |
logReplication.error("ReplicationServlet.handleGetOrPost - Metacat utility error in ReplicationServlet.handleGetOrPost: " |
|
262 |
+ mue.getMessage()); |
|
263 | 189 |
} finally { |
264 | 190 |
if (out != null) { |
265 | 191 |
out.close(); |
Also available in: Unified diff
move replication configuration actions to the admin servlet and out of the replication servlet
http://bugzilla.ecoinformatics.org/show_bug.cgi?id=5528