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

Revision 31776, 34.4 KB (checked in by ak19, 4 months 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
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 browser.