/** *######################################################################### * * A component of the Gatherer application, part of the Greenstone digital * library suite from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * Author: Michael Dewsnip, NZDL Project, University of Waikato * * Copyright (C) 2005 New Zealand Digital Library Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *######################################################################## */ package org.greenstone.gatherer.remote; import java.io.*; import java.net.*; import java.util.*; import java.util.zip.*; import javax.swing.*; import org.greenstone.gatherer.Configuration; import org.greenstone.gatherer.DebugStream; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.GAuthenticator; import org.greenstone.gatherer.Gatherer; import org.greenstone.gatherer.collection.CollectionManager; import org.greenstone.gatherer.shell.GShell; import org.greenstone.gatherer.util.UnzipTools; import org.greenstone.gatherer.util.Utility; public class RemoteGreenstoneServer { // ---------------------------------------------------------------------------------------------------- // PUBLIC LAYER // ---------------------------------------------------------------------------------------------------- static public String deleteCollection(String collection_name) { return performAction(new RemoteGreenstoneServerDeleteCollectionAction(collection_name)); } static public String deleteCollectionFile(String collection_name, File collection_file) { return performAction(new RemoteGreenstoneServerDeleteCollectionFileAction(collection_name, collection_file)); } static public String downloadCollection(String collection_name) { return performAction(new RemoteGreenstoneServerDownloadCollectionAction(collection_name)); } static public String downloadCollectionArchives(String collection_name) { return performAction(new RemoteGreenstoneServerDownloadCollectionArchivesAction(collection_name)); } static public String downloadCollectionConfigurations() { return performAction(new RemoteGreenstoneServerDownloadCollectionConfigurationsAction()); } static public String downloadCollectionFile(String collection_name, File collection_file) { return performAction(new RemoteGreenstoneServerDownloadCollectionFileAction(collection_name, collection_file)); } static public String getScriptOptions(String script_name, String script_arguments) { return performAction(new RemoteGreenstoneServerGetScriptOptionsAction(script_name, script_arguments)); } static public String moveCollectionFile(String collection_name, File source_collection_file, File target_collection_file) { return performAction(new RemoteGreenstoneServerMoveCollectionFileAction(collection_name, source_collection_file, target_collection_file)); } static public String newCollectionDirectory(String collection_name, File new_collection_directory) { return performAction(new RemoteGreenstoneServerNewCollectionDirectoryAction(collection_name, new_collection_directory)); } static public String runScript(String collection_name, String script_name, String script_arguments, GShell shell) { return performAction(new RemoteGreenstoneServerRunScriptAction(collection_name, script_name, script_arguments, shell)); } static public String uploadCollectionFile(String collection_name, File collection_file) { return performAction(new RemoteGreenstoneServerUploadCollectionFilesAction(collection_name, new File[] { collection_file })); } static public String uploadCollectionFiles(String collection_name, File[] collection_files) { return performAction(new RemoteGreenstoneServerUploadCollectionFilesAction(collection_name, collection_files)); } static public String uploadFilesIntoCollection(String collection_name, File[] source_files, File target_collection_directory) { return performAction(new RemoteGreenstoneServerUploadFilesIntoCollectionAction(collection_name, source_files, target_collection_directory)); } // ---------------------------------------------------------------------------------------------------- static public void exit() { System.err.println("Exiting, number of jobs on queue: " + remote_greenstone_server_action_queue.size()); // If there are still jobs on the queue we must wait for the jobs to finish while (remote_greenstone_server_action_queue.size() > 0) { synchronized (remote_greenstone_server_action_queue) { try { DebugStream.println("Waiting for queue to become empty..."); remote_greenstone_server_action_queue.wait(500); } catch (InterruptedException exception) {} } } } // ---------------------------------------------------------------------------------------------------- // QUEUE LAYER // ---------------------------------------------------------------------------------------------------- /** Returns null if we cannot wait for the action to finish, "" if the action failed, or the action output. */ static private String performAction(RemoteGreenstoneServerAction remote_greenstone_server_action) { // Add the action to the queue remote_greenstone_server_action_queue.addAction(remote_greenstone_server_action); // If we're running in the GUI thread we must return immediately // We cannot wait for the action to complete because this will block any GUI updates if (SwingUtilities.isEventDispatchThread()) { System.err.println("WARNING: In event dispatch thread, returning immediately..."); return null; } // Otherwise wait until the action is processed while (!remote_greenstone_server_action.processed) { synchronized (remote_greenstone_server_action) { try { DebugStream.println("Waiting for action to complete..."); remote_greenstone_server_action.wait(500); } catch (InterruptedException exception) {} } } // Return "" if the action failed if (!remote_greenstone_server_action.processed_successfully) { return ""; } // Otherwise return the action output return remote_greenstone_server_action.action_output; } static private RemoteGreenstoneServerActionQueue remote_greenstone_server_action_queue = new RemoteGreenstoneServerActionQueue(); static private class RemoteGreenstoneServerActionQueue extends Thread { /** The queue of waiting jobs. */ private ArrayList queue = null; public RemoteGreenstoneServerActionQueue() { if (Gatherer.isGsdlRemote) { queue = new ArrayList(); start(); } } synchronized public void addAction(RemoteGreenstoneServerAction remote_greenstone_server_action) { queue.add(remote_greenstone_server_action); notifyAll(); } public int size() { return queue.size(); } public void run() { while (true) { // If there are jobs on the queue, get the next in line and process it if (queue.size() > 0) { RemoteGreenstoneServerAction remote_greenstone_server_action = (RemoteGreenstoneServerAction) queue.get(0); try { remote_greenstone_server_action.perform(); // No exceptions were thrown, so the action was successful remote_greenstone_server_action.processed_successfully = true; } catch (RemoteGreenstoneServerActionCancelledException exception) { remote_greenstone_server_action.processed_successfully = false; } catch (Exception exception) { DebugStream.printStackTrace(exception); JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", exception.getMessage()), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE); remote_greenstone_server_action.processed_successfully = false; } // We're done with this action, for better or worse remote_greenstone_server_action.processed = true; queue.remove(0); } // Otherwise the queue is empty else { progress_bar.setAction(null); // Wait until we are notify()ed by addAction that there is a new job on the queue synchronized (this) { try { wait(); } catch (InterruptedException exception) { } } } } } } // ---------------------------------------------------------------------------------------------------- // PROGRESS BAR // ---------------------------------------------------------------------------------------------------- static private RemoteGreenstoneServerProgressBar progress_bar = new RemoteGreenstoneServerProgressBar(); static private class RemoteGreenstoneServerProgressBar extends JProgressBar { public RemoteGreenstoneServerProgressBar() { setBackground(Configuration.getColor("coloring.collection_tree_background", false)); setForeground(Configuration.getColor("coloring.collection_tree_foreground", false)); setString(Dictionary.get("FileActions.No_Activity")); setStringPainted(true); } public void setAction(String action) { if (action != null) { DebugStream.println(action); } // We cannot call this from the GUI thread otherwise the progress bar won't start if (SwingUtilities.isEventDispatchThread()) { System.err.println("ERROR: RemoteGreenstoneServerProgressBar.setAction() called from event dispatch thread!"); return; } // Set the string on the progress bar, and start or stop it if (action == null) { setString(Dictionary.get("FileActions.No_Activity")); setIndeterminate(false); } else { setString(action); setIndeterminate(true); } } } static public RemoteGreenstoneServerProgressBar getProgressBar() { return progress_bar; } // ---------------------------------------------------------------------------------------------------- // ACTIONS // ---------------------------------------------------------------------------------------------------- static private abstract class RemoteGreenstoneServerAction { public String action_output = null; public boolean processed = false; public boolean processed_successfully; abstract public void perform() throws Exception; } static private class RemoteGreenstoneServerActionCancelledException extends Exception { } /** * -------------------------------------------------------------------------------------------- * DELETE COLLECTION * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerDeleteCollectionAction extends RemoteGreenstoneServerAction { private String collection_name; public RemoteGreenstoneServerDeleteCollectionAction(String collection_name) { this.collection_name = collection_name; } public void perform() throws Exception { progress_bar.setAction("Deleting collection " + collection_name + "..."); String delete_collection_command = "cmd=delete-collection"; delete_collection_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); action_output = sendCommandToServer(delete_collection_command, null); } } /** * -------------------------------------------------------------------------------------------- * DELETE COLLECTION FILE * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerDeleteCollectionFileAction extends RemoteGreenstoneServerAction { private String collection_name; private File collection_file; public RemoteGreenstoneServerDeleteCollectionFileAction(String collection_name, File collection_file) { this.collection_name = collection_name; this.collection_file = collection_file; } public void perform() throws Exception { String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name); String collection_file_relative_path = getPathRelativeToDirectory(collection_file, collection_directory_path); collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|"); progress_bar.setAction("Deleting collection file " + collection_file_relative_path + "..."); String delete_collection_file_command = "cmd=delete-collection-file"; delete_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); delete_collection_file_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8"); action_output = sendCommandToServer(delete_collection_file_command, null); } } /** * -------------------------------------------------------------------------------------------- * DOWNLOAD COLLECTION * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerDownloadCollectionAction extends RemoteGreenstoneServerAction { private String collection_name; public RemoteGreenstoneServerDownloadCollectionAction(String collection_name) { this.collection_name = collection_name; } public void perform() throws Exception { progress_bar.setAction("Downloading remote collection " + collection_name + "..."); String download_collection_command = "cmd=download-collection"; download_collection_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); String zip_file_path = Gatherer.getCollectDirectoryPath() + collection_name + ".zip"; action_output = downloadFile(download_collection_command, zip_file_path); // Delete the existing (local) collection directory Utility.delete(new File(CollectionManager.getCollectionDirectoryPath(collection_name))); // Unzip the collection just downloaded UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath()); } } /** * -------------------------------------------------------------------------------------------- * DOWNLOAD COLLECTION ARCHIVES * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerDownloadCollectionArchivesAction extends RemoteGreenstoneServerAction { private String collection_name; public RemoteGreenstoneServerDownloadCollectionArchivesAction(String collection_name) { this.collection_name = collection_name; } public void perform() throws Exception { progress_bar.setAction("Downloading collection archives for " + collection_name + "..."); String download_collection_archives_command = "cmd=download-collection-archives"; download_collection_archives_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); String zip_file_path = Gatherer.getCollectDirectoryPath() + collection_name + "-archives.zip"; action_output = downloadFile(download_collection_archives_command, zip_file_path); // Delete the existing (local) collection archives Utility.delete(new File(CollectionManager.getLoadedCollectionArchivesDirectoryPath())); // Unzip the collection archives just downloaded UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath()); } } /** * -------------------------------------------------------------------------------------------- * DOWNLOAD COLLECTION CONFIGURATIONS * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerDownloadCollectionConfigurationsAction extends RemoteGreenstoneServerAction { public RemoteGreenstoneServerDownloadCollectionConfigurationsAction() { } public void perform() throws Exception { progress_bar.setAction("Downloading collection configurations..."); // Delete the existing (local) collect directory Utility.delete(new File(Gatherer.getCollectDirectoryPath())); new File(Gatherer.getCollectDirectoryPath()).mkdirs(); String download_collection_configurations_command = "cmd=download-collection-configurations"; String zip_file_path = Gatherer.getCollectDirectoryPath() + "collections.zip"; action_output = downloadFile(download_collection_configurations_command, zip_file_path); // Unzip the collection configurations just downloaded UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath()); } } /** * -------------------------------------------------------------------------------------------- * DOWNLOAD COLLECTION FILE * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerDownloadCollectionFileAction extends RemoteGreenstoneServerAction { private String collection_name; private File collection_file; public RemoteGreenstoneServerDownloadCollectionFileAction(String collection_name, File collection_file) { this.collection_name = collection_name; this.collection_file = collection_file; } public void perform() throws Exception { String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name); String collection_file_relative_path = getPathRelativeToDirectory(collection_file, collection_directory_path); collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|"); progress_bar.setAction("Downloading collection file " + collection_file_relative_path + "..."); String download_collection_file_command = "cmd=download-collection-file"; download_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); download_collection_file_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8"); String zip_file_name = collection_name + "-" + collection_file.getName() + ".zip"; String zip_file_path = collection_directory_path + zip_file_name; action_output = downloadFile(download_collection_file_command, zip_file_path); // Unzip the collection file just downloaded UnzipTools.unzipFile(zip_file_path, collection_directory_path); } } /** * -------------------------------------------------------------------------------------------- * GET SCRIPT OPTIONS * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerGetScriptOptionsAction extends RemoteGreenstoneServerAction { private String script_name; private String script_arguments; public RemoteGreenstoneServerGetScriptOptionsAction(String script_name, String script_arguments) { this.script_name = script_name; this.script_arguments = script_arguments; } public void perform() throws Exception { progress_bar.setAction("Getting options for " + script_name + "..."); String get_script_options_command = "cmd=get-script-options"; get_script_options_command += "&script=" + script_name; get_script_options_command += "&xml="; get_script_options_command += "&language=" + Configuration.getLanguage(); get_script_options_command += script_arguments; action_output = sendCommandToServer(get_script_options_command, null); } } /** * -------------------------------------------------------------------------------------------- * MOVE COLLECTION FILE * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerMoveCollectionFileAction extends RemoteGreenstoneServerAction { private String collection_name; private File source_collection_file; private File target_collection_file; public RemoteGreenstoneServerMoveCollectionFileAction(String collection_name, File source_collection_file, File target_collection_file) { this.collection_name = collection_name; this.source_collection_file = source_collection_file; this.target_collection_file = target_collection_file; } public void perform() throws Exception { String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name); String source_collection_file_relative_path = getPathRelativeToDirectory(source_collection_file, collection_directory_path); source_collection_file_relative_path = source_collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|"); String target_collection_file_relative_path = getPathRelativeToDirectory(target_collection_file, collection_directory_path); target_collection_file_relative_path = target_collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|"); progress_bar.setAction("Moving file " + source_collection_file_relative_path + " -> " + target_collection_file_relative_path + "..."); String move_collection_file_command = "cmd=move-collection-file"; move_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); move_collection_file_command += "&source=" + URLEncoder.encode(source_collection_file_relative_path, "UTF-8"); move_collection_file_command += "&target=" + URLEncoder.encode(target_collection_file_relative_path, "UTF-8"); action_output = sendCommandToServer(move_collection_file_command, null); } } /** * -------------------------------------------------------------------------------------------- * NEW COLLECTION DIRECTORY * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerNewCollectionDirectoryAction extends RemoteGreenstoneServerAction { private String collection_name; private File new_collection_directory; public RemoteGreenstoneServerNewCollectionDirectoryAction(String collection_name, File new_collection_directory) { this.collection_name = collection_name; this.new_collection_directory = new_collection_directory; } public void perform() throws Exception { String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name); String new_collection_directory_relative_path = getPathRelativeToDirectory(new_collection_directory, collection_directory_path); new_collection_directory_relative_path = new_collection_directory_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|"); progress_bar.setAction("Creating new directory " + new_collection_directory_relative_path + "..."); String new_collection_directory_command = "cmd=new-collection-directory"; new_collection_directory_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); new_collection_directory_command += "&directory=" + URLEncoder.encode(new_collection_directory_relative_path, "UTF-8"); action_output = sendCommandToServer(new_collection_directory_command, null); } } /** * -------------------------------------------------------------------------------------------- * RUN SCRIPT * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerRunScriptAction extends RemoteGreenstoneServerAction { private String collection_name; private String script_name; private String script_arguments; private GShell shell; public RemoteGreenstoneServerRunScriptAction(String collection_name, String script_name, String script_arguments, GShell shell) { this.collection_name = collection_name; this.script_name = script_name; this.script_arguments = script_arguments; this.shell = shell; } public void perform() throws Exception { progress_bar.setAction("Running " + script_name + "..."); String run_script_command = "cmd=run-script"; run_script_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); run_script_command += "&script=" + script_name; run_script_command += "&language=" + Configuration.getLanguage(); run_script_command += script_arguments; action_output = sendCommandToServer(run_script_command, shell); } } /** * -------------------------------------------------------------------------------------------- * UPLOAD COLLECTION FILE * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerUploadCollectionFilesAction extends RemoteGreenstoneServerAction { private String collection_name; private File[] collection_files; public RemoteGreenstoneServerUploadCollectionFilesAction(String collection_name, File[] collection_files) { this.collection_name = collection_name; this.collection_files = collection_files; } public void perform() throws Exception { progress_bar.setAction("Uploading collection files..."); // Determine the file paths relative to the collection directory String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name); String[] collection_file_relative_paths = new String[collection_files.length]; for (int i = 0; i < collection_files.length; i++) { collection_file_relative_paths[i] = getPathRelativeToDirectory(collection_files[i], collection_directory_path); } // Zip up the files to send to the server String zip_file_name = collection_name + "-" + System.currentTimeMillis() + ".zip"; String zip_file_path = collection_directory_path + zip_file_name; ZipTools.zipFiles(zip_file_path, collection_directory_path, collection_file_relative_paths); // Upload the zip file String upload_collection_file_command = "cmd=upload-collection-file"; upload_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); upload_collection_file_command += "&file=" + URLEncoder.encode(zip_file_name, "UTF-8"); upload_collection_file_command += "&directory="; upload_collection_file_command += "&zip=true"; action_output = uploadFile(upload_collection_file_command, zip_file_path); } } /** * -------------------------------------------------------------------------------------------- * UPLOAD FILES INTO COLLECTION * -------------------------------------------------------------------------------------------- */ static private class RemoteGreenstoneServerUploadFilesIntoCollectionAction extends RemoteGreenstoneServerAction { private String collection_name; private File[] source_files; private File target_collection_directory; public RemoteGreenstoneServerUploadFilesIntoCollectionAction(String collection_name, File[] source_files, File target_collection_directory) { this.collection_name = collection_name; this.source_files = source_files; this.target_collection_directory = target_collection_directory; } public void perform() throws Exception { String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name); String target_collection_directory_relative_path = getPathRelativeToDirectory(target_collection_directory, collection_directory_path); target_collection_directory_relative_path = target_collection_directory_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|"); progress_bar.setAction("Uploading files into collection..."); String zip_file_name = collection_name + "-" + System.currentTimeMillis() + ".zip"; String zip_file_path = Gatherer.getCollectDirectoryPath() + zip_file_name; DebugStream.println("Zip file path: " + zip_file_path); String base_directory_path = source_files[0].getParentFile().getAbsolutePath(); DebugStream.println("Base directory path: " + base_directory_path); String[] source_file_relative_paths = new String[source_files.length]; for (int i = 0; i < source_files.length; i++) { DebugStream.println("Source file path: " + source_files[i]); source_file_relative_paths[i] = getPathRelativeToDirectory(source_files[i], base_directory_path); } ZipTools.zipFiles(zip_file_path, base_directory_path, source_file_relative_paths); String upload_collection_file_command = "cmd=upload-collection-file"; upload_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8"); upload_collection_file_command += "&file=" + URLEncoder.encode(zip_file_name, "UTF-8"); upload_collection_file_command += "&directory=" + URLEncoder.encode(target_collection_directory_relative_path, "UTF-8"); upload_collection_file_command += "&zip=true"; action_output = uploadFile(upload_collection_file_command, zip_file_path); } } // ---------------------------------------------------------------------------------------------------- // AUTHENTICATION LAYER // ---------------------------------------------------------------------------------------------------- static private PasswordAuthentication remote_greenstone_server_authentication = null; // static private PasswordAuthentication remote_greenstone_server_authentication = new PasswordAuthentication(System.getProperty("user.name"), new char[] { }); static private class RemoteGreenstoneServerAuthenticateTask extends Thread { public void run() { remote_greenstone_server_authentication = new RemoteGreenstoneServerAuthenticator().getAuthentication(); } static private class RemoteGreenstoneServerAuthenticator extends GAuthenticator { public PasswordAuthentication getAuthentication() { return getPasswordAuthentication(); } protected String getMessageString() { return Dictionary.get("RemoteGreenstoneServer.Authentication_Message"); } } } static private void authenticateUser() throws RemoteGreenstoneServerActionCancelledException { // If we don't have any authentication information then ask for it now if (remote_greenstone_server_authentication == null) { try { // We have to do this on the GUI thread SwingUtilities.invokeAndWait(new RemoteGreenstoneServerAuthenticateTask()); } catch (Exception exception) { DebugStream.printStackTrace(exception); } // If it is still null then the user has cancelled the authentication, so the action is cancelled if (remote_greenstone_server_authentication == null) { throw new RemoteGreenstoneServerActionCancelledException(); } } } static public String getUsername() { if (remote_greenstone_server_authentication != null) { return remote_greenstone_server_authentication.getUserName(); } return null; } // ---------------------------------------------------------------------------------------------------- // REQUEST LAYER // ---------------------------------------------------------------------------------------------------- /** Returns the command output if the action completed, throws some kind of exception otherwise. */ static private String downloadFile(String gliserver_args, String file_path) throws Exception { while (true) { // Check that Configuration.gliserver_url is set if (Configuration.gliserver_url == null) { throw new Exception("Empty gliserver URL: please set this in Preferences before continuing."); } // Ask for authentication information (if necessary), then perform the action authenticateUser(); String gliserver_url_string = Configuration.gliserver_url.toString(); String command_output = downloadFileInternal(gliserver_url_string, gliserver_args, file_path); // Check the first line to see if authentication has failed; if so, go around the loop again if (command_output.startsWith("ERROR: Authentication failed:")) { JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE); remote_greenstone_server_authentication = null; continue; } // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock else if (command_output.startsWith("ERROR: Collection is locked by: ")) { 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) { // The user has decided to cancel the action throw new RemoteGreenstoneServerActionCancelledException(); } // The user has decided to steal the lock... rerun the command with "&steal_lock=" gliserver_args += "&steal_lock="; continue; } // Handle other types of errors by throwing an exception else if (command_output.startsWith("ERROR: ")) { throw new Exception(command_output.substring("ERROR: ".length())); } // There were no exceptions thrown so the action must have succeeded return command_output; } } /** Returns the command output if the action completed, throws some kind of exception otherwise. */ static private String sendCommandToServer(String gliserver_args, GShell shell) throws Exception { while (true) { // Check that Configuration.gliserver_url is set if (Configuration.gliserver_url == null) { throw new Exception("Empty gliserver URL: please set this in Preferences before continuing."); } // Ask for authentication information (if necessary), then perform the action authenticateUser(); String gliserver_url_string = Configuration.gliserver_url.toString(); String command_output = sendCommandToServerInternal(gliserver_url_string, gliserver_args, shell); // System.err.println("Command output: " + command_output); // Check the first line to see if authentication has failed; if so, go around the loop again if (command_output.startsWith("ERROR: Authentication failed:")) { JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE); remote_greenstone_server_authentication = null; continue; } // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock else if (command_output.startsWith("ERROR: Collection is locked by: ")) { 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) { // The user has decided to cancel the action throw new RemoteGreenstoneServerActionCancelledException(); } // The user has decided to steal the lock... rerun the command with "&steal_lock=" gliserver_args += "&steal_lock="; continue; } // Handle other types of errors by throwing an exception else if (command_output.startsWith("ERROR: ")) { throw new Exception(command_output.substring("ERROR: ".length())); } // There were no exceptions thrown so the action must have succeeded return command_output; } } /** Returns the command output if the action completed, throws some kind of exception otherwise. */ static private String uploadFile(String gliserver_args, String file_path) throws Exception { while (true) { // Check that Configuration.gliserver_url is set if (Configuration.gliserver_url == null) { throw new Exception("Empty gliserver URL: please set this in Preferences before continuing."); } // Ask for authentication information (if necessary), then perform the action authenticateUser(); String gliserver_url_string = Configuration.gliserver_url.toString(); String command_output = uploadFileInternal(gliserver_url_string, gliserver_args, file_path); // System.err.println("Command output: " + command_output); // Check the first line to see if authentication has failed; if so, go around the loop again if (command_output.startsWith("ERROR: Authentication failed:")) { JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE); remote_greenstone_server_authentication = null; continue; } // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock else if (command_output.startsWith("ERROR: Collection is locked by: ")) { 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) { // The user has decided to cancel the action throw new RemoteGreenstoneServerActionCancelledException(); } // The user has decided to steal the lock... rerun the command with "&steal_lock=" gliserver_args += "&steal_lock="; continue; } // Handle other types of errors by throwing an exception else if (command_output.startsWith("ERROR: ")) { throw new Exception(command_output.substring("ERROR: ".length())); } // There were no exceptions thrown so the action must have succeeded return command_output; } } // ---------------------------------------------------------------------------------------------------- // NETWORK LAYER // ---------------------------------------------------------------------------------------------------- /** Returns the command output if the action completed, throws some kind of exception otherwise. */ static private String downloadFileInternal(String download_cgi, String cgi_args, String file_path) throws Exception { DebugStream.println("gliserver URL: " + download_cgi); System.err.println("gliserver args: " + cgi_args); // Add username and password cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName(); cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword()); URL download_url = new URL(download_cgi); URLConnection dl_connection = download_url.openConnection(); dl_connection.setDoOutput(true); OutputStream dl_os = dl_connection.getOutputStream(); PrintWriter dl_out = new PrintWriter(dl_os); dl_out.println(cgi_args); dl_out.close(); // Download result from running cgi script InputStream dl_is = dl_connection.getInputStream(); BufferedInputStream dl_bis = new BufferedInputStream(dl_is); DataInputStream dl_dbis = new DataInputStream(dl_bis); String first_line = ""; byte[] buf = new byte[1024]; int len = dl_dbis.read(buf); if (len >= 0) { String first_chunk = new String(buf, 0, len); first_line = first_chunk.substring(0, ((first_chunk.indexOf("\n") != -1) ? first_chunk.indexOf("\n") : len)); // Save the data to file FileOutputStream zip_fos = new FileOutputStream(file_path); BufferedOutputStream zip_bfos = new BufferedOutputStream(zip_fos); while (len >= 0) { zip_bfos.write(buf, 0, len); len = dl_dbis.read(buf); } zip_bfos.close(); zip_fos.close(); } dl_dbis.close(); dl_bis.close(); dl_is.close(); return first_line; } /** Returns the command output if the action completed, throws some kind of exception otherwise. */ static private String sendCommandToServerInternal(String gliserver_url_string, String cgi_args, GShell shell) throws Exception { DebugStream.println("gliserver URL: " + gliserver_url_string); System.err.println("gliserver args: " + cgi_args); // Add username and password cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName(); cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword()); URL gliserver_url = new URL(gliserver_url_string + "?" + cgi_args); URLConnection gliserver_connection = gliserver_url.openConnection(); // Read the output of the command from the server, and return it StringBuffer command_output_buffer = new StringBuffer(2048); InputStream gliserver_is = gliserver_connection.getInputStream(); BufferedReader gliserver_in = new BufferedReader(new InputStreamReader(gliserver_is, "UTF-8")); String gliserver_output_line = gliserver_in.readLine(); while (gliserver_output_line != null) { if (shell != null) { shell.fireMessage(gliserver_output_line); if (shell.hasSignalledStop()) { throw new RemoteGreenstoneServerActionCancelledException(); } } command_output_buffer.append(gliserver_output_line + "\n"); gliserver_output_line = gliserver_in.readLine(); } gliserver_in.close(); return command_output_buffer.toString(); } /** Returns the command output if the action completed, throws some kind of exception otherwise. */ static private String uploadFileInternal(String upload_cgi, String cgi_args, String file_path) throws Exception { DebugStream.println("gliserver URL: " + upload_cgi); System.err.println("gliserver args: " + cgi_args); // Add username and password cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName(); cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword()); // Open a HTTP connection to the URL URL url = new URL(upload_cgi); HttpURLConnection gliserver_connection = (HttpURLConnection) url.openConnection(); gliserver_connection.setDoInput(true); // Allow Inputs gliserver_connection.setDoOutput(true); // Allow Outputs gliserver_connection.setUseCaches(false); // Don't use a cached copy. gliserver_connection.setRequestProperty("Connection", "Keep-Alive"); DataOutputStream dos = new DataOutputStream(gliserver_connection.getOutputStream()); dos.writeBytes(cgi_args + "\n"); // Send zip file to server File file = new File(file_path); FileInputStream fileInputStream = new FileInputStream(file); // create a buffer of maximum size final int maxBufferSize = 1024; int bytesAvailable = fileInputStream.available(); int bufferSize = Math.min(bytesAvailable, maxBufferSize); byte[] buffer = new byte[bufferSize]; // read file and write it into form... // !! This uses a lot of memory when the file being uploaded is big -- Java seems to need to keep // the entire file in the DataOutputStream? (Use Runtime.getRuntime().totalMemory() to see) int bytesRead = fileInputStream.read(buffer, 0, bufferSize); while (bytesRead > 0) { dos.write(buffer, 0, bufferSize); bytesAvailable = fileInputStream.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); bytesRead = fileInputStream.read(buffer, 0, bufferSize); } // close streams fileInputStream.close(); dos.flush(); dos.close(); // Read the output of the command from the server, and return it String command_output = ""; InputStream gliserver_is = gliserver_connection.getInputStream(); BufferedReader gliserver_in = new BufferedReader(new InputStreamReader(gliserver_is, "UTF-8")); String gliserver_output_line = gliserver_in.readLine(); while (gliserver_output_line != null) { command_output += gliserver_output_line + "\n"; gliserver_output_line = gliserver_in.readLine(); } gliserver_in.close(); return command_output; } // ---------------------------------------------------------------------------------------------------- // UTILITIES // ---------------------------------------------------------------------------------------------------- static public String getPathRelativeToDirectory(File file, String directory_path) { String file_path = file.getAbsolutePath(); if (!file_path.startsWith(directory_path)) { System.err.println("ERROR: File path " + file_path + " is not a child of " + directory_path); return file_path; } String relative_file_path = file_path.substring(directory_path.length()); if (relative_file_path.startsWith(File.separator)) { relative_file_path = relative_file_path.substring(File.separator.length()); } return relative_file_path; } }