Jext.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
org.jext |
![]() |
![]() |
Jext |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
| Metric | Description | |
|---|---|---|
/*
* 22:13 09/04/2003
*
* Jext.java - A text editor for Java
* Copyright (C) 1999-2003 Romain Guy
* Portions copyright (C) 1998-2000 Slava Pestov
* romain.guy@jext.org
* www.jext.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.jext;
import java.net.*;
import java.lang.reflect.Method;
import java.io.*;
import java.text.*;
import java.util.*;
import java.util.zip.*;
import java.awt.Toolkit;
import java.awt.Window;
import javax.swing.UIManager;
import javax.swing.plaf.metal.MetalLookAndFeel;
import org.gjt.sp.jedit.textarea.DefaultInputHandler;
import org.gjt.sp.jedit.textarea.TextUtilities;
import org.jext.actions.*;
import org.jext.gui.*;
import org.jext.event.JextEvent;
import org.jext.misc.TabSwitcher;
import org.jext.misc.VersionCheck;
import org.jext.oneclick.*;
import org.jext.scripting.dawn.Run;
import org.jext.search.Search;
import org.jext.textarea.*;
import org.jext.xml.OneClickActionsReader;
import org.jext.xml.PyActionsReader;
import org.jext.xml.XPropertiesReader;
import org.python.util.PythonInterpreter;
/**
* Jext is a fully featured, 100% Pure Java, text editor. It
* has been mainly designed for programmers, and provides also
* very useful functions for them (syntax colorization, auto
* indentation...).
* @author Romain Guy
* @version 5.0
*/
public class Jext
{
//////////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC CONSTANTS
//////////////////////////////////////////////////////////////////////////////////////////////
/* If you change any of the final values here, you'll need to recompile every class that uses them.
* So some lost their "final" at some point, but mustn't be modified anyway.
*/
/** Current Jext's release. */
public static String RELEASE = "5.0 <Karsten/Tiger>";
/**
* Last Jext's build number. It's used actually only for plugin dependencies, so
* don't change it for simple bug-fix which don't bump the release number.*/
public static String BUILD = "05.00.01.00";
/** If true, Jext will delete user settings if this release is newer */
public static boolean DELETE_OLD_SETTINGS = true;
/** Debug mode(not final to avoid it being included in other .class files) */
public static boolean DEBUG = false;
/** Available new lines characters */
public static final String[] NEW_LINE = { "\r", "\n", "\r\n" };
/** Settings directory. */
public static final String SETTINGS_DIRECTORY = System.getProperty("user.home") +
File.separator + ".jext" + File.separator;
/** Jext home directory. */
public static final String JEXT_HOME = System.getProperty("user.dir");
/** Jext server base port number. Used to load all Jext instances with only one JVM. **/
public static final int JEXT_SERVER_PORT = 49152;
//////////////////////////////////////////////////////////////////////////////////////////////
// BEGINNING OF STATIC PART
//////////////////////////////////////////////////////////////////////////////////////////////
// STATIC FIELDS
//////////////////////////////////////////////////////////////////////////////////////////////
// modes
public static ArrayList modes;
public static ArrayList modesFileFilters;
// selected language
private static String language = "English";
private static ZipFile languagePack;
private static ArrayList languageEntries;
// GUI option to have, or not flat menus
private static boolean flatMenus = true;
// GUI option to have non highlighted buttons
private static boolean buttonsHighlight = true;
// server socket
private static JextLoader jextLoader;
private static boolean isServerEnabled;
// plugins specific variables
private static ArrayList plugins;
// user properties filename
public static String usrProps;
// the splash screen
private static SplashScreen splash;
// the properties files
private static Properties props, defaultProps;
// contains all the instances of Jext
// this is an object we synchronize on to avoid window being created concurrently or when is not ready
// enough(for instance by JextLoader when we didn't call initProperties() yet).
private static ArrayList instances = new ArrayList(5);
// contains all the actions
private static HashMap actionHash;
// contains all the python actions
private static HashMap pythonActionHash = new HashMap();
// auto check
private static VersionCheck check;
// input handler
private static DefaultInputHandler inputHandler;
// user properties file name
private static final String USER_PROPS = SETTINGS_DIRECTORY + ".jext-props.xml";
// this property(set by loadInSingleJVMInstance), if true, says we must not show
private static boolean runInBg = false;
private static boolean keepInMemory = false;
//the default value found during loading must be stored for the option dialog
private static boolean defaultKeepInMemory = false;
// when the user runs jext -kill, we store this here and go to kill the server(see
// loadInSingleJVMInstance)
private static boolean goingToKill = false;
// the text area we pre-build if running in background, that will be shown when Jext is started
// by the user(so it will be very fast!)
private static JextFrame builtTextArea = null;
//////////////////////////////////////////////////////////////////////////////////////////////
// STATIC METHODS
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns true if highlight buttons should not be highlighted on mouse over.
*/
public static boolean getButtonsHighlight()
{
return buttonsHighlight;
}
/**
* Returns true if menu should be flatened.
*/
public static boolean getFlatMenus()
{
return flatMenus;
}
/**
* Stop the auto check function. We just interrupt the
* <code>Thread</code> and then 'kill' it.
*/
public static void stopAutoCheck()
{
if (check != null)
{
check.interrupt();
check = null;
}
}
/**
* Returns the input handler.
*/
public static DefaultInputHandler getInputHandler()
{
return inputHandler;
}
/**
* Add an action listener to the list.
* @param action The action listener
*/
public static void addAction(MenuAction action)
{
String name = action.getName();
actionHash.put(name, action);
String keyStroke = getProperty(name.concat(".shortcut"));
if (keyStroke != null)
inputHandler.addKeyBinding(keyStroke, action);
}
/**
* Add a python action listener to the list.
* @param name Internal action name
* @param script The python source script
* @param editAction True if this is an edit action
*/
public static void addPythonAction(String name, String script, boolean editAction)
{
PythonAction action;
if (!editAction)
action = new PythonAction(name, script);
else
action = new PythonEditAction(name, script);
pythonActionHash.put(name, action);
String keyStroke = getProperty(name.concat(".shortcut"));
if (keyStroke != null)
inputHandler.addKeyBinding(keyStroke, action);
}
/**
* Returns a named action.
* @param action The action
*/
public static MenuAction getAction(String action)
{
Object o = actionHash.get(action);
if (o == null)
o = pythonActionHash.get(action);
return (MenuAction) o;
}
/**
* Load the action listeners.
*/
private static void initActions()
{
actionHash = new HashMap();
inputHandler = new DefaultInputHandler();
inputHandler.addDefaultKeyBindings();
// Python written actions
loadXMLActions(Jext.class.getResourceAsStream("jext.actions.xml"), "jext.actions.xml");
// native Java actions
addAction(new BeginLine());
addAction(new BoxComment());
addAction(new CompleteWord());
addAction(new CompleteWordAll());
addAction(new CreateTemplate());
addAction(new EndLine());
addAction(new JoinAllLines());
addAction(new JoinLines());
addAction(new LeftIndent());
addAction(new OpenUrl());
addAction(new Print());
// addAction(new RemoveSpaces());
addAction(new RemoveWhitespace());
addAction(new RightIndent());
addAction(new SimpleComment());
addAction(new SimpleUnComment());
addAction(new SpacesToTabs());
addAction(new TabsToSpaces());
addAction(new ToLowerCase());
addAction(new ToUpperCase());
addAction(new WingComment());
addAction(new WordCount());
// init OneClick! actions
addAction(new OneAutoIndent());
// One Click !
loadXMLOneClickActions(Jext.class.getResourceAsStream("jext.oneclickactions.xml"),
"jext.oneclickactions.xml");
// addAction(new OneClickAction("one_paste", "paste"));
// addAction(new OneClickAction("one_reverse_paste", "reverse_paste"));
// addAction(new OneClickAction("one_delete_line", "delete_line"));
// addAction(new OneClickAction("one_join_lines", "join_lines"));
// addAction(new OneClickAction("one_right_indent", "right_indent"));
// addAction(new OneClickAction("one_left_indent", "left_indent"));
// addAction(new OneClickAction("one_simple_comment", "simple_comment"));
// addAction(new OneClickAction("one_simple_uncomment", "simple_uncomment"));
// addAction(new OneClickAction("one_complete_word", "complete_word"));
// key bindings
addJextKeyBindings();
}
/**
* Adds Jext internal key bindings.
*/
private static void addJextKeyBindings()
{
inputHandler.addKeyBinding("CA+UP", new ScrollUp());
inputHandler.addKeyBinding("CA+PAGE_UP", new ScrollPageUp());
inputHandler.addKeyBinding("CA+DOWN", new ScrollDown());
inputHandler.addKeyBinding("CA+PAGE_DOWN", new ScrollPageDown());
inputHandler.addKeyBinding("C+UP", new PrevLineIndent());
inputHandler.addKeyBinding("C+DOWN", new NextLineIndent());
inputHandler.addKeyBinding("ENTER", new IndentOnEnter());
inputHandler.addKeyBinding("TAB", new IndentOnTab());
inputHandler.addKeyBinding("S+TAB", new LeftIndent());
inputHandler.addKeyBinding("C+INSERT", getAction("copy"));
inputHandler.addKeyBinding("S+INSERT", getAction("paste"));
inputHandler.addKeyBinding("CA+LEFT", new CsWord(CsWord.NO_ACTION, TextUtilities.BACKWARD));
inputHandler.addKeyBinding("CA+RIGHT", new CsWord(CsWord.NO_ACTION, TextUtilities.FORWARD));
inputHandler.addKeyBinding("CAS+LEFT", new CsWord(CsWord.SELECT, TextUtilities.BACKWARD));
inputHandler.addKeyBinding("CAS+RIGHT", new CsWord(CsWord.SELECT, TextUtilities.FORWARD));
inputHandler.addKeyBinding("CA+BACK_SPACE", new CsWord(CsWord.DELETE, TextUtilities.BACKWARD));
inputHandler.addKeyBinding("CAS+BACK_SPACE", new CsWord(CsWord.DELETE, TextUtilities.FORWARD));
if (Utilities.JDK_VERSION.charAt(2) >= '4')
{
inputHandler.addKeyBinding("C+PAGE_UP", new TabSwitcher(false));
inputHandler.addKeyBinding("C+PAGE_DOWN", new TabSwitcher(true));
}//end if JRE 1.4 or above
}
/**
* Loads plugins.
*/
private static void initPlugins()
{
plugins = new ArrayList();
loadPlugins(JEXT_HOME + File.separator + "plugins");
loadPlugins(SETTINGS_DIRECTORY + "plugins");
}
/**
* Makes each mode know what plugins to start when it is selected.
*/
public static void assocPluginsToModes()
{
Mode mode;
String modeName;
String pluginModes;
for (int i = 0; i < plugins.size(); i++)
{
Plugin plugin = (Plugin) plugins.get(i);
pluginModes = getProperty("plugin." + plugin.getClass().getName() + ".modes");
if (pluginModes != null)
{
StringTokenizer tok = new StringTokenizer(pluginModes);
while (tok.hasMoreTokens())
{
modeName = tok.nextToken();
mode = getMode(modeName);
mode.addPlugin( plugin);
}
}
}
}
/**
* Loads all plugins in a directory.
* @param directory The directory
*/
public static void loadPlugins(String directory)
{
String[] args = { directory };
System.out.println(getProperty("jar.scanningdir", args));
File file = new File(directory);
if (!(file.exists() || file.isDirectory()))
return;
String[] plugins = file.list();
if (plugins == null)
return;
for (int i = 0; i < plugins.length; i++)
{
String plugin = plugins[i];
if (!plugin.toLowerCase().endsWith(".jar"))
continue;
try
{
new JARClassLoader(directory + File.separator + plugin);
} catch(IOException io) {
String[] args2 = { plugin };
System.err.println(getProperty("jar.error.load", args2));
io.printStackTrace();
}
}
}
/**
* Registers a plugin with the editor. This will also call
* the <code>start()</code> method of the plugin.
*/
public static void addPlugin(Plugin plugin)
{
plugins.add(plugin);
try
{
plugin.start();
} catch (Throwable t) {
System.err.println("#--An exception has occurred while starting plugin:");
t.printStackTrace();
}
if (plugin instanceof SkinFactory)
{
//System.out.println("Added a SkinPlugin named: " + plugin.getClass().getName());
SkinManager.registerSkinFactory((SkinFactory) plugin);
}
}
/**
* Returns a plugin by it's class name.
* @param name The plugin to return
*/
public static Plugin getPlugin(String name)
{
for (int i = 0; i < plugins.size(); i++)
{
Plugin p = (Plugin) plugins.get(i);
if (p.getClass().getName().equalsIgnoreCase(name))
return p;
}
return null;
}
/**
* Returns an array of installed plugins.
*/
public static Plugin[] getPlugins()
{
/*Object[] o = plugins.toArray();
Plugin[] p = new Plugin[o.length];
for (int i = 0; i < o.length; i++)
p[i] = (Plugin) o[i];*/
Plugin[] p = (Plugin[]) plugins.toArray(new Plugin[0]);
return p;
}
/**
* Opens a new window.
* @param args Parameters from command line
*/
public static JextFrame newWindow(String args[])
{
return newWindow(args, true);
}
/**
* Opens a new window.
*/
public static JextFrame newWindow()
{
return newWindow(null, true);
}
/**
* Opens a new window, but eventually does not show it.
* @param args The command line arguments
* @param toShow When true the frame is shown
*/
//Note: until code doesn't need it, better leaving it only for the package.
/*friendly*/ static JextFrame newWindow(String args[], boolean toShow)
{
synchronized (instances)
{
JextFrame window;
if (toShow && builtTextArea != null)
{
if (args != null)
for (int i = 0; i < args.length; i++)
builtTextArea.open(args[i]);
builtTextArea.setVisible(true);
window = builtTextArea;
builtTextArea = null;
} else {
window = new JextFrame(args, toShow);
//if (toShow)
instances.add(window);
}
return window;
}
}
/**
* Returns amount of opened Jext
*/
public static int getWindowsCount()
{
return instances.size();
}
/**
* Notify all instances of Jext and all properties listeners to reload properties.
*/
public static void propertiesChanged()
{
// we send the event to all the listeners available
for (int i = 0; i < instances.size(); i++)
((JextFrame) instances.get(i)).loadProperties();
}
/**
* Notify all instances of Jext but the one which
* saved the file to reload recent menu
* @param The instance which saved a file
*/
public static void recentChanged(JextFrame instance)
{
// we send the event to all the listeners available
JextFrame listener;
for (int i = 0; i < instances.size(); i++)
{
listener = (JextFrame) instances.get(i);
if (listener != instance && listener != null)
listener.reloadRecent();
}
}
/**
* Some external classes may need to notify
* each instance of Jext. XTree does.
* @return A <code>ArrayList</code> containing all instances of Jext
*/
public static ArrayList getInstances()
{
return instances;
}
/**
* Many methods will need to use a <code>Toolkit</code>.
* This method simply avoid to write too many lines of
* code.
* @return The default <code>Toolkit</code>
*/
public static Toolkit getMyToolkit()
{
return Toolkit.getDefaultToolkit();
}
/**
* Jext startup directory is saved during execution.
* @return Jext's startup directory
*/
public static String getHomeDirectory()
{
return JEXT_HOME;
}
/**
* Store the properties on the HD. After having
* set up the properties, we need to store'em
* in a file.
* @deprecated Use <code>saveXMLProps()</code> instead
*/
public static void saveProps()
{
if (usrProps != null)
{
try
{
OutputStream out = new FileOutputStream(usrProps);
props.store(out, "Jext Properties");
out.close();
} catch (IOException io) { }
}
}
/**
* Saves the user's properties to a file using the XML specifications.
* @param description is a <code>String</code> containing a little
* description of the properties file. This String is stored on
* topmost of the user's properties file. Can be set to
* <code>null</code>.
*/
public static void saveXMLProps(String description)
{
saveXMLProps(usrProps, description);
}
/**
* Saves the user's properties to a file using the XML specifications.
* @param userProps is the path to the file in which properties will
* be stored. If it is set to <code>null</code>, properties are not
* saved at all.
* @param description is a <code>String</code> containing a little
* description of the properties file. This String is stored on
* topmost of the user's properties file. Can be set to
* <code>null</code>.
*/
public static void saveXMLProps(String userProps, String description)
{
if (userProps != null)
{
try
{
BufferedWriter out = new BufferedWriter(new FileWriter(userProps));
String _out = new String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
out.write(_out, 0, _out.length());
out.newLine();
_out = new String("<!DOCTYPE xproperties SYSTEM \"xproperties.dtd\" >");
out.write(_out, 0, _out.length());
out.newLine();
_out = "<!-- Last save: " + (new Date()).toString() + " -->";
out.write(_out, 0, _out.length());
out.newLine();
if (description == null)
description = new String("Properties");
description = "<!-- " + description + " -->";
out.write(description, 0, description.length());
out.newLine();
out.newLine();
_out = new String("<xproperties>");
out.write(_out, 0, _out.length());
out.newLine();
setProperty("properties.version", BUILD);
char c = '\0';
StringBuffer buf;
Enumeration k = props.keys();
Enumeration e = props.elements();
for ( ; e.hasMoreElements(); )
{
buf = new StringBuffer(" <property name=\"");
buf.append(k.nextElement());
buf.append("\" value=\"");
String _e = (String) e.nextElement();
for (int i = 0; i < _e.length(); i++)
{
switch(c = _e.charAt(i))
{
case '\\':
buf.append('\\');
buf.append('\\');
break;
case '\'':
buf.append("'");
break;
case '&':
buf.append("&");
break;
case '\"':
buf.append(""");
break;
case '\n':
buf.append('\\');
buf.append('n');
break;
case '\r':
buf.append('\\');
buf.append('r');
break;
default:
buf.append(c);
}
}
buf.append("\" />");
//for (int i = 0; i < buf.length(); i++)
// out.write(buf.charAt(i));
out.write(buf.toString(), 0, buf.length());
out.newLine();
}
_out = new String("</xproperties>");
out.write(_out, 0, _out.length());
out.close();
} catch (IOException io) { }
}
//JARClassLoader.saveDisabledList();
}
/**
* The <code>XPropertiesHandler</code> needs to get Jext's
* <code>Properties</code> object to achieve its purpose.
* @return The current <code>Properties</code> object
*/
public static Properties getProperties()
{
return props;
}
/**
* Load a set of properties from an XML file.
* This method, and not the caller, will search for the translated version of the XML.
* @param in An <code>InputStream</code> is specified to load properties from a JAR file
* @param fileName The XML filename
*/
public static void loadXMLProps(InputStream in, String fileName)
{
XPropertiesReader.read(in, fileName);
}
/**
* Load a set of properties from an XML file.
* It is provided for when the caller already provides the translated file(for instance for the plugin
* translation); in this case toTranslate must be true, otherwise it will be translated the default way.
* @param in An <code>InputStream</code> is specified to load properties from a JAR file
* @param fileName The XML filename
* @since Jext3.2pre1
*/
public static void loadXMLProps(InputStream in, String fileName, boolean toTranslate)
{
XPropertiesReader.read(in, fileName, toTranslate);
}
/**
* Load a set of actions from an XML file.
* @param in An <code>InputStream</code> is specified to load properties from a JAR file
* @param fileName The XML filename
*/
public static void loadXMLActions(InputStream in, String fileName)
{
PyActionsReader.read(in, fileName);
}
/**
* Load a set of actions from an XML file.
* @param in An <code>InputStream</code> is specified to load properties from a JAR file
* @param fileName The XML filename
*/
public static void loadXMLOneClickActions(InputStream in, String fileName)
{
OneClickActionsReader.read(in, fileName);
}
/**
* Returns an input stream corresponding to selected language.
* @param in The default stream
* @param fileName The requested file
*/
public static InputStream getLanguageStream(InputStream in, String fileName)
{
ZipEntry entry;
if (languagePack != null && (entry = languagePackContains(fileName)) != null)
{
try
{
return languagePack.getInputStream(entry);
} catch (IOException ioe) {
return in;
}
} else
return in;
}
// returns a non-null ZipEntry object if current language pack
// contains requested file
public static ZipEntry languagePackContains(String fileName)
{
for (int i = 0; i < languageEntries.size(); i++)
{
ZipEntry entry = (ZipEntry) languageEntries.get(i);
if (entry.getName().equalsIgnoreCase(fileName))
return entry;
}
return null;
}
/**
* Load a set of properties.
* @param in An <code>InputStream</code> is specified to load properties from a JAR file
* @deprecated Maintained only for plugins compliance. Use <code>loadXMLProps()</code>
* instead of this method.
*/
public static void loadProps(InputStream in)
{
try
{
props.load(new BufferedInputStream(in));
in.close();
} catch (IOException ioe) { }
}
/**
* Creates the necessary directories.
*/
public static void initDirectories()
{
File dir = new File(SETTINGS_DIRECTORY);
if (!dir.exists())
{
dir.mkdir();
dir = new File(SETTINGS_DIRECTORY + "plugins" + File.separator);
if (!dir.exists())
dir.mkdir();
dir = new File(SETTINGS_DIRECTORY + "scripts" + File.separator);
if (!dir.exists())
dir.mkdir();
dir = new File(SETTINGS_DIRECTORY + "xinsert" + File.separator);
if (!dir.exists())
dir.mkdir();
}
}
/**
* Init the properties.
*/
public static void initProperties()
{
usrProps = SETTINGS_DIRECTORY + ".jext-props.xml";
defaultProps = props = new Properties();
/////////////////////////////////////////////////////////////////
// DEPRECATED BY THE METHOD loadXMLProps()
/////////////////////////////////////////////////////////////////
// loadProps(Jext.class.getResourceAsStream("jext-gui.keys"));
// loadProps(Jext.class.getResourceAsStream("jext-gui.text"));
// loadProps(Jext.class.getResourceAsStream("jext.props"));
// loadProps(Jext.class.getResourceAsStream("jext.tips"));
/////////////////////////////////////////////////////////////////
// loads specified language pack
File lang = new File(SETTINGS_DIRECTORY + ".lang");
if (lang.exists())
{
try
{
BufferedReader reader = new BufferedReader(new FileReader(lang));
String language = reader.readLine();
reader.close();
if (language != null && !language.equals("English"))
{
File langPack = new File(JEXT_HOME + File.separator + "lang" +
File.separator + language + "_pack.jar");
if (langPack.exists())
{
languagePack = new ZipFile(langPack);
languageEntries = new ArrayList();
Enumeration entries = languagePack.entries();
while (entries.hasMoreElements())
languageEntries.add(entries.nextElement());
setLanguage(language);
} else
lang.delete();
}
} catch (IOException ioe) { }
}
//loadXMLProps(Jext.class.getResourceAsStream("jext.props.xml"), "jext.props.xml");
loadXMLProps(Jext.class.getResourceAsStream("jext-text.props.xml"), "jext-text.props.xml");
loadXMLProps(Jext.class.getResourceAsStream("jext-keys.props.xml"), "jext-keys.props.xml");
loadXMLProps(Jext.class.getResourceAsStream("jext-defs.props.xml"), "jext-defs.props.xml");
loadXMLProps(Jext.class.getResourceAsStream("jext-tips.props.xml"), "jext-tips.props.xml");
Properties pyProps = new Properties();
pyProps.put("python.cachedir", SETTINGS_DIRECTORY + "pythoncache" + File.separator);
PythonInterpreter.initialize(System.getProperties(), pyProps, new String[0]);
initPlugins();
if (usrProps != null)
{
props = new Properties(defaultProps);
try
{
loadXMLProps(new FileInputStream(USER_PROPS), ".jext-props.xml");
if (DELETE_OLD_SETTINGS)
{
String pVersion = getProperty("properties.version");
if (pVersion == null || BUILD.compareTo(pVersion) > 0)
{
File userSettings = new File(USER_PROPS);
if (userSettings.exists())
{
userSettings.delete();
defaultProps = props = new Properties();
//loadXMLProps(Jext.class.getResourceAsStream("jext.props.xml"), "jext.props.xml");
loadXMLProps(Jext.class.getResourceAsStream("jext-text.props.xml"), "jext-text.props.xml");
loadXMLProps(Jext.class.getResourceAsStream("jext-keys.props.xml"), "jext-keys.props.xml");
loadXMLProps(Jext.class.getResourceAsStream("jext-defs.props.xml"), "jext-defs.props.xml");
loadXMLProps(Jext.class.getResourceAsStream("jext-tips.props.xml"), "jext-tips.props.xml");
JARClassLoader.reloadPluginsProperties();
props = new Properties(defaultProps);
}
}
}
} catch (FileNotFoundException fnfe) {
} catch (IOException ioe) { }
}
initModes(); //must be here since the user can change the mode filters.
Search.load();
if (Utilities.JDK_VERSION.charAt(2) >= '4')
{
try
{
Class cl = Class.forName("org.jext.JavaSupport");
Method m = cl.getMethod("initJavaSupport", new Class[0]);
if (m != null)
m.invoke(null, new Object[0]);
} catch (Exception e) { }
}
// Add our protocols to java.net.URL's list
System.getProperties().put("java.protocol.handler.pkgs", "org.jext.protocol|" +
System.getProperty("java.protocol.handler.pkgs", ""));
initActions();
JARClassLoader.initPlugins();
initUI();
sortModes();
assocPluginsToModes();
}
/**
* Sets the current selected language.
* @param lang The label of the language
*/
public static void setLanguage(String lang)
{
language = lang;
}
/**
* Returns current selected language.
*/
public static String getLanguage()
{
return language;
}
/**
* Execute scripts found in user home directory.
*/
public static void executeScripts(JextFrame parent)
{
String dir = SETTINGS_DIRECTORY + "scripts" + File.separator;
String[] scripts = Utilities.getWildCardMatches(dir, "*.jext-script", false);
if (scripts == null)
return;
for (int i = 0; i < scripts.length; i++)
org.jext.scripting.dawn.Run.runScript(dir + scripts[i], parent, false);
scripts = Utilities.getWildCardMatches(dir, "*.py", false);
if (scripts == null)
return;
for (int i = 0; i < scripts.length; i++)
org.jext.scripting.python.Run.runScript(dir + scripts[i], parent);
}
// sort modes alphabetically
private static void sortModes()
{
String[] modeNames = new String[modes.size()];
for (int i = 0; i < modeNames.length; i++)
modeNames[i] = ((Mode) modes.get(i)).getUserModeName();
Arrays.sort(modeNames);
ArrayList v = new ArrayList(modeNames.length);
for (int i = 0; i < modeNames.length; i++)
{
int j = 0;
String name = modeNames[i];
while (!((Mode) modes.get(j)).getUserModeName().equals(name))
{
if (j == modes.size() - 1)
break;
else
j++;
}
v.add(modes.get(j));
}
modes = v;
v = null;
}
// changes some default UI settings such as trees leaf icons or font size and style...
private static void initUI()
{
/*if (getBooleanProperty("useJextTheme"))
MetalLookAndFeel.setCurrentTheme(new JextMetalTheme());*/
SkinManager.applySelectedSkin();
// check if menus are flat or not
flatMenus = getBooleanProperty("flatMenus");
// check if buttons are highlighted or not
buttonsHighlight = getBooleanProperty("buttonsHighlight");
// rollover
JextButton.setRollover(getBooleanProperty("toolbarRollover"));
}
/**
* Initialize syntax colorizing modes.
*/
private static void initModes()
{
StringTokenizer _tok = new StringTokenizer(getProperty("jext.modes"), " ");
Mode _mode;
modes = new ArrayList(_tok.countTokens());
modesFileFilters = new ArrayList(_tok.countTokens());
for ( ; _tok.hasMoreTokens(); )
{
modes.add(_mode = new Mode(_tok.nextToken()));
modesFileFilters.add(new ModeFileFilter(_mode));
}
}
/**
* Returns the mode according to its name.
*/
public static Mode getMode(String modeName)
{
for (int i = 0; i < modes.size(); i++)
{
Mode _mode = (Mode) modes.get(i);
if (_mode.getModeName().equalsIgnoreCase(modeName))
return _mode;
}
return null;
}
/**
* Returns modes list.
*/
public static ArrayList getModes()
{
return modes;
}
/**
* Adds a mode to Jext's syntax colorizing modes list
*/
public static void addMode(Mode mode)
{
modes.add(mode);
modesFileFilters.add(new ModeFileFilter(mode));
}
/**
* Set a property.
* @param name Property's name
* @param value The value to store as <code>name</code>
*/
public static void setProperty(String name, String value)
{
if (name == null || value == null)
return;
props.put(name, value);
}
/**
* Returns true if the property value equals to "on" or "true"
* @param name The name of the property to read
*/
public static boolean getBooleanProperty(String name)
{
String p = getProperty(name);
if (p == null)
return false;
else
return p.equals("on") || p.equals("true");
}
/**
* Returns true if the property value equals to "on" or "true"
* @param name The name of the property to read
*/
public static boolean getBooleanProperty(String name, String def)
{
String p = getProperty(name, def);
if (p == null)
return false;
else
return p.equals("on") || p.equals("true");
}
/**
* If we store properties, we need to read them, too !
* @param name The name of the property to read
* @return The value of the specified property
*/
public static String getProperty(String name)
{
return props.getProperty(name);
}
/**
* Fetches a property, returning the default value if it's not
* defined.
* @param name The property
* @param def The default value
*/
public static final String getProperty(String name, String def)
{
return props.getProperty(name, def);
}
/**
* Returns the property with the specified name, formatting it with
* the <code>java.text.MessageFormat.format()</code> method.
* @param name The property
* @param args The positional parameters
*/
public static final String getProperty(String name, Object[] args)
{
if (name == null)
return null;
if (args == null)
return props.getProperty(name, name);
else
return MessageFormat.format(props.getProperty(name, name), args);
}
/**
* Unsets (clears) a property.
* @param name The property
*/
public static void unsetProperty(String name)
{
if (defaultProps.get(name) != null)
props.put(name, "");
else
props.remove(name);
}
/**
* Exits Jext by closing all the windows. If backgrounding, it doesn't kill the jext server.
* This is synchronized because creating two windows at a time can be problematic.
*/
public static void exit()
{
synchronized (instances)
{
Object[] o = instances.toArray();
for (int i = o.length - 1; i >= 0; i--)
{
JextFrame instance = ((JextFrame) o[i]);
/*if (i == 0)
{
instance.fireJextEvent(JextEvent.KILLING_JEXT);
if (!isRunningBg())
stopPlugins();
} else
instance.fireJextEvent(JextEvent.CLOSE_WINDOW);*/
closeToQuit(instance);
}
/*if (isRunningBg())
{
builtTextArea = newWindow(null, false);
//instances.add(builtTextArea);
} else
finalCleanupBeforeExit();*/
}
}
/**
* Do the final cleanup that must be done at the real end of the session(when closing the server if
* running background server, or after killing the last window if no server is running).
*/
/* friendly*/ static void finalCleanupAndExit() {
//currently it does almost nothing, but it's used.
System.exit(0);
}
/**
* Stop plugins.
*/
/* friendly */ static void stopPlugins() {
Plugin[] plugins = getPlugins();
for (int i = 0; i < plugins.length; i++)
try
{
plugins[i].stop();
} catch (Throwable t) {
System.err.println("#--An exception has occurred while stopping plugin:");
t.printStackTrace();
}
}
/**
* Close a {@link JextFrame} by calling {@link JextFrame#closeToQuit()} and if it it the last window and we are not keeping the server open
* we close Jext completely.
*/
public static void closeToQuit(JextFrame frame) {
closeToQuit(frame,false);
}
//For JextLoader when it's killing Jext
/*friendly*/ static void closeToQuit(JextFrame frame, boolean isKillingServer) {
if (isKillingServer)
runInBg = false;//so when calling closeWindow(frame), which will happen, it will close completely Jext
//and stop plugins.
frame.closeToQuit();
}
public static void closeWindow(JextFrame frame) {
synchronized (instances)
{
if (getWindowsCount() == 1/* && !isRunningBg()*/)
frame.fireJextEvent(JextEvent.KILLING_JEXT);
else
frame.fireJextEvent(JextEvent.CLOSING_WINDOW);
frame.closeWindow();
if (getWindowsCount() == 0)
{
if (!isRunningBg())
stopServer();
Search.save();
if (!isRunningBg())
stopPlugins();
frame.saveConsole();
GUIUtilities.saveGeometry(frame, "jext");
saveXMLProps("Jext v" + Jext.RELEASE + " b" + Jext.BUILD);
//frame.cleanMemory();
frame = null;
System.gc();//this way, the garbage collector should do its work, without any NullPointerEx at all.
if (isRunningBg())
builtTextArea = newWindow(null, false);
else
System.exit(0);
}
}
}
/**
* Returns splash screen
*/
public static SplashScreen getSplashScreen()
{
return splash;
}
/**
* Set the splash screen progress value after
* having checked if it isn't null (in case of a new window).
* @param val The new value
*/
public static void setSplashProgress(int val)
{
if (splash != null)
splash.setProgress(val);
}
/**
* Set the splash screen text value after having checked if it
* isn't null (in case of a new window).
* @param text The new text
*/
public static void setSplashText(String text)
{
if (splash != null)
splash.setText(text);
}
/**
* Kills splash screen
*/
public static void killSplashScreen()
{
if (splash != null)
{
splash.dispose();
splash = null;
}
}
/**
* Stops the Jext server which loads every Jext instance in the same JVM.
*/
public static void stopServer()
{
if (jextLoader != null)
{
jextLoader.stop();
jextLoader = null;
}
}
/**
* Returns true if the server is enabled.
*/
public static boolean isServerEnabled()
{
return isServerEnabled;
}
/**
* Returns true if the backgrounding is enabled.
*/
public static boolean isDefaultKeepInMemory() {
return defaultKeepInMemory;
}
public static void setDefaultKeepInMemory(boolean val) {
defaultKeepInMemory = val;
if (val) //TODO:hack to active it from this session onwards
{
}
}
/**
* Used by security options panel to remember of the server status.
* @param on If true, the server will be runned at next start
*/
public static void setServerEnabled(boolean on)
{
isServerEnabled = on;
}
/**
* Attempts to load Jext in a single JVM instance only. If this instance of
* Jext is the very first to be loaded, then a ServerSocket is opened. Otherwise,
* this instance attemps to connect on to a specific socket port to tell other
* Jext instance to create a new window. This avoids to load on JVM for each
* launch of Jext. Opened port is securised so that no security hole is created.
* @param args The arguments of the new Jext window
*/
public static void loadInSingleJVMInstance(String[] args)
{
try
{
File security = new File(SETTINGS_DIRECTORY + ".security");
if (!security.exists())
isServerEnabled = true;
else
{
BufferedReader reader = new BufferedReader(new FileReader(security));
isServerEnabled = new Boolean(reader.readLine()).booleanValue();
reader.close();
}
} catch (IOException ioe) { }
if (!isServerEnabled && !runInBg)
return;
File authorizationKey = new File(SETTINGS_DIRECTORY + ".auth-key");
// if the authorization key exists, another Jext instance may
// be running
if (authorizationKey.exists())
{
// we attempt to log onto the other instance of Jext(but only if we are not backgrounding; no
// more than one bg instance is started, and if we are bg we don't pass anything to the other instance.
try
{
BufferedReader reader = new BufferedReader(new FileReader(authorizationKey));
int port = Integer.parseInt(reader.readLine());
String key = reader.readLine();
reader.close();
Socket client = new Socket("127.0.0.1", JEXT_SERVER_PORT + port);
if (!runInBg)
{ //now that we made sure that the other instance exists, if backgrounding we do
//nothing
PrintWriter writer = new PrintWriter(client.getOutputStream());
StringBuffer _args = new StringBuffer();
if (goingToKill)
{
_args.append("kill");
} else {
_args.append("load_jext:");
for (int i = 0; i < args.length; i++)
{
_args.append(args[i]);
if (i != args.length - 1)
_args.append('?');
}
}
_args.append(':').append(key);
writer.write(_args.toString());
writer.flush();
writer.close();
} else
System.out.println("Jext is already running, either in background or foreground.");
client.close();
System.exit(5);
} catch (Exception e) {
// no other jext instance is running, we delete the auth. file
authorizationKey.delete();
if (goingToKill) {
System.err.println("No jext instance found!");
System.exit(0);
} else
jextLoader = new JextLoader();
}
} else if (!goingToKill) {
jextLoader = new JextLoader();
} else {
System.err.println("No jext instance found!");
System.exit(0);
}
}
/**
* As Jext can be runned in background mode, some operations may need to know wether
* or not current instance is "up" or "crouched". This is the purpose of this method.
* @return A true boolean value is returned whenever Jext is running in background mode
*/
public static boolean isRunningBg()
{
return runInBg;
}
// check the command line arguments
private static String[] parseOptions(String [] args)
{
// Trap bg flag
int argLn = args.length;
ArrayList newArgs = new ArrayList(argLn);
//First, it checks defaults: if the user actived -showbg by default, read this setting.
try
{
File showbg = new File(SETTINGS_DIRECTORY + ".showBg");
if (!showbg.exists())
keepInMemory = false;
else
{
BufferedReader reader = new BufferedReader(new FileReader(showbg));
keepInMemory = new Boolean(reader.readLine()).booleanValue();
reader.close();
}
} catch (IOException ioe) { }
defaultKeepInMemory = runInBg = keepInMemory;
//Then, let's read options.
for (int i = 0; i < argLn; i++)
{
//Whenever it encounter an option it resets all contrary ones.
if ("-bg".equals(args[i]))
{
runInBg = true;
keepInMemory = false;
goingToKill = false;
}
else if ("-kill".equals(args[i]))
{
goingToKill = true;
keepInMemory = false;
runInBg = false;
}
else if ("-showbg".equals(args[i]))
{
runInBg = true;
keepInMemory = true;
goingToKill = false;
}
//This option is unrelated.
else if ("-debug".equals(args[i]))
DEBUG = true;
else
newArgs.add(args[i]);
}
return (String[]) newArgs.toArray(new String[0]);
}
//////////////////////////////////////////////////////////////////////////////////////////////
// END OF STATIC PART
//////////////////////////////////////////////////////////////////////////////////////////////
// MAIN ENTRY POINT
//////////////////////////////////////////////////////////////////////////////////////////////
/**
* Start method. Load the property file, set the look and feel, create a new GUI,
* load the options. If a file name is specified as first argument, we pass it
* to the window contructor which will construct its full path (because you can
* specify, for example, ..\..\test.java or ~\jext.props or ...../hello.cpp -
* both / and \ can be used -)
*/
public static void main(String args[])
{
///////////////////////////////// DEBUG
System.setErr(System.out);
initDirectories();
args = parseOptions(args);
synchronized (instances)
{
loadInSingleJVMInstance(args);
initProperties();
if (!isRunningBg())
{
splash = new SplashScreen();
newWindow(args);
} else {
if (keepInMemory)
splash = new SplashScreen();
//FIXME:maybe it should ignore arguments when backgrounding.
builtTextArea = newWindow(args, false);
if (keepInMemory)
newWindow(null, true);
}
}
if (getBooleanProperty("check"))
check = new VersionCheck();
}
}
// End of Jext.java
The table below shows all metrics for Jext.java.
| Metric | Value | Description | |
|---|---|---|---|



