/plugins/InfoViewer/branches/InfoViewer/InfoViewerPlugin.java

# · Java · 432 lines · 295 code · 53 blank · 84 comment · 49 complexity · 86938624cb4a0748e91077606025ffa9 MD5 · raw file

  1. /*
  2. * InfoViewerPlugin.java - an info viewer plugin for jEdit
  3. * Copyright (C) 1999 Dirk Moebius
  4. * based on the original jEdit HelpViewer by Slava Pestov.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. import infoviewer.InfoViewer;
  21. import java.awt.*;
  22. import java.awt.event.ActionEvent;
  23. import java.lang.reflect.*;
  24. import java.io.IOException;
  25. import java.net.URL;
  26. import java.util.Vector;
  27. import javax.swing.*;
  28. import org.gjt.sp.jedit.*;
  29. import org.gjt.sp.jedit.gui.OptionsDialog;
  30. import org.gjt.sp.jedit.msg.ViewURL;
  31. import org.gjt.sp.util.Log;
  32. public class InfoViewerPlugin extends EBPlugin {
  33. /** the shared InfoViewer instance */
  34. private static InfoViewer infoviewer = null;
  35. // begin EditPlugin implementation
  36. public void start() {
  37. jEdit.addAction(new infoviewer_open());
  38. jEdit.addAction(new infoviewer_open_buffer());
  39. jEdit.addAction(new infoviewer_open_sel());
  40. }
  41. public void createMenuItems(View view, Vector menus, Vector menuItems) {
  42. menus.addElement(GUIUtilities.loadMenu(view, "infoviewer-menu"));
  43. }
  44. public void createOptionPanes(OptionsDialog optionsDialog) {
  45. optionsDialog.addOptionPane(new infoviewer.InfoViewerOptionPane());
  46. }
  47. // end EditPlugin implementation
  48. // begin EBPlugin implementation
  49. /**
  50. * handle messages from the EditBus. InfoViewer reacts to messages of
  51. * type ViewURL. If it sees such a message, it will veto() it, so that
  52. * the sender knows that it was seen.
  53. * @param message the EditBus message
  54. * @see org.gjt.sp.jedit.msg.ViewURL
  55. * @see org.gjt.sp.jedit.EBMessage#veto()
  56. */
  57. public void handleMessage(EBMessage message) {
  58. if (message instanceof ViewURL) {
  59. ViewURL vu = (ViewURL) message;
  60. // TODO: only veto, if InfoViewer understands the URL protocol!
  61. vu.veto();
  62. showURL(vu.getURL());
  63. }
  64. }
  65. // end EBPlugin implementation
  66. /**
  67. * this function demonstrates how ViewURL messages should be send on
  68. * the EditBus.
  69. * @param url an URL that should be displayed in InfoViewer
  70. * @param view a View from which the message is sent
  71. */
  72. protected void sendURL(URL url, View view) {
  73. // create a new ViewURL message with 'this' as source and the
  74. // current view.
  75. ViewURL vu = new ViewURL(this, view, url);
  76. // send the message on the EditBus
  77. EditBus.send(vu);
  78. // check if the message was heard by some other component. If it
  79. // was veto()ed, the message was heard, otherwise no component on
  80. // the EditBus listened for this message.
  81. // (This is not really necessary *here* because this *is* the
  82. // InfoViewer, that sends itself a message, but I put it here for
  83. // demonstrational purposes.)
  84. if (!vu.isVetoed()) {
  85. // no EditBus component listened for this message. Show an
  86. // error:
  87. GUIUtilities.error(view, "infoviewer.error.noinfoviewer", null);
  88. return;
  89. }
  90. }
  91. private void showURL(URL url) {
  92. String u = (url==null ? "" : url.toString());
  93. String browsertype = jEdit.getProperty("infoviewer.browsertype");
  94. if (u.startsWith("jeditresource:")) {
  95. browsertype = "internal";
  96. }
  97. Log.log(Log.DEBUG, this, "showURL (" + browsertype + "): " + u);
  98. if ("external".equals(browsertype)) {
  99. // use external browser:
  100. String cmd = jEdit.getProperty("infoviewer.otherBrowser");
  101. String[] args = convertCommandString(cmd, u);
  102. try {
  103. Runtime.getRuntime().exec(args);
  104. }
  105. catch(Exception ex) {
  106. GUIUtilities.error(null, "infoviewer.error.invokeBrowser",
  107. new Object[] { ex, args.toString() });
  108. return;
  109. }
  110. } else if ("class".equals(browsertype)) {
  111. // use class + method
  112. String clazzname = jEdit.getProperty("infoviewer.class");
  113. String methodname = jEdit.getProperty("infoviewer.method");
  114. showURLWithMethod(u, clazzname, methodname);
  115. } else if ("netscape".equals(browsertype)) {
  116. String[] args = new String[3];
  117. args[0] = "sh";
  118. args[1] = "-c";
  119. args[2] = "netscape -remote openURL\\(\'" + convertURL(u) + "\'\\)"
  120. + " || netscape \'" + convertURL(u) + "\'";
  121. try {
  122. Runtime.getRuntime().exec(args);
  123. }
  124. catch(Exception ex) {
  125. GUIUtilities.error(null,"infoviewer.error.invokeBrowser",
  126. new Object[] { ex, args.toString() });
  127. }
  128. } else {
  129. // use internal InfoViewer browser:
  130. if (infoviewer == null) {
  131. infoviewer = new InfoViewer();
  132. }
  133. infoviewer.setVisible(true);
  134. infoviewer.gotoURL(url, true);
  135. }
  136. }
  137. /**
  138. * converts the command string, which may contain "$u" as placeholders
  139. * for an url, into an array of strings, tokenized at the space char.
  140. * Characters in the command string may be escaped with '\\', which
  141. * in the case of space prevents tokenization.
  142. * @param command the command string.
  143. * @param url the URL. Spaces in the URL are converted to "%20".
  144. * @return the space separated parts of the command string, as array
  145. * of Strings.
  146. */
  147. private String[] convertCommandString(String command, String url) {
  148. String convURL = convertURL(url);
  149. Vector args = new Vector();
  150. StringBuffer buf = new StringBuffer();
  151. for (int i = 0; i < command.length(); i++) {
  152. char c = command.charAt(i);
  153. switch (c) {
  154. case '$':
  155. if (i == command.length() - 1)
  156. buf.append(c);
  157. else {
  158. char c2 = command.charAt(++i);
  159. switch (c2) {
  160. case 'u':
  161. buf.append(convURL);
  162. break;
  163. default:
  164. buf.append(c2);
  165. break;
  166. }
  167. }
  168. break;
  169. case ' ':
  170. args.addElement(buf.toString());
  171. buf = new StringBuffer();
  172. break;
  173. case '\\': // quote char
  174. if (i == command.length() - 1)
  175. buf.append(c);
  176. else
  177. buf.append(command.charAt(++i));
  178. break;
  179. default:
  180. buf.append(c);
  181. break;
  182. }
  183. }
  184. args.addElement(buf.toString());
  185. String[] result = new String[args.size()];
  186. args.copyInto(result);
  187. return result;
  188. }
  189. /**
  190. * returns a new copy of the URL string, where the spaces are converted
  191. * to "%20".
  192. */
  193. private String convertURL(String url) {
  194. StringBuffer buf = new StringBuffer();
  195. char c;
  196. for (int i = 0; i < url.length(); i++)
  197. if ((c = url.charAt(i)) == ' ')
  198. buf.append("%20");
  199. else
  200. buf.append(c);
  201. return buf.toString();
  202. }
  203. private void showURLWithMethod(String url, String clazz, String method) {
  204. Class c = null;
  205. Object obj = null;
  206. try {
  207. c = Class.forName(clazz);
  208. }
  209. catch (Throwable e) {
  210. GUIUtilities.error(null, "infoviewer.error.classnotfound",
  211. new Object[] {clazz} );
  212. return;
  213. }
  214. if (method == null) {
  215. // no method: try to find URL or String or empty constructor
  216. Constructor constr = null;
  217. try {
  218. constr = c.getConstructor(new Class[] {URL.class} );
  219. obj = constr.newInstance(new Object[] { new URL(url)} );
  220. }
  221. catch(Exception ex) {
  222. Log.log(Log.DEBUG, this, ex);
  223. }
  224. if (obj == null) {
  225. try {
  226. constr = c.getConstructor(new Class[] {String.class} );
  227. obj = constr.newInstance(new Object[] { url} );
  228. }
  229. catch(Exception ex) {
  230. Log.log(Log.DEBUG, this, ex);
  231. }
  232. }
  233. if (obj == null) {
  234. try {
  235. constr = c.getConstructor(new Class[0]);
  236. obj = constr.newInstance(new Object[0]);
  237. }
  238. catch(Exception ex) {
  239. Log.log(Log.DEBUG, this, ex);
  240. }
  241. }
  242. if (obj == null) {
  243. GUIUtilities.error(null, "infoviewer.error.classnotfound",
  244. new Object[] {clazz} );
  245. return;
  246. }
  247. } else {
  248. // there is a method name:
  249. Method meth = null;
  250. boolean ok = false;
  251. try {
  252. meth = c.getDeclaredMethod(method, new Class[] {URL.class} );
  253. obj = meth.invoke(null, new Object[] { new URL(url)} );
  254. ok = true;
  255. }
  256. catch(Exception ex) {
  257. Log.log(Log.DEBUG, this, ex);
  258. }
  259. if (!ok) {
  260. try {
  261. meth = c.getDeclaredMethod(method, new Class[] {String.class} );
  262. obj = meth.invoke(null, new Object[] { url} );
  263. ok = true;
  264. }
  265. catch(Exception ex) {
  266. Log.log(Log.DEBUG, this, ex);
  267. }
  268. }
  269. if (!ok) {
  270. try {
  271. meth = c.getDeclaredMethod(method, new Class[0]);
  272. obj = meth.invoke(null, new Object[0]);
  273. ok = true;
  274. }
  275. catch(Exception ex) {
  276. Log.log(Log.DEBUG, this, ex);
  277. }
  278. }
  279. if (!ok) {
  280. GUIUtilities.error(null, "infoviewer.error.methodnotfound",
  281. new Object[] {clazz, method} );
  282. return;
  283. }
  284. }
  285. if (obj != null) {
  286. if (obj instanceof JComponent) {
  287. JFrame f = new JFrame("Infoviewer JWrapper");
  288. f.getContentPane().add((JComponent)obj);
  289. f.pack();
  290. f.setVisible(true);
  291. } else if (obj instanceof Component) {
  292. Frame f = new Frame("Infoviewer Wrapper");
  293. f.add((Component)obj);
  294. f.pack();
  295. f.setVisible(true);
  296. }
  297. }
  298. }
  299. /**********************************************************************/
  300. /**
  301. * an action for opening the InfoViewer
  302. */
  303. protected class infoviewer_open extends EditAction {
  304. public infoviewer_open() {
  305. super("infoviewer-open");
  306. }
  307. public void actionPerformed(ActionEvent evt) {
  308. // sends a help message to itself
  309. sendURL(null, getView(evt));
  310. }
  311. }
  312. /**********************************************************************/
  313. /**
  314. * an action for opening the current buffer file in the InfoViewer.
  315. */
  316. // stolen from Slava Pestov's HTML plugin, file browser_open_url.java
  317. public class infoviewer_open_buffer extends EditAction {
  318. public infoviewer_open_buffer() {
  319. super("infoviewer-open-buffer");
  320. }
  321. public void actionPerformed(ActionEvent evt) {
  322. View view = getView(evt);
  323. Buffer buffer = view.getBuffer();
  324. if (buffer.isDirty()) {
  325. String[] args = { buffer.getName() };
  326. int result = JOptionPane.showConfirmDialog(view,
  327. jEdit.getProperty("notsaved.message",args),
  328. jEdit.getProperty("notsaved.title"),
  329. JOptionPane.YES_NO_CANCEL_OPTION,
  330. JOptionPane.WARNING_MESSAGE);
  331. if (result == JOptionPane.YES_OPTION) {
  332. buffer.save(view, null);
  333. } else if (result != JOptionPane.NO_OPTION) {
  334. return;
  335. }
  336. }
  337. URL u = buffer.getURL();
  338. if (u == null) {
  339. String bufpath = "file:" + buffer.getPath();
  340. try {
  341. u = new URL(bufpath);
  342. } catch (java.net.MalformedURLException e) {
  343. GUIUtilities.error(view, "infoviewer.error.badurl",
  344. new String[] { bufpath } );
  345. return;
  346. }
  347. }
  348. sendURL(u, getView(evt));
  349. }
  350. }
  351. /**********************************************************************/
  352. /**
  353. * an action for opening the selected URL in the InfoViewer
  354. */
  355. // stolen from Slava Pestov's HTML plugin, file browser_open_sel.java
  356. protected class infoviewer_open_sel extends EditAction {
  357. public infoviewer_open_sel() {
  358. super("infoviewer-open-sel");
  359. }
  360. public void actionPerformed(ActionEvent evt) {
  361. View view = getView(evt);
  362. Buffer buffer = view.getBuffer();
  363. String selection = view.getTextArea().getSelectedText();
  364. if (selection == null) {
  365. GUIUtilities.error(view, "infoviewer.error.noselection", null);
  366. return;
  367. }
  368. URL u;
  369. try {
  370. u = new URL(selection);
  371. } catch (java.net.MalformedURLException e) {
  372. GUIUtilities.error(view, "infoviewer.error.badurl",
  373. new String[] { selection } );
  374. return;
  375. }
  376. sendURL(u, getView(evt));
  377. }
  378. }
  379. }