source: main/trunk/gli/src/org/greenstone/gatherer/collection/CollectionManager.java@ 34158

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

Fixing discovery of client-gli issues with previewing a different library (e.g. /default-library instead of /library). This commit adds to Kathy's recent work on supporting other libraries when previewing especially in the remote case, where Diego had detected problems. 1. First fixed a foolish copy paste error I made last time in full-rebuild.pl, commit 34128, when I was fixing up the script to accept the library_name parameter so it could pass this to buildcol.pl calling activate and/or to activate.pl directly. Only detected the problem when I was going to copy paste it into incremental-rebuild.pl. 2. Similar solution added to incremental-rebuild.pl and tested from commandline that this script too now accepts and passes on the library_name parameter to buildcol.pl to reach activate when needed. 3. GLI now passes library_name to building process, so activate can call the correct library to activate a collection. The library_name is obtained from client-gli, where the library (servlet_path) is set when configuring the site in use.

  • Property svn:keywords set to Author Date Id Revision
File size: 96.6 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.collection;
38
39import java.io.*;
40import java.util.*;
41import javax.swing.*;
42import javax.swing.event.*;
43import javax.swing.filechooser.FileSystemView;
44import javax.swing.tree.*;
45import org.greenstone.gatherer.Configuration;
46import org.greenstone.gatherer.DebugStream;
47import org.greenstone.gatherer.Dictionary;
48import org.greenstone.gatherer.Gatherer;
49import org.greenstone.gatherer.cdm.CollectionDesignManager;
50import org.greenstone.gatherer.cdm.CollectionMeta;
51import org.greenstone.gatherer.cdm.CollectionMetaManager;
52import org.greenstone.gatherer.cdm.CommandTokenizer;
53import org.greenstone.gatherer.cdm.BuildTypeManager;
54import org.greenstone.gatherer.cdm.CollectionConfiguration;
55import org.greenstone.gatherer.greenstone.Classifiers;
56import org.greenstone.gatherer.greenstone.LocalGreenstone;
57import org.greenstone.gatherer.greenstone.LocalLibraryServer;
58import org.greenstone.gatherer.greenstone.Plugins;
59import org.greenstone.gatherer.greenstone3.ServletConfiguration;
60import org.greenstone.gatherer.gui.LockFileDialog;
61import org.greenstone.gatherer.gui.ModalProgressPopup;
62import org.greenstone.gatherer.gui.TestingPreparation;
63import org.greenstone.gatherer.gui.WarningDialog;
64import org.greenstone.gatherer.metadata.DocXMLFileManager;
65import org.greenstone.gatherer.metadata.FilenameEncoding;
66import org.greenstone.gatherer.metadata.MetadataChangedListener;
67import org.greenstone.gatherer.metadata.MetadataSet;
68import org.greenstone.gatherer.metadata.MetadataSetManager;
69import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
70import org.greenstone.gatherer.metadata.ProfileXMLFileManager;
71import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
72import org.greenstone.gatherer.shell.GShell;
73import org.greenstone.gatherer.shell.GShellEvent;
74import org.greenstone.gatherer.shell.GShellListener;
75import org.greenstone.gatherer.shell.GShellProgressMonitor;
76import org.greenstone.gatherer.util.Codec;
77import org.greenstone.gatherer.util.StaticStrings;
78import org.greenstone.gatherer.util.Utility;
79import org.greenstone.gatherer.util.XMLTools;
80import org.w3c.dom.*;
81
82import org.greenstone.gatherer.util.GS3ServerThread;
83
84/** This class manages many aspects of the collection, from its creation via scripts, data access via methods and its importing and building into the final collection. It is also responsible for firing appropriate event when significant changes have occured within the collection, and for creating a new metadata set manager as necessary.
85 * @author John Thompson
86 * @version 2.3
87 */
88public class CollectionManager
89 implements GShellListener, MetadataChangedListener
90{
91 /** Are we currently in the process of building? */
92 static private boolean building = false;
93 /** Are we currently in the process of importing? */
94 static private boolean importing = false;
95 /** Are we currently in the process of scheduling? */
96 static private boolean scheduling = false;
97 /** The objects listening for CollectionContentsChanged events. */
98 static private ArrayList collection_contents_changed_listeners = new ArrayList();
99 /** The collection this manager is managing! */
100 static private Collection collection = null;
101 /** The collection tree (used in both Gather and Enrich panes). */
102 static private CollectionTree collection_tree = null;
103 /** The collection tree model. */
104 static private CollectionTreeModel collection_tree_model = null;
105 /** An inner class listener responsible for noting tree changes and resetting saved when they occur. */
106 static private FMTreeModelListener fm_tree_model_listener = null;
107 /** The monitor responsible for parsing the build process. */
108 static private GShellProgressMonitor build_monitor = null;
109 /** The monitor responsible for parsing the import process. */
110 static private GShellProgressMonitor import_monitor = null;
111 /** The monitor responsible for parsing the scheduler process. */
112 static private GShellProgressMonitor schedule_monitor = null;
113 ///** The monitor responsible for parsing the fedora collection delete process. */
114 //static private GShellProgressMonitor fedora_coldelete_monitor = null;
115
116 static private String delete_collection_name = null;
117
118 /** The name of the standard lock file. */
119 static final public String LOCK_FILE = "gli.lck";
120
121 /** Used to indicate the source of the message is the file collection methods. */
122 static final public int COLLECT = 3;
123 /** Used to indicate the source of the message is the building methods. */
124 static final public int BUILDING = 5;
125 /** Used to indicate the source of the message is in the scheduling methods...? */
126 static final public int SCHEDULING = 7;
127
128 /** To store the path to the perl scripts. In the case of local Greenstone servers,
129 * this will be the local bin/script folder. */
130 static private String scriptPath = "";
131
132 /** Constructor. */
133 public CollectionManager() {
134 // Initialisation.
135 this.building = false;
136 this.importing = false;
137 this.scheduling = false;
138 this.collection = null;
139
140 MetadataXMLFileManager.addMetadataChangedListener(this);
141
142 // If using a remote Greenstone server, delete the local collect directory because it will be out of date
143 if (Gatherer.isGsdlRemote) {
144 System.err.println("Deleting user's local collect directory...");
145 Utility.delete(new File(Gatherer.getCollectDirectoryPath()));
146 System.err.println("Done.");
147 new File(Gatherer.getCollectDirectoryPath()).mkdirs();
148
149 scriptPath = ""; // remote greenstone: scriptPath will be determined on remote server side
150 }
151 else { // local greenstone case: scripts are inside bin/script
152 scriptPath = LocalGreenstone.getBinScriptDirectoryPath();
153 }
154 }
155
156
157 static public void addCollectionContentsChangedListener(CollectionContentsChangedListener listener)
158 {
159 collection_contents_changed_listeners.add(listener);
160 }
161
162
163 /** This method calls the builcol.pl scripts via a GShell so as to not lock up the processor.
164 * @see org.greenstone.gatherer.Configuration
165 * @see org.greenstone.gatherer.Gatherer
166 * @see org.greenstone.gatherer.collection.Collection
167 * @see org.greenstone.gatherer.gui.BuildOptions
168 * @see org.greenstone.gatherer.shell.GShell
169 * @see org.greenstone.gatherer.shell.GShellListener
170 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
171 * @see org.greenstone.gatherer.util.Utility
172 */
173 public void buildCollection()
174 {
175
176 DebugStream.println("In CollectionManager.buildCollection(), CollectionDesignManager.isCompleteBuild(): " + CollectionDesignManager.isCompleteBuild());
177 DebugStream.println("Is event dispatch thread: " + SwingUtilities.isEventDispatchThread());
178 building = true;
179
180 // Generate the buildcol.pl command
181 ArrayList command_parts_list = new ArrayList();
182 if (!Gatherer.isGsdlRemote) {
183 command_parts_list.add(Configuration.perl_path);
184 command_parts_list.add("-S");
185 }
186
187 if (Configuration.fedora_info.isActive()) {
188 command_parts_list.add(scriptPath + "g2f-buildcol.pl");
189
190 command_parts_list.add("-hostname");
191 command_parts_list.add(Configuration.fedora_info.getHostname());
192
193 command_parts_list.add("-port");
194 command_parts_list.add(Configuration.fedora_info.getPort());
195
196 command_parts_list.add("-username");
197 command_parts_list.add(Configuration.fedora_info.getUsername());
198
199 command_parts_list.add("-password");
200 command_parts_list.add(Configuration.fedora_info.getPassword());
201
202 command_parts_list.add("-protocol");
203 command_parts_list.add(Configuration.fedora_info.getProtocol());
204
205 }
206 else {
207
208 if ( !CollectionDesignManager.isCompleteBuild() && CollectionDesignManager.index_manager.isLucene() ) {
209 command_parts_list.add(scriptPath + "incremental-buildcol.pl");
210 CollectionDesignManager.setBuildcolWasFull(false);
211 } else {
212 command_parts_list.add(scriptPath + "full-buildcol.pl");
213 CollectionDesignManager.setBuildcolWasFull(true);
214 }
215 }
216
217 command_parts_list.add("-gli");
218 command_parts_list.add("-language");
219 command_parts_list.add(Configuration.getLanguage());
220
221 // For now, for solr collections, we pass in -activate
222 // but GLI won't do moving building to index
223
224 //if(CollectionManager.isSolrCollection()) {
225 command_parts_list.add("-activate");
226 //}
227
228 if(Gatherer.GS3) {
229 command_parts_list.add("-site");
230 command_parts_list.add(Configuration.site_name);
231 }
232
233 if(!Gatherer.isGsdlRemote) {
234 command_parts_list.add("-collectdir");
235 command_parts_list.add(getCollectDirectory()); // <../collect/>
236 } else { // actually this should work in local Greenstone case too:
237 command_parts_list.add("-library_name");
238 String library_servlet_name = Configuration.servlet_path;
239 if(library_servlet_name.startsWith("/")) {
240 library_servlet_name = library_servlet_name.substring(1);
241 }
242 command_parts_list.add(library_servlet_name);
243 }
244
245 String[] build_options = collection.build_options.getValues();
246 for (int i = 0; i < build_options.length; i++) {
247 command_parts_list.add(build_options[i]);
248 }
249
250 command_parts_list.add(collection.getGroupQualifiedName(false)); // (colgroup/)colname
251
252 // Run the buildcol.pl and
253 String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
254 GShell shell = new GShell(command_parts, GShell.BUILD, BUILDING, this, build_monitor, GShell.GSHELL_BUILD);
255 shell.addGShellListener(Gatherer.g_man.create_pane);
256 Gatherer.g_man.create_pane.setGShell(shell); // allow the create pane to call shell.cancel()
257 shell.addGShellListener(Gatherer.g_man.format_pane);
258 shell.start();
259
260 }
261
262 /*probably repeating alot of work, but I want to keep this separate... wendy*/
263 public void scheduleBuild()
264 {
265 DebugStream.println("In CollectionManager.scheduleBuild(), CollectionDesignManager.isCompleteBuild(): " + CollectionDesignManager.isCompleteBuild());
266 DebugStream.println("Is event dispatch threa: " + SwingUtilities.isEventDispatchThread());
267
268 ArrayList sched_list = new ArrayList();
269 if (!Gatherer.isGsdlRemote) {
270 sched_list.add(Configuration.perl_path);
271 sched_list.add("-S");
272 }
273 sched_list.add(scriptPath + "schedule.pl");
274 sched_list.add("-colname");
275 sched_list.add(collection.getName());
276 sched_list.add("-gli");
277
278 // First, generate the import.pl command, also converting to a string
279 // Generate the import.pl command
280 ArrayList import_list = new ArrayList();
281 if (!Gatherer.isGsdlRemote) {
282 import_list.add(Configuration.perl_path);
283 import_list.add("-S");
284 }
285
286 String cmdPrefix = CollectionDesignManager.isCompleteBuild() ? "full-" : "incremental-";
287 import_list.add(scriptPath + cmdPrefix + "import.pl");
288 import_list.add("-language");
289 import_list.add(Configuration.getLanguage());
290
291 if(Gatherer.GS3) {
292 import_list.add("-site");
293 import_list.add(Configuration.site_name);
294 }
295
296 if(!Gatherer.isGsdlRemote) {
297 import_list.add("-collectdir");
298 import_list.add(getCollectDirectory());
299 }
300 // import.pl does not at present need to know the library/servlet_path
301 // whether in a remote or local GS server situation
302
303 String[] import_options = collection.import_options.getValues();
304 int i = 0;
305 for (i = 0; i < import_options.length; i++) {
306 import_list.add(import_options[i]);
307 }
308
309 import_list.add(collection.getGroupQualifiedName(false)); // (colgroup/)colname
310
311 String[] import_parts = (String[]) import_list.toArray(new String[0]);
312 String command = "";
313 i = 0;
314 for (i = 0; i < import_parts.length-1; i++) {
315 command = command + import_parts[i] + " ";
316 }
317 command = command + import_parts[i];
318
319 sched_list.add("-import");
320 sched_list.add("\"" + command + "\"");
321
322 // Generate the buildcol.pl command, also converting to a string
323 ArrayList build_list = new ArrayList();
324
325 // i'm not doing this in schedule.pl right now - should i be?
326 if (!Gatherer.isGsdlRemote) {
327 build_list.add(Configuration.perl_path);
328 build_list.add("-S");
329 }
330
331 String buildType = (new CollectionMeta( CollectionDesignManager.collect_config.getBuildType() )).getValue(CollectionMeta.TEXT);
332 if ( !CollectionDesignManager.isCompleteBuild() && buildType.equals( BuildTypeManager.BUILD_TYPE_LUCENE ) ) {
333 build_list.add(scriptPath + "incremental-buildcol.pl");
334 } else {
335 build_list.add(scriptPath + "full-buildcol.pl");
336 }
337
338 build_list.add("-language");
339 build_list.add(Configuration.getLanguage());
340
341 if(Gatherer.GS3) {
342 build_list.add("-site");
343 build_list.add(Configuration.site_name);
344 }
345
346 if(!Gatherer.isGsdlRemote) {
347 build_list.add("-collectdir");
348 build_list.add(getCollectDirectory());
349 } else { // actually this should work in local Greenstone case too:
350 build_list.add("-library_name");
351 String library_servlet_name = Configuration.servlet_path;
352 if(library_servlet_name.startsWith("/")) {
353 library_servlet_name = library_servlet_name.substring(1);
354 }
355 build_list.add(library_servlet_name);
356 }
357
358 String[] build_options = collection.build_options.getValues();
359 for (i = 0; i < build_options.length; i++) {
360 build_list.add(build_options[i]);
361 }
362
363 build_list.add(collection.getGroupQualifiedName(false)); // (colgroup/)colname
364
365 //build actual string
366 String[] build_parts = (String[]) build_list.toArray(new String[0]);
367 String command2 = "";
368 for(i = 0; i < build_parts.length-1; i++) {
369 command2 = command2 + build_parts[i] + " ";
370 }
371 command2 = command2 + build_parts[i];
372
373 sched_list.add("-build");
374 sched_list.add("\"" + command2 + "\"");
375
376 //next, the scheduling frequency goes here
377 String[] schedule_options = collection.schedule_options.getValues();
378 for(i = 0; i < schedule_options.length; i++) {
379 sched_list.add(schedule_options[i]);
380 }
381
382 //now, hope it will run. ;)
383 String[] sched_parts = (String[]) sched_list.toArray(new String[0]);
384
385 GShell shell = new GShell(sched_parts, GShell.SCHEDULE, SCHEDULING, this, schedule_monitor, GShell.GSHELL_SCHEDULE);
386 shell.addGShellListener(Gatherer.g_man.create_pane);
387 Gatherer.g_man.create_pane.setGShell(shell); // allow the create pane to call shell.cancel()
388 shell.addGShellListener(Gatherer.g_man.format_pane);
389 shell.start();
390 }
391
392 /** Used to determine whether the currently active collection has been built.
393 * @return A boolean indicating the built status of the collection.
394 */
395 public boolean built() {
396 if(collection != null) {
397 // Determine if the collection has been built by looking for the build.cfg (gs2)
398 // buildConfig.xml (gs3) or export.inf (fedora) file
399 String file_name = "";
400
401 if (Configuration.fedora_info != null && Configuration.fedora_info.isActive()) { // FLI case
402 // Fedora build
403 //file_name = getLoadedCollectionArchivesDirectoryPath() + "import.inf";
404 //file_name = getLoadedCollectionExportDirectoryPath() + "export.inf"; // export.pl no longer generates this
405 file_name = getLoadedCollectionExportDirectoryPath() + "archiveinf-doc.gdb";
406 } else {
407 // GLI is running, check if it's greenstone 3 or greenstone 2
408 if (Gatherer.GS3) { // GS3 GLI
409 file_name = getLoadedCollectionIndexDirectoryPath() + Utility.BUILD_CONFIG_XML;
410 }
411 else { // greenstone 2 GLI
412 file_name = getLoadedCollectionIndexDirectoryPath() + Utility.BUILD_CFG;
413 }
414 }
415 File test_file = new File(file_name);
416
417 if(Gatherer.isGsdlRemote) {
418 return Gatherer.remoteGreenstoneServer.exists(collection.getGroupQualifiedName(false), test_file);
419 } else {
420 return test_file.exists();
421 }
422 }
423 return false;
424 }
425
426 /** Used to determine whether the currently active collection has been imported.
427 * @return A boolean indicating the imported status of the collection.
428 */
429 public boolean imported() {
430 if ( collection != null ) {
431 String file_name = getLoadedCollectionDirectoryPath() + "archives";
432 File test_file = new File(file_name);
433 return test_file.exists();
434 }
435 return false;
436 }
437
438 /** a test method to see if we can delete a directory/file - returns false is the file or any of the contents of a directory cannot be deleted */
439 static private boolean canDelete(File file)
440 {
441 if (!file.isDirectory()) {
442 return file.canWrite();
443 }
444 File [] file_list = file.listFiles();
445 for (int i=0; i<file_list.length; i++) {
446 if (!canDelete(file_list[i])) {
447 return false;
448 }
449 }
450 return true;
451 }
452
453
454 /** Called to close the current collection and remove its lock file.
455 * @see org.greenstone.gatherer.Gatherer
456 * @see org.greenstone.gatherer.collection.Collection
457 * @see org.greenstone.gatherer.util.Utility
458 */
459 public void closeCollection() {
460 if (collection == null) {
461 return;
462 }
463 DebugStream.println("Close collection: " + collection.getName());
464
465 // Remove the lock on this file, then remove the collection.
466 File lock_file = new File(getLoadedCollectionDirectoryPath() + LOCK_FILE);
467 lock_file.delete();
468 if (lock_file.exists()) {
469 System.err.println("Warning: Lockfile was not successfully deleted.");
470 }
471
472 // Remove the lock file on the server
473 if (Gatherer.isGsdlRemote) {
474 Gatherer.remoteGreenstoneServer.deleteCollectionFile(collection.getGroupQualifiedName(false), lock_file);
475 }
476
477 // release the current build_log file - else we're unable to delete the last closed collection
478 // until another collection is opened and its opening a new build_log closes this old one
479 Gatherer.g_man.create_pane.options_pane.closeCurrentLogDocument();
480
481 MetadataSetManager.clearMetadataSets();
482 MetadataXMLFileManager.clearMetadataXMLFiles();
483 DocXMLFileManager.clearDocXMLFiles();
484 ProfileXMLFileManager.clearProfileXMLFile();
485
486 collection.destroy();
487 collection = null;
488 collection_tree_model = null;
489 //Configuration.setCollectionConfiguration(null);
490 Gatherer.refresh(Gatherer.COLLECTION_CLOSED);
491 if (Gatherer.g_man != null) {
492 Gatherer.g_man.updateUI(); // !!! Necessary?
493 }
494 }
495
496//This method is no longer used in gs3 since the modification of CollectionConfiguration.java
497// public void convertToGS3Collection() {
498// // Generate the convert_coll_from_gs2.pl command
499// ArrayList command_parts_list = new ArrayList();
500// if ((Utility.isWindows()) && (!Gatherer.isGsdlRemote)) {
501// command_parts_list.add(Configuration.perl_path);
502// command_parts_list.add("-S");
503// }
504// command_parts_list.add(Configuration.getGS3ScriptPath() + "convert_coll_from_gs2.pl");
505//
506// command_parts_list.add("-site");
507// command_parts_list.add(Configuration.site_name);
508//
509// command_parts_list.add("-collectdir");
510// command_parts_list.add(getCollectDirectory());
511// command_parts_list.add(collection.getGroupQualifiedName(false)); // (colgroup/)colname
512//
513// // Run the convert_coll_from_gs2.pl command
514// String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
515// GShell process = new GShell(command_parts, GShell.CONVERT, COLLECT, this, null, GShell.GSHELL_CONVERT);
516// process.addGShellListener(this);
517// process.run(); // Don't bother threading this... yet
518//
519// }
520
521 /** When basing a new collection on an existing one, we need to copy
522 * over some extra directories: all except import, archives, building, index
523 * really we just want images, macros, perllib, but there may also be eg style, or other dirs.
524 */
525 private boolean copyExtraBaseCollStuff(File new_coll_dir, File base_coll_dir) {
526 if (!new_coll_dir.isDirectory() || !base_coll_dir.isDirectory()) {
527 return false;
528 }
529 DebugStream.println("Copying extra dirs from the base collection");
530
531
532 File subdirs[] = base_coll_dir.listFiles();
533 for (int i = 0; subdirs != null && i < subdirs.length; i++) {
534 File subdir = subdirs[i];
535 if (subdir.isDirectory()) {
536 String dir_name = subdir.getName();
537 // ignore those we don't need, (archives, buildng, index) and
538 // those we are handling in another place (import, etc, metadata)
539 if (dir_name.startsWith ("import") || dir_name.startsWith("archives") || dir_name.startsWith("building") || dir_name.startsWith("index") || dir_name.startsWith("etc") || dir_name.startsWith("metadata") || dir_name.startsWith("log") || dir_name.startsWith("tmp")) {
540 continue;
541 }
542 try {
543 // copy the directory
544 File new_coll_subdir = new File(new_coll_dir, dir_name);
545 new_coll_subdir.mkdirs();
546 // Copy with force overwrite, since it's a new collection that's currently
547 // being created and won't have anything in it but at most modelcol stuff
548 Gatherer.f_man.getQueue().copyDirectoryContents(subdir, new_coll_subdir, true);
549 }
550 catch (Exception e) {
551 DebugStream.println("Couldn't copy over the" + subdir+" dir from the base collection: "+e.toString());
552 }
553 }
554 }
555
556 return true;
557 }
558
559 /** Used to set the current collection to the given collection. Note that this call should -always- be proceeded by a ready call, and if the collection is ready and the saved flag is unset then the user should be prompted to save. Also note that this method creates yet another GShell to run buildcol.pl.
560 * @param description a description of the collection as a String
561 * @param email the email address of the author/maintainer as a String
562 * @param name the short name of the collection, which will subsequently be used to refer to this particular collection, as a String
563 * @param title the longer title of the collection as a String
564 * @param base_collection_directory if the user has chosen to base their new collection on an existing one, this is the directory where this base collection can be found, as a File, otherwise its null
565 * @param metadata_sets if the user has decided to select several metadata sets with which to initially populate the GLI then this is an ArrayList of metadata set file names, otherwise its null
566 */
567 public void createCollection(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets)
568 {
569 // Display a modal progress popup to indicate that the collection is being loaded
570 ModalProgressPopup create_collection_progress_popup = new ModalProgressPopup(Dictionary.get("CollectionManager.Creating_Collection"), Dictionary.get("CollectionManager.Creating_Collection_Please_Wait"));
571 create_collection_progress_popup.display();
572
573 // Create the collection on a separate thread so the progress bar updates correctly
574 (new CreateCollectionTask(description, email, name, title, base_collection_directory, metadata_sets, create_collection_progress_popup)).start();
575 //SwingUtilities.invokeLater(new CreateCollectionTask(description, email, name, title, base_collection_directory, metadata_sets, create_collection_progress_popup));
576 }
577
578
579 private class CreateCollectionTask
580 extends Thread
581 {
582 private String description = null;
583 private String email = null;
584 private String name = null;
585 private String title = null;
586 private File base_collection_directory = null;
587 private ArrayList metadata_sets = null;
588 private ModalProgressPopup create_collection_progress_popup = null;
589
590 public CreateCollectionTask(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets, ModalProgressPopup create_collection_progress_popup)
591 {
592 this.description = description;
593 this.email = email;
594 this.name = name;
595 this.title = title;
596 this.base_collection_directory = base_collection_directory;
597 this.metadata_sets = metadata_sets;
598 this.create_collection_progress_popup = create_collection_progress_popup;
599 }
600
601 public void run()
602 {
603 createCollectionInternal(description, email, name, title, base_collection_directory, metadata_sets);
604 create_collection_progress_popup.close();
605 }
606 }
607
608
609 private void createCollectionInternal(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets)
610 {
611 try {
612 // first make sure that the collect directory exists
613 File collect_dir = new File(getDefaultCollectDirectory());
614 if (!collect_dir.exists()) {
615 collect_dir.mkdirs();
616 }
617
618 // Create the new collection
619 makeCollection(name, email);
620
621 // Check that the collection has been created successfully
622 String collection_directory_path = getCollectionDirectoryPath(name);
623 if (!new File(collection_directory_path).exists()) {
624 // If there is no collection directory then the creation was unsuccessful, or cancelled
625
626 return;
627 }
628
629 // Check for the existence of the collection configuration file
630 String file_name = ((Gatherer.GS3 == true)? Utility.COLLECTION_CONFIG_XML : Utility.COLLECT_CFG);
631 File collect_cfg_file = new File(collection_directory_path + "etc" + File.separator + file_name);
632
633 if (!collect_cfg_file.exists()) {
634 System.err.println("Error: no " + file_name + " file has been created!");
635 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Create_Collection_With_Reason", Dictionary.get("CollectionManager.No_Config_File")), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
636 return;
637 }
638
639 // ACTIVE_DIR/log/
640 File log_dir = new File(collection_directory_path + "log");
641 log_dir.mkdirs();
642
643 // Make sure an import folder exists
644 File collection_import_directory = new File(collection_directory_path + "import");
645 if (!collection_import_directory.exists()) {
646 collection_import_directory.mkdirs();
647 if (Gatherer.isGsdlRemote) {
648 Gatherer.remoteGreenstoneServer.newCollectionDirectory(name, collection_import_directory);
649 }
650 }
651
652 // Now create the collection object around the directory.
653 collection = new Collection(new File(collection_directory_path, "gli.col"));
654
655 // for remote case, scheduling causes an Exception on creating a new collection that
656 // can't be recovered from. For GS3, it doesn't work since it it trying to access etc/main.cfg
657 if (canDoScheduling()) {
658 scheduling();
659 }
660
661 MetadataSetManager.clearMetadataSets();
662 MetadataXMLFileManager.clearMetadataXMLFiles();
663 DocXMLFileManager.clearDocXMLFiles();
664
665 // Import default metadata sets, if any
666 // for (int i = 0; metadata_sets != null && i < metadata_sets.size(); i++) {
667 // importMetadataSet((MetadataSet) metadata_sets.get(i));
668 // }
669
670 ProfileXMLFileManager.loadProfileXMLFile(new File(collection_directory_path + "metadata"));
671
672 // Before creating the CollectionDesignManager check if we are basing it upon some other collection
673 if (base_collection_directory != null) {
674 DebugStream.println("Basing new collection on existing one: " + base_collection_directory);
675
676 // If we're using a remote Greenstone server, download the collection shell to get the files needed
677 if (Gatherer.isGsdlRemote) {
678 String base_collection_name = base_collection_directory.getName();
679 Gatherer.remoteGreenstoneServer.downloadCollection(base_collection_name);
680 }
681
682 collection.setBaseCollection(base_collection_directory.getAbsolutePath());
683 // copy over other needed directories
684 copyExtraBaseCollStuff(new File(collection_directory_path), base_collection_directory);
685
686 // Try to import any existing metadata sets for this collection
687 // Look in base_collection_directory/metadata and import any metadata sets found.
688 File base_metadata_directory = new File(base_collection_directory, "metadata");
689 ArrayList base_metadata_sets = MetadataSetManager.listMetadataSets(base_metadata_directory);
690 if (base_metadata_sets != null) {
691 for (int i = 0; i < base_metadata_sets.size(); i++) {
692 importMetadataSet((MetadataSet) base_metadata_sets.get(i));
693 }
694 }
695 else {
696 DebugStream.println("This base collection has no metadata directory.");
697 }
698
699 // Now we update our collect.cfg
700 DebugStream.println("Copy and update " + file_name + " from base collection.");
701
702 if (Gatherer.GS3 == true) {
703 updateCollectionConfigXML(new File(base_collection_directory, Utility.CONFIG_GS3_FILE),
704 new File(collection_directory_path, Utility.CONFIG_GS3_FILE));
705 } else {
706 updateCollectionCFG(new File(base_collection_directory, Utility.CONFIG_FILE),
707 new File(collection_directory_path, Utility.CONFIG_FILE),
708 description, email, title);
709 }
710 }
711 else {
712 // only load metadata sets here if we have not based the collection on any other.
713 // Load the default metadata sets
714 addDefaultMetadataSets();
715
716 // Make sure we always have the extracted metadata set
717 addRequiredMetadataSets();
718 }
719
720 collection.cdm = new CollectionDesignManager(new File(getLoadedCollectionCfgFilePath()));
721
722 // We always set title and description here rather than calling mkcol.pl with Unicode arguments
723
724 // First though, if we based this collection on another collection and thereyby inherited multilingual
725 // collection names and descriptions, clear those before setting description and name to new values.
726 ArrayList colname_metas = collection.cdm.collectionmeta_manager.getMetadata(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR); // retrieves all languages
727 ArrayList coldesc_metas = collection.cdm.collectionmeta_manager.getMetadata(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR);
728 for(int i = 0; i < colname_metas.size(); i++) {
729 CollectionMeta colname_meta = (CollectionMeta)colname_metas.get(i);
730 colname_meta.setValue("");
731 }
732 for(int i = 0; i < coldesc_metas.size(); i++) {
733 CollectionMeta coldesc_meta = (CollectionMeta)coldesc_metas.get(i);
734 coldesc_meta.setValue("");
735 }
736
737 // set the collection name and description (in the default language)
738 CollectionMeta collection_name_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR); // retrieves default language
739 collection_name_collectionmeta.setValue(title);
740 CollectionMeta collection_extra_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR);
741 collection_extra_collectionmeta.setValue(description);
742
743 // Now that we have a CDM, update several settings, such as if we created this collection by basing it on another, set it as public automatically. This update is done to the internal xml structure which may be saved into collect.cfg or collectionConfig.xml accordingly.
744 if (base_collection_directory != null) {
745 // Update the creator and maintainer
746 CollectionMeta creator_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getCreator());
747 creator_collectionmeta.setValue(email);
748 creator_collectionmeta = null;
749 CollectionMeta maintainer_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getMaintainer());
750 maintainer_collectionmeta.setValue(email);
751 maintainer_collectionmeta = null;
752
753 // All collections based on others are automatically public
754 CollectionMeta public_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getPublic());
755 public_collectionmeta.setValue(StaticStrings.TRUE_STR);
756 public_collectionmeta = null;
757
758 // Finally reset the icons
759 CollectionMeta icon_collection_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR);
760 icon_collection_collectionmeta.setValue(StaticStrings.EMPTY_STR);
761 icon_collection_collectionmeta = null;
762 CollectionMeta icon_collection_small_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR);
763 icon_collection_small_collectionmeta.setValue(StaticStrings.EMPTY_STR);
764 icon_collection_small_collectionmeta = null;
765 }
766
767 saveCollection();
768
769 // Create a lock file
770 createLockFile(new File(collection_directory_path, LOCK_FILE));
771
772 // We're done. Let everyone know.
773 Gatherer.refresh(Gatherer.COLLECTION_OPENED);
774 }
775 catch (Exception error) {
776 DebugStream.printStackTrace(error);
777 }
778 }
779
780 private void scheduling()
781 throws Exception
782 {
783 //try to obtain email address of collection owner if it exists...
784 String stmp = Configuration.getEmail();
785 if(stmp != null) {
786 collection.schedule_options.setValue("toaddr", false, Configuration.getEmail());
787 }
788
789 //The next few items deal with updating the SMTP server, and the to: and from: addresses
790 //from main.cfg and the collection configuration. if no changes are made, or the
791 //values are result to NULL, any existing values are kept.
792
793 //try to obtain email address of Greenstone installation webmaster for - used to indicate "sender".
794 File mcfg = new File(LocalGreenstone.getDirectoryPath() + File.separator + "etc" + File.separator + "main.cfg");
795 BufferedReader maincfg = new BufferedReader(new FileReader(mcfg));
796 stmp = "";
797 String fromaddr = "";
798 while((stmp = maincfg.readLine()) != null) {
799 if(stmp.startsWith("maintainer")) {
800 fromaddr = stmp.substring(10); //length of MailServer
801 fromaddr = fromaddr.trim();
802 break;
803 }
804 }
805 maincfg.close();
806 if(!fromaddr.equals("NULL") && !fromaddr.equals("null")) {
807 collection.schedule_options.setValue("fromaddr", false, fromaddr);
808 }
809
810 //try to obtain an smtp server address from main.cfg. If that fails,
811 //try mail.server if an email address exists. If that fails,
812 //maybe a message to set attribute in main.cfg?
813 //i'm pretty sure there exists functionality to do this, but
814 //i'll finish this faster if I just wrote it
815
816
817 maincfg = new BufferedReader(new FileReader(mcfg));
818 String smtptmp = "NULL";
819 while((stmp = maincfg.readLine()) != null) {
820 if(stmp.startsWith("MailServer")) {
821 smtptmp = stmp.substring(10); //length of MailServer
822 smtptmp = smtptmp.trim();
823 break;
824 }
825 }
826 maincfg.close();
827
828 //try if lookup fails
829 if(smtptmp.equals("NULL") || smtptmp.equals("null")) {
830 String email2=fromaddr;
831 if(!email2.equals("NULL") && !email2.equals("null")) {
832 int loc = email2.indexOf('@');
833 email2 = email2.substring(loc+1);
834 smtptmp = "mail."+email2;
835 }
836 }
837 if(!smtptmp.equals("NULL") && !smtptmp.equals("null")) {
838 collection.schedule_options.setValue("smtp", false, smtptmp);
839 }
840
841 }
842
843
844 private void createLockFile(File lock_file)
845 {
846 try {
847 Document default_lockfile = XMLTools.parseXMLFile("xml/" + LOCK_FILE, true);
848 String user_name = System.getProperty("user.name");
849 Element person_element = (Element) XMLTools.getNodeFromNamed(default_lockfile.getDocumentElement(), "User");
850 person_element.appendChild(default_lockfile.createTextNode(user_name));
851 person_element = null;
852 user_name = null;
853 String machine_name = Utility.getMachineName();
854 Element machine_element = (Element) XMLTools.getNodeFromNamed(default_lockfile.getDocumentElement(), "Machine");
855 machine_element.appendChild(default_lockfile.createTextNode(machine_name));
856 machine_element = null;
857 machine_name = null;
858 String date_time = Utility.getDateString();
859 Element date_element = (Element) XMLTools.getNodeFromNamed(default_lockfile.getDocumentElement(), "Date");
860 date_element.appendChild(default_lockfile.createTextNode(date_time));
861 date_element = null;
862 date_time = null;
863 XMLTools.writeXMLFile(lock_file, default_lockfile);
864 }
865 catch (Exception exception) {
866 DebugStream.printStackTrace(exception);
867 }
868 }
869
870
871 public boolean deleteCollection(String collection_name)
872 {
873 // First we must release the collection from the local library, if it's running
874 if (LocalLibraryServer.isRunning() == true) {
875 LocalLibraryServer.releaseCollection(collection_name);
876 }
877
878 // if we're running FLI, it's a fedora collection, and we need to call a special
879 // delete script to delete the collection and all its documents from the fedora
880 // repository and from fedora-gsearch's index.
881 if (Configuration.fedora_info.isActive()) {
882
883 // Generate the buildcol.pl command
884 ArrayList command_parts_list = new ArrayList();
885 if (!Gatherer.isGsdlRemote) {
886 command_parts_list.add(Configuration.perl_path);
887 command_parts_list.add("-S");
888 }
889
890 command_parts_list.add(scriptPath + "g2f-deletecol.pl");
891
892 command_parts_list.add("-hostname");
893 command_parts_list.add(Configuration.fedora_info.getHostname());
894
895 command_parts_list.add("-port");
896 command_parts_list.add(Configuration.fedora_info.getPort());
897
898 command_parts_list.add("-username");
899 command_parts_list.add(Configuration.fedora_info.getUsername());
900
901 command_parts_list.add("-password");
902 command_parts_list.add(Configuration.fedora_info.getPassword());
903
904 command_parts_list.add("-protocol");
905 command_parts_list.add(Configuration.fedora_info.getProtocol());
906
907 command_parts_list.add("-gli");
908 command_parts_list.add("-language");
909 command_parts_list.add(Configuration.getLanguage());
910
911 if(Gatherer.GS3) {
912 command_parts_list.add("-site");
913 command_parts_list.add(Configuration.site_name);
914 }
915
916 if(!Gatherer.isGsdlRemote) {
917 command_parts_list.add("-collectdir");
918 command_parts_list.add(getCollectDirectory()); // <../collect/>
919 }
920
921 command_parts_list.add(collection_name);
922
923 // Run the g2f-deletecol.pl to remove the fedora collection
924 String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
925 GShell shell = new GShell(command_parts, GShell.DELETE, COLLECT, this, null, GShell.GSHELL_FEDORA_COLDELETE); // fedora_coldelete_monitor set to null
926 shell.start();
927
928 delete_collection_name = collection_name;
929 return true; // we assume it succeeded for now, wait until the process returns
930 // and then proceed to delete the collection directory
931 }
932 else { // not a fedora collection
933
934 // Delete the collection on the server if we're using a remote Greenstone
935 if (Gatherer.isGsdlRemote) {
936 Gatherer.remoteGreenstoneServer.deleteCollection(collection_name);
937 }
938
939 // if Greenstone3, need to deactivate the collection on the server
940 if (Gatherer.GS3) {
941 Gatherer.configGS3Server(Configuration.site_name, ServletConfiguration.DEACTIVATE_COMMAND + collection_name);
942 }
943 // Now delete the collection directory
944 return Utility.delete(new File(getCollectionDirectoryPath(collection_name)));
945 }
946 }
947
948
949 public void fireFileAddedToCollection(File file)
950 {
951 // Send the event off to all the CollectionContentsChangedListeners
952 for (int i = 0; i < collection_contents_changed_listeners.size(); i++) {
953 ((CollectionContentsChangedListener) collection_contents_changed_listeners.get(i)).fileAddedToCollection(file);
954 }
955 }
956
957
958 /** Retrieve the current collection.
959 * @return The <strong>Collection</strong> itself.
960 */
961 public Collection getCollection() {
962 return collection;
963 }
964
965
966 /** Returns the absolute filename of the specified collection's directory.
967 */
968 static public String getCollectionDirectoryPath(String collection_name)
969 {
970 return Gatherer.getCollectDirectoryPath() + collection_name + File.separator;
971 }
972
973
974 /** Returns the absolute filename of the loaded collection's archives directory.
975 */
976 static public String getLoadedCollectionArchivesDirectoryPath()
977 {
978 return getLoadedCollectionDirectoryPath() + "archives" + File.separator;
979 }
980
981 /** Returns the absolute filename of the loaded collection's export directory.
982 */
983 static public String getLoadedCollectionExportDirectoryPath()
984 {
985 return getLoadedCollectionDirectoryPath() + "export" + File.separator;
986 }
987
988
989
990 /** Returns the absolute filename of the loaded collection's building directory.
991 */
992 static public String getLoadedCollectionBuildingDirectoryPath()
993 {
994 return getLoadedCollectionDirectoryPath() + "building" + File.separator;
995 }
996
997
998 /** Returns the absolute filename of the loaded collection's collect.cfg file.
999 */
1000 static public String getLoadedCollectionCfgFilePath()
1001 {
1002 String path = (Gatherer.GS3 == true)? Utility.COLLECTION_CONFIG_XML : Utility.COLLECT_CFG;
1003 return getLoadedCollectionEtcDirectoryPath() + path;
1004 }
1005
1006
1007 /** Returns the absolute filename of the loaded collection's directory.
1008 */
1009 static public String getLoadedCollectionDirectoryPath()
1010 {
1011 return collection.getCollectionDirectory().getPath() + File.separator;
1012 }
1013
1014
1015 /** Returns the absolute filename of the loaded collection's etc directory.
1016 */
1017 static public String getLoadedCollectionEtcDirectoryPath()
1018 {
1019 return getLoadedCollectionDirectoryPath() + "etc" + File.separator;
1020 }
1021
1022
1023 /** Returns the absolute filename of the loaded collection's .col file.
1024 */
1025 static public String getLoadedCollectionColFilePath()
1026 {
1027 return getLoadedCollectionDirectoryPath() + "gli.col";
1028 }
1029
1030
1031 /** Returns the absolute filename of the loaded collection's images directory.
1032 */
1033 static public String getLoadedCollectionImagesDirectoryPath()
1034 {
1035 return getLoadedCollectionDirectoryPath() + "images" + File.separator;
1036 }
1037
1038
1039 /** Returns the absolute filename of the loaded collection's import directory.
1040 */
1041 static public String getLoadedCollectionImportDirectoryPath()
1042 {
1043 return getLoadedCollectionDirectoryPath() + "import" + File.separator;
1044 }
1045
1046
1047 /** Returns the absolute filename of the loaded collection's index directory.
1048 */
1049 static public String getLoadedCollectionIndexDirectoryPath()
1050 {
1051 return getLoadedCollectionDirectoryPath() + "index" + File.separator;
1052 }
1053
1054
1055 /** Returns the absolute filename of the loaded collection's log directory.
1056 */
1057 static public String getLoadedCollectionLogDirectoryPath()
1058 {
1059 return getLoadedCollectionDirectoryPath() + "log" + File.separator;
1060 }
1061
1062
1063 /** Returns the absolute filename of the loaded collection's macros directory.
1064 */
1065 static public String getLoadedCollectionMacrosDirectoryPath()
1066 {
1067 return getLoadedCollectionDirectoryPath() + "macros" + File.separator;
1068 }
1069
1070
1071 /** Returns the absolute filename of the loaded collection's metadata directory.
1072 */
1073 static public String getLoadedCollectionMetadataDirectoryPath()
1074 {
1075 return getLoadedCollectionDirectoryPath() + "metadata" + File.separator;
1076 }
1077
1078
1079 /** Returns the (group-qualified) name of the loaded collection with
1080 * OS-dependent file separator.
1081 */
1082 static public String getLoadedCollectionName()
1083 {
1084 return CollectionManager.getLoadedCollectionName(false);
1085 }
1086
1087 /** Returns the (group-qualified) name of the loaded collection with
1088 * OS-dependent space separator.
1089 * @url true if url-type forward slashes, false if OS-dependent filesystem slashes.
1090 */
1091 static public String getLoadedCollectionName(boolean url)
1092 {
1093 if (collection != null) {
1094 //return collection.getName();
1095 return collection.getGroupQualifiedName(url);
1096 }
1097
1098 return null;
1099 }
1100
1101 /** @return the subname of any collection (stripped of any collection-group). */
1102 static public String getLoadedCollectionTailName()
1103 {
1104 if (collection != null) {
1105 return collection.getCollectionTailName();
1106 }
1107
1108 return null;
1109 }
1110
1111 /** Returns the "collectionGroupName/collectionName" or just the collectionName
1112 * depending on whether the collection is part of a collection group or not.
1113 * If url = true, then returns the sub-path as a URL (containing / only),
1114 * and if url = false, then the sub-path is returned in filepath form
1115 * (\ or /, depending on the OS).
1116 */
1117 static public String getLoadedGroupQualifiedCollectionName(boolean url)
1118 {
1119 if (collection != null) {
1120 return collection.getGroupQualifiedName(url);
1121 }
1122
1123 return null;
1124 }
1125
1126 public CollectionTree getCollectionTree()
1127 {
1128 if (collection_tree == null) {
1129 collection_tree = new CollectionTree(collection_tree_model, true);
1130 }
1131
1132 return collection_tree;
1133 }
1134
1135
1136 /** Retrieve the tree model associated with the current collection. */
1137 public CollectionTreeModel getCollectionTreeModel()
1138 {
1139 if (collection_tree_model == null && collection != null) {
1140 // Use the import directory to generate a new CollectionTreeModel
1141 collection_tree_model = new CollectionTreeModel(new CollectionTreeNode(new File(getLoadedCollectionImportDirectoryPath())));
1142 // Ensure that the manager is a change listener for the tree.
1143 if (fm_tree_model_listener == null) {
1144 fm_tree_model_listener = new FMTreeModelListener();
1145 }
1146 collection_tree_model.addTreeModelListener(fm_tree_model_listener);
1147 }
1148 return collection_tree_model;
1149 }
1150
1151
1152 /** This method when called, creates a new GShell in order to run the import.pl script.
1153 * @see org.greenstone.gatherer.Configuration
1154 * @see org.greenstone.gatherer.Gatherer
1155 * @see org.greenstone.gatherer.gui.BuildOptions
1156 * @see org.greenstone.gatherer.shell.GShell
1157 * @see org.greenstone.gatherer.shell.GShellListener
1158 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
1159 * @see org.greenstone.gatherer.util.Utility
1160 */
1161 public void importCollection() {
1162 importing = true;
1163
1164 if (!saved()) {
1165 DebugStream.println("CollectionManager.importCollection().forcesave");
1166 import_monitor.saving();
1167 saveCollection();
1168 }
1169
1170 DebugStream.println("CollectionManager.importCollection()");
1171 DebugStream.println("Is event dispatch thread: " + SwingUtilities.isEventDispatchThread());
1172 //check that we can remove the old index before starting import
1173 File index_dir = new File(getLoadedCollectionIndexDirectoryPath());
1174 if (index_dir.exists()) {
1175 DebugStream.println("Old Index = " + index_dir.getAbsolutePath()+", testing for deletability");
1176 if (!canDelete(index_dir)) {
1177 // tell the user
1178 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Delete_Index"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1179 // tell the gui manager
1180 // a message for the building log
1181 GShellEvent event = new GShellEvent(this, 0, GShell.IMPORT, Dictionary.get("CollectionManager.Cannot_Delete_Index_Log"), GShell.ERROR);
1182 Gatherer.g_man.create_pane.message(event);
1183 event = new GShellEvent(this, 0, GShell.IMPORT, "", GShell.ERROR);
1184 Gatherer.g_man.create_pane.processComplete(event);
1185 importing = false;
1186 return;
1187 }
1188 }
1189
1190 // Generate the import.pl command
1191 ArrayList command_parts_list = new ArrayList();
1192 if (!Gatherer.isGsdlRemote) {
1193 command_parts_list.add(Configuration.perl_path);
1194 command_parts_list.add("-S");
1195 }
1196
1197 if (Configuration.fedora_info.isActive()) {
1198 command_parts_list.add(scriptPath + "g2f-import.pl");
1199
1200 command_parts_list.add("-hostname");
1201 command_parts_list.add(Configuration.fedora_info.getHostname());
1202
1203 command_parts_list.add("-port");
1204 command_parts_list.add(Configuration.fedora_info.getPort());
1205
1206 command_parts_list.add("-username");
1207 command_parts_list.add(Configuration.fedora_info.getUsername());
1208
1209 command_parts_list.add("-password");
1210 command_parts_list.add(Configuration.fedora_info.getPassword());
1211
1212 command_parts_list.add("-protocol");
1213 command_parts_list.add(Configuration.fedora_info.getProtocol());
1214 }
1215 else {
1216 String cmdPrefix = null;
1217 if ( CollectionDesignManager.isCompleteBuild() ) {
1218 cmdPrefix = "full-";
1219 CollectionDesignManager.setImportWasFull( true );
1220 } else {
1221 cmdPrefix = "incremental-";
1222 CollectionDesignManager.setImportWasFull( false );
1223 }
1224 command_parts_list.add(scriptPath + cmdPrefix + "import.pl"); // scriptPath already set according to local or remote case
1225 }
1226
1227 command_parts_list.add("-gli");
1228 command_parts_list.add("-language");
1229 command_parts_list.add(Configuration.getLanguage());
1230
1231 if(Gatherer.GS3) {
1232 command_parts_list.add("-site");
1233 command_parts_list.add(Configuration.site_name);
1234 }
1235
1236 if(!Gatherer.isGsdlRemote) {
1237 command_parts_list.add("-collectdir");
1238 command_parts_list.add(getCollectDirectory());
1239 }
1240
1241 String[] import_options = collection.import_options.getValues();
1242 for (int i = 0; i < import_options.length; i++) {
1243 System.err.println( "Tacking on option: " + import_options[i] );
1244 command_parts_list.add(import_options[i]);
1245 }
1246
1247 command_parts_list.add(collection.getGroupQualifiedName(false)); // (colgroup/)colname
1248
1249 // Run the import.pl command
1250 String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
1251 GShell shell = new GShell(command_parts, GShell.IMPORT, BUILDING, this, import_monitor, GShell.GSHELL_IMPORT);
1252 //shell.setEventProperty("is_incremental", Boolean.toString(is_incremental));
1253 shell.addGShellListener(Gatherer.g_man.create_pane);
1254 Gatherer.g_man.create_pane.setGShell(shell); // allow the create pane to call shell.cancel()
1255 shell.addGShellListener(Gatherer.g_man.format_pane);
1256 shell.start();
1257 DebugStream.println("CollectionManager.importCollection().return");
1258
1259 importing = false;
1260 }
1261
1262
1263 public void importMetadataSet(MetadataSet external_metadata_set)
1264 {
1265 // Copy the .mds file into the collection's "metadata" folder...
1266 File external_metadata_set_file = external_metadata_set.getMetadataSetFile();
1267
1268 // ...but not if it is the redundant "hidden.mds" file
1269 if (external_metadata_set_file.getName().equals("hidden.mds")) {
1270 return;
1271 }
1272
1273 // ...and only if it doesn't already exist
1274 File metadata_set_file = new File(getLoadedCollectionMetadataDirectoryPath(), external_metadata_set_file.getName());
1275 if (!metadata_set_file.exists()) {
1276 try {
1277 Gatherer.f_man.getQueue().copyFile(external_metadata_set_file, metadata_set_file, false);
1278
1279 // If we're using a remote Greenstone server, upload the metadata file
1280 if (Gatherer.isGsdlRemote) {
1281 Gatherer.remoteGreenstoneServer.uploadCollectionFile(collection.getGroupQualifiedName(false), metadata_set_file);
1282 }
1283 }
1284 catch (Exception exception) {
1285 DebugStream.printStackTrace(exception);
1286 }
1287
1288 // Load it into the MetadataSetManager
1289 MetadataSetManager.loadMetadataSet(metadata_set_file);
1290 }
1291 }
1292
1293
1294 /** Determine if we are currently in the middle of importing (and thus, in this case, we can't allow the log writer to exit). Boy was this a mission to track down. The cascade of crap rolls out something like this: Joe Schmo clicks 'Build Collection', which calls the importCollection() method above, which in turn saves the collection with a saveTask, which fires a collectionChanged message once its finished, which drives the list of logs shown on the create pane to update, which fires a itemChanged() event to the OptionsPane who dutifully tells the current log writer thread to finish up writing (all zero lines its been asked to write) and then die. Wereapon Joe Schmo gets a pretty log to look at, but it isn't actually being written to file so the next time he tries to view it faeces hits the air motion cooling device. Joy.
1295 * @return true if the gli is currently importing
1296 */
1297 public boolean isImporting() {
1298 return importing;
1299 }
1300
1301
1302 public void loadCollection(String collection_file_path)
1303 {
1304 // Display a modal progress popup to indicate that the collection is being loaded
1305 ModalProgressPopup load_collection_progress_popup = new ModalProgressPopup(Dictionary.get("CollectionManager.Loading_Collection"), Dictionary.get("CollectionManager.Loading_Collection_Please_Wait"));
1306 load_collection_progress_popup.display();
1307
1308 // Load the collection on a separate thread so the progress bar updates correctly
1309 (new LoadCollectionTask(collection_file_path, load_collection_progress_popup)).start();
1310 //SwingUtilities.invokeLater(new LoadCollectionTask(collection_file_path, load_collection_progress_popup));
1311 }
1312
1313
1314 private class LoadCollectionTask
1315 extends Thread
1316 {
1317 private String collection_file_path = null;
1318 private ModalProgressPopup load_collection_progress_popup = null;
1319
1320 public LoadCollectionTask(String collection_file_path, ModalProgressPopup load_collection_progress_popup)
1321 {
1322 this.collection_file_path = collection_file_path;
1323 this.load_collection_progress_popup = load_collection_progress_popup;
1324 }
1325
1326 public void run()
1327 {
1328 loadCollectionInternal(collection_file_path);
1329 load_collection_progress_popup.close();
1330 Gatherer.setMenuBarEnabled(true);
1331 }
1332 }
1333
1334
1335 /** Attempts to load the given collection. Currently uses simple serialization of the collection class.
1336 * @param location The path to the collection as a <strong>String</strong>.
1337 * @see org.greenstone.gatherer.Configuration
1338 * @see org.greenstone.gatherer.Gatherer
1339 * @see org.greenstone.gatherer.collection.Collection
1340 * @see org.greenstone.gatherer.util.Utility
1341 */
1342 private void loadCollectionInternal(String location)
1343 {
1344 DebugStream.println("Loading collection " + location + "...");
1345
1346
1347 // Check we have actually been given a .col file.
1348 if (!location.endsWith(".col")) {
1349 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Not_Col_File", location), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1350 DebugStream.println("CollectionManager.loadCollection: Haven't been given a .col file.");
1351 return;
1352 }
1353
1354 // Check that the collection configuration file is available
1355 File collection_file = new File(location);
1356
1357 //String collection_name = collection_directory.getName();
1358 String collection_name = "";
1359 File collection_directory = collection_file.getParentFile();
1360
1361 // To get colname = (colgroup/)coltailname, subtract Gatherer.getCollectDirectoryPath() from collection_directory:
1362 int index = collection_directory.getAbsolutePath().indexOf(Gatherer.getCollectDirectoryPath());
1363 if(index == -1) {
1364 System.err.println("*** ERROR: collection directory " + collection_directory + " is not located in collect folder: " + Gatherer.getCollectDirectoryPath());
1365 } else {
1366 index += Gatherer.getCollectDirectoryPath().length();
1367 collection_name = collection_directory.getAbsolutePath().substring(index);
1368 }
1369
1370 if (Gatherer.isGsdlRemote) {
1371 if (Gatherer.remoteGreenstoneServer.downloadCollection(collection_name).equals("")) {
1372 return;
1373 }
1374 }
1375
1376 // Ensure that the collection directory exists
1377 if (collection_directory == null || !collection_directory.exists()) {
1378 // We can't open this
1379 System.err.println("CollectionManager.loadCollection: No collection directory.");
1380 return;
1381 }
1382
1383 String file_str = (Gatherer.GS3)? Utility.CONFIG_GS3_FILE : Utility.CONFIG_FILE;
1384 File collection_config_file = new File(collection_directory, file_str);
1385 if (!collection_config_file.exists()) {
1386 System.err.println("CollectionManager.loadCollection: No config file.");
1387 collection_directory = null;
1388 collection_config_file = null;
1389 return;
1390 }
1391
1392 // Ensure that an import directory exists for this collection
1393 File collection_import_directory = new File(collection_directory, "import");
1394 if (!collection_import_directory.exists()) {
1395 collection_import_directory.mkdir();
1396 }
1397
1398 // Special case of a user trying to open an old greenstone collection.
1399 boolean non_gli_collection = false;
1400 File collection_metadata_directory = new File(collection_directory, "metadata");
1401 if (!collection_metadata_directory.exists()) {
1402 DebugStream.println("Loading non-gatherer collection...");
1403 // Show a warning message in case user wants to quit now
1404 non_gli_collection = true;
1405 WarningDialog legacy_dialog = new WarningDialog("warning.LegacyCollection", Dictionary.get("LegacyCollection.Title"), Dictionary.get("LegacyCollection.Message"), null, true);
1406 if (legacy_dialog.display()==JOptionPane.CANCEL_OPTION) {
1407 legacy_dialog.dispose();
1408 collection_directory = null;
1409 collection_config_file = null;
1410 return;
1411 }
1412 legacy_dialog.dispose();
1413
1414 }
1415
1416 // Now determine if a lock already exists on this collection.
1417 File lock_file = new File(collection_file.getParentFile(), LOCK_FILE);
1418 if (lock_file.exists()) {
1419 LockFileDialog dialog = new LockFileDialog(Gatherer.g_man, collection_name, lock_file);
1420 TestingPreparation.setNamesRecursively(dialog);
1421 int choice = dialog.getChoice();
1422 dialog.dispose();
1423 dialog = null;
1424
1425 if (choice != LockFileDialog.YES_OPTION) {
1426 // user has cancelled
1427 lock_file = null;
1428 collection_directory = null;
1429 collection_config_file = null;
1430 return;
1431 }
1432
1433 lock_file.delete();
1434 }
1435
1436 // now we are using gli.col - old colls may have used the collection name
1437 if (!collection_file.exists()) {
1438 File old_coll_file = new File(collection_directory, collection_name+".col");
1439 if (old_coll_file.exists()) {
1440 try {
1441 old_coll_file.renameTo(collection_file);
1442 } catch (Exception e) {
1443 DebugStream.println("Couldn't rename "+old_coll_file.getName()+" to gli.col. Will just carry on with default gli.col");
1444 // but just carry on.
1445 }
1446 }
1447 }
1448
1449 try {
1450 // Create a lock file.
1451 createLockFile(lock_file);
1452 // This lock file may not have been created so check
1453 if(!lock_file.canWrite()) {
1454 // The lock file cannot be written to. Most likely cause incorrect file permissions.
1455 System.err.println("Cannot write lock file!");
1456 String args[] = new String[2];
1457 args[0] = location;
1458 args[1] = Dictionary.get("FileActions.Write_Not_Permitted_Message", new String[]{lock_file.getAbsolutePath()});
1459 if(Gatherer.client_operating_system.toUpperCase().indexOf("WINDOWS")!=-1){
1460 //if(Gatherer.client_operating_system.toUpperCase().indexOf("VISTA")!=-1){
1461 args[1] += Dictionary.get("FileActions.File_Permission_Detail", new String[]{Configuration.gsdl_path, System.getProperty("user.name")});
1462 //}
1463 }
1464 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Open_With_Reason", args), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1465 args = null;
1466 return;
1467 }
1468
1469 // need to fix this up as currently it craps out if the .col file is not there, which is may not always be.
1470 if (canDoScheduling() && collection_file.exists()) {
1471 //THIS LOOKS LIKE THE BEST PLACE TO TRY AND UPDATE .col FILES FOR EXISTING COLLECTIONS...Wendy
1472 // Don't need to update anything if collection_file doesn't exist yet.
1473 //First, see if "Schedule" exists in the XMl File...
1474 BufferedReader bir = new BufferedReader(new FileReader(collection_file));
1475 boolean flag = false;
1476 try {
1477 String stmp = new String();
1478
1479 while((stmp = bir.readLine()) != null) {
1480 stmp = stmp.trim();
1481 if(stmp.equals("<Schedule>") || stmp.equals("<Schedule/>")) {
1482 flag = true;
1483 break;
1484 }
1485 }
1486 bir.close();
1487
1488 } catch (IOException ioe) {
1489 DebugStream.printStackTrace(ioe);
1490 }
1491
1492 //modify if old .col (i.e. no Schedule exists in XML file)
1493 if(!flag) {
1494 File new_collection_file = new File(collection_directory.getAbsolutePath() + "/tmp.col");
1495
1496
1497 BufferedWriter bor = new BufferedWriter(new FileWriter(new_collection_file));
1498 bir = new BufferedReader(new FileReader(collection_file));
1499
1500 try {
1501 String stmp = new String();
1502 while((stmp = bir.readLine()) != null) {
1503 String stmp2 = stmp.trim();
1504 if(stmp2.startsWith("<!ELEMENT Argument")) {
1505 bor.write(" <!ELEMENT Schedule (Arguments*)>\n");
1506 }
1507 else if(stmp2.equals("</BuildConfig>")) {
1508 bor.write(" <Schedule/>\n");
1509 }
1510
1511 bor.write(stmp + "\n");
1512
1513 }
1514 bir.close();
1515 bor.close();
1516 } catch (IOException ioe) {
1517 DebugStream.printStackTrace(ioe);
1518 }
1519
1520 //copy over tmp.col to replace
1521 try {
1522 collection_file.delete();
1523 new_collection_file.renameTo(collection_file);
1524 } catch (Exception e) {
1525 DebugStream.printStackTrace(e);
1526 }
1527 }
1528 }
1529
1530 // Open the collection file
1531 this.collection = new Collection(collection_file);
1532 if (collection.error) {
1533 collection = null;
1534 // Remove lock file
1535 if (lock_file.exists()) {
1536 lock_file.delete();
1537 }
1538 throw(new Exception(Dictionary.get("CollectionManager.Missing_Config"))); // this error message does not agree with the error
1539 }
1540
1541 if (canDoScheduling()) {
1542 scheduling();
1543 }
1544
1545 // These may have been set in the past, but are no longer used
1546 // by GLI
1547 collection.import_options.removeValue("removeold");
1548 collection.import_options.removeValue("keepold");
1549
1550 MetadataSetManager.clearMetadataSets();
1551 MetadataSetManager.loadMetadataSets(collection_metadata_directory);
1552
1553 // Make sure we always have the extracted metadata set
1554 addRequiredMetadataSets();
1555
1556 ProfileXMLFileManager.loadProfileXMLFile(collection_metadata_directory);
1557
1558 // If this is a non-GLI (legacy) collection, load the default metadata sets
1559 if (non_gli_collection) {
1560 addDefaultMetadataSets();
1561
1562 // Recurse the import folder tree, backing up the metadata.xml files before they are edited
1563 LegacyCollectionImporter.backupMetadataXMLFiles(collection_directory);
1564 }
1565
1566 // Read through the metadata.xml files in the import directory, building up the metadata value trees
1567 MetadataXMLFileManager.clearMetadataXMLFiles();
1568 MetadataXMLFileManager.loadMetadataXMLFiles(collection_import_directory,collection.toSkimFile());
1569
1570
1571 // get rid of the previous scan through docxml files
1572 DocXMLFileManager.clearDocXMLFiles();
1573
1574 if (Configuration.fedora_info.isActive()) { // FLI case
1575 // Read through the docmets.xml files in the export directory
1576 File collection_export_directory = new File(getLoadedCollectionExportDirectoryPath());
1577 DocXMLFileManager.loadDocXMLFiles(collection_export_directory,"docmets.xml");
1578 }
1579 else {
1580 // Read through the doc.xml files in the archives directory
1581 File collection_archives_directory = new File(getLoadedCollectionArchivesDirectoryPath());
1582 DocXMLFileManager.loadDocXMLFiles(collection_archives_directory,"doc.xml");
1583 }
1584
1585
1586 // Get a list of the collection specific classifiers and plugins
1587 Classifiers.loadClassifiersList(collection_name);
1588 Plugins.loadPluginsList(collection_name);
1589
1590 collection.cdm = new CollectionDesignManager(collection_config_file);
1591 if (non_gli_collection) {
1592 // Change the classifiers to use the namespaced element names
1593 LegacyCollectionImporter.updateClassifiers(collection.cdm);
1594 }
1595
1596 // We're done. Let everyone know.
1597 DebugStream.println(Dictionary.get("CollectionManager.Loading_Successful", collection_name));
1598 Gatherer.refresh(Gatherer.COLLECTION_OPENED);
1599 }
1600 catch (Exception error) {
1601 // There is obviously no existing collection present.
1602 DebugStream.printStackTrace(error);
1603 error.printStackTrace();
1604 if(error.getMessage() != null) {
1605 String[] args = new String[2];
1606 args[0] = location;
1607 args[1] = error.getMessage();
1608 //args[1] = "The Librarian Interface does not have permission to write to... Please check file permissions.";
1609 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Open_With_Reason", args), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1610 }
1611 else {
1612 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Open", location), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1613 }
1614 }
1615
1616 lock_file = null;
1617 collection_directory = null;
1618 collection_config_file = null;
1619 }
1620
1621 /** At present, scheduling only works for GS2, only when GS2 is local and only when GLI runs from
1622 * within a GS2 installation. This method can be adjusted as scheduling becomes available for more
1623 * more situations. */
1624 public static boolean canDoScheduling() {
1625 // Would be nice to support more of these, rather than returning false
1626 if(Gatherer.isGsdlRemote) {
1627 return false;
1628 }
1629 if(Gatherer.GS3) {
1630 return false;
1631 }
1632 if (Configuration.fedora_info.isActive()) {
1633 return false;
1634 }
1635
1636 // GS2's etc/main.cfg is necessary for scheduling, but scheduling looks for it locally:
1637 // it assumes GLI is inside a GS2 installation
1638 File mcfg = new File(LocalGreenstone.getDirectoryPath() + File.separator + "etc" + File.separator + "main.cfg");
1639 if(!mcfg.exists()) {
1640 System.out.println("Cannot do scheduling, since there is no file: " + mcfg.getAbsolutePath()
1641 + ".\nScheduling presently depends on GLI running from inside a GS2.");
1642 return false;
1643 }
1644
1645 return true;
1646 }
1647
1648 private void makeCollection(String name, String email)
1649 {
1650 // Generate the mkcol.pl command
1651 ArrayList command_parts_list = new ArrayList();
1652 if (!Gatherer.isGsdlRemote) {
1653 command_parts_list.add(Configuration.perl_path);
1654 command_parts_list.add("-S");
1655 }
1656 command_parts_list.add(scriptPath + "mkcol.pl");
1657 if(Gatherer.GS3) {
1658 command_parts_list.add(Utility.GS3MODE_ARGUMENT); // add '-gs3mode'
1659 command_parts_list.add("-site");
1660 command_parts_list.add(Configuration.site_name);
1661 }
1662
1663 if(!Gatherer.isGsdlRemote) {
1664 command_parts_list.add("-collectdir");
1665 command_parts_list.add(getDefaultCollectDirectory());
1666 }
1667 command_parts_list.add("-win31compat");
1668 command_parts_list.add((Gatherer.isGsdlRemote) ? "false" : "true");
1669
1670 if (email != null && !email.equals("")) {
1671 command_parts_list.add("-creator");
1672 command_parts_list.add(email);
1673 }
1674
1675 command_parts_list.add(name);
1676
1677 // Run the mkcol.pl command
1678 String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
1679 //for(int i = 0; i < command_parts.length; i++) {
1680 ///ystem.err.println("\""+command_parts[i]+"\"");
1681 //}
1682
1683 GShell process = new GShell(command_parts, GShell.NEW, COLLECT, this, null, GShell.GSHELL_NEW);
1684 process.run(); // Don't bother threading this... yet
1685 }
1686
1687
1688 /** Any implementation of GShellListener must include this method to allow the GShell to send messages to listeners. However in this case the CollectionManager is in no way interested in what the messages are, just the import events which have a specific type and are handled elsewhere. Thus we can safely ignore this event.
1689 * @param event A <strong>GShellEvent</strong> which contains a the message.
1690 */
1691 public synchronized void message(GShellEvent event) {
1692
1693 }
1694
1695
1696 public void metadataChanged(CollectionTreeNode[] file_nodes)
1697 {
1698 if (collection != null) {
1699 collection.setMetadataChanged(true);
1700
1701 // we're only going to refresh the tree's already visible nodes (and reselect them) IFF
1702 // gs.FilenameEncoding meta was set on any files/folders and the filenames of the
1703 // affected CollectionTreeNodes need to be recalculated
1704 if(FilenameEncoding.isRefreshRequired()) {
1705
1706 // refreshes the relevant part of the tree
1707 TreePath[] paths = collection_tree.getSelectionPaths();
1708 if(paths != null) {
1709 for(int i = 0; i < paths.length; i++) {
1710 collection_tree_model.refresh(paths[i]);
1711 collection_tree.setSelectionPath(paths[i]);
1712 }
1713 }
1714 // refreshed the tree, so turn off the requirement to refresh
1715 FilenameEncoding.setRefreshRequired(false);
1716 }
1717 }
1718 }
1719
1720
1721 public void openCollectionFromLastTime() {
1722 // If there was an open collection last session, reopen it.
1723 // (this method doesn't get called if there was no open collection or only a collect folder
1724 // instead of any previously-opened collection)
1725
1726 // Load the collection now
1727 loadCollection(Gatherer.open_collection_file_path);
1728 }
1729
1730
1731 /** This call is fired whenever a process within a GShell created by this class begins.
1732 * @param event A <strong>GShellEvent</strong> containing information about the GShell process.
1733 * @see org.greenstone.gatherer.Gatherer
1734 * @see org.greenstone.gatherer.gui.GUIManager
1735 * @see org.greenstone.gatherer.shell.GShell
1736 */
1737 public synchronized void processBegun(GShellEvent event) {
1738 DebugStream.println("CollectionManager.processBegun(" + event.getType() + ")");
1739 ///ystem.err.println("ProcessBegun " + event.getType());
1740 // If this is one of the types where we wish to lock user control
1741 Gatherer.g_man.lockCollection((event.getType() == GShell.IMPORT), true);
1742 }
1743 /** This call is fired whenever a process within a GShell created by this class ends.
1744 * @param event A <strong>GShellEvent</strong> containing information about the GShell process.
1745 * @see org.greenstone.gatherer.Gatherer
1746 * @see org.greenstone.gatherer.gui.GUIManager
1747 * @see org.greenstone.gatherer.shell.GShell
1748 */
1749 public synchronized void processComplete(GShellEvent event) {
1750 //ystem.err.println("CollectionManager.processComplete(" + event.getType() + ")");
1751 Gatherer.g_man.lockCollection((event.getType() == GShell.IMPORT), false);
1752 ///ystem.err.println("Received process complete event - " + event);
1753 // If we were running an import, now run a build.
1754 if(event.getType() == GShell.IMPORT && event.getStatus() == GShell.OK) {
1755 // Finish import.
1756 collection.setImported(true);
1757 collection.setFilesChanged(false);
1758 collection.setMetadataChanged(false);
1759 buildCollection();
1760 }
1761 else if(event.getType() == GShell.SCHEDULE && event.getStatus() == GShell.OK ) {
1762
1763 WarningDialog collection_built_warning_dialog = new WarningDialog("warning.ScheduleBuilt", Dictionary.get("ScheduleBuilt.Title"), Dictionary.get("ScheduleBuilt.Message"), null, false);
1764 collection_built_warning_dialog.setMessageOnly(true); // Not a warning
1765 collection_built_warning_dialog.display();
1766 collection_built_warning_dialog.dispose();
1767 collection_built_warning_dialog = null;
1768 }
1769 // If we were running a build, now is when we move files across.
1770 else if(event.getType() == GShell.BUILD && event.getStatus() == GShell.OK) {
1771
1772 if ( CollectionDesignManager.buildcolWasFull() ) {
1773
1774 // No installCollection() for GS3 solr collection: activate will take care of that
1775 // and no call to configGS3Server for solr collection
1776 if(CollectionManager.isSolrCollection()) {
1777
1778 DebugStream.println("Solr collection build complete: building already moved to index by activate.pl.");
1779
1780 // Finished building,
1781 // For now, for a GS3 solr collection, we'd have stopped the GS3 server before building
1782 // and will now need to restart it.
1783 /*GS3ServerThread thread = new GS3ServerThread(Configuration.gsdl3_src_path, "restart");
1784 thread.start();*/
1785
1786 // Give the GS3 server time to restart:
1787 // the GS3ServerThread above waits for the process to terminate. ant restart target calls the start-tomcat ant target
1788 // and that takes waits 5 seconds and polls to see if a GS3 server index page has loaded. So no need to sleep here
1789
1790 }
1791
1792 else if(installCollection()) {
1793 // If we have a local library running then ask it to add our newly created collection
1794 if (LocalLibraryServer.isRunning() == true) {
1795 LocalLibraryServer.addCollection(collection.getName());
1796 }
1797 else if (Gatherer.GS3) {
1798 //xiao comment out this: convertToGS3Collection();
1799 Gatherer.configGS3Server(Configuration.site_name, ServletConfiguration.ADD_COMMAND + collection.getName());
1800 }
1801
1802 // Fire a collection changed first to update the preview etc buttons
1803 Gatherer.refresh(Gatherer.COLLECTION_REBUILT);
1804
1805 // Now display a message dialog saying its all built
1806 WarningDialog collection_built_warning_dialog = new WarningDialog("warning.CollectionBuilt", Dictionary.get("CollectionBuilt.Title"), Dictionary.get("CollectionBuilt.Message"), null, false);
1807 collection_built_warning_dialog.setMessageOnly(true); // Not a warning
1808 collection_built_warning_dialog.display();
1809 collection_built_warning_dialog.dispose();
1810 collection_built_warning_dialog = null;
1811
1812 //Set nothing as needing rebuilding, as a build has just finished :-)
1813 CollectionDesignManager.resetRebuildTypeRequired();
1814 }
1815 else {
1816 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Preview_Ready_Failed"), Dictionary.get("CollectionManager.Preview_Ready_Title"), JOptionPane.ERROR_MESSAGE);
1817 Gatherer.refresh(Gatherer.COLLECTION_REBUILT);
1818 DebugStream.println("Status is ok but !installCollection()");
1819 }
1820 }
1821 }
1822
1823 else if(event.getType() == GShell.DELETE) {
1824
1825 // we can only get here if we tried to delete a fedora collection
1826
1827 if(event.getStatus() == GShell.ERROR) { // error purging the collection from fedora
1828
1829 JOptionPane.showMessageDialog(Gatherer.g_man,Dictionary.get("DeleteCollectionPrompt.Failed_Fedora_Delete", new String[]{delete_collection_name}),Dictionary.get("DeleteCollectionPrompt.Failed_Title"),JOptionPane.WARNING_MESSAGE);
1830 delete_collection_name = null; // re-zero
1831 }
1832
1833 else if(event.getStatus() == GShell.OK) { // fedora purge was successful
1834
1835 if(delete_collection_name != null) {
1836 if (Gatherer.isGsdlRemote) {
1837 Gatherer.remoteGreenstoneServer.deleteCollection(delete_collection_name);
1838 }
1839
1840 // if Greenstone3, need to deactivate the collection on the server
1841 if (Gatherer.GS3) {
1842 Gatherer.configGS3Server(Configuration.site_name, ServletConfiguration.DEACTIVATE_COMMAND + delete_collection_name);
1843 }
1844
1845 // Now at last, can delete the collection directory as for a normal collection
1846 boolean success = Utility.delete(new File(getCollectionDirectoryPath(delete_collection_name)));
1847
1848 if (!success) {
1849 JOptionPane.showMessageDialog(Gatherer.g_man,Dictionary.get("DeleteCollectionPrompt.Failed_Delete", new String[]{delete_collection_name}),Dictionary.get("DeleteCollectionPrompt.Failed_Title"),JOptionPane.WARNING_MESSAGE);
1850 }
1851 delete_collection_name = null; // re-zero
1852 }
1853
1854 }
1855 }
1856
1857 else if (event.getStatus() == GShell.CANCELLED) {
1858 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Build_Cancelled"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1859 Gatherer.g_man.repaint();
1860 }
1861 else if (event.getStatus() == GShell.ERROR) {
1862 if (event.getType() == GShell.NEW) {
1863 String name = event.getMessage();
1864 String collectDir = getCollectionDirectoryPath(name);
1865 String errMsg = "";
1866 if (!new File(getCollectionDirectoryPath(name)).exists() || !new File(getCollectionDirectoryPath(name)).canWrite()) {
1867 String reason = Dictionary.get("FileActions.Write_Not_Permitted_Message", new String[]{collectDir});
1868 errMsg = Dictionary.get("CollectionManager.Cannot_Create_Collection_With_Reason", new String[]{reason});
1869 if(Gatherer.client_operating_system.toUpperCase().indexOf("WINDOWS") != -1){
1870 //if(Gatherer.client_operating_system.toUpperCase().indexOf("VISTA")!=-1){
1871 errMsg += Dictionary.get("FileActions.File_Permission_Detail", new String[]{Configuration.gsdl_path, System.getProperty("user.name")});
1872 //}
1873 }
1874 } else {
1875 errMsg = Dictionary.get("CollectionManager.Cannot_Create_Collection");
1876 }
1877 JOptionPane.showMessageDialog(Gatherer.g_man, errMsg, Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
1878 }
1879 else if(event.getType() == GShell.SCHEDULE) {
1880 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Schedule_Failed"), Dictionary.get("CollectionManager.Schedule_Ready_Title"), JOptionPane.ERROR_MESSAGE);
1881 }
1882 else {
1883 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Preview_Ready_Failed"), Dictionary.get("CollectionManager.Preview_Ready_Title"), JOptionPane.ERROR_MESSAGE);
1884 Gatherer.refresh(Gatherer.COLLECTION_REBUILT);
1885 }
1886
1887 Gatherer.g_man.repaint(); // It appears Java's own dialogs have the same not always painting correct area bug that I suffer from. Well I don't suffer from it personally, but my ModalDialog components do.
1888 }
1889 }
1890
1891
1892 /** Determine if the manager is ready for actions apon its collection.
1893 * @return A <i>boolean</i> which is <i>true</i> to indicate a collection has been loaded and thus the collection is ready for editing, <i>false</i> otherwise.
1894 */
1895 static public synchronized boolean ready() {
1896 if(collection != null) {
1897 return true;
1898 }
1899 else {
1900 return false;
1901 }
1902 }
1903
1904
1905 /** This method associates the collection build monitor with the build monitor created in CreatePane.
1906 * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the build monitor.
1907 */
1908 public void registerBuildMonitor(GShellProgressMonitor monitor) {
1909 build_monitor = monitor;
1910 }
1911 /** This method associates the collection import monitor with the import monitor created in CreatePane.
1912 * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the import monitor.
1913 */
1914 public void registerImportMonitor(GShellProgressMonitor monitor) {
1915 import_monitor = monitor;
1916 }
1917
1918 public void registerScheduleMonitor(GShellProgressMonitor monitor) {
1919 schedule_monitor = monitor;
1920 }
1921
1922
1923 static public void removeCollectionContentsChangedListener(CollectionContentsChangedListener listener)
1924 {
1925 collection_contents_changed_listeners.remove(listener);
1926 }
1927
1928
1929 public void removeMetadataSet(MetadataSet metadata_set)
1930 {
1931 DebugStream.println("Removing metadata set...");
1932
1933 // Delete the .mds file from the collection's "metadata" folder...
1934 File metadata_set_file = metadata_set.getMetadataSetFile();
1935
1936 // ...but not if it is the "ex.mds" file
1937 if (metadata_set_file.getName().equals("ex.mds")) {
1938 return;
1939 }
1940
1941 // ...and only if it exists
1942 if (metadata_set_file.exists()) {
1943 metadata_set_file.delete();
1944
1945 // Unload it from the MetadataSetManager
1946 MetadataSetManager.unloadMetadataSet(metadata_set);
1947
1948 // If we're using a remote Greenstone server, delete the metadata file on the server
1949 if (Gatherer.isGsdlRemote) {
1950 Gatherer.remoteGreenstoneServer.deleteCollectionFile(collection.getGroupQualifiedName(false), metadata_set_file);
1951 }
1952 }
1953 }
1954
1955
1956 /** Used to check whether all open collections have a 'saved' state.
1957 * @return A <i>boolean</i> which is <i>true</i> if the collection has been saved.
1958 * @see org.greenstone.gatherer.collection.Collection
1959 */
1960 public boolean saved() {
1961 boolean result = true;
1962 if(collection != null) {
1963 result = collection.getSaved();
1964 }
1965 return result;
1966 }
1967
1968
1969 /** Saves the currently loaded collection. */
1970 public void saveCollection()
1971 {
1972
1973 if (collection == null) return;
1974
1975 DebugStream.println("Saving collection " + collection.getName() + "...");
1976
1977 // Change cursor to hourglass
1978 Gatherer.g_man.wait(true);
1979
1980 // Create a backup of the collection file, just in case anything goes wrong
1981 File collection_file = new File(getLoadedCollectionColFilePath());
1982 if (collection_file.exists()) {
1983 File collection_file_backup = new File(collection_file.getAbsolutePath() + "~");
1984 if (!collection_file.renameTo(collection_file_backup)) {
1985 DebugStream.println("Error in CollectionManager.saveCollection(): could not create backup file.");
1986 }
1987 collection_file_backup.deleteOnExit();
1988 }
1989
1990 // Write out the collection file
1991 collection.save();
1992
1993 // Write out the collection configuration file
1994 collection.cdm.save();
1995
1996 // Change cursor back to normal
1997 Gatherer.g_man.wait(false);
1998 }
1999
2000
2001 /** I started giving the user the choice of using an existing meta set or creating a new one. The second option being so that they didn't have to add/merge/ignore each element, they could all be added automatically. However, I am not sure where the merge prompt gets called from, and it is not essential, so I am leaving it for now - it should be added back in and finished. [kjdon] */
2002 // now add in greenstone metadata set too.
2003 private void addDefaultMetadataSets()
2004 {
2005 // Add dublin core which is the default metadata set. The user
2006 // can change this later
2007 File dc_file = new File(Gatherer.getGLIMetadataDirectoryPath()+"dublin.mds");
2008 if (dc_file.exists()) {
2009 importMetadataSet(new MetadataSet(dc_file));
2010 }
2011 File gs_file = new File(Gatherer.getGLIMetadataDirectoryPath()+"greenstone.mds");
2012 if (gs_file.exists()) {
2013 importMetadataSet(new MetadataSet(gs_file));
2014 }
2015 }
2016
2017
2018 private void addRequiredMetadataSets()
2019 {
2020 // Always import the extracted metadata set
2021 File extracted_metadata_set_file = new File(Gatherer.getGLIMetadataDirectoryPath() + MetadataSetManager.EXTRACTED_METADATA_NAMESPACE + StaticStrings.METADATA_SET_EXTENSION);
2022 importMetadataSet(new MetadataSet(extracted_metadata_set_file));
2023 }
2024
2025 private String getDefaultCollectDirectory() {
2026 String collect_dir = Gatherer.getCollectDirectoryPath();
2027 // Remove erroneous file windows file separator as it causes problems when running import.pl
2028 if(collect_dir.length() > 2 && collect_dir.endsWith("\\")) {
2029 collect_dir = collect_dir.substring(0, collect_dir.length() - 1);
2030 }
2031 return collect_dir;
2032 }
2033
2034 // used as arg in the perl scripts
2035 private String getCollectDirectory() {
2036 String collect_dir = Gatherer.getCollectDirectoryPath();
2037 return collect_dir.substring(0, collect_dir.length()-1); // remove trailing slash
2038
2039 // the following will stick any colgroup at the end of the collect directory, making it no longer
2040 // possible to get the real collect dir in a general manner if this were located outside greenstone
2041 //String collect_dir = collection.getCollectionDirectory().getParentFile().getPath();
2042 //return collect_dir;
2043 }
2044
2045 public static String getBuildType() {
2046 String buildType = (new CollectionMeta( CollectionDesignManager.collect_config.getBuildType() )).getValue(CollectionMeta.TEXT);
2047 return buildType;
2048 }
2049
2050 public static boolean isSolrCollection() {
2051 return (Gatherer.GS3 && CollectionManager.getBuildType().equals("solr"));
2052 }
2053
2054
2055 /** Install collection by moving its files from building to index after a successful build.
2056 * @see org.greenstone.gatherer.Gatherer
2057 * @see org.greenstone.gatherer.util.Utility
2058 */
2059 private boolean installCollection()
2060 {
2061 if (Configuration.fedora_info.isActive()) {
2062 DebugStream.println("Fedora build complete. No need to move files.");
2063 return true;
2064 }
2065
2066 DebugStream.println("Build complete. Moving files.");
2067
2068 try {
2069 // Ensure that the local library has released this collection so we can delete the index directory
2070 if (LocalLibraryServer.isRunning() == true) {
2071 LocalLibraryServer.releaseCollection(getLoadedCollectionName(true)); // URL style slash //collection.getName());
2072 }
2073 // deactivate it in tomcat so that windows will release the index files
2074 if (Gatherer.GS3 && !Gatherer.isGsdlRemote) {
2075 Gatherer.configGS3Server(Configuration.site_name, ServletConfiguration.DEACTIVATE_COMMAND + collection.getName());
2076 }
2077 /*
2078 File index_dir = new File(getLoadedCollectionIndexDirectoryPath());
2079 DebugStream.println("Index = " + index_dir.getAbsolutePath());
2080
2081 File building_dir = new File(getLoadedCollectionBuildingDirectoryPath());
2082 DebugStream.println("Building = " + building_dir.getAbsolutePath());
2083
2084 // Get the build mode from the build options
2085 String build_mode = collection.build_options.getValue("mode");
2086
2087 // Special case for build mode "all": replace index dir with building dir
2088 if (build_mode == null || build_mode.equals(Dictionary.get("CreatePane.Mode_All"))) {
2089 // Remove the old index directory
2090 if (index_dir.exists()) {
2091 Utility.delete(index_dir);
2092
2093 // Wait for a couple of seconds, just for luck
2094 wait(2000);
2095
2096 // Check the delete worked
2097 if (index_dir.exists()) {
2098 throw new Exception(Dictionary.get("CollectionManager.Index_Not_Deleted"));
2099 }
2100 }
2101
2102 if (Gatherer.isGsdlRemote) {
2103 Gatherer.remoteGreenstoneServer.deleteCollectionFile(
2104 collection.getGroupQualifiedName(false), new File(getLoadedCollectionIndexDirectoryPath()));
2105 Gatherer.remoteGreenstoneServer.moveCollectionFile(collection.getGroupQualifiedName(false),
2106 new File(getLoadedCollectionBuildingDirectoryPath()), new File(getLoadedCollectionIndexDirectoryPath()));
2107 }
2108
2109 // Move the building directory to become the new index directory
2110 if (building_dir.renameTo(index_dir) == false) {
2111 throw new Exception(Dictionary.get("CollectionManager.Build_Not_Moved"));
2112 }
2113 }
2114
2115 // Otherwise copy everything in the building dir into the index dir
2116 else {
2117 moveContentsInto(building_dir, index_dir);
2118 }
2119
2120 // move oai tmpdb to oai livedb
2121 */
2122
2123 }
2124 catch (Exception exception) {
2125 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Install_Exception", exception.getMessage()), "Error", JOptionPane.ERROR_MESSAGE);
2126 return false;
2127 }
2128 return true;
2129 }
2130
2131
2132 /** Moves all the files in one directory into another, overwriting existing files */
2133 private void moveContentsInto(File source_directory, File target_directory)
2134 {
2135 File[] source_files = source_directory.listFiles();
2136 for (int i = 0; i < source_files.length; i++) {
2137 File source_file = source_files[i];
2138 File target_file = new File(target_directory, source_file.getName());
2139
2140 if (source_file.isDirectory()) {
2141 moveContentsInto(source_file, target_file);
2142 source_file.delete();
2143 }
2144 else {
2145 if (target_file.exists()) {
2146 target_file.delete();
2147 }
2148
2149 source_file.renameTo(target_file);
2150 }
2151 }
2152 }
2153
2154 private void updateCollectionConfigXML(File base_cfg, File new_cfg) {
2155 //In this method, the files base_cfg and new_cfg are all xml files.
2156
2157 Document base_cfg_doc = XMLTools.parseXMLFile(base_cfg);
2158 XMLTools.writeXMLFile(new_cfg, base_cfg_doc);
2159 Document new_cfg_doc = XMLTools.parseXMLFile(new_cfg);
2160 Element collection_config = new_cfg_doc.getDocumentElement();
2161
2162 Node browseNode = XMLTools.getChildByTagNameIndexed(collection_config, StaticStrings.BROWSE_STR, 0);
2163 NodeList classifier_children = ((Element)browseNode).getElementsByTagName(StaticStrings.CLASSIFIER_STR);
2164 int num_nodes = classifier_children.getLength();
2165
2166 if (num_nodes < 1) {
2167 return;
2168 }
2169
2170 // Read in the classifier command watching for hfile, metadata and sort arguments.
2171 String buttonname = null;
2172 String hfile = null;
2173 String metadata = null;
2174 String sort = null;
2175
2176 for (int i=0; i<num_nodes; i++) {
2177 Element classifier_element = (Element)classifier_children.item(i);
2178 NodeList option_children = classifier_element.getElementsByTagName(StaticStrings.OPTION_STR);
2179 for (int j=0; j<option_children.getLength(); j++) {
2180 Element option_element = (Element)option_children.item(j);
2181 String name_str = option_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
2182 String value_str = option_element.getAttribute(StaticStrings.VALUE_ATTRIBUTE);
2183
2184 if (name_str == null || name_str.equals("")) {
2185 continue;
2186 }
2187 if (name_str != null && value_str == null ) {
2188 value_str = "";
2189 }
2190 if (name_str.equals("hfile")) {
2191 hfile = value_str;
2192 }
2193 else if (name_str.equals("metadata") && value_str != null) {
2194 String replacement = ProfileXMLFileManager.getMetadataElementFor(value_str);
2195 if (replacement != null && !replacement.equals("")) {
2196 metadata = replacement;
2197 }
2198 }
2199 else if (name_str.equals("sort") && value_str != null) {
2200 String replacement = ProfileXMLFileManager.getMetadataElementFor(value_str);
2201 if (replacement != null && !replacement.equals("")) {
2202 sort = replacement;
2203 }
2204 }
2205 else if(name_str.equals("buttonname") && value_str != null) {
2206 buttonname = value_str;
2207 }
2208 }
2209 }
2210 for (int i=0; i<num_nodes; i++) {
2211 Element classifier_element = (Element)classifier_children.item(i);
2212 NodeList option_children = classifier_element.getElementsByTagName(StaticStrings.OPTION_STR);
2213 for (int j=0; j<option_children.getLength(); j++) {
2214 Element option_element = (Element)option_children.item(j);
2215 String name_str = option_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
2216
2217 if (name_str.equals("metadata") && metadata != null) {
2218 option_element.setAttribute(StaticStrings.VALUE_ATTRIBUTE, metadata);
2219 }
2220 else if (name_str.equals("hfile") && hfile != null) {
2221 option_element.setAttribute(StaticStrings.VALUE_ATTRIBUTE, metadata + ".txt");
2222 }
2223 else if (name_str.equals("sort") && sort != null) {
2224 option_element.setAttribute(StaticStrings.VALUE_ATTRIBUTE, sort);
2225 }
2226 else if(name_str.equals("buttonname") && (buttonname == "" || buttonname == null)) {
2227 // No buttonname has been specified. Lets create one using the metadata as its value
2228 Element option = new_cfg_doc.createElement(StaticStrings.OPTION_STR);
2229 option.setAttribute(StaticStrings.NAME_ATTRIBUTE, "buttonname");
2230 option_element.setAttribute(StaticStrings.VALUE_ATTRIBUTE, metadata);
2231 classifier_element.appendChild(option);
2232 }
2233 }
2234 }
2235 }
2236
2237 private void updateCollectionCFG(File base_cfg, File new_cfg, String description, String email, String title)
2238 {
2239 boolean first_name = true;
2240 boolean first_extra = true;
2241
2242 // Now read in base_cfg line by line, parsing important onces and/or replacing them with information pertinent to our collection. Each line is then written back out to the new collect.cfg file.
2243 try {
2244 BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(base_cfg), "UTF-8"));
2245 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new_cfg), "UTF-8"));
2246 String command = null;
2247 while((command = in.readLine()) != null) {
2248 if (command.length()==0) {
2249 // output a new line
2250 out.newLine();
2251 continue;
2252 }
2253 // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat.
2254 while(command.trim().endsWith("\\")) {
2255 command = command.substring(0, command.lastIndexOf("\\"));
2256 String next_line = in.readLine();
2257 if(next_line != null) {
2258 command = command + next_line;
2259 }
2260 }
2261 // commands can extend over more than one line so use the CommandTokenizer which takes care of that
2262 CommandTokenizer tokenizer = new CommandTokenizer(command, in, false);
2263 String command_type_str = tokenizer.nextToken().toLowerCase();
2264
2265 if (command_type_str.equals(StaticStrings.COLLECTIONMETADATA_STR)) {
2266 // read the whole thing in, but for collectionname, collectionextra, iconcollection, iconcollectionsmall we will ignore them
2267 StringBuffer new_command = new StringBuffer(command_type_str);
2268 String meta_name = tokenizer.nextToken();
2269 new_command.append(' ');
2270 new_command.append(meta_name);
2271 while (tokenizer.hasMoreTokens()) {
2272 new_command.append(' ');
2273 new_command.append(tokenizer.nextToken());
2274 }
2275 if (meta_name.equals(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR) || meta_name.equals(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR) || meta_name.equals(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR) || meta_name.equals(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR)) {
2276 // dont save
2277 } else {
2278 write(out, new_command.toString());
2279 }
2280 new_command = null;
2281 continue;
2282 } // if collectionmeta
2283
2284 if (command_type_str.equals("classify")) {
2285 StringBuffer text = new StringBuffer(command_type_str);
2286 // Read in the classifier command watching for hfile, metadata and sort arguments.
2287 String buttonname = null;
2288 String hfile = null;
2289 String new_metadata = null;
2290 String old_metadata = null;
2291
2292 while(tokenizer.hasMoreTokens()) {
2293 String token = tokenizer.nextToken();
2294 if (token.equals("-hfile")) {
2295 if(tokenizer.hasMoreTokens()) {
2296 text.append(" ");
2297 text.append(token);
2298 token = tokenizer.nextToken();
2299 hfile = token;
2300 }
2301 }
2302 else if (token.equals("-metadata")) {
2303 if(tokenizer.hasMoreTokens()) {
2304 text.append(" ");
2305 text.append(token);
2306 String temp_metadata = tokenizer.nextToken();
2307 String replacement = ProfileXMLFileManager.getMetadataElementFor(temp_metadata);
2308 if (replacement != null && !replacement.equals("")) {
2309 token = replacement;
2310 old_metadata = temp_metadata;
2311 new_metadata = replacement;
2312 }
2313 else {
2314 token = temp_metadata;
2315 }
2316 temp_metadata = null;
2317 replacement = null;
2318 }
2319 }
2320 else if (token.equals("-sort")) {
2321 if(tokenizer.hasMoreTokens()) {
2322 text.append(" ");
2323 text.append(token);
2324 String temp_metadata = tokenizer.nextToken();
2325 String replacement = ProfileXMLFileManager.getMetadataElementFor(temp_metadata);
2326 if (replacement != null && !replacement.equals("")) {
2327 token = replacement;
2328 }
2329 else {
2330 token = temp_metadata;
2331 }
2332 temp_metadata = null;
2333 replacement = null;
2334 }
2335 }
2336 else if(token.equals("-buttonname")) {
2337 buttonname = token;
2338 }
2339 text.append(' ');
2340 text.append(token);
2341 token = null;
2342 }
2343
2344 // If we replaced the metadata argument and didn't encounter a buttonname, then add one now pointing back to the old metadata name in order to accomodate macro files which required such names (buttonname is metadata name by default)!
2345 if(old_metadata != null && new_metadata != null && buttonname == null) {
2346 text.append(' ');
2347 text.append("-buttonname");
2348 text.append(' ');
2349 text.append(old_metadata);
2350 }
2351 command = text.toString();
2352 // Replace the hfile if we found it
2353 if(hfile != null && new_metadata != null) {
2354 command = command.replaceAll(hfile, new_metadata + ".txt");
2355 }
2356
2357 buttonname = null;
2358 hfile = null;
2359 new_metadata = null;
2360 old_metadata = null;
2361 write(out, command);
2362 } else {
2363 // the rest of the commands just want a string - we read in all the tokens from the tokeniser and get rid of it.
2364 StringBuffer new_command = new StringBuffer(command_type_str);
2365 while (tokenizer.hasMoreTokens()) {
2366 new_command.append(' ');
2367 new_command.append(tokenizer.nextToken());
2368 }
2369
2370 command = new_command.toString();
2371
2372 // There is still one special case, that of the format command. In such a command we have to search for [<target>] to ensure we don't change parts of the format which have nothing to do with the metadata elements.
2373 // we really want to build up the whole command here
2374 boolean format_command = command_type_str.equals("format");
2375 HashMap metadata_mapping = ProfileXMLFileManager.getMetadataMapping();
2376 if (metadata_mapping != null) {
2377 Iterator keys = metadata_mapping.keySet().iterator();
2378 while (keys.hasNext()) {
2379 String target = (String) keys.next();
2380 String replacement = (String) metadata_mapping.get(target);
2381 if (replacement != null && !replacement.equals("")) {
2382 if (format_command) {
2383 target = "\\[" + target + "\\]";
2384 replacement = "{Or}{[" + replacement + "]," + target + "}";
2385 }
2386 command = command.replaceAll(target, replacement);
2387 }
2388 }
2389 }
2390
2391 write(out, command);
2392 }
2393 tokenizer = null;
2394 }
2395 in.close();
2396 in = null;
2397 out.flush();
2398 out.close();
2399 out = null;
2400 }
2401 catch(Exception error) {
2402 DebugStream.printStackTrace(error);
2403 }
2404 // All done, I hope.
2405 }
2406
2407 private void write(BufferedWriter out, String message)
2408 throws Exception {
2409 out.write(message, 0, message.length());
2410 out.newLine();
2411 }
2412
2413
2414 /** The CollectionManager class is getting too confusing by half so I'll implement this TreeModelListener in a private class to make responsibility clear. */
2415 private class FMTreeModelListener
2416 implements TreeModelListener {
2417 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
2418 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
2419 */
2420 public void treeNodesChanged(TreeModelEvent event) {
2421 if(collection != null) {
2422 collection.setSaved(false);
2423 collection.setFilesChanged(true);
2424 }
2425 }
2426 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
2427 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
2428 */
2429 public void treeNodesInserted(TreeModelEvent event) {
2430 if(collection != null) {
2431 collection.setSaved(false);
2432 collection.setFilesChanged(true);
2433 }
2434 }
2435 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
2436 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
2437 */
2438 public void treeNodesRemoved(TreeModelEvent event) {
2439 if(collection != null) {
2440 collection.setSaved(false);
2441 collection.setFilesChanged(true);
2442
2443 }
2444 }
2445 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
2446 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
2447 */
2448 public void treeStructureChanged(TreeModelEvent event) {
2449 if(collection != null) {
2450 collection.setSaved(false);
2451 }
2452 }
2453 }
2454}
Note: See TracBrowser for help on using the repository browser.