View Javadoc

1   /*
2    * Fsgrep is a simple Java application which allows a user to
3    * search all files in a directory structure for lines matching
4    * a given pattern.  Its functionality is a combination of the
5    * Unix 'find' and 'grep' utilities.
6    * Visit [http://fsgrep.sourceforge.net/] for more information.
7    * 
8    * Copyright (C) 2003-2006 Murali Krishnan [murali_ca_us@users.sourceforge.net]
9    * 
10   * Fsgrep is free software; you can redistribute it and/or modify
11   * it under the terms of version 2 of the GNU General Public
12   * License as published by the Free Software Foundation.
13   * 
14   * Fsgrep is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public License
20   * along with Fsgrep (see the file named LICENSE.txt); if not, write
21   * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22   * Boston, MA  02111-1307  USA
23   */
24  
25  package mk.fsgrep.util;
26  
27  
28  import java.io.*;
29  import java.util.*;
30  import java.util.regex.*;
31  
32  import mk.fsgrep.util.output.OutputDestination;
33  
34  
35  /***
36   * A utility for launching an external editor on a match file.
37   * 
38   * @author  Murali Krishnan
39   *
40   */
41  public abstract class ExternalEditor {
42  
43      //------------------------------------------------------------
44      //- Class Variables
45  
46      protected static ExternalEditor _instance = null;
47  
48      protected static ExternalEditor UNDEFINED = new Undefined();
49  
50      public static final String PERSISTENT_MAP_KEY = "external_editor";
51  
52      private static final PersistentData pdata = PersistentData.getInstance();
53  
54      public static final Pattern RE_FILE_NAME = Pattern.compile("%f");
55      public static final Pattern RE_LINE_NUM = Pattern.compile("%n");
56      public static final Pattern P_BACKSLASH = Pattern.compile("////");
57      public static final Pattern P_DOLLAR = Pattern.compile("//$");
58  
59  
60      //------------------------------------------------------------
61      //- Class Functions
62  
63      public static synchronized ExternalEditor getInstance() {
64          ExternalEditor result = UNDEFINED;
65  
66          if (_instance == null) {
67              String definition = lookupDefinition();
68              if (!"".equals(definition)) {
69                  _instance = new Defined(definition);
70                  result = _instance;
71              }
72          } else {
73              result = _instance;
74          }
75  
76          return result;
77      }
78  
79  
80      public static void reset() {
81          _instance = null;
82      }
83  
84  
85      protected static String lookupDefinition() {
86          String result = "";  // Pessimistic.
87  
88          String candidate = pdata.getProperty(PERSISTENT_MAP_KEY);
89          if ((candidate != null)) {
90              result = candidate;
91          }
92  
93          return result;
94      }
95  
96  
97      protected static String[] createCmdArray(String cmd) {
98          List<String> list = new ArrayList<String>();
99  //         StringTokenizer tokenizer = new StringTokenizer(cmd, " ");
100 //         while (tokenizer.hasMoreTokens()) {
101 //             list.add(tokenizer.nextToken());
102 //         }
103         boolean inDouble = false;
104         boolean inSingle = false;
105         StringBuffer buffer = new StringBuffer();
106         char[] charray = cmd.toCharArray();
107         for (char ch : charray) {
108             if (inDouble) {
109                 if (ch == '\"') {
110                     inDouble = false;
111                 } else {
112                     buffer.append(ch);
113                 }
114             } else if (inSingle) {
115                 if (ch == '\'') {
116                     inSingle = false;
117                 } else {
118                     buffer.append(ch);
119                 }
120             } else {
121                 if (ch == '\"') {
122                     inDouble = true;
123                 } else if (ch == '\'') {
124                     inSingle = true;
125                 } else if (Character.isWhitespace(ch)) {
126                     if (buffer.length() > 0) {
127                         list.add(buffer.toString());
128                         buffer.delete(0, buffer.length());
129                     }
130                 } else {
131                     buffer.append(ch);
132                 }
133             }
134         }
135 
136         if (buffer.length() > 0) {
137             list.add(buffer.toString());
138         }
139 
140         String[] result = list.toArray(new String[0]);
141 
142         return result;
143     }
144 
145 
146     //------------------------------------------------------------
147     //- Instance Variables
148 
149     private String _spec = "";
150 
151 
152     //------------------------------------------------------------
153     //- Constructors
154 
155     ExternalEditor(String string) {
156         _spec = string;
157     }
158 
159 
160     //------------------------------------------------------------
161     //- Accessors
162 
163     protected String getSpec() {return _spec;}
164 
165 
166     //------------------------------------------------------------
167     //- Settors
168 
169 
170 
171     //------------------------------------------------------------
172     //- Private/Protected Utility Functions
173 
174     protected String createCommand(String filename, String linenum) {
175         String result = getSpec();
176 
177         // If the filename pattern occurs in the spec, then replace it with
178         // the filename.  Otherwise append the filename.
179         Matcher matcher = RE_FILE_NAME.matcher(getSpec());
180         if (matcher.find()) {
181             // Note that the replacement string processes '\' and '$', so
182             // these must be escaped.
183             String processed = P_BACKSLASH.matcher(filename).replaceAll("////////");
184             processed = P_DOLLAR.matcher(processed).replaceAll("//////$");
185             result = matcher.replaceAll(processed);
186         } else {
187             result += " " + filename;
188         }
189 
190         // Replace the linenumber pattern with the linenumber.
191         result = RE_LINE_NUM.matcher(result).replaceAll(linenum);
192 
193         return result;
194     }
195 
196 
197     //------------------------------------------------------------
198     //- Public Interface Functions
199 
200     public String toString() {
201         String result = "ExternalEditor[" + (isDefined()?getSpec():"UNDEFINED") + "]";
202 
203         return result;
204     }
205 
206 
207     public void launch(String filename, String linenum, OutputDestination pStatus, OutputDestination pError) {
208         System.err.println("Launch capability is undefined.");
209     }
210 
211 
212     //------------------------------------------------------------
213     //- Class Interface Functions
214 
215     public boolean isDefined() {return true;}
216 
217 
218     //------------------------------------------------------------
219     //- Inner Classes
220 
221     static class Undefined extends ExternalEditor {
222         Undefined() {super("");}
223         public boolean isDefined() {return false;}
224     }
225 
226     static class Defined extends ExternalEditor {
227         Defined(String string) {super(string);}
228 
229 
230         public void launch(String filename, String linenum, OutputDestination pStatus, OutputDestination pError) {
231             String cmd = createCommand(filename, linenum);
232             String[] cmdarray = createCmdArray(cmd);
233             // for (int i = 0; i < cmdarray.length; i++) {
234             //     String arg = cmdarray[i];
235             //     System.out.println("[" + arg + "]");
236             // }
237             pStatus.print("Launching [" + cmd + "]");
238             Runtime runtime = Runtime.getRuntime();
239             try {
240                 //noinspection UnusedDeclaration
241                 Process process = runtime.exec(cmdarray);
242                 // process.waitFor();
243             } catch (IOException ioe) {
244                 System.err.println("Could not exec [" + cmd + "].");
245                 ioe.printStackTrace();
246                 pError.print("Could not exec:\n" + cmd);
247             }
248         }
249     }
250 
251 
252     //------------------------------------------------------------
253     //- Main
254 
255 
256 
257 }