source: main/trunk/gli/src/org/greenstone/gatherer/file/FileAssociationManager.java@ 37688

Last change on this file since 37688 was 37688, checked in by anupama, 12 months ago

Some improvements to comments that don't belong with upcoming commits

  • Property svn:keywords set to Author Date Id Revision
File size: 14.0 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.file;
28
29import java.io.*;
30import java.util.regex.*;
31import javax.swing.table.*;
32import org.greenstone.gatherer.Gatherer;
33import org.greenstone.gatherer.Configuration;
34import org.greenstone.gatherer.DebugStream;
35import org.greenstone.gatherer.Dictionary;
36import org.greenstone.gatherer.gui.FileAssociationDialog;
37import org.greenstone.gatherer.gui.PreviewCommandDialog;
38import org.greenstone.gatherer.util.SafeProcess;
39import org.greenstone.gatherer.util.StaticStrings;
40import org.greenstone.gatherer.util.Utility;
41import org.greenstone.gatherer.util.XMLTools;
42import org.w3c.dom.*;
43
44public class FileAssociationManager
45 extends AbstractTableModel {
46 static final public String FILENAME_ARG = "%1";
47 static final private String ESCAPE = "\\\\"; // '\'
48 static final private String ESCAPED_ESCAPE = "\\\\\\\\"; // '\\'
49 static final private String SPACE = " ";
50 static final private String ESCAPED_SPACE = "\\\\ ";
51 private Element associations_element;
52 private File data_file;
53
54 public FileAssociationManager() {
55 // Retrieve the associations_element from the config
56 associations_element = Configuration.getFileAssociations();
57 // Initialize the associations. This involves looking through all current associations searching for those with a command of "".
58 if(associations_element != null) {
59 NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
60 for(int i = 0; i < entries.getLength(); i++) {
61 Element entry = (Element) entries.item(i);
62 String command = XMLTools.getValue(entry);
63 // If we encounter a command of ""...
64 if(command.length() == 0) {
65 // if we are on windows, we default to the start command
66 if(Utility.isWindows()) {
67 if (Utility.isWindows9x()) {
68 XMLTools.setValue(entry, StaticStrings.WIN_9X_OPEN_COMMAND);
69 } else {
70 XMLTools.setValue(entry, StaticStrings.WIN_OPEN_COMMAND);
71 }
72 }
73 // and if we are on mac, we default to the open program
74 else if(Utility.isMac()) {
75 XMLTools.setValue(entry, StaticStrings.MAC_OPEN_COMMAND);
76 }
77 else { // On Linux, we need to discover which of a range of possible solutions
78 // works on this machine. If any works, we remember and use that choice
79 // for all file extensions for which no file association has been set yet.
80
81 // If we worked out the default linux file open command in a previous
82 // round of the FileAssociationManager loop, use it for the current file
83 // extension also
84
85 if(StaticStrings.LINUX_OPEN_COMMAND != null &&
86 !StaticStrings.LINUX_OPEN_COMMAND.equals("")) {
87
88 XMLTools.setValue(entry, StaticStrings.LINUX_OPEN_COMMAND);
89 } else if(StaticStrings.LINUX_OPEN_COMMAND == null) {
90 // StaticStrings.LINUX_OPEN_COMMAND not set yet: if we never tried to
91 // work out the default linux file launch command yet, then we'll now
92 // test whether any known linux open command is available on this linux.
93
94 // xdg-open comes pre-installed on Ubuntu linux, but not on all linux
95 // https://www.cyberciti.biz/faq/unix-linux-command-to-view-file/
96 // Listing xdg-open 1st as it works on Ubuntu, reducing GLI load time
97 final String[] linux_open_cmds = {"xdg-open", "kde-open", "gnome-open"};
98
99 for(String open_cmd : linux_open_cmds) {
100 Gatherer.ProgramInstalledTest installTest = new Gatherer.ProgramInstalledTest(open_cmd);
101 if(installTest.found()) {
102 System.err.println("*********** Linux file open command " + installTest + " was found to be installed.");
103 StaticStrings.LINUX_OPEN_COMMAND = open_cmd + " %1";
104 XMLTools.setValue(entry, StaticStrings.LINUX_OPEN_COMMAND);
105 break;
106 } else {
107 System.err.println("*********** Linux file open command " + installTest + " was not installed.");
108 }
109 }
110
111 // either we have a default linux open command or not
112 // If we don't, set it to empty, so we don't try working out
113 // the linux open command value for each file extension (for
114 // each iteration of the FileAssociationManager loop) hereafter.
115 if(StaticStrings.LINUX_OPEN_COMMAND == null) {
116 StaticStrings.LINUX_OPEN_COMMAND = "";
117 }
118 }
119 // else StaticStrings.LINUX_OPEN_COMMAND = ""; which means at some point
120 // we'd tried but failed to work out a feasible file open command for this linux
121 }
122 }
123 command = null;
124 entry = null;
125 }
126 entries = null;
127 }
128 else {
129 DebugStream.println("Didn't parse anything. About to crash.");
130 }
131 }
132
133 public void edit() {
134 FileAssociationDialog dialog = new FileAssociationDialog(this);
135 dialog.display(null);
136 dialog = null;
137 }
138
139 public String getBrowserCommand(String url) {
140 DebugStream.println("Get browser command: " + url);
141 // First off we try to retrieve one from the configuration
142 String command = Configuration.getPreviewCommand();
143 // If that worked, substitute in the url and return
144 if(command != null && command.length() > 0) {
145 command = command.replaceAll("%1", url);
146 DebugStream.println("Result = " + command);
147 return command;
148 }
149 command = null;
150 // Failing that we have a guess at a sensible default
151 if(Utility.isWindows()) {
152 // we use cmd and start
153 if (Utility.isWindows9x()) {
154 command = StaticStrings.WIN_9X_OPEN_COMMAND;//"command.com /c start \""+url+"\"";
155 } else {
156 command = StaticStrings.WIN_OPEN_COMMAND;//"cmd.exe /c start \"\" \""+url+"\"";
157 }
158 } else if (Utility.isMac()) {
159 command = StaticStrings.MAC_OPEN_COMMAND; // "open %1"
160 } else {
161 // we try to look for a browser
162 String [] browsers = new String [] {"mozilla", "netscape", "firefox"};
163 for (int i=0; i<browsers.length; i++) {
164 if (SafeProcess.isAvailable(browsers[i])) {
165 command = browsers[i]+ " %1";
166 break;
167 }
168 }
169 //if (command == null) { command = StaticStrings.LINUX_OPEN_COMMAND; } // "xdg-open %1"
170 }
171
172 // if we still haven't found something, prompt the user
173 if (command == null) {
174 PreviewCommandDialog dialog = new PreviewCommandDialog();
175 command = dialog.display();
176 dialog.dispose();
177 dialog = null;
178 }
179
180 // Store the result if any
181 if(command != null && !command.equals("")) {
182 Configuration.setPreviewCommand(command);
183 command = command.replaceAll(FILENAME_ARG, url);
184 DebugStream.println("Result = " + command);
185 return command;
186 }
187 // if we haven't got a command by now, we'll never get one
188 DebugStream.println("Result = null");
189 return null;
190
191 }
192
193 public int getColumnCount() {
194 return 2;
195 }
196
197 public String getColumnName(int column) {
198 String name;
199 switch(column) {
200 case 0:
201 name = Dictionary.get("FileAssociationDialog.Table.Extension");
202 break;
203 default:
204 name = Dictionary.get("FileAssociationDialog.Table.Command");
205 }
206 return name;
207 }
208
209 public String [] getCommand(File file) {
210 String command = null;
211 String [] commands = null;
212 if(file.isFile()) {
213 // Determine extension
214 String filename = file.getAbsolutePath();
215 String extension = filename.substring(filename.lastIndexOf(".") + 1);
216 // Try to retrieve a value from cache
217 Element entry = getCommand(extension);
218 if(entry != null) {
219 ///ystem.err.println("Retrieved Value From Cache");
220 command = XMLTools.getValue(entry);
221 }
222 if(command == null || command.length() == 0) {
223 ///ystem.err.println("No Existing Command");
224 // If command is null, and we are on windows try searching the registry.
225 if(Utility.isWindows()) {
226 //try the start command
227 if (Utility.isWindows9x()) {
228 command = StaticStrings.WIN_9X_OPEN_COMMAND;
229 } else {
230 command = StaticStrings.WIN_OPEN_COMMAND;
231 }
232
233 }
234
235 // If we are on a mac, default to using the open program
236 else if(Utility.isMac()) {
237 command = StaticStrings.MAC_OPEN_COMMAND;
238 }
239
240 //else { command = StaticStrings.LINUX_OPEN_COMMAND; } // If linux, default to using xdg-open
241
242 // Otherwise display the dialog and ask the user to enter launching command.
243 if(command == null || command.length() == 0) {
244 ///ystem.err.println("Show Dialog");
245 // Show the dialog which forces a user to select the launch command for a certain file.
246 FileAssociationDialog dialog = new FileAssociationDialog(this);
247 command = dialog.display(extension);
248 dialog = null;
249 }
250
251 // Hopefully by now we have a command, or else we're never going to get one. Add the association.
252 if (command != null && !command.equals("")) {
253 // If no previous entry existed create one.
254 if(entry == null) {
255 entry = associations_element.getOwnerDocument().createElement(StaticStrings.ENTRY_ELEMENT);
256 entry.setAttribute(StaticStrings.EXTENSION_ATTRIBUTE, extension);
257 associations_element.appendChild(entry);
258 }
259 // Replace the text in this node. Remember to replace the dummy filename with %1 - I dont think the filename will ever be in the comand now
260 //XMLTools.setValue(entry, command.replaceAll(filename, FILENAME_ARG));
261 XMLTools.setValue(entry, command);
262 }
263 }
264
265 if (command != null && !command.equals("")) {
266
267 // Make the command into a string []
268 commands = command.split(" ");
269
270 // Now substitute any occurrences of %1 with its filename
271 // Note this is done after the split on spaces to avoid
272 // any conflict with filenames with spaces in them.
273
274 // We have to fix filename under windows to escape the backslashes
275 filename = filename.replaceAll(ESCAPE, ESCAPED_ESCAPE);
276
277 // dealing with spaces in filepath when using start command
278 if(Utility.isWindows() && filename.indexOf(" ") != -1 && command.indexOf("start") != -1) {
279 // On Windows, start command used spaces in filepath. In this case:
280 // start and its arguments all together need to go into one element of the commands array
281 // otherwise <cmd /c start "window title" "%1"> does not work if there are spaces in the
282 // file path %1, when running the Process with a command array.
283
284 // Need <"start \"window\" \"%1\""> to be an element in the command array:
285 String[] tmp = commands;
286 int index = 0;
287
288 for(int i = 0; i < commands.length; i++) {
289 if(commands[i].indexOf("start") != -1) {
290 index = i;
291 }
292 }
293
294 commands = new String[index+1];
295 for(int i = 0; i < index; i++) {
296 commands[i] = tmp[i];
297 }
298
299 commands[index] = tmp[index];
300 for(int i = index+1; i < tmp.length; i++) {
301 commands[index] = commands[index] + " " + tmp[i];
302 }
303
304 }
305
306 for (int i=0; i<commands.length; i++) {
307 // Replace %1 with the appropriate filename
308 commands[i] = commands[i].replaceAll(FILENAME_ARG, filename);
309 }
310 }
311
312 entry = null;
313 extension = null;
314 filename = null;
315 }
316 return commands;
317 }
318
319 public Element getCommand(String target_extension) {
320 NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
321 for(int i = 0; i < entries.getLength(); i++) {
322 Element entry = (Element) entries.item(i);
323 String extension = entry.getAttribute(StaticStrings.EXTENSION_ATTRIBUTE);
324 if(extension.equalsIgnoreCase(target_extension)) {
325 entries = null;
326 extension = null;
327 return entry;
328 }
329 }
330 entries = null;
331 return null;
332 }
333
334 public String getCommandString(String target_extension) {
335 Element entry = getCommand(target_extension);
336 if(entry != null) {
337 return XMLTools.getValue(entry);
338 }
339 else {
340 return "";
341 }
342 }
343
344 public String getExtension(int index) {
345 NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
346 if(0 <= index && index < entries.getLength()) {
347 Element entry = (Element) entries.item(index);
348 return entry.getAttribute(StaticStrings.EXTENSION_ATTRIBUTE);
349 }
350 return "";
351 }
352
353 public int getRowCount() {
354 return size();
355 }
356
357 public Object getValueAt(int row, int column) {
358 String extension = getExtension(row);
359 switch(column) {
360 case 0:
361 return extension;
362 default:
363 return getCommandString(extension);
364 }
365 }
366
367 public void save() {
368 }
369
370 public void setCommand(String extension, String command) {
371 DebugStream.println("Set Launch: " + extension + " with " + command);
372 // Retrieve any existing entry for this extension
373 Element entry = getCommand(extension);
374 // If no previous entry existed create one.
375 if(entry == null && command != null) {
376 entry = associations_element.getOwnerDocument().createElement(StaticStrings.ENTRY_ELEMENT);
377 entry.setAttribute(StaticStrings.EXTENSION_ATTRIBUTE, extension);
378 associations_element.appendChild(entry);
379 }
380
381 if(command != null) {
382 // Replace the text in this node. If the user has used filename instead of %1 then too bad.
383 XMLTools.setValue(entry, command);
384 }
385 else {
386 // Remove the entry
387 associations_element.removeChild(entry);
388 }
389 entry = null;
390 fireTableDataChanged(); // Can't be anymore efficient as DOM does not gareuntee ordering of new child nodes is consistant
391 }
392
393 public int size() {
394 NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
395 return entries.getLength();
396 }
397
398}
Note: See TracBrowser for help on using the repository browser.