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

Last change on this file since 24704 was 24704, checked in by ak19, 13 years ago

Dr Bainbridge found a default Linux file open command (xdg-open). This is now used for file associations when the user has not provided one.

  • Property svn:keywords set to Author Date Id Revision
File size: 11.2 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.Configuration;
33import org.greenstone.gatherer.DebugStream;
34import org.greenstone.gatherer.Dictionary;
35import org.greenstone.gatherer.gui.FileAssociationDialog;
36import org.greenstone.gatherer.gui.PreviewCommandDialog;
37import org.greenstone.gatherer.util.ExternalProgram;
38import org.greenstone.gatherer.util.StaticStrings;
39import org.greenstone.gatherer.util.Utility;
40import org.greenstone.gatherer.util.XMLTools;
41import org.w3c.dom.*;
42
43public class FileAssociationManager
44 extends AbstractTableModel {
45 static final public String FILENAME_ARG = "%1";
46 static final private String ESCAPE = "\\\\"; // '\'
47 static final private String ESCAPED_ESCAPE = "\\\\\\\\"; // '\\'
48 static final private String SPACE = " ";
49 static final private String ESCAPED_SPACE = "\\\\ ";
50 private Element associations_element;
51 private File data_file;
52
53 public FileAssociationManager() {
54 // Retrieve the associations_element from the config
55 associations_element = Configuration.getFileAssociations();
56 // Initialize the associations. This involves looking through all current associations searching for those with a command of "".
57 if(associations_element != null) {
58 NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
59 for(int i = 0; i < entries.getLength(); i++) {
60 Element entry = (Element) entries.item(i);
61 String command = XMLTools.getValue(entry);
62 // If we encounter a command of ""...
63 if(command.length() == 0) {
64 // if we are on windows, we default to the start command
65 if(Utility.isWindows()) {
66 if (Utility.isWindows9x()) {
67 XMLTools.setValue(entry, StaticStrings.WIN_9X_OPEN_COMMAND);
68 } else {
69 XMLTools.setValue(entry, StaticStrings.WIN_OPEN_COMMAND);
70 }
71 }
72 // and if we are on mac, we default to the open program
73 else if(Utility.isMac()) {
74 XMLTools.setValue(entry, StaticStrings.MAC_OPEN_COMMAND);
75 }
76 else { // assume linux?
77 XMLTools.setValue(entry, StaticStrings.LINUX_OPEN_COMMAND);
78 }
79 }
80 command = null;
81 entry = null;
82 }
83 entries = null;
84 }
85 else {
86 DebugStream.println("Didn't parse anything. About to crash.");
87 }
88 }
89
90 public void edit() {
91 FileAssociationDialog dialog = new FileAssociationDialog(this);
92 dialog.display(null);
93 dialog = null;
94 }
95
96 public String getBrowserCommand(String url) {
97 DebugStream.println("Get browser command: " + url);
98 // First off we try to retrieve one from the configuration
99 String command = Configuration.getPreviewCommand();
100 // If that worked, substitute in the url and return
101 if(command != null && command.length() > 0) {
102 command = command.replaceAll("%1", url);
103 DebugStream.println("Result = " + command);
104 return command;
105 }
106 command = null;
107 // Failing that we have a guess at a sensible default
108 if(Utility.isWindows()) {
109 // we use cmd and start
110 if (Utility.isWindows9x()) {
111 command = StaticStrings.WIN_9X_OPEN_COMMAND;//"command.com /c start \""+url+"\"";
112 } else {
113 command = StaticStrings.WIN_OPEN_COMMAND;//"cmd.exe /c start \"\" \""+url+"\"";
114 }
115 } else if (Utility.isMac()) {
116 command = StaticStrings.MAC_OPEN_COMMAND; // "open %1"
117 } else {
118 // we try to look for a browser
119 String [] browsers = new String [] {"mozilla", "netscape"};
120 for (int i=0; i<browsers.length; i++) {
121 if (isAvailable(browsers[i])) {
122 command = browsers[i]+ " %1";
123 break;
124 }
125 }
126 if (command == null) {
127 command = StaticStrings.LINUX_OPEN_COMMAND; // "xdg-open %1"
128 }
129 }
130
131 // if we still haven't found something, prompt the user
132 if (command == null) {
133 PreviewCommandDialog dialog = new PreviewCommandDialog();
134 command = dialog.display();
135 dialog.dispose();
136 dialog = null;
137 }
138
139 // Store the result if any
140 if(command != null && !command.equals("")) {
141 Configuration.setPreviewCommand(command);
142 command = command.replaceAll(FILENAME_ARG, url);
143 DebugStream.println("Result = " + command);
144 return command;
145 }
146 // if we haven't got a command by now, we'll never get one
147 DebugStream.println("Result = null");
148 return null;
149
150 }
151
152 public int getColumnCount() {
153 return 2;
154 }
155
156 public String getColumnName(int column) {
157 String name;
158 switch(column) {
159 case 0:
160 name = Dictionary.get("FileAssociationDialog.Table.Extension");
161 break;
162 default:
163 name = Dictionary.get("FileAssociationDialog.Table.Command");
164 }
165 return name;
166 }
167
168 public String [] getCommand(File file) {
169 String command = null;
170 String [] commands = null;
171 if(file.isFile()) {
172 // Determine extension
173 String filename = file.getAbsolutePath();
174 String extension = filename.substring(filename.lastIndexOf(".") + 1);
175 // Try to retrieve a value from cache
176 Element entry = getCommand(extension);
177 if(entry != null) {
178 ///ystem.err.println("Retrieved Value From Cache");
179 command = XMLTools.getValue(entry);
180 }
181 if(command == null || command.length() == 0) {
182 ///ystem.err.println("No Existing Command");
183 // If command is null, and we are on windows try searching the registry.
184 if(Utility.isWindows()) {
185 //try the start command
186 if (Utility.isWindows9x()) {
187 command = StaticStrings.WIN_9X_OPEN_COMMAND;
188 } else {
189 command = StaticStrings.WIN_OPEN_COMMAND;
190 }
191
192 }
193
194 // If we are on a mac, default to using the open program
195 else if(Utility.isMac()) {
196 command = StaticStrings.MAC_OPEN_COMMAND;
197 }
198
199 else { // If we are on a linux, default to using the xdg-open program
200 command = StaticStrings.LINUX_OPEN_COMMAND;
201 }
202
203 // Otherwise display the dialog and ask the user to enter launching command.
204 if(command == null || command.length() == 0) {
205 ///ystem.err.println("Show Dialog");
206 // Show the dialog which forces a user to select the launch command for a certain file.
207 FileAssociationDialog dialog = new FileAssociationDialog(this);
208 command = dialog.display(extension);
209 dialog = null;
210 }
211
212 // Hopefully by now we have a command, or else we're never going to get one. Add the association.
213 if (command != null && !command.equals("")) {
214 // If no previous entry existed create one.
215 if(entry == null) {
216 entry = associations_element.getOwnerDocument().createElement(StaticStrings.ENTRY_ELEMENT);
217 entry.setAttribute(StaticStrings.EXTENSION_ATTRIBUTE, extension);
218 associations_element.appendChild(entry);
219 }
220 // 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
221 //XMLTools.setValue(entry, command.replaceAll(filename, FILENAME_ARG));
222 XMLTools.setValue(entry, command);
223 }
224 }
225
226 if (command != null && !command.equals("")) {
227 // Make the command into a string []
228 commands = command.split(" ");
229
230 // Now substitute any occurrences of %1 with its filename
231 // Note this is done after the split on spaces to avoid
232 // any conflict with filenames with spaces in them.
233
234 // We have to fix filename under windows to escape the backslashes
235 filename = filename.replaceAll(ESCAPE, ESCAPED_ESCAPE);
236
237 for (int i=0; i<commands.length; i++) {
238 // Replace %1 with the appropriate filename
239 commands[i] = commands[i].replaceAll(FILENAME_ARG, filename);
240 }
241 }
242
243 entry = null;
244 extension = null;
245 filename = null;
246 }
247 return commands;
248 }
249
250 public Element getCommand(String target_extension) {
251 NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
252 for(int i = 0; i < entries.getLength(); i++) {
253 Element entry = (Element) entries.item(i);
254 String extension = entry.getAttribute(StaticStrings.EXTENSION_ATTRIBUTE);
255 if(extension.equalsIgnoreCase(target_extension)) {
256 entries = null;
257 extension = null;
258 return entry;
259 }
260 }
261 entries = null;
262 return null;
263 }
264
265 public String getCommandString(String target_extension) {
266 Element entry = getCommand(target_extension);
267 if(entry != null) {
268 return XMLTools.getValue(entry);
269 }
270 else {
271 return "";
272 }
273 }
274
275 public String getExtension(int index) {
276 NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
277 if(0 <= index && index < entries.getLength()) {
278 Element entry = (Element) entries.item(index);
279 return entry.getAttribute(StaticStrings.EXTENSION_ATTRIBUTE);
280 }
281 return "";
282 }
283
284 public int getRowCount() {
285 return size();
286 }
287
288 public Object getValueAt(int row, int column) {
289 String extension = getExtension(row);
290 switch(column) {
291 case 0:
292 return extension;
293 default:
294 return getCommandString(extension);
295 }
296 }
297
298 public void save() {
299 }
300
301 public void setCommand(String extension, String command) {
302 DebugStream.println("Set Launch: " + extension + " with " + command);
303 // Retrieve any existing entry for this extension
304 Element entry = getCommand(extension);
305 // If no previous entry existed create one.
306 if(entry == null && command != null) {
307 entry = associations_element.getOwnerDocument().createElement(StaticStrings.ENTRY_ELEMENT);
308 entry.setAttribute(StaticStrings.EXTENSION_ATTRIBUTE, extension);
309 associations_element.appendChild(entry);
310 }
311
312 if(command != null) {
313 // Replace the text in this node. If the user has used filename instead of %1 then too bad.
314 XMLTools.setValue(entry, command);
315 }
316 else {
317 // Remove the entry
318 associations_element.removeChild(entry);
319 }
320 entry = null;
321 fireTableDataChanged(); // Can't be anymore efficient as DOM does not gareuntee ordering of new child nodes is consistant
322 }
323
324 public int size() {
325 NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
326 return entries.getLength();
327 }
328
329
330 protected boolean isAvailable(String program) {
331 try {
332 ExternalProgram e = new ExternalProgram("which", program);
333 e.exitProgram();
334 String out = e.getLineOfProgramOutput();
335 if (out == null) {
336 return false;
337 }
338 return true;
339 } catch (Exception exc) {
340 return false;
341 }
342 }
343}
Note: See TracBrowser for help on using the repository browser.