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

Last change on this file since 34160 was 34160, checked in by ak19, 4 years ago

Completing TODO from Kathy's commit message for 34116 for ServletRealmCheck: still todo - get servlet name from input args, can't assume library.

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