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

Revision 22692, 33.5 KB (checked in by ak19, 7 years ago)

Clean exit out of client GLI if the user cancelled out of the authentication popup that appears at the start

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