Source Code Cross Referenced for PluginJAR.java in  » Swing-Library » jEdit » org » gjt » sp » jedit » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » jEdit » org.gjt.sp.jedit 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * PluginJAR.java - Controls JAR loading and unloading
0003:         * :tabSize=8:indentSize=8:noTabs=false:
0004:         * :folding=explicit:collapseFolds=1:
0005:         *
0006:         * Copyright (C) 1999, 2004 Slava Pestov
0007:         *
0008:         * This program is free software; you can redistribute it and/or
0009:         * modify it under the terms of the GNU General Public License
0010:         * as published by the Free Software Foundation; either version 2
0011:         * of the License, or any later version.
0012:         *
0013:         * This program is distributed in the hope that it will be useful,
0014:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0016:         * GNU General Public License for more details.
0017:         *
0018:         * You should have received a copy of the GNU General Public License
0019:         * along with this program; if not, write to the Free Software
0020:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0021:         */
0022:
0023:        package org.gjt.sp.jedit;
0024:
0025:        //{{{ Imports
0026:        import java.io.BufferedInputStream;
0027:        import java.io.BufferedOutputStream;
0028:        import java.io.DataInputStream;
0029:        import java.io.DataOutputStream;
0030:        import java.io.File;
0031:        import java.io.FileInputStream;
0032:        import java.io.FileNotFoundException;
0033:        import java.io.FileOutputStream;
0034:        import java.io.IOException;
0035:        import java.io.InputStream;
0036:        import java.lang.reflect.Modifier;
0037:        import java.net.URL;
0038:        import java.util.Enumeration;
0039:        import java.util.LinkedHashSet;
0040:        import java.util.LinkedList;
0041:        import java.util.List;
0042:        import java.util.Map;
0043:        import java.util.Properties;
0044:        import java.util.Set;
0045:        import java.util.StringTokenizer;
0046:        import java.util.zip.ZipEntry;
0047:        import java.util.zip.ZipFile;
0048:
0049:        import javax.swing.SwingUtilities;
0050:
0051:        import org.gjt.sp.jedit.browser.VFSBrowser;
0052:        import org.gjt.sp.jedit.buffer.DummyFoldHandler;
0053:        import org.gjt.sp.jedit.buffer.FoldHandler;
0054:        import org.gjt.sp.jedit.gui.DockableWindowFactory;
0055:        import org.gjt.sp.jedit.msg.PluginUpdate;
0056:        import org.gjt.sp.util.Log;
0057:        import org.gjt.sp.util.StandardUtilities;
0058:        import org.gjt.sp.util.IOUtilities;
0059:
0060:        //}}}
0061:
0062:        /**
0063:         * Loads and unloads plugins.<p>
0064:         *
0065:         * <h3>JAR file contents</h3>
0066:         *
0067:         * When loading a plugin, jEdit looks for the following resources:
0068:         *
0069:         * <ul>
0070:         * <li>A file named <code>actions.xml</code> defining plugin actions.
0071:         * Only one such file per plugin is allowed. See {@link ActionSet} for
0072:         * syntax.</li>
0073:         * <li>A file named <code>browser.actions.xml</code> defining file system
0074:         * browser actions.
0075:         * Only one such file per plugin is allowed. See {@link ActionSet} for
0076:         * syntax.</li>
0077:         * <li>A file named <code>dockables.xml</code> defining dockable windows.
0078:         * Only one such file per plugin is allowed. See {@link
0079:         * org.gjt.sp.jedit.gui.DockableWindowManager} for
0080:         * syntax.</li>
0081:         * <li>A file named <code>services.xml</code> defining additional services
0082:         * offered by the plugin, such as virtual file systems.
0083:         * Only one such file per plugin is allowed. See {@link
0084:         * org.gjt.sp.jedit.ServiceManager} for
0085:         * syntax.</li>
0086:         * <li>File with extension <code>.props</code> containing name/value pairs
0087:         * separated by an equals sign.
0088:         * A plugin can supply any number of property files. Property files are used
0089:         * to define plugin men items, plugin option panes, as well as arbitriary
0090:         * settings and strings used by the plugin. See {@link EditPlugin} for
0091:         * information about properties used by jEdit. See
0092:         * <code>java.util.Properties</code> for property file syntax.</li>
0093:         * </ul>
0094:         *
0095:         * For a plugin to actually do something once it is resident in memory,
0096:         * it must contain a class whose name ends with <code>Plugin</code>.
0097:         * This class, known as the <i>plugin core class</i> must extend
0098:         * {@link EditPlugin} and define a few required properties, otherwise it is
0099:         * ignored.
0100:         *
0101:         * <h3>Dynamic and deferred loading</h3>
0102:         *
0103:         * Unlike in prior jEdit versions, jEdit 4.2 and later allow
0104:         * plugins to be added and removed to the resident set at any time using
0105:         * the {@link jEdit#addPluginJAR(String)} and
0106:         * {@link jEdit#removePluginJAR(PluginJAR,boolean)} methods. Furthermore, the
0107:         *  plugin core class might not be loaded until the plugin is first used. See
0108:         * {@link EditPlugin#start()} for a full description.
0109:         *
0110:         *
0111:         * @see org.gjt.sp.jedit.jEdit#getProperty(String)
0112:         * @see org.gjt.sp.jedit.jEdit#getPlugin(String)
0113:         * @see org.gjt.sp.jedit.jEdit#getPlugins()
0114:         * @see org.gjt.sp.jedit.jEdit#getPluginJAR(String)
0115:         * @see org.gjt.sp.jedit.jEdit#getPluginJARs()
0116:         * @see org.gjt.sp.jedit.jEdit#addPluginJAR(String)
0117:         * @see org.gjt.sp.jedit.jEdit#removePluginJAR(PluginJAR,boolean)
0118:         * @see org.gjt.sp.jedit.ActionSet
0119:         * @see org.gjt.sp.jedit.gui.DockableWindowManager
0120:         * @see org.gjt.sp.jedit.OptionPane
0121:         * @see org.gjt.sp.jedit.PluginJAR
0122:         * @see org.gjt.sp.jedit.ServiceManager
0123:         *
0124:         * @author Slava Pestov
0125:         * @version $Id: PluginJAR.java 10832 2007-10-07 11:19:37Z kpouer $
0126:         * @since jEdit 4.2pre1
0127:         */
0128:        public class PluginJAR {
0129:            //{{{ Instance variables
0130:            private final String path;
0131:            private String cachePath;
0132:            private final File file;
0133:
0134:            private final JARClassLoader classLoader;
0135:            private ZipFile zipFile;
0136:            private Properties properties;
0137:            private String[] classes;
0138:            private ActionSet actions;
0139:            private ActionSet browserActions;
0140:            private EditPlugin plugin;
0141:            private URL dockablesURI;
0142:            private URL servicesURI;
0143:            private boolean activated;
0144:
0145:            // Lists of jarPaths
0146:            private final Set<String> theseRequireMe = new LinkedHashSet<String>();
0147:            /** The plugins that uses me as optional dependency. */
0148:            private final Set<String> theseUseMe = new LinkedHashSet<String>();
0149:            private final Set<String> weRequireThese = new LinkedHashSet<String>();
0150:            private final Set<String> weUseThese = new LinkedHashSet<String>();
0151:
0152:            //}}}
0153:
0154:            //{{{ load(String jarPath, boolean activateDependentIfNecessary)
0155:            /**
0156:             * Loads a plugin, and its dependent plugins if necessary.
0157:             *
0158:             * @since jEdit 4.3pre7
0159:             *
0160:             */
0161:            public static PluginJAR load(String path, boolean loadDependents) {
0162:                PluginJAR jar = jEdit.getPluginJAR(path);
0163:                if (jar != null && jar.getPlugin() != null) {
0164:                    return jar;
0165:                }
0166:                jEdit.addPluginJAR(path);
0167:                jar = jEdit.getPluginJAR(path);
0168:                String className = jar.getPlugin().getClassName();
0169:                if (loadDependents) {
0170:                    Set<String> pluginLoadList = getDependencySet(className);
0171:                    for (String jarName : pluginLoadList) {
0172:                        String jarPath = findPlugin(jarName);
0173:                        load(jarPath, false);
0174:                    }
0175:                }
0176:                // Load extra jars that are part of this plugin
0177:                String jars = jEdit
0178:                        .getProperty("plugin." + className + ".jars");
0179:                if (jars != null) {
0180:                    String dir = MiscUtilities.getParentOfPath(path);
0181:                    StringTokenizer st = new StringTokenizer(jars);
0182:                    while (st.hasMoreTokens()) {
0183:                        String _jarPath = MiscUtilities.constructPath(dir, st
0184:                                .nextToken());
0185:                        PluginJAR _jar = jEdit.getPluginJAR(_jarPath);
0186:                        if (_jar == null) {
0187:                            jEdit.addPluginJAR(_jarPath);
0188:                        }
0189:                    }
0190:                }
0191:                jar.checkDependencies();
0192:                jar.activatePluginIfNecessary();
0193:                return jar;
0194:            } // }}}
0195:
0196:            //{{{ getPath() method
0197:            /**
0198:             * Returns the full path name of this plugin's JAR file.
0199:             */
0200:            public String getPath() {
0201:                return path;
0202:            } //}}}
0203:
0204:            //{{{ findPlugin() method
0205:            /**
0206:             * Unlike getPlugin(), will return a PluginJAR that is not yet loaded,
0207:             * given its classname.
0208:             *
0209:             * @param className a class name
0210:             * @return the JARpath of the first PluginJAR it can find which contains this className,
0211:             * 		    or null if not found.
0212:             * @since 4.3pre7
0213:             */
0214:            public static String findPlugin(String className) {
0215:                EditPlugin ep = jEdit.getPlugin(className);
0216:                if (ep != null)
0217:                    return ep.getPluginJAR().getPath();
0218:
0219:                for (String JARpath : jEdit.getNotLoadedPluginJARs()) {
0220:                    PluginJAR pjar = new PluginJAR(new File(JARpath));
0221:                    if (pjar.containsClass(className)) {
0222:                        return JARpath;
0223:                    }
0224:                }
0225:                return null;
0226:            } // }}}
0227:
0228:            //{{{ containsClass() function
0229:            /**
0230:             * @param className a class name
0231:             * @return true if this jar contains a class with that classname.
0232:             * @since jedit 4.3pre7
0233:             */
0234:            boolean containsClass(String className) {
0235:                try {
0236:                    getZipFile();
0237:                } catch (IOException ioe) {
0238:                    throw new RuntimeException(ioe);
0239:                }
0240:                Enumeration itr = zipFile.entries();
0241:                while (itr.hasMoreElements()) {
0242:                    String entry = itr.nextElement().toString();
0243:                    if (entry.endsWith(".class")) {
0244:                        String name = entry.substring(0, entry.length() - 6)
0245:                                .replace('/', '.');
0246:                        if (name.equals(className))
0247:                            return true;
0248:                    }
0249:                }
0250:                return false;
0251:
0252:            } // }}}
0253:
0254:            //{{{ getCachePath() method
0255:            /**
0256:             * Returns the full path name of this plugin's summary file.
0257:             * The summary file is used to store certain information which allows
0258:             * loading of the plugin's resources and core class to be deferred
0259:             * until the plugin is first used. As long as a plugin is using the
0260:             * jEdit 4.2 plugin API, no extra effort is required to take advantage
0261:             * of the summary cache.
0262:             */
0263:            public String getCachePath() {
0264:                return cachePath;
0265:            } //}}}
0266:
0267:            //{{{ getDependencySet() method
0268:            /**
0269:             *
0270:             * @param className of a plugin that we wish to load
0271:             * @return an ordered set of JARpaths that contains the
0272:             *      plugins that need to be (re)loaded, in the correct order.
0273:             */
0274:            public static Set<String> getDependencySet(String className) {
0275:                String dep;
0276:                Set<String> retval = new LinkedHashSet<String>();
0277:                int i = 0;
0278:                while ((dep = jEdit.getProperty("plugin." + className
0279:                        + ".depend." + i++)) != null) {
0280:                    PluginDepends pluginDepends;
0281:                    try {
0282:                        pluginDepends = getPluginDepends(dep);
0283:                    } catch (IllegalArgumentException e) {
0284:                        Log.log(Log.ERROR, PluginJAR.class, className
0285:                                + " has an invalid dependency: " + dep);
0286:                        continue;
0287:                    }
0288:
0289:                    if (pluginDepends.what.equals("plugin")) {
0290:                        int index2 = pluginDepends.arg.indexOf(' ');
0291:                        if (index2 == -1) {
0292:                            Log.log(Log.ERROR, PluginJAR.class, className
0293:                                    + " has an invalid dependency: " + dep
0294:                                    + " (version is missing)");
0295:                            continue;
0296:                        }
0297:
0298:                        String pluginName = pluginDepends.arg.substring(0,
0299:                                index2);
0300:                        String needVersion = pluginDepends.arg
0301:                                .substring(index2 + 1);
0302:                        //todo : check version ?
0303:                        Set<String> loadTheseFirst = getDependencySet(pluginName);
0304:                        loadTheseFirst.add(pluginName);
0305:                        loadTheseFirst.addAll(retval);
0306:                        retval = loadTheseFirst;
0307:                    }
0308:                }
0309:                return retval;
0310:            } // }}}
0311:
0312:            //{{{ getFile() method
0313:            /**
0314:             * Returns a file pointing to the plugin JAR.
0315:             */
0316:            public File getFile() {
0317:                return file;
0318:            } //}}}
0319:
0320:            //{{{ getClassLoader() method
0321:            /**
0322:             * Returns the plugin's class loader.
0323:             */
0324:            public JARClassLoader getClassLoader() {
0325:                return classLoader;
0326:            } //}}}
0327:
0328:            //{{{ getZipFile() method
0329:            /**
0330:             * Returns the plugin's JAR file, opening it if necessary.
0331:             * @since jEdit 4.2pre1
0332:             */
0333:            public synchronized ZipFile getZipFile() throws IOException {
0334:                if (zipFile == null) {
0335:                    Log.log(Log.DEBUG, this , "Opening " + path);
0336:                    zipFile = new ZipFile(path);
0337:                }
0338:                return zipFile;
0339:            } //}}}
0340:
0341:            //{{{ getActions() method
0342:            /**
0343:             * @deprecated Call getActionSet() instead
0344:             */
0345:            public ActionSet getActions() {
0346:                return getActionSet();
0347:            } //}}}
0348:
0349:            //{{{ getActionSet() method
0350:            /**
0351:             * Returns the plugin's action set for the jEdit action context
0352:             * {@link jEdit#getActionContext()}. These actions are loaded from
0353:             * the <code>actions.xml</code> file; see {@link ActionSet}.
0354:             *.
0355:             * @since jEdit 4.2pre1
0356:             */
0357:            public ActionSet getActionSet() {
0358:                return actions;
0359:            } //}}}
0360:
0361:            //{{{ getBrowserActionSet() method
0362:            /**
0363:             * Returns the plugin's action set for the file system browser action
0364:             * context {@link
0365:             * org.gjt.sp.jedit.browser.VFSBrowser#getActionContext()}.
0366:             * These actions are loaded from
0367:             * the <code>browser.actions.xml</code> file; see {@link ActionSet}.
0368:             *.
0369:             * @since jEdit 4.2pre1
0370:             */
0371:            public ActionSet getBrowserActionSet() {
0372:                return browserActions;
0373:            } //}}}
0374:
0375:            //{{{ checkDependencies() method
0376:            /**
0377:             * Returns true if all dependencies are satisified, false otherwise.
0378:             * Also if dependencies are not satisfied, the plugin is marked as
0379:             * "broken".
0380:             *
0381:             */
0382:            public boolean checkDependencies() {
0383:                if (plugin == null)
0384:                    return true;
0385:                int i = 0;
0386:                boolean ok = true;
0387:
0388:                String name = plugin.getClassName();
0389:
0390:                String dep;
0391:                while ((dep = jEdit.getProperty("plugin." + name + ".depend."
0392:                        + i++)) != null) {
0393:                    PluginDepends pluginDepends;
0394:                    try {
0395:                        pluginDepends = getPluginDepends(dep);
0396:                    } catch (IllegalArgumentException e) {
0397:                        Log.log(Log.ERROR, this , name + " has an invalid"
0398:                                + " dependency: " + dep);
0399:                        ok = false;
0400:                        continue;
0401:                    }
0402:
0403:                    if (pluginDepends.what.equals("jdk")) {
0404:                        if (!pluginDepends.optional
0405:                                && StandardUtilities.compareStrings(System
0406:                                        .getProperty("java.version"),
0407:                                        pluginDepends.arg, false) < 0) {
0408:                            String[] args = { pluginDepends.arg,
0409:                                    System.getProperty("java.version") };
0410:                            jEdit.pluginError(path, "plugin-error.dep-jdk",
0411:                                    args);
0412:                            ok = false;
0413:                        }
0414:                    } else if (pluginDepends.what.equals("jedit")) {
0415:                        if (pluginDepends.arg.length() != 11) {
0416:                            Log.log(Log.ERROR, this , "Invalid jEdit version"
0417:                                    + " number: " + pluginDepends.arg);
0418:                            ok = false;
0419:                        }
0420:
0421:                        if (!pluginDepends.optional
0422:                                && StandardUtilities.compareStrings(jEdit
0423:                                        .getBuild(), pluginDepends.arg, false) < 0) {
0424:                            String needs = MiscUtilities
0425:                                    .buildToVersion(pluginDepends.arg);
0426:                            String[] args = { needs, jEdit.getVersion() };
0427:                            jEdit.pluginError(path, "plugin-error.dep-jedit",
0428:                                    args);
0429:                            ok = false;
0430:                        }
0431:                    } else if (pluginDepends.what.equals("plugin")) {
0432:                        int index2 = pluginDepends.arg.indexOf(' ');
0433:                        if (index2 == -1) {
0434:                            Log.log(Log.ERROR, this , name
0435:                                    + " has an invalid dependency: " + dep
0436:                                    + " (version is missing)");
0437:                            ok = false;
0438:                            continue;
0439:                        }
0440:
0441:                        String pluginName = pluginDepends.arg.substring(0,
0442:                                index2);
0443:                        String needVersion = pluginDepends.arg
0444:                                .substring(index2 + 1);
0445:                        String currVersion = jEdit.getProperty("plugin."
0446:                                + pluginName + ".version");
0447:
0448:                        EditPlugin editPlugin = jEdit.getPlugin(pluginName,
0449:                                false);
0450:                        if (editPlugin == null) {
0451:                            if (!pluginDepends.optional) {
0452:                                String[] args = { needVersion, pluginName };
0453:                                jEdit.pluginError(path,
0454:                                        "plugin-error.dep-plugin.no-version",
0455:                                        args);
0456:                                ok = false;
0457:                            }
0458:                        } else if (StandardUtilities.compareStrings(
0459:                                currVersion, needVersion, false) < 0) {
0460:                            if (!pluginDepends.optional) {
0461:                                String[] args = { needVersion, pluginName,
0462:                                        currVersion };
0463:                                jEdit.pluginError(path,
0464:                                        "plugin-error.dep-plugin", args);
0465:                                ok = false;
0466:                            }
0467:                        } else if (editPlugin instanceof  EditPlugin.Broken) {
0468:                            if (!pluginDepends.optional) {
0469:                                String[] args = { pluginName };
0470:                                jEdit.pluginError(path,
0471:                                        "plugin-error.dep-plugin.broken", args);
0472:                                ok = false;
0473:                            }
0474:                        } else {
0475:                            PluginJAR jar = editPlugin.getPluginJAR();
0476:                            if (pluginDepends.optional) {
0477:                                jar.theseUseMe.add(path);
0478:                                weUseThese.add(jar.getPath());
0479:                            } else {
0480:                                jar.theseRequireMe.add(path);
0481:                                weRequireThese.add(jar.getPath());
0482:                            }
0483:                        }
0484:                    } else if (pluginDepends.what.equals("class")) {
0485:                        if (!pluginDepends.optional) {
0486:                            try {
0487:                                classLoader.loadClass(pluginDepends.arg, false);
0488:                            } catch (Exception e) {
0489:                                String[] args = { pluginDepends.arg };
0490:                                jEdit.pluginError(path,
0491:                                        "plugin-error.dep-class", args);
0492:                                ok = false;
0493:                            }
0494:                        }
0495:                    } else {
0496:                        Log.log(Log.ERROR, this , name + " has unknown"
0497:                                + " dependency: " + dep);
0498:                        ok = false;
0499:                    }
0500:                }
0501:
0502:                // each JAR file listed in the plugin's jars property
0503:                // needs to know that we need them
0504:                String jars = jEdit.getProperty("plugin."
0505:                        + plugin.getClassName() + ".jars");
0506:                if (jars != null) {
0507:                    String dir = MiscUtilities.getParentOfPath(path);
0508:
0509:                    StringTokenizer st = new StringTokenizer(jars);
0510:                    while (st.hasMoreTokens()) {
0511:                        String jarPath = MiscUtilities.constructPath(dir, st
0512:                                .nextToken());
0513:                        PluginJAR jar = jEdit.getPluginJAR(jarPath);
0514:                        if (jar == null) {
0515:                            String[] args = { jarPath };
0516:                            jEdit.pluginError(path, "plugin-error.missing-jar",
0517:                                    args);
0518:                            ok = false;
0519:                        } else {
0520:                            weRequireThese.add(jarPath);
0521:                            jar.theseRequireMe.add(path);
0522:                        }
0523:                    }
0524:                }
0525:
0526:                if (!ok)
0527:                    breakPlugin();
0528:
0529:                return ok;
0530:            } //}}}
0531:
0532:            //{{{ getRequiredJars() method
0533:            /**
0534:             * Returns the required jars of this plugin.
0535:             *
0536:             * @return the required jars of this plugin
0537:             * @since jEdit 4.3pre12
0538:             */
0539:            public Set<String> getRequiredJars() {
0540:                return weRequireThese;
0541:            } //}}}
0542:
0543:            //{{{ getPluginDepends() method
0544:            private static PluginDepends getPluginDepends(String dep)
0545:                    throws IllegalArgumentException {
0546:                boolean optional;
0547:                if (dep.startsWith("optional ")) {
0548:                    optional = true;
0549:                    dep = dep.substring("optional ".length());
0550:                } else {
0551:                    optional = false;
0552:                }
0553:
0554:                int index = dep.indexOf(' ');
0555:                if (index == -1)
0556:                    throw new IllegalArgumentException("wrong dependency");
0557:
0558:                String what = dep.substring(0, index);
0559:                String arg = dep.substring(index + 1);
0560:                PluginDepends depends = new PluginDepends();
0561:                depends.what = what;
0562:                depends.arg = arg;
0563:                depends.optional = optional;
0564:                return depends;
0565:            } //}}}
0566:
0567:            //{{{ PluginDepends class
0568:            private static class PluginDepends {
0569:                String what;
0570:                String arg;
0571:                boolean optional;
0572:            } //}}}
0573:
0574:            //{{{ transitiveClosure()
0575:            /**
0576:             * If plugin A is needed by B, and B is needed by C, we want to
0577:             * tell the user that A is needed by B and C when they try to
0578:             * unload A.
0579:             *
0580:             * @param dependents a set of plugins which we wish to disable
0581:             * @param listModel a set of plugins which will be affected, and will need
0582:             *  to be disabled also.
0583:             */
0584:            public static void transitiveClosure(String[] dependents,
0585:                    List<String> listModel) {
0586:                for (int i = 0; i < dependents.length; i++) {
0587:                    String jarPath = dependents[i];
0588:                    if (!listModel.contains(jarPath)) {
0589:                        listModel.add(jarPath);
0590:                        PluginJAR jar = jEdit.getPluginJAR(jarPath);
0591:                        transitiveClosure(jar.getDependentPlugins(), listModel);
0592:                    }
0593:                }
0594:            } //}}}
0595:
0596:            //{{{ getDependentPlugins() method
0597:            public String[] getDependentPlugins() {
0598:                return theseRequireMe
0599:                        .toArray(new String[theseRequireMe.size()]);
0600:            } //}}}
0601:
0602:            //{{{ getPlugin() method
0603:            /**
0604:             * Returns the plugin core class for this JAR file. Note that if the
0605:             * plugin has not been activated, this will return an instance of
0606:             * {@link EditPlugin.Deferred}. If you need the actual plugin core
0607:             * class instance, call {@link #activatePlugin()} first.
0608:             * If the plugin is not yet loaded, returns null
0609:             *
0610:             * @since jEdit 4.2pre1
0611:             */
0612:            public EditPlugin getPlugin() {
0613:                return plugin;
0614:            } //}}}
0615:
0616:            //{{{ activatePlugin() method
0617:            /**
0618:             * Loads the plugin core class. Does nothing if the plugin core class
0619:             * has already been loaded. This method might be called on startup,
0620:             * depending on what properties are set. See {@link EditPlugin#start()}.
0621:             * This method is thread-safe.
0622:             *
0623:             * @since jEdit 4.2pre1
0624:             */
0625:            public void activatePlugin() {
0626:                synchronized (this ) {
0627:                    if (activated) {
0628:                        // recursive call
0629:                        return;
0630:                    }
0631:
0632:                    activated = true;
0633:                }
0634:
0635:                if (!(plugin instanceof  EditPlugin.Deferred)) {
0636:                    return;
0637:                }
0638:
0639:                String className = plugin.getClassName();
0640:
0641:                try {
0642:                    Class clazz = classLoader.loadClass(className, false);
0643:                    int modifiers = clazz.getModifiers();
0644:                    if (Modifier.isInterface(modifiers)
0645:                            || Modifier.isAbstract(modifiers)
0646:                            || !EditPlugin.class.isAssignableFrom(clazz)) {
0647:                        Log.log(Log.ERROR, this ,
0648:                                "Plugin has properties but does not extend EditPlugin: "
0649:                                        + className);
0650:                        breakPlugin();
0651:                        return;
0652:                    }
0653:
0654:                    plugin = (EditPlugin) clazz.newInstance();
0655:                    plugin.jar = this ;
0656:                } catch (Throwable t) {
0657:                    breakPlugin();
0658:
0659:                    Log.log(Log.ERROR, this , "Error while starting plugin "
0660:                            + className);
0661:                    Log.log(Log.ERROR, this , t);
0662:                    String[] args = { t.toString() };
0663:                    jEdit.pluginError(path, "plugin-error.start-error", args);
0664:
0665:                    return;
0666:                }
0667:
0668:                if (jEdit.isMainThread()
0669:                        || SwingUtilities.isEventDispatchThread()) {
0670:                    startPlugin();
0671:                } else {
0672:                    // for thread safety
0673:                    startPluginLater();
0674:                }
0675:
0676:                EditBus.send(new PluginUpdate(this , PluginUpdate.ACTIVATED,
0677:                        false));
0678:            } //}}}
0679:
0680:            //{{{ activateIfNecessary() method
0681:            /**
0682:             * Should be called after a new plugin is installed.
0683:             * @since jEdit 4.2pre2
0684:             */
0685:            public void activatePluginIfNecessary() {
0686:                String filename = MiscUtilities.getFileName(getPath());
0687:                jEdit.setBooleanProperty("plugin-blacklist." + filename, false);
0688:                if (!(plugin instanceof  EditPlugin.Deferred && plugin != null)) {
0689:                    return;
0690:                }
0691:
0692:                String className = plugin.getClassName();
0693:
0694:                // default for plugins that don't specify this property (ie,
0695:                // 4.1-style plugins) is to load them on startup
0696:                String activate = jEdit.getProperty("plugin." + className
0697:                        + ".activate");
0698:
0699:                if (activate == null) {
0700:                    // 4.1 plugin
0701:                    if (!jEdit.isMainThread()) {
0702:                        breakPlugin();
0703:
0704:                        jEdit.pluginError(path, "plugin-error.not-42", null);
0705:                    } else {
0706:                        activatePlugin();
0707:                    }
0708:                } else {
0709:                    // 4.2 plugin
0710:
0711:                    // if at least one property listed here is true,
0712:                    // load the plugin
0713:                    boolean load = false;
0714:
0715:                    StringTokenizer st = new StringTokenizer(activate);
0716:                    while (st.hasMoreTokens()) {
0717:                        String prop = st.nextToken();
0718:                        boolean value = jEdit.getBooleanProperty(prop);
0719:                        if (value) {
0720:                            Log.log(Log.DEBUG, this , "Activating " + className
0721:                                    + " because of " + prop);
0722:                            load = true;
0723:                            break;
0724:                        }
0725:                    }
0726:
0727:                    if (load) {
0728:                        activatePlugin();
0729:                    }
0730:                }
0731:            } //}}}
0732:
0733:            //{{{ deactivatePlugin() method
0734:            /**
0735:             * Unloads the plugin core class. Does nothing if the plugin core class
0736:             * has not been loaded.
0737:             * This method can only be called from the AWT event dispatch thread!
0738:             * @see EditPlugin#stop()
0739:             *
0740:             * @since jEdit 4.2pre3
0741:             */
0742:            public void deactivatePlugin(boolean exit) {
0743:                if (!activated)
0744:                    return;
0745:
0746:                if (!exit) {
0747:                    // buffers retain a reference to the fold handler in
0748:                    // question... and the easiest way to handle fold
0749:                    // handler unloading is this...
0750:                    Buffer buffer = jEdit.getFirstBuffer();
0751:                    while (buffer != null) {
0752:                        if (buffer.getFoldHandler() != null
0753:                                && buffer.getFoldHandler().getClass()
0754:                                        .getClassLoader() == classLoader) {
0755:                            buffer.setFoldHandler(new DummyFoldHandler());
0756:                        }
0757:                        buffer = buffer.getNext();
0758:                    }
0759:                }
0760:
0761:                if (plugin != null && !(plugin instanceof  EditPlugin.Broken)) {
0762:                    if (plugin instanceof  EBPlugin)
0763:                        EditBus.removeFromBus((EBPlugin) plugin);
0764:
0765:                    try {
0766:                        plugin.stop();
0767:                    } catch (Throwable t) {
0768:                        Log.log(Log.ERROR, this , "Error while "
0769:                                + "stopping plugin:");
0770:                        Log.log(Log.ERROR, this , t);
0771:                    }
0772:
0773:                    plugin = new EditPlugin.Deferred(this , plugin
0774:                            .getClassName());
0775:
0776:                    EditBus.send(new PluginUpdate(this ,
0777:                            PluginUpdate.DEACTIVATED, exit));
0778:
0779:                    if (!exit) {
0780:                        // see if this is a 4.1-style plugin
0781:                        String activate = jEdit.getProperty("plugin."
0782:                                + plugin.getClassName() + ".activate");
0783:
0784:                        if (activate == null) {
0785:                            breakPlugin();
0786:                            jEdit
0787:                                    .pluginError(path, "plugin-error.not-42",
0788:                                            null);
0789:                        }
0790:                    }
0791:                }
0792:
0793:                activated = false;
0794:            } //}}}
0795:
0796:            //{{{ getDockablesURI() method
0797:            /**
0798:             * Returns the location of the plugin's
0799:             * <code>dockables.xml</code> file.
0800:             * @since jEdit 4.2pre1
0801:             */
0802:            public URL getDockablesURI() {
0803:                return dockablesURI;
0804:            } //}}}
0805:
0806:            //{{{ getServicesURI() method
0807:            /**
0808:             * Returns the location of the plugin's
0809:             * <code>services.xml</code> file.
0810:             * @since jEdit 4.2pre1
0811:             */
0812:            public URL getServicesURI() {
0813:                return servicesURI;
0814:            } //}}}
0815:
0816:            //{{{ toString() method
0817:            public String toString() {
0818:                if (plugin == null)
0819:                    return path;
0820:                else
0821:                    return path + ",class=" + plugin.getClassName();
0822:            } //}}}
0823:
0824:            //{{{ Package-private members
0825:
0826:            //{{{ Static methods
0827:
0828:            //{{{ getPluginCache() method
0829:            public static PluginCacheEntry getPluginCache(PluginJAR plugin) {
0830:                String jarCachePath = plugin.getCachePath();
0831:                if (jarCachePath == null)
0832:                    return null;
0833:
0834:                DataInputStream din = null;
0835:                try {
0836:                    PluginCacheEntry cache = new PluginCacheEntry();
0837:                    cache.plugin = plugin;
0838:                    cache.modTime = plugin.getFile().lastModified();
0839:                    din = new DataInputStream(new BufferedInputStream(
0840:                            new FileInputStream(jarCachePath)));
0841:                    if (cache.read(din))
0842:                        return cache;
0843:                    else {
0844:                        // returns false with outdated cache
0845:                        return null;
0846:                    }
0847:                } catch (FileNotFoundException fnf) {
0848:                    return null;
0849:                } catch (IOException io) {
0850:                    Log.log(Log.ERROR, PluginJAR.class, io);
0851:                    return null;
0852:                } finally {
0853:                    IOUtilities.closeQuietly(din);
0854:                }
0855:            } //}}}
0856:
0857:            //{{{ setPluginCache() method
0858:            static void setPluginCache(PluginJAR plugin, PluginCacheEntry cache) {
0859:                String jarCachePath = plugin.getCachePath();
0860:                if (jarCachePath == null)
0861:                    return;
0862:
0863:                Log.log(Log.DEBUG, PluginJAR.class, "Writing " + jarCachePath);
0864:
0865:                DataOutputStream dout = null;
0866:                try {
0867:                    dout = new DataOutputStream(new BufferedOutputStream(
0868:                            new FileOutputStream(jarCachePath)));
0869:                    cache.write(dout);
0870:                    dout.close();
0871:                } catch (IOException io) {
0872:                    Log.log(Log.ERROR, PluginJAR.class, io);
0873:                    IOUtilities.closeQuietly(dout);
0874:                    new File(jarCachePath).delete();
0875:                }
0876:            } //}}}
0877:
0878:            //}}}
0879:
0880:            //{{{ PluginJAR constructor
0881:            /**
0882:             * Creates a PluginJAR object which is not necessarily loaded, but can be later.
0883:             * @see #load(String, boolean)
0884:             */
0885:            public PluginJAR(File file) {
0886:                this .path = file.getPath();
0887:                String jarCacheDir = jEdit.getJARCacheDirectory();
0888:                if (jarCacheDir != null) {
0889:                    cachePath = MiscUtilities.constructPath(jarCacheDir, file
0890:                            .getName()
0891:                            + ".summary");
0892:                }
0893:                this .file = file;
0894:                classLoader = new JARClassLoader(this );
0895:                actions = new ActionSet();
0896:            } //}}}
0897:
0898:            //{{{ init() method
0899:            void init() {
0900:                PluginCacheEntry cache = getPluginCache(this );
0901:                if (cache != null) {
0902:                    loadCache(cache);
0903:                    classLoader.activate();
0904:                } else {
0905:                    try {
0906:                        cache = generateCache();
0907:                        if (cache != null) {
0908:                            setPluginCache(this , cache);
0909:                            classLoader.activate();
0910:                        }
0911:                    } catch (IOException io) {
0912:                        Log.log(Log.ERROR, this , "Cannot load" + " plugin "
0913:                                + path);
0914:                        Log.log(Log.ERROR, this , io);
0915:
0916:                        String[] args = { io.toString() };
0917:                        jEdit
0918:                                .pluginError(path, "plugin-error.load-error",
0919:                                        args);
0920:
0921:                        uninit(false);
0922:                    }
0923:                }
0924:            } //}}}
0925:
0926:            //{{{ uninit() method
0927:            void uninit(boolean exit) {
0928:                deactivatePlugin(exit);
0929:
0930:                if (!exit) {
0931:                    for (String path : weRequireThese) {
0932:                        PluginJAR jar = jEdit.getPluginJAR(path);
0933:                        if (jar != null)
0934:                            jar.theseRequireMe.remove(this .path);
0935:                    }
0936:
0937:                    for (String path : weUseThese) {
0938:                        PluginJAR jar = jEdit.getPluginJAR(path);
0939:                        if (jar != null)
0940:                            jar.theseUseMe.remove(this .path);
0941:                    }
0942:
0943:                    classLoader.deactivate();
0944:                    BeanShell.resetClassManager();
0945:
0946:                    if (actions != null)
0947:                        jEdit.removeActionSet(actions);
0948:                    if (browserActions != null)
0949:                        VFSBrowser.getActionContext().removeActionSet(
0950:                                browserActions);
0951:
0952:                    DockableWindowFactory.getInstance().unloadDockableWindows(
0953:                            this );
0954:                    ServiceManager.unloadServices(this );
0955:
0956:                    jEdit.removePluginProps(properties);
0957:
0958:                    try {
0959:                        if (zipFile != null) {
0960:                            zipFile.close();
0961:                            zipFile = null;
0962:                        }
0963:                    } catch (IOException io) {
0964:                        Log.log(Log.ERROR, this , io);
0965:                    }
0966:                }
0967:            } //}}}
0968:
0969:            //{{{ getClasses() method
0970:            String[] getClasses() {
0971:                return classes;
0972:            } //}}}
0973:
0974:            //}}}
0975:
0976:            //{{{ Private members
0977:
0978:            //{{{ actionsPresentButNotCoreClass() method
0979:            private void actionsPresentButNotCoreClass() {
0980:                Log.log(Log.WARNING, this , getPath()
0981:                        + " has an actions.xml but no plugin core class");
0982:                actions.setLabel("MISSING PLUGIN CORE CLASS");
0983:            } //}}}
0984:
0985:            //{{{ loadCache() method
0986:            private void loadCache(PluginCacheEntry cache) {
0987:                classes = cache.classes;
0988:
0989:                /* this should be before dockables are initialized */
0990:                if (cache.cachedProperties != null) {
0991:                    properties = cache.cachedProperties;
0992:                    jEdit.addPluginProps(cache.cachedProperties);
0993:                }
0994:
0995:                if (cache.actionsURI != null && cache.cachedActionNames != null) {
0996:                    actions = new ActionSet(this , cache.cachedActionNames,
0997:                            cache.cachedActionToggleFlags, cache.actionsURI);
0998:                }
0999:
1000:                if (cache.browserActionsURI != null
1001:                        && cache.cachedBrowserActionNames != null) {
1002:                    browserActions = new ActionSet(this ,
1003:                            cache.cachedBrowserActionNames,
1004:                            cache.cachedBrowserActionToggleFlags,
1005:                            cache.browserActionsURI);
1006:                    VFSBrowser.getActionContext().addActionSet(browserActions);
1007:                }
1008:
1009:                if (cache.dockablesURI != null
1010:                        && cache.cachedDockableNames != null
1011:                        && cache.cachedDockableActionFlags != null
1012:                        && cache.cachedDockableMovableFlags != null) {
1013:                    dockablesURI = cache.dockablesURI;
1014:                    DockableWindowFactory.getInstance().cacheDockableWindows(
1015:                            this , cache.cachedDockableNames,
1016:                            cache.cachedDockableActionFlags,
1017:                            cache.cachedDockableMovableFlags);
1018:                }
1019:
1020:                if (actions.size() != 0)
1021:                    jEdit.addActionSet(actions);
1022:
1023:                if (cache.servicesURI != null && cache.cachedServices != null) {
1024:                    servicesURI = cache.servicesURI;
1025:                    for (int i = 0; i < cache.cachedServices.length; i++) {
1026:                        ServiceManager.Descriptor d = cache.cachedServices[i];
1027:                        ServiceManager.registerService(d);
1028:                    }
1029:                }
1030:
1031:                if (cache.pluginClass != null) {
1032:                    // Check if a plugin with the same name
1033:                    // is already loaded
1034:                    if (jEdit.getPlugin(cache.pluginClass) != null) {
1035:                        jEdit.pluginError(path, "plugin-error.already-loaded",
1036:                                null);
1037:                        uninit(false);
1038:                    } else {
1039:                        String label = jEdit.getProperty("plugin."
1040:                                + cache.pluginClass + ".name");
1041:                        actions.setLabel(jEdit.getProperty("action-set.plugin",
1042:                                new String[] { label }));
1043:                        plugin = new EditPlugin.Deferred(this ,
1044:                                cache.pluginClass);
1045:                    }
1046:                } else {
1047:                    if (actions.size() != 0)
1048:                        actionsPresentButNotCoreClass();
1049:                }
1050:            } //}}}
1051:
1052:            //{{{ generateCache() method
1053:            public PluginCacheEntry generateCache() throws IOException {
1054:                properties = new Properties();
1055:
1056:                List<String> classes = new LinkedList<String>();
1057:
1058:                ZipFile zipFile = getZipFile();
1059:
1060:                List<String> plugins = new LinkedList<String>();
1061:
1062:                PluginCacheEntry cache = new PluginCacheEntry();
1063:                cache.modTime = file.lastModified();
1064:                cache.cachedProperties = new Properties();
1065:
1066:                Enumeration<? extends ZipEntry> entries = zipFile.entries();
1067:                while (entries.hasMoreElements()) {
1068:                    ZipEntry entry = entries.nextElement();
1069:                    String name = entry.getName();
1070:                    String lname = name.toLowerCase();
1071:                    if (lname.equals("actions.xml")) {
1072:                        cache.actionsURI = classLoader.getResource(name);
1073:                    } else if (lname.equals("browser.actions.xml")) {
1074:                        cache.browserActionsURI = classLoader.getResource(name);
1075:                    } else if (lname.equals("dockables.xml")) {
1076:                        dockablesURI = classLoader.getResource(name);
1077:                        cache.dockablesURI = dockablesURI;
1078:                    } else if (lname.equals("services.xml")) {
1079:                        servicesURI = classLoader.getResource(name);
1080:                        cache.servicesURI = servicesURI;
1081:                    } else if (lname.endsWith(".props")) {
1082:                        InputStream in = classLoader.getResourceAsStream(name);
1083:                        properties.load(in);
1084:                        in.close();
1085:                    } else if (name.endsWith(".class")) {
1086:                        String className = MiscUtilities.fileToClass(name);
1087:                        if (className.endsWith("Plugin")) {
1088:                            plugins.add(className);
1089:                        }
1090:                        classes.add(className);
1091:                    }
1092:                }
1093:
1094:                cache.cachedProperties = properties;
1095:                jEdit.addPluginProps(properties);
1096:
1097:                this .classes = cache.classes = classes
1098:                        .toArray(new String[classes.size()]);
1099:
1100:                String label = null;
1101:
1102:                for (String className : plugins) {
1103:                    String _label = jEdit.getProperty("plugin." + className
1104:                            + ".name");
1105:                    String version = jEdit.getProperty("plugin." + className
1106:                            + ".version");
1107:                    if (_label == null || version == null) {
1108:                        Log.log(Log.WARNING, this , "Ignoring: " + className);
1109:                    } else {
1110:                        cache.pluginClass = className;
1111:
1112:                        // Check if a plugin with the same name
1113:                        // is already loaded
1114:                        if (jEdit.getPlugin(className) != null) {
1115:                            jEdit.pluginError(path,
1116:                                    "plugin-error.already-loaded", null);
1117:                            return null;
1118:                        }
1119:                        plugin = new EditPlugin.Deferred(this , className);
1120:                        label = _label;
1121:
1122:                        break;
1123:                    }
1124:                }
1125:
1126:                if (cache.actionsURI != null) {
1127:                    actions = new ActionSet(this , null, null, cache.actionsURI);
1128:                    actions.load();
1129:                    cache.cachedActionNames = actions.getCacheableActionNames();
1130:                    cache.cachedActionToggleFlags = new boolean[cache.cachedActionNames.length];
1131:                    for (int i = 0; i < cache.cachedActionNames.length; i++) {
1132:                        cache.cachedActionToggleFlags[i] = jEdit
1133:                                .getBooleanProperty(cache.cachedActionNames[i]
1134:                                        + ".toggle");
1135:                    }
1136:                }
1137:
1138:                if (cache.browserActionsURI != null) {
1139:                    browserActions = new ActionSet(this , null, null,
1140:                            cache.browserActionsURI);
1141:                    browserActions.load();
1142:                    VFSBrowser.getActionContext().addActionSet(browserActions);
1143:                    cache.cachedBrowserActionNames = browserActions
1144:                            .getCacheableActionNames();
1145:                    cache.cachedBrowserActionToggleFlags = new boolean[cache.cachedBrowserActionNames.length];
1146:                    for (int i = 0; i < cache.cachedBrowserActionNames.length; i++) {
1147:                        cache.cachedBrowserActionToggleFlags[i] = jEdit
1148:                                .getBooleanProperty(cache.cachedBrowserActionNames[i]
1149:                                        + ".toggle");
1150:                    }
1151:                }
1152:
1153:                if (dockablesURI != null) {
1154:                    DockableWindowFactory.getInstance().loadDockableWindows(
1155:                            this , dockablesURI, cache);
1156:                }
1157:
1158:                if (actions.size() != 0) {
1159:                    if (label != null) {
1160:                        actions.setLabel(jEdit.getProperty("action-set.plugin",
1161:                                new String[] { label }));
1162:                    } else
1163:                        actionsPresentButNotCoreClass();
1164:
1165:                    jEdit.addActionSet(actions);
1166:                }
1167:
1168:                if (servicesURI != null) {
1169:                    ServiceManager.loadServices(this , servicesURI, cache);
1170:                }
1171:
1172:                return cache;
1173:            } //}}}
1174:
1175:            //{{{ startPlugin() method
1176:            private void startPlugin() {
1177:                try {
1178:                    plugin.start();
1179:                } catch (Throwable t) {
1180:                    breakPlugin();
1181:
1182:                    Log.log(Log.ERROR, PluginJAR.this ,
1183:                            "Error while starting plugin "
1184:                                    + plugin.getClassName());
1185:                    Log.log(Log.ERROR, PluginJAR.this , t);
1186:                    String[] args = { t.toString() };
1187:                    jEdit.pluginError(path, "plugin-error.start-error", args);
1188:                }
1189:
1190:                if (plugin instanceof  EBPlugin) {
1191:                    if (jEdit.getProperty("plugin." + plugin.getClassName()
1192:                            + ".activate") == null) {
1193:                        // old plugins expected jEdit 4.1-style
1194:                        // behavior, where a PropertiesChanged
1195:                        // was sent after plugins were started
1196:                        ((EBComponent) plugin)
1197:                                .handleMessage(new org.gjt.sp.jedit.msg.PropertiesChanged(
1198:                                        null));
1199:                    }
1200:                    EditBus.addToBus((EBPlugin) plugin);
1201:                }
1202:
1203:                // buffers retain a reference to the fold handler in
1204:                // question... and the easiest way to handle fold
1205:                // handler loading is this...
1206:                Buffer buffer = jEdit.getFirstBuffer();
1207:                while (buffer != null) {
1208:                    FoldHandler handler = FoldHandler.getFoldHandler(buffer
1209:                            .getStringProperty("folding"));
1210:                    // == null before loaded
1211:                    if (buffer.getFoldHandler() != null && handler != null
1212:                            && handler != buffer.getFoldHandler()) {
1213:                        buffer.setFoldHandler(handler);
1214:                    }
1215:                    buffer = buffer.getNext();
1216:                }
1217:            } //}}}
1218:
1219:            //{{{ startPluginLater() method
1220:            private void startPluginLater() {
1221:                SwingUtilities.invokeLater(new Runnable() {
1222:                    public void run() {
1223:                        if (!activated)
1224:                            return;
1225:
1226:                        startPlugin();
1227:                    }
1228:                });
1229:            } //}}}
1230:
1231:            //{{{ breakPlugin() method
1232:            private void breakPlugin() {
1233:                plugin = new EditPlugin.Broken(this , plugin.getClassName());
1234:
1235:                // remove action sets, dockables, etc so that user doesn't
1236:                // see the broken plugin
1237:                uninit(false);
1238:                // but we want properties to hang around
1239:                jEdit.addPluginProps(properties);
1240:            } //}}}
1241:
1242:            //}}}
1243:
1244:            //{{{ PluginCacheEntry class
1245:            /**
1246:             * Used by the <code>DockableWindowManager</code> and
1247:             * <code>ServiceManager</code> to handle caching.
1248:             * @since jEdit 4.2pre1
1249:             */
1250:            public static class PluginCacheEntry {
1251:                public static final int MAGIC = 0xB7A2E421;
1252:
1253:                //{{{ Instance variables
1254:                public PluginJAR plugin;
1255:                public long modTime;
1256:
1257:                public String[] classes;
1258:                public URL actionsURI;
1259:                public String[] cachedActionNames;
1260:                public boolean[] cachedActionToggleFlags;
1261:                public URL browserActionsURI;
1262:                public String[] cachedBrowserActionNames;
1263:                public boolean[] cachedBrowserActionToggleFlags;
1264:                public URL dockablesURI;
1265:                public String[] cachedDockableNames;
1266:                public boolean[] cachedDockableActionFlags;
1267:                public boolean[] cachedDockableMovableFlags;
1268:                public URL servicesURI;
1269:                ServiceManager.Descriptor[] cachedServices;
1270:
1271:                public Properties cachedProperties;
1272:                public String pluginClass;
1273:
1274:                //}}}
1275:
1276:                /* read() and write() must be kept perfectly in sync...
1277:                 * its a very simple file format. doing it this way is
1278:                 * faster than serializing since serialization calls
1279:                 * reflection, etc. */
1280:
1281:                //{{{ read() method
1282:                public boolean read(DataInputStream din) throws IOException {
1283:                    int cacheMagic = din.readInt();
1284:                    if (cacheMagic != MAGIC)
1285:                        return false;
1286:
1287:                    String cacheBuild = readString(din);
1288:                    if (!cacheBuild.equals(jEdit.getBuild()))
1289:                        return false;
1290:
1291:                    long cacheModTime = din.readLong();
1292:                    if (cacheModTime != modTime)
1293:                        return false;
1294:
1295:                    actionsURI = readURI(din);
1296:                    cachedActionNames = readStringArray(din);
1297:                    cachedActionToggleFlags = readBooleanArray(din);
1298:
1299:                    browserActionsURI = readURI(din);
1300:                    cachedBrowserActionNames = readStringArray(din);
1301:                    cachedBrowserActionToggleFlags = readBooleanArray(din);
1302:
1303:                    dockablesURI = readURI(din);
1304:                    cachedDockableNames = readStringArray(din);
1305:                    cachedDockableActionFlags = readBooleanArray(din);
1306:                    cachedDockableMovableFlags = readBooleanArray(din);
1307:
1308:                    servicesURI = readURI(din);
1309:                    int len = din.readInt();
1310:                    if (len == 0)
1311:                        cachedServices = null;
1312:                    else {
1313:                        cachedServices = new ServiceManager.Descriptor[len];
1314:                        for (int i = 0; i < len; i++) {
1315:                            ServiceManager.Descriptor d = new ServiceManager.Descriptor(
1316:                                    readString(din), readString(din), null,
1317:                                    plugin);
1318:                            cachedServices[i] = d;
1319:                        }
1320:                    }
1321:
1322:                    classes = readStringArray(din);
1323:
1324:                    cachedProperties = readMap(din);
1325:
1326:                    pluginClass = readString(din);
1327:
1328:                    return true;
1329:                } //}}}
1330:
1331:                //{{{ write() method
1332:                public void write(DataOutputStream dout) throws IOException {
1333:                    dout.writeInt(MAGIC);
1334:                    writeString(dout, jEdit.getBuild());
1335:
1336:                    dout.writeLong(modTime);
1337:
1338:                    writeString(dout, actionsURI);
1339:                    writeStringArray(dout, cachedActionNames);
1340:                    writeBooleanArray(dout, cachedActionToggleFlags);
1341:
1342:                    writeString(dout, browserActionsURI);
1343:                    writeStringArray(dout, cachedBrowserActionNames);
1344:                    writeBooleanArray(dout, cachedBrowserActionToggleFlags);
1345:
1346:                    writeString(dout, dockablesURI);
1347:                    writeStringArray(dout, cachedDockableNames);
1348:                    writeBooleanArray(dout, cachedDockableActionFlags);
1349:                    writeBooleanArray(dout, cachedDockableMovableFlags);
1350:
1351:                    writeString(dout, servicesURI);
1352:                    if (cachedServices == null)
1353:                        dout.writeInt(0);
1354:                    else {
1355:                        dout.writeInt(cachedServices.length);
1356:                        for (int i = 0; i < cachedServices.length; i++) {
1357:                            writeString(dout, cachedServices[i].clazz);
1358:                            writeString(dout, cachedServices[i].name);
1359:                        }
1360:                    }
1361:
1362:                    writeStringArray(dout, classes);
1363:
1364:                    writeMap(dout, cachedProperties);
1365:
1366:                    writeString(dout, pluginClass);
1367:                } //}}}
1368:
1369:                //{{{ Private members
1370:
1371:                //{{{ readString() method
1372:                private static String readString(DataInputStream din)
1373:                        throws IOException {
1374:                    int len = din.readInt();
1375:                    if (len == 0)
1376:                        return null;
1377:                    char[] str = new char[len];
1378:                    for (int i = 0; i < len; i++)
1379:                        str[i] = din.readChar();
1380:                    return new String(str);
1381:                } //}}}
1382:
1383:                //{{{ readURI() method
1384:                private static URL readURI(DataInputStream din)
1385:                        throws IOException {
1386:                    String str = readString(din);
1387:                    if (str == null)
1388:                        return null;
1389:                    else
1390:                        return new URL(str);
1391:                } //}}}
1392:
1393:                //{{{ readStringArray() method
1394:                private static String[] readStringArray(DataInputStream din)
1395:                        throws IOException {
1396:                    int len = din.readInt();
1397:                    if (len == 0)
1398:                        return null;
1399:                    String[] str = new String[len];
1400:                    for (int i = 0; i < len; i++) {
1401:                        str[i] = readString(din);
1402:                    }
1403:                    return str;
1404:                } //}}}
1405:
1406:                //{{{ readBooleanArray() method
1407:                private static boolean[] readBooleanArray(DataInputStream din)
1408:                        throws IOException {
1409:                    int len = din.readInt();
1410:                    if (len == 0)
1411:                        return null;
1412:                    boolean[] bools = new boolean[len];
1413:                    for (int i = 0; i < len; i++) {
1414:                        bools[i] = din.readBoolean();
1415:                    }
1416:                    return bools;
1417:                } //}}}
1418:
1419:                //{{{ readMap() method
1420:                private static Properties readMap(DataInputStream din)
1421:                        throws IOException {
1422:                    Properties returnValue = new Properties();
1423:                    int count = din.readInt();
1424:                    for (int i = 0; i < count; i++) {
1425:                        String key = readString(din);
1426:                        String value = readString(din);
1427:                        if (value == null)
1428:                            value = "";
1429:                        returnValue.put(key, value);
1430:                    }
1431:                    return returnValue;
1432:                } //}}}
1433:
1434:                //{{{ writeString() method
1435:                private static void writeString(DataOutputStream dout,
1436:                        Object obj) throws IOException {
1437:                    if (obj == null) {
1438:                        dout.writeInt(0);
1439:                    } else {
1440:                        String str = obj.toString();
1441:                        dout.writeInt(str.length());
1442:                        dout.writeChars(str);
1443:                    }
1444:                } //}}}
1445:
1446:                //{{{ writeStringArray() method
1447:                private static void writeStringArray(DataOutputStream dout,
1448:                        String[] str) throws IOException {
1449:                    if (str == null) {
1450:                        dout.writeInt(0);
1451:                    } else {
1452:                        dout.writeInt(str.length);
1453:                        for (int i = 0; i < str.length; i++) {
1454:                            writeString(dout, str[i]);
1455:                        }
1456:                    }
1457:                } //}}}
1458:
1459:                //{{{ writeBooleanArray() method
1460:                private static void writeBooleanArray(DataOutputStream dout,
1461:                        boolean[] bools) throws IOException {
1462:                    if (bools == null) {
1463:                        dout.writeInt(0);
1464:                    } else {
1465:                        dout.writeInt(bools.length);
1466:                        for (int i = 0; i < bools.length; i++) {
1467:                            dout.writeBoolean(bools[i]);
1468:                        }
1469:                    }
1470:                } //}}}
1471:
1472:                //{{{ writeMap() method
1473:                private static void writeMap(DataOutputStream dout, Map map)
1474:                        throws IOException {
1475:                    dout.writeInt(map.size());
1476:                    Set<Map.Entry<Object, Object>> set = map.entrySet();
1477:                    for (Map.Entry<Object, Object> entry : set) {
1478:                        writeString(dout, entry.getKey());
1479:                        writeString(dout, entry.getValue());
1480:                    }
1481:                } //}}}
1482:
1483:                //}}}
1484:            } //}}}
1485:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.