1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.xmlhammer.gui.util;
22
23 import java.io.BufferedReader;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.PrintStream;
29 import java.net.MalformedURLException;
30 import java.net.URI;
31 import java.util.StringTokenizer;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34
35 import org.apache.log4j.Logger;
36 import org.bounce.util.URIUtils;
37
38 import edu.stanford.ejalbert.BrowserLauncher;
39 import edu.stanford.ejalbert.BrowserLauncherRunner;
40 import edu.stanford.ejalbert.exception.BrowserLaunchingInitializingException;
41 import edu.stanford.ejalbert.exception.UnsupportedOperatingSystemException;
42
43 public class ExternalApplicationLauncher {
44 public static String FILE_PATTERN = "${file}";
45 public static String LINE_PATTERN = "${line}";
46 public static String COLUMN_PATTERN = "${column}";
47
48 private static ExternalApplicationLauncher instance = null;
49 private String extensions = null;
50 private String defaultCommand = null;
51 private String editorCommand = null;
52
53 private ExternalApplicationLauncher() {
54 super();
55 }
56
57 public static ExternalApplicationLauncher getInstance() {
58 if (instance == null) {
59 instance = new ExternalApplicationLauncher();
60 }
61
62 return instance;
63 }
64
65 public void setBrowserExtensions(String extensions) {
66 this.extensions = extensions;
67 }
68
69 public void setDefaultCommand(String command) {
70 defaultCommand = command;
71 }
72
73 public void setEditorCommand(String command) {
74 editorCommand = command;
75 }
76
77 public void open(URI uri, int line, int column) {
78 File file = getFile(uri);
79
80 if (isBrowserExtension(uri) || file == null || defaultCommand == null || defaultCommand.trim().length() == 0) {
81 browse(uri);
82 } else {
83 run(defaultCommand, file, line, column);
84 }
85 }
86
87 public void edit(URI uri, int line, int column) {
88 File file = getFile(uri);
89
90 if (file != null) {
91 if (editorCommand != null && editorCommand.trim().length() > 0) {
92 run(editorCommand, file, line, column);
93 } else {
94 open(uri, line, column);
95 }
96 } else {
97 browse(uri);
98 }
99 }
100
101 public File getFile(URI uri) {
102 File result = null;
103
104 try {
105 result = new File(uri);
106 } catch (Exception e) {
107 }
108
109 return result;
110 }
111
112 public void browse(URI uri) {
113 if (uri != null) {
114 try {
115 BrowserLauncher launcher = new BrowserLauncher(null);
116 BrowserLauncherRunner runner = new BrowserLauncherRunner(launcher, URIUtils.toString(uri), null);
117 Thread launcherThread = new Thread(runner);
118 launcherThread.start();
119 } catch (BrowserLaunchingInitializingException e) {
120 Logger.getLogger("org.xmlhammer.gui.util.ExternalApplicationLauncher").debug(e);
121 } catch (UnsupportedOperatingSystemException e) {
122 Logger.getLogger("org.xmlhammer.gui.util.ExternalApplicationLauncher").debug(e);
123 }
124 }
125 }
126
127 public void run(String command, File file, int line, int column) {
128 String resolvedCommand = replace(command, LINE_PATTERN, ""+Math.max(0,line));;
129 resolvedCommand = replace(resolvedCommand, COLUMN_PATTERN, ""+Math.max(0,column));
130
131 if (resolvedCommand.indexOf(FILE_PATTERN) != -1) {
132 resolvedCommand = replace(resolvedCommand, FILE_PATTERN, file.toString());
133 } else {
134 resolvedCommand = resolvedCommand+" \""+file+"\"";
135 }
136
137 try {
138 Process process = Runtime.getRuntime().exec(resolvedCommand);
139
140 StreamReader errorReader = new StreamReader(process.getErrorStream(), System.err);
141 StreamReader outputReader = new StreamReader(process.getInputStream(), System.out);
142
143
144 errorReader.start();
145 outputReader.start();
146 } catch (MalformedURLException e) {
147 Logger.getLogger("org.xmlhammer.gui.util.ExternalApplicationLauncher").debug(e);
148 } catch (IOException e) {
149 Logger.getLogger("org.xmlhammer.gui.util.ExternalApplicationLauncher").debug(e);
150 }
151 }
152
153 private boolean isBrowserExtension(URI uri) {
154 StringTokenizer tokenizer = new StringTokenizer(extensions, " \t\n\r\f,;|");
155
156 while (tokenizer.hasMoreTokens()) {
157 String extension = tokenizer.nextToken();
158 if (uri.getPath().endsWith(extension)) {
159 return true;
160 }
161 }
162
163 return false;
164 }
165
166 class StreamReader extends Thread {
167 InputStream input = null;
168 PrintStream printer = null;
169
170 public StreamReader(InputStream input, PrintStream printer) {
171 this.input = input;
172 this.printer = printer;
173 }
174
175 public void run() {
176 try {
177 BufferedReader reader = new BufferedReader(
178 new InputStreamReader(input));
179 String line = reader.readLine();
180
181 while (line != null) {
182 printer.println(line);
183 line = reader.readLine();
184 }
185 } catch (IOException e) {
186 Logger.getLogger("org.xmlhammer.gui.util.ExternalApplicationLauncher").debug(e);
187 }
188 }
189 }
190
191 private static String replace(String source, String search, String replacement) {
192 String result = null;
193
194 search = "//Q"+prepareNonRegularExpression(search)+"//E";
195 replacement = prepareNonRegularExpressionReplacement(replacement);
196
197 Pattern pattern = Pattern.compile(search, Pattern.CASE_INSENSITIVE);
198
199 try {
200 Matcher matcher = pattern.matcher(source);
201 result = matcher.replaceAll(replacement);
202 } catch( Exception e) {
203 Logger.getLogger("org.xmlhammer.gui.util.ExternalApplicationLauncher").debug(e);
204 }
205
206 return result;
207 }
208
209 private static String prepareNonRegularExpressionReplacement( String regexp) {
210 StringBuffer result = new StringBuffer( regexp);
211
212 int index = result.indexOf( "//");
213
214 while ( index != -1) {
215 result.replace( index, index+1, "////");
216 index = result.indexOf( "//", index+2);
217 }
218
219 index = result.indexOf( "$");
220
221 while ( index != -1) {
222 result.replace( index, index+1, "//$");
223 index = result.indexOf( "$", index+2);
224 }
225
226 return result.toString();
227 }
228
229 private static String prepareNonRegularExpression( String regexp) {
230 StringBuffer result = new StringBuffer( regexp);
231
232 int index = result.indexOf( "//E");
233
234 while ( index != -1) {
235 result.replace( index, index+2, "//E////E//Q");
236 index = result.indexOf( "//E", index+7);
237 }
238
239
240
241 if ( result.charAt( result.length()-1) == '//') {
242 result.append( "E//////Q");
243 }
244
245 return result.toString();
246 }
247 }