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

Last change on this file since 31776 was 31776, checked in by ak19, 7 years ago

Kathy described a problem on the mailing list about the AutoLoadConverters msg appearing before XML content when connecting with a client-GLI to a remote GS3, which breaks parsing of the XML. (I found it was present in my GS3 installation from 4 May 2016.) I've narrowed it down to running client-gli with the debug flag turned on, which seemed related to the same problem I'd seen when running gli -debug after the change to SafeProcess in Plugins.java, which I fixed by removing lines preceding XML content before parsing the XML. For client-gli, SafeProcess isn't used which is also why the problem with client-gli is much older, but I'm now using a common and existing solution for both: doing what Plugins.java used to do before the change to SafeProcess, which is call XMLTools.readXMLStream(), which would parse out content before XML. The RemoteGreenstoneServer should only call this method if it actually has some XML content it's dealing with. Could have solved this in RemoteGreenstoneServerAction.java's GetScriptOptions, but am solving it in RemoteGreenstoneServer's sendCommandToServerInternal, since there may be many Actions returning XML, not just GetScriptOptions.

  • Property svn:keywords set to Author Date Id Revision
File size: 34.4 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 // If we're running in the GUI thread we must return immediately
268 // We cannot wait for the action to complete because this will block any GUI updates
269 if (SwingUtilities.isEventDispatchThread()) {
270 System.err.println(threadName
271 + "\tACTION QUEUED: In event dispatch thread, returning immediately...\n\t"
272 + remote_greenstone_server_action);
273 return null;
274 }
275
276 // Otherwise wait until the action is processed
277 try {
278 synchronized (remote_greenstone_server_action) {
279 while(!remote_greenstone_server_action.processed) {
280 //System.err.println("Waiting for action to complete...: " + remote_greenstone_server_action);
281 DebugStream.println("Waiting for action to complete...");
282 remote_greenstone_server_action.wait(); // wait to be notified when the action has been processed
283 }
284 }
285 } catch (Exception e) {
286 System.err.println("RemoteGreenstoneServer.performAction() - exception: " + e);
287 e.printStackTrace();
288 }
289
290 // Return "" if the action failed
291 if (!remote_greenstone_server_action.processed_successfully) {
292 return "";
293 }
294 // Otherwise return the action output
295 return remote_greenstone_server_action.action_output;
296 }
297
298
299 // ----------------------------------------------------------------------------------------------------
300 // PROGRESS BAR
301 // ----------------------------------------------------------------------------------------------------
302
303 static class ProgressBar
304 extends JProgressBar
305 {
306 public ProgressBar()
307 {
308 setBackground(Configuration.getColor("coloring.collection_tree_background", false));
309 setForeground(Configuration.getColor("coloring.collection_tree_foreground", false));
310 setString(Dictionary.get("FileActions.No_Activity"));
311 setStringPainted(true);
312 }
313
314 /** synchronized to avoid conflicts since several threads access this */
315 synchronized public void setAction(String action)
316 {
317 if (action != null) {
318 DebugStream.println(action);
319 }
320
321 // We cannot call this from the GUI thread otherwise the progress bar won't start
322 if (SwingUtilities.isEventDispatchThread()) {
323 System.err.println("ERROR: RemoteGreenstoneServerProgressBar.setAction() called from event dispatch thread!");
324 return;
325 }
326
327 // Set the string on the progress bar, and start or stop it
328 if (action == null) {
329 setString(Dictionary.get("FileActions.No_Activity"));
330 setIndeterminate(false);
331 }
332 else {
333 setString(action);
334 setIndeterminate(true);
335 }
336 }
337 }
338
339 /** synchronized to avoid conflicts since several threads access this */
340 synchronized public RemoteGreenstoneServer.ProgressBar getProgressBar()
341 {
342 return progress_bar;
343 }
344
345
346 // ----------------------------------------------------------------------------------------------------
347 // AUTHENTICATION LAYER
348 // ----------------------------------------------------------------------------------------------------
349
350 static private class RemoteGreenstoneServerAuthenticateTask
351 extends Thread
352 {
353 public void run()
354 {
355 remote_greenstone_server_authentication = new RemoteGreenstoneServerAuthenticator().getAuthentication();
356 }
357
358
359 static private class RemoteGreenstoneServerAuthenticator
360 extends GAuthenticator
361 {
362 public PasswordAuthentication getAuthentication(String username, String password)
363 {
364 return getPasswordAuthentication(username,password);
365 }
366
367 public PasswordAuthentication getAuthentication()
368 {
369 return getPasswordAuthentication();
370 }
371
372 protected String getMessageString()
373 {
374 if (Gatherer.GS3){
375 return (Dictionary.get("RemoteGreenstoneServer.Authentication_Message_gs3") + " " + Configuration.site_name);
376 }
377 return Dictionary.get("RemoteGreenstoneServer.Authentication_Message");
378 }
379 }
380 }
381
382 public void set_remote_greenstone_server_authentication_to_null() {
383 remote_greenstone_server_authentication = null;
384 }
385
386 private void authenticateUser()
387 throws RemoteGreenstoneServerAction.ActionCancelledException
388 {
389 // If we don't have any authentication information then ask for it now
390 if (remote_greenstone_server_authentication == null) {
391 try {
392 // We have to do this on the GUI thread
393 SwingUtilities.invokeAndWait(new RemoteGreenstoneServerAuthenticateTask());
394 }
395 catch (Exception exception) {
396 System.err.println("Exception occurred when authenticating the user: " + exception);
397 DebugStream.printStackTrace(exception);
398 }
399
400 // If it is still null then the user has cancelled the authentication, so the action is cancelled
401 if (remote_greenstone_server_authentication == null) {
402 throw new RemoteGreenstoneServerAction.ActionCancelledException();
403 }
404 }
405 }
406
407
408 public String getUsername()
409 {
410 if (remote_greenstone_server_authentication != null) {
411 return remote_greenstone_server_authentication.getUserName();
412 }
413
414 return null;
415 }
416
417
418 // ----------------------------------------------------------------------------------------------------
419 // REQUEST LAYER
420 // ----------------------------------------------------------------------------------------------------
421
422
423 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
424 String downloadFile(String gliserver_args, String file_path)
425 throws Exception
426 {
427 while (true) {
428 // Check that Configuration.gliserver_url is set
429 if (Configuration.gliserver_url == null) {
430 throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
431 }
432
433 // Ask for authentication information (if necessary), then perform the action
434 authenticateUser();
435 String gliserver_url_string = Configuration.gliserver_url.toString();
436 String command_output = downloadFileInternal(gliserver_url_string, gliserver_args, file_path);
437
438 // Debugging - print any ok messages to stderr
439 //System.err.println("**** RECEIVED (sendCommandToServer()): " + command_output);
440
441 // Check the first line to see if authentication has failed; if so, go around the loop again
442 if (command_output.startsWith("ERROR: Authentication failed:")) {
443 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
444 remote_greenstone_server_authentication = null;
445 continue;
446 }
447 // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
448 else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
449 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) {
450 // The user has decided to cancel the action
451 throw new RemoteGreenstoneServerAction.ActionCancelledException();
452 }
453
454 // The user has decided to steal the lock... rerun the command with "&steal_lock="
455 gliserver_args += "&steal_lock=";
456 continue;
457 }
458 // Handle other types of errors by throwing an exception
459 else if (command_output.startsWith("ERROR: ")) {
460 throw new Exception(command_output.substring("ERROR: ".length()));
461 }
462
463 // There were no exceptions thrown so the action must have succeeded
464 return command_output;
465 }
466 }
467
468 /** Returns true or false depending on whether authentication is required for the cmd
469 * string embedded in the given gliserver_args. No authentication is required for either
470 * of the commands greenstone-server-version and get-library-url-suffix. */
471 private boolean isAuthenticationRequired(String gliserver_args) {
472 return ((gliserver_args.indexOf("greenstone-server-version") == -1)
473 && (gliserver_args.indexOf("get-library-url-suffix") == -1));
474 }
475
476
477 /** Returns the command output if the action completed, throws some kind of exception otherwise.
478 * Package access, so that RemoteGreenstoneServerAction.java can call this.
479 */
480 String sendCommandToServer(String gliserver_args, GShell shell)
481 throws Exception
482 {
483 while (true) {
484
485 // Check that Configuration.gliserver_url is set
486 if (Configuration.gliserver_url == null) {
487 throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
488 }
489
490 // Ask for authentication information (if necessary), then perform the action
491 if(isAuthenticationRequired(gliserver_args)) {
492 try {
493 authenticateUser();
494 } catch (RemoteGreenstoneServerAction.ActionCancelledException e) {
495 // Authentication popup only appears at the start. If the user cancelled
496 // out of it, then another remote action always remains on the queue,
497 // preventing a clean exit. Need to clear queue before exit.
498 synchronized (remote_greenstone_server_action_queue) {
499 remote_greenstone_server_action_queue.clear();
500 }
501 Gatherer.exit();
502 }
503 }
504 String gliserver_url_string = Configuration.gliserver_url.toString();
505 String command_output = sendCommandToServerInternal(gliserver_url_string, gliserver_args, shell);
506
507 // Debugging - print any ok messages to stderr
508 //if(!(command_output.trim().startsWith("<"))) {
509 //System.err.println("**** RECEIVED (sendCommandToServer()): " + command_output);
510 //}
511
512 // Check the first line to see if authentication has failed; if so, go around the loop again
513 if (command_output.startsWith("ERROR: Authentication failed:")) {
514 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
515 remote_greenstone_server_authentication = null;
516 continue;
517 }
518 // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
519 else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
520 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) {
521 // The user has decided to cancel the action
522 throw new RemoteGreenstoneServerAction.ActionCancelledException();
523 }
524
525 // The user has decided to steal the lock... rerun the command with "&steal_lock="
526 gliserver_args += "&steal_lock=";
527 continue;
528 }
529 // Handle other types of errors by throwing an exception
530 else if (command_output.startsWith("ERROR: ")) {
531 throw new Exception(command_output.substring("ERROR: ".length()));
532 } else if (command_output.indexOf("ERROR: ") != -1) { // check if ERROR occurs anywhere else in the output
533 throw new Exception(command_output);
534 }
535
536
537 // There were no exceptions thrown so the action must have succeeded
538 return command_output;
539 }
540 }
541
542
543 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
544 String uploadFile(String gliserver_args, String file_path)
545 throws Exception
546 {
547 while (true) {
548 // Check that Configuration.gliserver_url is set
549 if (Configuration.gliserver_url == null) {
550 throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
551 }
552
553 // Ask for authentication information (if necessary), then perform the action
554 authenticateUser();
555 String gliserver_url_string = Configuration.gliserver_url.toString();
556 String command_output = uploadFileInternal(gliserver_url_string, gliserver_args, file_path);
557 // System.err.println("Command output: " + command_output);
558
559 // Check the first line to see if authentication has failed; if so, go around the loop again
560 if (command_output.startsWith("ERROR: Authentication failed:")) {
561 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
562 remote_greenstone_server_authentication = null;
563 continue;
564 }
565 // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
566 else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
567 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) {
568 // The user has decided to cancel the action
569 throw new RemoteGreenstoneServerAction.ActionCancelledException();
570 }
571
572 // The user has decided to steal the lock... rerun the command with "&steal_lock="
573 gliserver_args += "&steal_lock=";
574 continue;
575 }
576 // Handle other types of errors by throwing an exception
577 else if (command_output.startsWith("ERROR: ")) {
578 throw new Exception(command_output.substring("ERROR: ".length()));
579 }
580
581 // There were no exceptions thrown so the action must have succeeded
582 return command_output;
583 }
584 }
585
586
587 // ----------------------------------------------------------------------------------------------------
588 // NETWORK LAYER
589 // ----------------------------------------------------------------------------------------------------
590
591
592 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
593 private String downloadFileInternal(String download_cgi, String cgi_args, String file_path)
594 throws Exception
595 {
596 DebugStream.println("gliserver URL: " + download_cgi);
597 System.err.println("gliserver args: " + cgi_args);
598
599 // Add username and password, and a timestamp
600 cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
601 cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
602 cgi_args += "&ts=" + System.currentTimeMillis();
603 if (Gatherer.GS3){
604 cgi_args += "&site=" + Configuration.site_name;
605 }
606
607 URL download_url = new URL(download_cgi);
608 URLConnection dl_connection = download_url.openConnection();
609 dl_connection.setDoOutput(true);
610 OutputStream dl_os = dl_connection.getOutputStream();
611
612 PrintWriter dl_out = new PrintWriter(dl_os);
613 dl_out.println(cgi_args);
614 dl_out.close();
615
616 // Download result from running cgi script
617 InputStream dl_is = dl_connection.getInputStream();
618 BufferedInputStream dl_bis = new BufferedInputStream(dl_is);
619 DataInputStream dl_dbis = new DataInputStream(dl_bis);
620
621 String first_line = "";
622 byte[] buf = new byte[1024];
623 int len = dl_dbis.read(buf);
624 if (len >= 0) {
625 String first_chunk = new String(buf, 0, len);
626 // first_line = first_chunk.substring(0, ((first_chunk.indexOf("\n") != -1) ? first_chunk.indexOf("\n") : len));
627 first_line = first_chunk.substring(0, ((first_chunk.indexOf("\n") != -1) ? first_chunk.indexOf("\n") : ((first_chunk.length()<len) ? first_chunk.length():len)));
628 // Save the data to file
629 FileOutputStream zip_fos = new FileOutputStream(file_path);
630 BufferedOutputStream zip_bfos = new BufferedOutputStream(zip_fos);
631
632 while (len >= 0) {
633 zip_bfos.write(buf, 0, len);
634 len = dl_dbis.read(buf);
635 }
636
637 zip_bfos.close();
638 zip_fos.close();
639 }
640
641 dl_dbis.close();
642 dl_bis.close();
643 dl_is.close();
644 return first_line;
645 }
646
647
648 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
649 private String sendCommandToServerInternal(String gliserver_url_string, String cgi_args, GShell shell)
650 throws Exception
651 {
652 DebugStream.println("gliserver URL: " + gliserver_url_string);
653 System.err.println("gliserver args: " + cgi_args);
654
655 // Add username and password, and a timestamp
656 if(isAuthenticationRequired(cgi_args)) {
657 cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
658 cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
659 }
660 cgi_args += "&ts=" + System.currentTimeMillis();
661 if (Gatherer.GS3){
662 cgi_args += "&site=" + Configuration.site_name;
663 }
664
665 URL gliserver_url = new URL(gliserver_url_string + "?" + cgi_args);
666 URLConnection gliserver_connection = gliserver_url.openConnection();
667
668 // Read the output of the command from the server, and return it
669 StringBuffer command_output_buffer = new StringBuffer(2048);
670 InputStream gliserver_is = gliserver_connection.getInputStream();
671 BufferedReader gliserver_in = new BufferedReader(new InputStreamReader(gliserver_is, "UTF-8"));
672 String gliserver_output_line = gliserver_in.readLine();
673 while (gliserver_output_line != null) {
674 if (shell != null) {
675 shell.fireMessage(gliserver_output_line);
676 if (shell.hasSignalledStop()) {
677 throw new RemoteGreenstoneServerAction.ActionCancelledException();
678 }
679 }
680 command_output_buffer.append(gliserver_output_line + "\n");
681 gliserver_output_line = gliserver_in.readLine();
682 }
683 gliserver_in.close();
684
685
686 int startIndex = command_output_buffer.indexOf("<?xml");
687 if(startIndex > 0) { // not -1, so "<?xml" is present, and not 0, so not at start
688
689 // iff dealing with XML, make sure to parse out any lines preceding the XML content
690 command_output_buffer = XMLTools.readXMLStream(command_output_buffer.toString());
691 /*if(DebugStream.isDebuggingEnabled()) {
692 String prefix = command_output_buffer.substring(0, startIndex);
693 DebugStream.println("Removing the following found before start of XML:");
694 DebugStream.println("---------------------------------");
695 DebugStream.println(prefix);
696 DebugStream.println("---------------------------------");
697 }
698 // remove the prefix
699 return command_output_buffer.substring(startIndex); // remove anything before the start of XML
700 */
701 }
702
703 return command_output_buffer.toString();
704 }
705
706
707 /** Returns the command output if the action completed, throws some kind of exception otherwise. */
708 private String uploadFileInternal(String upload_cgi, String cgi_args, String file_path)
709 throws Exception
710 {
711 System.err.println("gliserver URL: " + upload_cgi);
712 System.err.println("gliserver args: " + cgi_args);
713
714 //For a remote GS3
715 //GS3 is running on Tomcat, and Tomcat requires a connection timeout to be set up at the client
716 //side while uploading files. As HttpURLConnection couldn't set the connection timeout, HttpClient.jar
717 //from Jakarta is applied to solve this problem only for uploading files.
718 if (Gatherer.GS3) {
719
720 // Setup the POST method
721 PostMethod httppost = new PostMethod(upload_cgi+"?"+cgi_args); // cgi_args: QUERY_STRING on perl server side
722
723 // construct the multipartrequest form
724 String[] cgi_array=cgi_args.split("&");// get parameter-value pairs from cgi_args string
725 Part[] parts=new Part[cgi_array.length+5];
726
727 // The FilePart: consisting of the (cgi-arg) name and (optional) filename in the Content-Disposition
728 // of the POST request Header (see CGI.pm), and the actual zip file itself. It uses the defaults:
729 // Content-Type: application/octet-stream; charset=ISO-8859-1,Content-Transfer-Encoding: binary
730 parts[0]= new FilePart("uploaded_file", "zipFile", new File(file_path));
731
732 parts[1]= new StringPart("un", remote_greenstone_server_authentication.getUserName());
733 parts[2]= new StringPart("pw", new String(remote_greenstone_server_authentication.getPassword()));
734 parts[3]= new StringPart("ts", String.valueOf(System.currentTimeMillis()));
735 parts[4]= new StringPart("site", Configuration.site_name);
736 // find all parameters of cgi-args and add them into Part[]
737 for (int i=0; i<cgi_array.length;i++){
738 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()));
739 }
740
741 // set MultipartRequestEntity on the POST method
742 httppost.setRequestEntity(new MultipartRequestEntity(parts, httppost.getParams()));
743
744 // See file gli/request.txt for the multipart request that's been generated:
745 //httppost.getRequestEntity().writeRequest(new FileOutputStream("request.txt", true)); // true: appends
746
747 //set up the HttpClient connection
748 HttpClient client=new HttpClient();
749 client.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
750 client.getParams().setConnectionManagerTimeout(200000); //set the connection timeout
751 // get the output of the command from the server
752 String command_output = "";
753 try{
754 client.executeMethod(httppost);
755 if (httppost.getStatusCode() == HttpStatus.SC_OK) {
756 command_output = httppost.getStatusLine().toString();
757 } else {
758 command_output = httppost.getStatusLine().toString();
759 System.out.println("Unexpected failure: " + httppost.getStatusLine().toString());
760 }
761 }catch(IOException e){
762 e.printStackTrace();
763 }finally{
764 httppost.releaseConnection();
765 }
766 return command_output;
767 }
768
769 //For a remote GS2
770 // Add username and password, and a timestamp
771 cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
772 cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
773 cgi_args += "&ts=" + System.currentTimeMillis();
774
775 // Open a HTTP connection to the URL
776 URL url = new URL(upload_cgi);
777 HttpURLConnection gliserver_connection = (HttpURLConnection) url.openConnection();
778
779 gliserver_connection.setDoInput(true); // Allow Inputs
780 gliserver_connection.setDoOutput(true); // Allow Outputs
781 gliserver_connection.setUseCaches(false); // Don't use a cached copy.
782
783 gliserver_connection.setRequestProperty("Connection", "Keep-Alive");
784
785 // Send zip file to server
786 File file = new File(file_path);
787 FileInputStream fileInputStream = new FileInputStream(file);
788
789 // Add file size argument, because IIS 6 needs a lot of help
790 int file_size = fileInputStream.available();
791 cgi_args += "&fs=" + file_size;
792
793 DataOutputStream dos = new DataOutputStream(gliserver_connection.getOutputStream());
794 dos.writeBytes(cgi_args + "\n");
795
796 // create a buffer of maximum size
797 final int maxBufferSize = 1024;
798 int bytesAvailable = file_size;
799 int bufferSize = Math.min(bytesAvailable, maxBufferSize);
800 byte[] buffer = new byte[bufferSize];
801
802 // read file and write it into form...
803 // !! This uses a lot of memory when the file being uploaded is big -- Java seems to need to keep
804 // the entire file in the DataOutputStream? (Use Runtime.getRuntime().totalMemory() to see)
805 int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
806 while (bytesRead > 0) {
807 dos.write(buffer, 0, bytesRead);
808 bytesAvailable = fileInputStream.available();
809 bufferSize = Math.min(bytesAvailable, maxBufferSize);
810 bytesRead = fileInputStream.read(buffer, 0, bufferSize);
811 }
812
813 // close streams
814 fileInputStream.close();
815 dos.flush();
816 dos.close();
817
818 // Read the output of the command from the server, and return it
819 String command_output = "";
820 InputStream gliserver_is = gliserver_connection.getInputStream();
821 BufferedReader gliserver_in = new BufferedReader(new InputStreamReader(gliserver_is, "UTF-8"));
822 String gliserver_output_line = gliserver_in.readLine();
823 while (gliserver_output_line != null) {
824 command_output += gliserver_output_line + "\n";
825 gliserver_output_line = gliserver_in.readLine();
826 }
827 gliserver_in.close();
828
829 return command_output;
830 }
831
832
833 // ----------------------------------------------------------------------------------------------------
834 // UTILITIES
835 // ----------------------------------------------------------------------------------------------------
836
837
838 public String getPathRelativeToDirectory(File file, String directory_path)
839 {
840 String file_path = file.getAbsolutePath();
841 if (!file_path.startsWith(directory_path)) {
842 System.err.println("ERROR: File path " + file_path + " is not a child of " + directory_path);
843 return file_path;
844 }
845
846 String relative_file_path = file_path.substring(directory_path.length());
847 if (relative_file_path.startsWith(File.separator)) {
848 relative_file_path = relative_file_path.substring(File.separator.length());
849 }
850 return relative_file_path;
851 }
852}
Note: See TracBrowser for help on using the repository browser.