source: gli/trunk/src/org/greenstone/gatherer/remote/RemoteGreenstoneServer.java@ 17630

Last change on this file since 17630 was 17630, checked in by ak19, 15 years ago
  1. Previously the GLI client and GLI applet used to have a problem that manifested very rarely and randomly: every so often, one of the gliserver Action commands would get stuck in an infinite wait loop. The current code, after running it about 50 times and not showing this problem anymore, seems to have fixed this. The changes made were to RemoteGreenstoneServer.performAction() where a wait() is now used instead of a timed wait() and the ActionQueue.java class where more methods are now synchronised and the infinite while loop in the Thread's run() method has been reorganised to check for any increase in the size of the action queue at the start. 2. An exit condition is now used instead of an infinite while loop in ActionQueue's run(), so that the loop is terminated when the user cancels or a connect exception occurs. This ends the thread (which is particularly necessary in Applets, else they keep consuming processor time). RemoteGreenstoneServer.performAction() checks for whether the ActionQueue thread has exited and if so GLI's Gatherer exits, otherwise performAction proceeds to add the next action to the queue as before.
  • Property svn:keywords set to Author Date Id Revision
File size: 32.3 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: Michael Dewsnip, NZDL Project, University of Waikato
9 *
10 * Copyright (C) 2005 New Zealand Digital Library Project
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., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27
28package org.greenstone.gatherer.remote;
29
30import java.io.*;
31import java.net.*;
32import java.util.*;
33import java.util.zip.*;
34import javax.swing.*;
35import java.io.ByteArrayOutputStream;
36import org.greenstone.gatherer.Configuration;
37import org.greenstone.gatherer.DebugStream;
38import org.greenstone.gatherer.Dictionary;
39import org.greenstone.gatherer.FedoraInfo;
40import org.greenstone.gatherer.GAuthenticator;
41import org.greenstone.gatherer.Gatherer;
42import org.greenstone.gatherer.collection.CollectionManager;
43import org.greenstone.gatherer.shell.GShell;
44import org.greenstone.gatherer.util.UnzipTools;
45import org.greenstone.gatherer.util.Utility;
46import org.apache.commons.httpclient.HttpClient;
47import org.apache.commons.httpclient.methods.PostMethod;
48import org.apache.commons.httpclient.methods.GetMethod;
49import org.apache.commons.httpclient.HttpException;
50import org.apache.commons.httpclient.methods.multipart.FilePart;
51import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
52import org.apache.commons.httpclient.methods.multipart.Part;
53import org.apache.commons.httpclient.methods.multipart.*;
54import org.apache.commons.httpclient.params.*;
55import org.apache.commons.httpclient.HttpStatus;
56
57
58public class RemoteGreenstoneServer
59{
60 // A PasswordAuthentication object is created whenever it is required
61 static private PasswordAuthentication remote_greenstone_server_authentication = null;
62 // static private PasswordAuthentication remote_greenstone_server_authentication = new PasswordAuthentication(System.getProperty("user.name"), new char[] { });
63
64 private ActionQueue remote_greenstone_server_action_queue;
65 private RemoteGreenstoneServer.ProgressBar progress_bar;
66
67 public RemoteGreenstoneServer() {
68 // Create the progress_bar first since ActionQueue uses it in its thread
69 // (the thread will start immediately).
70 progress_bar = new RemoteGreenstoneServer.ProgressBar();
71 remote_greenstone_server_action_queue = new ActionQueue();
72 }
73
74 // ----------------------------------------------------------------------------------------------------
75 // PUBLIC LAYER
76 // ----------------------------------------------------------------------------------------------------
77 public String deleteCollection(String collection_name)
78 {
79 return performAction(new RemoteGreenstoneServerAction.DeleteCollectionAction(collection_name));
80 }
81
82
83 public String deleteCollectionFile(String collection_name, File collection_file)
84 {
85 return performAction(new RemoteGreenstoneServerAction.DeleteCollectionFileAction(collection_name, collection_file));
86 }
87
88
89 public String downloadCollection(String collection_name)
90 {
91 return performAction(new RemoteGreenstoneServerAction.DownloadCollectionAction(collection_name));
92 }
93
94
95 public String downloadCollectionArchives(String collection_name)
96 {
97 return performAction(new RemoteGreenstoneServerAction.DownloadCollectionArchivesAction(collection_name));
98 }
99
100
101 public String downloadCollectionConfigurations()
102 {
103 return performAction(new RemoteGreenstoneServerAction.DownloadCollectionConfigurationsAction());
104 }
105
106
107 public String downloadCollectionFile(String collection_name, File collection_file)
108 {
109 return performAction(new RemoteGreenstoneServerAction.DownloadCollectionFileAction(collection_name, collection_file));
110 }
111
112 // get web.xml from the server -- for a remote gli of GS3
113 public String downloadWebXMLFile()
114 {
115 return performAction(new RemoteGreenstoneServerAction.DownloadWebXMLFileAction());
116 }
117
118 public String getScriptOptions(String script_name, String script_arguments)
119 {
120 return performAction(new RemoteGreenstoneServerAction.GetScriptOptionsAction(script_name, script_arguments));
121 }
122
123 //get all available site names from the server -- for a remote gli of GS3
124 public String getSiteNames()
125 {
126 return performAction(new RemoteGreenstoneServerAction.GetSiteNamesAction());
127 }
128
129 public String moveCollectionFile(String collection_name, File source_collection_file, File target_collection_file)
130 {
131 return performAction(new RemoteGreenstoneServerAction.MoveCollectionFileAction(
132 collection_name, source_collection_file, target_collection_file));
133 }
134
135
136 public String newCollectionDirectory(String collection_name, File new_collection_directory)
137 {
138 return performAction(new RemoteGreenstoneServerAction.NewCollectionDirectoryAction(
139 collection_name, new_collection_directory));
140 }
141
142
143 public String runScript(String collection_name, String script_name, String script_arguments, GShell shell)
144 {
145 return performAction(new RemoteGreenstoneServerAction.RunScriptAction(
146 collection_name, script_name, script_arguments, shell));
147 }
148
149
150 public String uploadCollectionFile(String collection_name, File collection_file)
151 {
152 return performAction(new RemoteGreenstoneServerAction.UploadCollectionFilesAction(
153 collection_name, new File[] { collection_file }));
154 }
155
156
157 public String uploadCollectionFiles(String collection_name, File[] collection_files)
158 {
159 return performAction(new RemoteGreenstoneServerAction.UploadCollectionFilesAction(collection_name, collection_files));
160 }
161
162
163 public String uploadFilesIntoCollection(String collection_name, File[] source_files, File target_collection_directory)
164 {
165 return performAction(new RemoteGreenstoneServerAction.UploadFilesIntoCollectionAction(
166 collection_name, source_files, target_collection_directory));
167 }
168
169 public boolean exists(String collection_name, File collection_file)
170 {
171 String result = performAction(new RemoteGreenstoneServerAction.ExistsAction(collection_name, collection_file));
172 if(result.indexOf("exists") != -1) {
173 return true;
174 }
175 else if(result.indexOf("does not exist") != -1) {
176 return false;
177 }
178 return false;
179 }
180
181 public int getGreenstoneVersion()
182 {
183 // returns message "Greenstone version is: <version number of the Greenstone remote server>"
184 String result = performAction(new RemoteGreenstoneServerAction.VersionAction());
185 int index = result.indexOf(":");
186 if(index != -1) {
187 result = result.substring(index+1).trim(); // skip the space after colon, must remove surrounding spaces
188 }
189 int greenstoneVersion = Integer.parseInt(result);
190 return greenstoneVersion;
191 }
192
193 /** For constructing the preview command (the library URL) with */
194 public String getLibraryURL(String serverHomeURL)
195 {
196 // returns message "Greenstone library URL suffix is: <e.g. /greenstone3/library or /gsdl/cgi-bin/library>"
197 String libSuffix = performAction(new RemoteGreenstoneServerAction.LibraryURLSuffixAction());
198 int index = libSuffix.indexOf(":");
199 if(index != -1) {
200 libSuffix = libSuffix.substring(index+1).trim(); // skip the space after colon and remove surrounding spaces
201 }
202
203 // serverHomeURL is of the form, http://domain/other/stuff. We want the prefix upto & including domain
204 // and prepend that to the libraryURLSuffix
205 index = -1;
206 for(int i = 0; i < 3; i++) {
207 index = serverHomeURL.indexOf("/", index+1);
208 if(index == -1) { // shouldn't happen, but if it does, we'll be in an infinite loop
209 break;
210 }
211 }
212 serverHomeURL = serverHomeURL.substring(0, index);
213 return serverHomeURL + libSuffix;
214 }
215
216 // ----------------------------------------------------------------------------------------------------
217
218
219 public void exit()
220 {
221 System.err.println("Exiting, number of jobs on queue: " + remote_greenstone_server_action_queue.size());
222
223 // If there are still jobs on the queue we must wait for the jobs to finish
224 while (remote_greenstone_server_action_queue.size() > 0) {
225 synchronized (remote_greenstone_server_action_queue) {
226 try {
227 DebugStream.println("Waiting for queue to become empty...");
228 remote_greenstone_server_action_queue.wait(500);
229 }
230 catch (InterruptedException exception) {}
231 }
232 }
233 }
234
235
236 // ----------------------------------------------------------------------------------------------------
237 // QUEUE LAYER
238 // ----------------------------------------------------------------------------------------------------
239
240
241 /** Returns null if we cannot wait for the action to finish, "" if the action failed, or the action output. */
242 private String performAction(RemoteGreenstoneServerAction remote_greenstone_server_action)
243 {
244 // Check for whether the queue thread stopped running because
245 // the user cancelled out. If so, exit GLI.
246 if(remote_greenstone_server_action_queue.hasExited()) {
247 remote_greenstone_server_action_queue.clear();
248 //remote_greenstone_server_action_queue = null;
249 Gatherer.exit();
250 return "";
251 }
252
253 // Add the action to the queue
254 remote_greenstone_server_action_queue.addAction(remote_greenstone_server_action);
255 String threadName = Thread.currentThread().getName();
256
257 // If we're running in the GUI thread we must return immediately
258 // We cannot wait for the action to complete because this will block any GUI updates
259 if (SwingUtilities.isEventDispatchThread()) {
260 System.err.println(threadName
261 + "\tACTION QUEUED: In event dispatch thread, returning immediately...\n\t"
262 + remote_greenstone_server_action);
263 return null;
264 }
265
266 // Otherwise wait until the action is processed
267 try {
268 synchronized (remote_greenstone_server_action) {
269 while(!remote_greenstone_server_action.processed) {
270 //System.err.println("Waiting for action to complete...: " + remote_greenstone_server_action);
271 DebugStream.println("Waiting for action to complete...");
272 remote_greenstone_server_action.wait(); // wait to be notified when the action has been processed
273 }
274 }
275 } catch (Exception e) {
276 System.err.println("RemoteGreenstoneServer.performAction() - exception: " + e);
277 e.printStackTrace();
278 }
279
280 // Return "" if the action failed
281 if (!remote_greenstone_server_action.processed_successfully) {
282 return "";
283 }
284 // Otherwise return the action output
285 return remote_greenstone_server_action.action_output;
286 }
287
288
289 // ----------------------------------------------------------------------------------------------------
290 // PROGRESS BAR
291 // ----------------------------------------------------------------------------------------------------
292
293 static class ProgressBar
294 extends JProgressBar
295 {
296 public ProgressBar()
297 {
298 setBackground(Configuration.getColor("coloring.collection_tree_background", false));
299 setForeground(Configuration.getColor("coloring.collection_tree_foreground", false));
300 setString(Dictionary.get("FileActions.No_Activity"));
301 setStringPainted(true);
302 }
303
304 /** synchronized to avoid conflicts since several threads access this */
305 synchronized public void setAction(String action)
306 {
307 if (action != null) {
308 DebugStream.println(action);
309 }
310
311 // We cannot call this from the GUI thread otherwise the progress bar won't start
312 if (SwingUtilities.isEventDispatchThread()) {
313 System.err.println("ERROR: RemoteGreenstoneServerProgressBar.setAction() called from event dispatch thread!");
314 return;
315 }
316
317 // Set the string on the progress bar, and start or stop it
318 if (action == null) {
319 setString(Dictionary.get("FileActions.No_Activity"));
320 setIndeterminate(false);
321 }
322 else {
323 setString(action);
324 setIndeterminate(true);
325 }
326 }
327 }
328
329 /** synchronized to avoid conflicts since several threads access this */
330 synchronized public RemoteGreenstoneServer.ProgressBar getProgressBar()
331 {
332 return progress_bar;
333 }
334
335
336 // ----------------------------------------------------------------------------------------------------
337 // AUTHENTICATION LAYER
338 // ----------------------------------------------------------------------------------------------------
339
340 static private class RemoteGreenstoneServerAuthenticateTask
341 extends Thread
342 {
343 public void run()
344 {
345 remote_greenstone_server_authentication = new RemoteGreenstoneServerAuthenticator().getAuthentication();
346 }
347
348
349 static private class RemoteGreenstoneServerAuthenticator
350 extends GAuthenticator
351 {
352 public PasswordAuthentication getAuthentication(String username, String password)
353 {
354 return getPasswordAuthentication(username,password);
355 }
356
357 public PasswordAuthentication getAuthentication()
358 {
359 return getPasswordAuthentication();
360 }
361
362 protected String getMessageString()
363 {
364 if (Gatherer.GS3){
365 return (Dictionary.get("RemoteGreenstoneServer.Authentication_Message_gs3") + " " + Configuration.site_name);
366 }
367 return Dictionary.get("RemoteGreenstoneServer.Authentication_Message");
368 }
369 }
370 }
371
372 public void set_remote_greenstone_server_authentication_to_null() {
373 remote_greenstone_server_authentication = null;
374 }
375
376 private void authenticateUser()
377 throws RemoteGreenstoneServerAction.ActionCancelledException
378 {
379 // If we don't have any authentication information then ask for it now
380 if (remote_greenstone_server_authentication == null) {
381 try {
382 // We have to do this on the GUI thread
383 SwingUtilities.invokeAndWait(new RemoteGreenstoneServerAuthenticateTask());
384 }
385 catch (Exception exception) {
386 System.err.println("Exception occurred when authenticating the user: " + exception);
387 DebugStream.printStackTrace(exception);
388 }
389
390 // If it is still null then the user has cancelled the authentication, so the action is cancelled
391 if (remote_greenstone_server_authentication == null) {
392 throw new RemoteGreenstoneServerAction.ActionCancelledException();
393 }
394 }
395 }
396
397
398 public String getUsername()
399 {
400 if (remote_greenstone_server_authentication != null) {
401 return remote_greenstone_server_authentication.getUserName();
402 }
403
404 return null;
405 }
406
407
408 // ----------------------------------------------------------------------------------------------------
409 // REQUEST LAYER
410 // ----------------------------------------------------------------------------------------------------
411
412
413 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
414 String downloadFile(String gliserver_args, String file_path)
415 throws Exception
416 {
417 while (true) {
418 // Check that Configuration.gliserver_url is set
419 if (Configuration.gliserver_url == null) {
420 throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
421 }
422
423 // Ask for authentication information (if necessary), then perform the action
424 authenticateUser();
425 String gliserver_url_string = Configuration.gliserver_url.toString();
426 String command_output = downloadFileInternal(gliserver_url_string, gliserver_args, file_path);
427
428 // Check the first line to see if authentication has failed; if so, go around the loop again
429 if (command_output.startsWith("ERROR: Authentication failed:")) {
430 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
431 remote_greenstone_server_authentication = null;
432 continue;
433 }
434 // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
435 else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
436 if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
437 // The user has decided to cancel the action
438 throw new RemoteGreenstoneServerAction.ActionCancelledException();
439 }
440
441 // The user has decided to steal the lock... rerun the command with "&steal_lock="
442 gliserver_args += "&steal_lock=";
443 continue;
444 }
445 // Handle other types of errors by throwing an exception
446 else if (command_output.startsWith("ERROR: ")) {
447 throw new Exception(command_output.substring("ERROR: ".length()));
448 }
449
450 // There were no exceptions thrown so the action must have succeeded
451 return command_output;
452 }
453 }
454
455 /** Returns true or false depending on whether authentication is required for the cmd
456 * string embedded in the given gliserver_args. No authentication is required for either
457 * of the commands greenstone-server-version and get-library-url-suffix. */
458 private boolean isAuthenticationRequired(String gliserver_args) {
459 return ((gliserver_args.indexOf("greenstone-server-version") == -1)
460 && (gliserver_args.indexOf("get-library-url-suffix") == -1));
461 }
462
463
464 /** Returns the command output if the action completed, throws some kind of exception otherwise.
465 * Package access, so that RemoteGreenstoneServerAction.java can call this.
466 */
467 String sendCommandToServer(String gliserver_args, GShell shell)
468 throws Exception
469 {
470 while (true) {
471
472 // Check that Configuration.gliserver_url is set
473 if (Configuration.gliserver_url == null) {
474 throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
475 }
476
477 // Ask for authentication information (if necessary), then perform the action
478 if(isAuthenticationRequired(gliserver_args)) {
479 authenticateUser();
480 }
481 String gliserver_url_string = Configuration.gliserver_url.toString();
482 String command_output = sendCommandToServerInternal(gliserver_url_string, gliserver_args, shell);
483
484 // Check the first line to see if authentication has failed; if so, go around the loop again
485 if (command_output.startsWith("ERROR: Authentication failed:")) {
486 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
487 remote_greenstone_server_authentication = null;
488 continue;
489 }
490 // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
491 else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
492 if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
493 // The user has decided to cancel the action
494 throw new RemoteGreenstoneServerAction.ActionCancelledException();
495 }
496
497 // The user has decided to steal the lock... rerun the command with "&steal_lock="
498 gliserver_args += "&steal_lock=";
499 continue;
500 }
501 // Handle other types of errors by throwing an exception
502 else if (command_output.startsWith("ERROR: ")) {
503 throw new Exception(command_output.substring("ERROR: ".length()));
504 } else if (command_output.indexOf("ERROR: ") != -1) { // check if ERROR occurs anywhere else in the output
505 throw new Exception(command_output);
506 }
507
508
509 // There were no exceptions thrown so the action must have succeeded
510 return command_output;
511 }
512 }
513
514
515 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
516 String uploadFile(String gliserver_args, String file_path)
517 throws Exception
518 {
519 while (true) {
520 // Check that Configuration.gliserver_url is set
521 if (Configuration.gliserver_url == null) {
522 throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
523 }
524
525 // Ask for authentication information (if necessary), then perform the action
526 authenticateUser();
527 String gliserver_url_string = Configuration.gliserver_url.toString();
528 String command_output = uploadFileInternal(gliserver_url_string, gliserver_args, file_path);
529 // System.err.println("Command output: " + command_output);
530
531 // Check the first line to see if authentication has failed; if so, go around the loop again
532 if (command_output.startsWith("ERROR: Authentication failed:")) {
533 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
534 remote_greenstone_server_authentication = null;
535 continue;
536 }
537 // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
538 else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
539 if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
540 // The user has decided to cancel the action
541 throw new RemoteGreenstoneServerAction.ActionCancelledException();
542 }
543
544 // The user has decided to steal the lock... rerun the command with "&steal_lock="
545 gliserver_args += "&steal_lock=";
546 continue;
547 }
548 // Handle other types of errors by throwing an exception
549 else if (command_output.startsWith("ERROR: ")) {
550 throw new Exception(command_output.substring("ERROR: ".length()));
551 }
552
553 // There were no exceptions thrown so the action must have succeeded
554 return command_output;
555 }
556 }
557
558
559 // ----------------------------------------------------------------------------------------------------
560 // NETWORK LAYER
561 // ----------------------------------------------------------------------------------------------------
562
563
564 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
565 private String downloadFileInternal(String download_cgi, String cgi_args, String file_path)
566 throws Exception
567 {
568 DebugStream.println("gliserver URL: " + download_cgi);
569 System.err.println("gliserver args: " + cgi_args);
570
571 // Add username and password, and a timestamp
572 cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
573 cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
574 cgi_args += "&ts=" + System.currentTimeMillis();
575 if (Gatherer.GS3){
576 cgi_args += "&site=" + Configuration.site_name;
577 }
578
579 URL download_url = new URL(download_cgi);
580 URLConnection dl_connection = download_url.openConnection();
581 dl_connection.setDoOutput(true);
582 OutputStream dl_os = dl_connection.getOutputStream();
583
584 PrintWriter dl_out = new PrintWriter(dl_os);
585 dl_out.println(cgi_args);
586 dl_out.close();
587
588 // Download result from running cgi script
589 InputStream dl_is = dl_connection.getInputStream();
590 BufferedInputStream dl_bis = new BufferedInputStream(dl_is);
591 DataInputStream dl_dbis = new DataInputStream(dl_bis);
592
593 String first_line = "";
594 byte[] buf = new byte[1024];
595 int len = dl_dbis.read(buf);
596 if (len >= 0) {
597 String first_chunk = new String(buf, 0, len);
598 // first_line = first_chunk.substring(0, ((first_chunk.indexOf("\n") != -1) ? first_chunk.indexOf("\n") : len));
599 first_line = first_chunk.substring(0, ((first_chunk.indexOf("\n") != -1) ? first_chunk.indexOf("\n") : ((first_chunk.length()<len) ? first_chunk.length():len)));
600 // Save the data to file
601 FileOutputStream zip_fos = new FileOutputStream(file_path);
602 BufferedOutputStream zip_bfos = new BufferedOutputStream(zip_fos);
603
604 while (len >= 0) {
605 zip_bfos.write(buf, 0, len);
606 len = dl_dbis.read(buf);
607 }
608
609 zip_bfos.close();
610 zip_fos.close();
611 }
612
613 dl_dbis.close();
614 dl_bis.close();
615 dl_is.close();
616 return first_line;
617 }
618
619
620 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
621 private String sendCommandToServerInternal(String gliserver_url_string, String cgi_args, GShell shell)
622 throws Exception
623 {
624 DebugStream.println("gliserver URL: " + gliserver_url_string);
625 System.err.println("gliserver args: " + cgi_args);
626
627 // Add username and password, and a timestamp
628 if(isAuthenticationRequired(cgi_args)) {
629 cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
630 cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
631 }
632 cgi_args += "&ts=" + System.currentTimeMillis();
633 if (Gatherer.GS3){
634 cgi_args += "&site=" + Configuration.site_name;
635 }
636
637 URL gliserver_url = new URL(gliserver_url_string + "?" + cgi_args);
638 URLConnection gliserver_connection = gliserver_url.openConnection();
639
640 // Read the output of the command from the server, and return it
641 StringBuffer command_output_buffer = new StringBuffer(2048);
642 InputStream gliserver_is = gliserver_connection.getInputStream();
643 BufferedReader gliserver_in = new BufferedReader(new InputStreamReader(gliserver_is, "UTF-8"));
644 String gliserver_output_line = gliserver_in.readLine();
645 while (gliserver_output_line != null) {
646 if (shell != null) {
647 shell.fireMessage(gliserver_output_line);
648 if (shell.hasSignalledStop()) {
649 throw new RemoteGreenstoneServerAction.ActionCancelledException();
650 }
651 }
652 command_output_buffer.append(gliserver_output_line + "\n");
653 gliserver_output_line = gliserver_in.readLine();
654 }
655 gliserver_in.close();
656
657 return command_output_buffer.toString();
658 }
659
660
661 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
662 private String uploadFileInternal(String upload_cgi, String cgi_args, String file_path)
663 throws Exception
664 {
665 System.err.println("gliserver URL: " + upload_cgi);
666 System.err.println("gliserver args: " + cgi_args);
667
668 //For a remote GS3
669 //GS3 is running on Tomcat, and Tomcat requires a connection timeout to be set up at the client
670 //side while uploading files. As HttpURLConnection couldn't set the connection timeout, HttpClient.jar
671 //from Jakarta is applied to solve this problem only for uploading files.
672 if (Gatherer.GS3) {
673
674 // Setup the POST method
675 PostMethod httppost = new PostMethod(upload_cgi+"?"+cgi_args); // cgi_args: QUERY_STRING on perl server side
676
677 // construct the multipartrequest form
678 String[] cgi_array=cgi_args.split("&");// get parameter-value pairs from cgi_args string
679 Part[] parts=new Part[cgi_array.length+5];
680
681 // The FilePart: consisting of the (cgi-arg) name and (optional) filename in the Content-Disposition
682 // of the POST request Header (see CGI.pm), and the actual zip file itself. It uses the defaults:
683 // Content-Type: application/octet-stream; charset=ISO-8859-1,Content-Transfer-Encoding: binary
684 parts[0]= new FilePart("uploaded_file", "zipFile", new File(file_path));
685
686 parts[1]= new StringPart("un", remote_greenstone_server_authentication.getUserName());
687 parts[2]= new StringPart("pw", new String(remote_greenstone_server_authentication.getPassword()));
688 parts[3]= new StringPart("ts", String.valueOf(System.currentTimeMillis()));
689 parts[4]= new StringPart("site", Configuration.site_name);
690 // find all parameters of cgi-args and add them into Part[]
691 for (int i=0; i<cgi_array.length;i++){
692 parts[5+i]=new StringPart(cgi_array[i].substring(0,cgi_array[i].indexOf("=")),cgi_array[i].substring(cgi_array[i].indexOf("=")+1,cgi_array[i].length()));
693 }
694
695 // set MultipartRequestEntity on the POST method
696 httppost.setRequestEntity(new MultipartRequestEntity(parts, httppost.getParams()));
697
698 // See file gli/request.txt for the multipart request that's been generated:
699 //httppost.getRequestEntity().writeRequest(new FileOutputStream("request.txt", true)); // true: appends
700
701 //set up the HttpClient connection
702 HttpClient client=new HttpClient();
703 client.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
704 client.getParams().setConnectionManagerTimeout(200000); //set the connection timeout
705 // get the output of the command from the server
706 String command_output = "";
707 try{
708 client.executeMethod(httppost);
709 if (httppost.getStatusCode() == HttpStatus.SC_OK) {
710 command_output = httppost.getStatusLine().toString();
711 } else {
712 command_output = httppost.getStatusLine().toString();
713 System.out.println("Unexpected failure: " + httppost.getStatusLine().toString());
714 }
715 }catch(IOException e){
716 e.printStackTrace();
717 }finally{
718 httppost.releaseConnection();
719 }
720 return command_output;
721 }
722
723 //For a remote GS2
724 // Add username and password, and a timestamp
725 cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
726 cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
727 cgi_args += "&ts=" + System.currentTimeMillis();
728
729 // Open a HTTP connection to the URL
730 URL url = new URL(upload_cgi);
731 HttpURLConnection gliserver_connection = (HttpURLConnection) url.openConnection();
732
733 gliserver_connection.setDoInput(true); // Allow Inputs
734 gliserver_connection.setDoOutput(true); // Allow Outputs
735 gliserver_connection.setUseCaches(false); // Don't use a cached copy.
736
737 gliserver_connection.setRequestProperty("Connection", "Keep-Alive");
738
739 // Send zip file to server
740 File file = new File(file_path);
741 FileInputStream fileInputStream = new FileInputStream(file);
742
743 // Add file size argument, because IIS 6 needs a lot of help
744 int file_size = fileInputStream.available();
745 cgi_args += "&fs=" + file_size;
746
747 DataOutputStream dos = new DataOutputStream(gliserver_connection.getOutputStream());
748 dos.writeBytes(cgi_args + "\n");
749
750 // create a buffer of maximum size
751 final int maxBufferSize = 1024;
752 int bytesAvailable = file_size;
753 int bufferSize = Math.min(bytesAvailable, maxBufferSize);
754 byte[] buffer = new byte[bufferSize];
755
756 // read file and write it into form...
757 // !! This uses a lot of memory when the file being uploaded is big -- Java seems to need to keep
758 // the entire file in the DataOutputStream? (Use Runtime.getRuntime().totalMemory() to see)
759 int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
760 while (bytesRead > 0) {
761 dos.write(buffer, 0, bytesRead);
762 bytesAvailable = fileInputStream.available();
763 bufferSize = Math.min(bytesAvailable, maxBufferSize);
764 bytesRead = fileInputStream.read(buffer, 0, bufferSize);
765 }
766
767 // close streams
768 fileInputStream.close();
769 dos.flush();
770 dos.close();
771
772 // Read the output of the command from the server, and return it
773 String command_output = "";
774 InputStream gliserver_is = gliserver_connection.getInputStream();
775 BufferedReader gliserver_in = new BufferedReader(new InputStreamReader(gliserver_is, "UTF-8"));
776 String gliserver_output_line = gliserver_in.readLine();
777 while (gliserver_output_line != null) {
778 command_output += gliserver_output_line + "\n";
779 gliserver_output_line = gliserver_in.readLine();
780 }
781 gliserver_in.close();
782
783 return command_output;
784 }
785
786
787 // ----------------------------------------------------------------------------------------------------
788 // UTILITIES
789 // ----------------------------------------------------------------------------------------------------
790
791
792 public String getPathRelativeToDirectory(File file, String directory_path)
793 {
794 String file_path = file.getAbsolutePath();
795 if (!file_path.startsWith(directory_path)) {
796 System.err.println("ERROR: File path " + file_path + " is not a child of " + directory_path);
797 return file_path;
798 }
799
800 String relative_file_path = file_path.substring(directory_path.length());
801 if (relative_file_path.startsWith(File.separator)) {
802 relative_file_path = relative_file_path.substring(File.separator.length());
803 }
804 return relative_file_path;
805 }
806}
Note: See TracBrowser for help on using the repository browser.