Home> Products> IntelliJ IDEA> Plugins> Plugin Structure

IntelliJ IDEA Plugin Structure

Purpose

Plugins are the only possible way for third-parties to extend IDEA functionality. Every plugin uses API exposed by IDEA or other plugins to implement its functionality. This document is focused on plugin system architecture and plugin lifecycle. It doesn’t specify any of the other APIs which may be used by plugins.

Plugin Content

There are 3 ways how to organize plugin content:

1. Plugin consists of one .jar file placed in IDEA_HOME/plugins/. The archive should contain configuration file (META-INF/plugin.xml) and classes which implement the plugin functionality. Configuration file specifies plugin name, description, version, vendor, IDEA version plugin is supposed to be used with, plugin components, actions and action groups, action user interface placement.

IDEA_HOME
Plugins Sample.jar/ com/foo/..... ... ... META-INF plugin.xml

2. Plugin files are located in a folder:

IDEA_HOME
Plugins Sample lib libfoo.jar libbar.jar classes com/foo/..... ... ... META-INF plugin.xml

The 'classes' folder and all jars located in the 'lib' folder are automatically added to the classpath.

3. Plugin files are located in a jar-file which is placed to the lib folder:

IDEA_HOME
Plugins Sample lib libfoo.jar libbar.jar Sample.jar/ com/foo/..... ... ... META-INF plugin.xml

All the jars from 'lib' folder are automatically added to the classpath.

Plugin Class Loaders

For loading the classes of each plugin, IDEA uses a separate class loader. This allows each plugin to use a different version of some library, even if the same library is used by IDEA itself or another plugin.

By default, the classes not found in the plugin class loader are loaded through the main IDEA class loader. However, it is possible to use the depends element in plugin.xml to specify that a plugin depends on one or more other plugins. In this case, the class loaders of those plugins will be used for classes not found in the current plugin. This allows a plugin to reference classes from other plugins.

Plugin Components

Components are the fundamental concept of plugins integration. There are three kinds of components: application-level, project-level and module-level. Application-level components are created and initialized on IDEA start-up. Project-level components are created for each Project instance present in IDEA (please note that components might be created for even unopened projects). Module-level components are created for each Module in every project loaded in IDEA.

Application-level components can be acquired from the Application instance with getComponent(Class) method. Project-level components can be acquired from the Project instance with getComponent(Class) method. Module-level component can be acquired from Module instance with the same method.

Every component should have interface and implementation classes specified in the configuration file. The interface class will be used for retrieving the component from other components and the implementation class will be used for component instantiation. Note that two components of the same level (Application, Project or Module) cannot have the same interface class. Interface and implementation classes can be the same.

Each component has the unique name which is used for its externalization and other internal needs. The name of component is returned by its getComponentName() method.

Components Naming Notation

It's recommended to name components in plugin_name.component_name form.

Application Level Components

Application-level component's implementation class should implement the ApplicationComponent interface. It should have constructor with no parameters which will be used for its instantiation.

Project Level Components

Project-level component's implementation class should implement the ProjectComponent interface. It should have constructor with a single parameter of Project type or with no parameters. If a component needs the Project instance it should provide constructor of the first form and store its parameter into a field for later use.

Module Level Components

Module-level component's implementation class should implement the ModuleComponent interface. It should have constructor with a single parameter of Module type or with no parameters. If a component needs the Module instance it should provide constructor of the first form and store its parameter into a field for later use.

Plug-In Components Configuration

The state of every component will be automatically saved and loaded if the component implements the JDOMExternalizable interface.
The state of application-level components state is saved in the XML file with the same name as the plugin in the config/plugins subfolder of the IDEA settings folder.
Project-level components save their state to the project (.ipr) file. If workspace option in the plugin.xml is set to true, the component will save its configuration to the workspace (.iws) file instead of project (.ipr) file.
Module-level components save their state to the module (.iml) file.
Note that a component should always be ready to save its state.

Defaults

Defaults (components' predefined settings) should be placed in the component_name.xml file. Put this file in the plugin's classpath in the folder corresponding to the default package. readExternal() method will be called on the <component> root tag. If component has defaults, the readExternal() method is called twice: the first time for defaults and the second time for saved configuration.

Plug-In Components Lifecycle

The components are loaded in the following order:

  • Creation - constructor is invoked
  • Initialization - the initComponent method is invoked
  • Configuration - the readExternal method is invoked (if component implements JDOMExternalizable interface)
  • For module components, the moduleAdded method is invoked to notify that a module has been added to the project
  • For project components, the projectOpened method is invoked to notify that a project has been loaded

The components are unloaded in the following order:

Note that you should not request any other components in the constructor of your component, otherwise you'll get an assertion. If you need access to other components when initializing your component you can access them in the initComponent method.

Plug-In Configuration (plugin.xml)

Here is a sample plugin configuration file. This sample showcases and describes all elements which can be used in the plugin.xml file.

<!-- url="" specifies the URL of the plugin homepage (displayed in the Welcome Screen and in "Plugins" settings dialog) -->
<idea-plugin url=http://www.jetbrains.com/idea>
    
    <!-- Plugin name -->
    <name>VssIntegration</name>
    
    
<!-- Unique identifier of the plugin. Must not change between plugin versions. If not         specified, assumed to be equal to <name>. -->
    
<id>VssIntegration</id>
    
    
<!-- Description of the plugin. -->
    <description>Vss integration plugin</description>
    
    
<!-- Description of changes in the latest version of the plugin. Displayed in the "Plugins"         settings dialog and in the plugin repository Web interface. -->
    
<change-notes>Initial release of the plugin.</change-notes>
    
    
<!-- Plugin version -->
    <version>1.0</version>
    
    <!-- The vendor of the plugin. The optional "url" attribute specifies the URL of the vendor         homepage. The optional "email" attribute specifies the e-mail address of the vendor. The         optional "logo" attribute specifies the path within the plugin JAR to a 16x16 icon which is         displayed next to the plugin name in the welcome screen.   -->
    <vendor url="http://www.jetbrains.com" email="support@jetbrains.com"         logo="icons/plugin.png">Foo Inc.</vendor>
    
    
<!-- The unique identifiers of the plugins on which this plugin depends. -->
    
<depends>MyFirstPlugin</depends>
    
<depends>MySecondPlugin</depends>

   
<!-- Allows a plugin to integrate its help system (in JavaHelp format) with the IDEA help         system. The "file" attribute specifies the name of the JAR file in the "help" subdirectory of         the plugin directory. The "path" attribute specifies the name of the helpset file within the         JAR file.-->
    <helpset file="myhelp.jar" path="/Help.hs" />
   
    <!-- Minimum and maximum build of IDEA compatible with the plugin -->
    <idea-version since-build=”3000” until-build=”3999”/>    
    
    <!-- Plugin's application components -->
    <application-components>
        <component>
            <!-- Component's interface class -->
            <interface-class>com.foo.Component1Interface</interface-class>
            <!-- Component's implementation class -->
            <implementation-class>com.foo.impl.Component1Impl</implementation-class>
        </component>
    </application-components>
    
    <!-- Plugin's project components -->
    <project-components>
        <component>
            <!-- Interface and implementation classes are the same -->
            <interface-class>com.foo.Component2</interface-class>
            <!-- Save state to the .iws instead of .ipr -->
            <option name="workspace" value="true" />            
        </component>
    </project-components>
    
    
<!-- Plugin's module components -->
    
<module-components>
        
<component>
            
<interface-class>com.foo.Component3</interface-class>
        
</component>
    
</module-components>

    
<!-- Actions -->
    <actions>    
        <action id="VssIntegration.GarbageCollection" class="com.foo.impl.CollectGarbage"             text="Collect _Garbage" description="Run garbage collector">
            <keyboard-shortcut first-keystroke="control alt G" second-keystroke="C"             keymap="$default"/>
        </action>
    </actions>
    
    
<!-- Extension points defined by the plugin. Extension points are registered by a plugin so         that other plugins can provide this plugin with certain data. The "beanClass" attribute         specifies the class the implementations of which can be used for the extension point. -->
    
<extensionPoints>    
        
<extensionPoint name="testExtensionPoint"             beanClass="com.foo.impl.MyExtensionBean"/>
    
</extensionPoints>

    
<!-- Extensions which the plugin adds to extension points defined by the IDEA core or by         other plugins. The "xmlns" attribute specifies the ID of the plugin defining the extension         point, or "com.intellij" if the extension point is defined by the IDEA core. The name of the         tag within the <extensions> tag matches the name of the extension point, and the         "implementation" class specifies the name of the class added to the extension point. -->
    
<extensions xmlns="VssIntegration">    
        
<testExtensionPoint implementation="com.foo.impl.MyExtensionImpl"/>
    
</extensions>
</idea-plugin>