Java tutorial
/* * This file is part of the OpenCms plugin for IntelliJ by mediaworx. * * For further information about the OpenCms plugin for IntelliJ, please * see the project website at GitHub: * https://github.com/mediaworx/opencms-intellijplugin * * Copyright (C) 2007-2016 mediaworx berlin AG (http://www.mediaworx.com) * * 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 3 of the License, or (at your * option) 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package com.mediaworx.intellij.opencmsplugin; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileManagerListener; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; import com.mediaworx.intellij.opencmsplugin.actions.menus.OpenCmsEditorPopupMenu; import com.mediaworx.intellij.opencmsplugin.actions.menus.OpenCmsEditorTabPopupMenu; import com.mediaworx.intellij.opencmsplugin.actions.menus.OpenCmsMainMenu; import com.mediaworx.intellij.opencmsplugin.actions.menus.OpenCmsProjectPopupMenu; import com.mediaworx.intellij.opencmsplugin.configuration.OpenCmsPluginConfigurationComponent; import com.mediaworx.intellij.opencmsplugin.configuration.OpenCmsPluginConfigurationData; import com.mediaworx.intellij.opencmsplugin.connector.OpenCmsPluginConnector; import com.mediaworx.intellij.opencmsplugin.listeners.OpenCmsModuleFileChangeListener; import com.mediaworx.intellij.opencmsplugin.opencms.OpenCmsConfiguration; import com.mediaworx.intellij.opencmsplugin.opencms.OpenCmsModules; import com.mediaworx.intellij.opencmsplugin.sync.VfsAdapter; import com.mediaworx.intellij.opencmsplugin.toolwindow.OpenCmsPluginToolWindowFactory; import com.mediaworx.intellij.opencmsplugin.toolwindow.OpenCmsToolWindowConsole; import com.mediaworx.opencms.ideconnector.client.IDEConnectorClient; import com.mediaworx.opencms.ideconnector.client.IDEConnectorClientConfiguration; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.io.File; /** * OpenCms plugin for IntelliJ providing IntelliJ menu actions to sync resources to and from the OpenCms VFS, to publish * resources right from your IDE (using an additional OpenCms module), to create module manifest files, to package * OpenCms modules into module zips and to import those module zips to your local OpenCms instance. * OpenCms menu actions are provided in four different locations: * <ul> * <li>At the main menu</li> * <li>In the project window (left)</li> * <li>In the main editor window (center)</li> * <li>In the file tabs (usually on top of the editor)</li> * </ul> * * The configuration of the plugin is done on two levels: * <br /><br /> * <strong>Project level</strong> * <br /> * Some general options like the path to your local OpenCms webapp, your OpenCms user credentials or generic settings * are done on the project level. These options can be found under File > Settings > OpenCms Plugin. * <br /><br /> * <strong>Module level</strong> * <br /> * Module specific settings are configured for each separate module under File > Project Structure > Modules > [name of * the module] > Tab "OpenCms Module". Some module settings can be configured globally on the project level and changed * for individual modules on the module level. * * <p>See the plugin's <a href="https://github.com/mediaworx/opencms-intellijplugin/wiki">Wiki</a> on GitHub for more * information.</p> * * @author Kai Widmann, 2007-2016 mediaworx berlin AG */ public class OpenCmsPlugin implements ProjectComponent { private static final Logger LOG = Logger.getInstance(OpenCmsPlugin.class); public static final String TOOLWINDOW_ID = "OpenCms"; private static final String OPENCMS_MENU_ID = "OpenCmsPlugin.ActionMenu"; private static final String PROJECT_POPUP_MENU_ID = "OpenCmsPlugin.ProjectPopupMenu"; private static final String EDITOR_POPUP_MENU_ID = "OpenCmsPlugin.EditorPopupMenu"; private static final String TAB_POPUP_MENU_ID = "OpenCmsPlugin.TabsPopupGroup"; private static final Icon MENU_ICON = new ImageIcon(OpenCmsPlugin.class.getResource("/icons/opencms_menu.png")); /** The IntelliJ project */ private Project project; private VirtualFileManagerListener virtualFileManagerListener; /** Helper object to retrieve configuration data from the OpenCms configuration */ private OpenCmsConfiguration openCmsConfiguration; /** Container for all OpenCms modules configured in the project */ private OpenCmsModules openCmsModules; /** Adapter used to sync the RFS with the OpenCms VFS */ private VfsAdapter vfsAdapter; /** * Connector used to retrieve module or resource information from OpenCms and execute actions in OpenCms * (e.g. publishing), backed by the OpenCms module "com.mediaworx.opencms.ideconnector" */ private OpenCmsPluginConnector pluginConnector; /** * Client used to execute actions in OpenCms (new with version 1.7). Right now it runs side by side with the old * {@link #pluginConnector} and adds some additional functionality (importing modules). In a future release the * connectorClient is planned to replace the old pluginConnector. */ private IDEConnectorClient connectorClient; /** * ToolWindow for the OpenCms plugin */ private ToolWindow toolWindow; /** * Console used to log OpenCms actions like sync or publish */ private OpenCmsToolWindowConsole console; /** IntelliJ's action manager */ private ActionManager actionManager; /** * Set to <code>true</code> the first time the OpenCms plugin is enabled */ private boolean wasInitialized = false; /** * Creates a new plugin instance, called by IntelliJ * @param project the IntelliJ project */ public OpenCmsPlugin(Project project) { this.project = project; openCmsModules = new OpenCmsModules(this); } /** * Initializes the plugin, called by IntelliJ */ public void initComponent() { LOG.warn("initComponent called, project: " + project.getName()); actionManager = ActionManager.getInstance(); } /** * Enables the plugin (if it is enabled in the project level configuration), called by IntelliJ whenever a project * is opened. */ public void projectOpened() { OpenCmsPluginConfigurationData config = getPluginConfiguration(); if (config != null && config.isOpenCmsPluginEnabled()) { enable(); } } /** * Does nothing, called by IntelliJ whenever a project is closed. */ public void projectClosed() { } /** * Enables the plugin for the current project. Initializes the plugin and its actions if initialization was not * done before. If the plugin connector is activated in the project level configuration it gets initialized as well. */ public void enable() { if (!wasInitialized) { OpenCmsPluginConfigurationData config = getPluginConfiguration(); if (config != null && config.isOpenCmsPluginEnabled()) { if (config.isPluginConnectorEnabled()) { pluginConnector = new OpenCmsPluginConnector(config.getConnectorUrl(), config.getUsername(), config.getPassword(), config.isUseMetaDateVariablesEnabled(), config.isUseMetaIdVariablesEnabled()); } } registerListeners(); registerMenus(); wasInitialized = true; checkWebappRootConfiguration(true); } else { setToolWindowAvailable(true); } } /** * Disables the plugin. The only thing done here is deactivating the plugin's tool window, menus are disabled * automatically because all actions are hidden if the plugin is deactivated */ public void disable() { if (wasInitialized) { setToolWindowAvailable(false); } } /** * Registers the OpenCms menus for MainMenu, ProjectPopup, EditorPopup and EditorTabPopup */ private void registerMenus() { registerMainMenu(); registerProjectPopupMenu(); registerEditorPopupMenu(); registerEditorTabPopupMenu(); } /** * Registers listeners for IntelliJ events. The listeners only listen for file change events and only file * deletions, renames and moves are handled (depending on the project level configuration these changes may * be synced back to OpenCms). */ private void registerListeners() { MessageBus bus = ApplicationManager.getApplication().getMessageBus(); MessageBusConnection connection = bus.connect(); OpenCmsModuleFileChangeListener fileChangeListener = new OpenCmsModuleFileChangeListener(this); connection.subscribe(VirtualFileManager.VFS_CHANGES, fileChangeListener); } /** * Adds a menu action to a given menu group. * @param group the menu group the action should be added to * @param id the action's identifier * @param action the action itself * @param text text to be displayed in the menu */ public void addAction(DefaultActionGroup group, String id, AnAction action, String text) { addAction(group, id, action, text, null, null); } /** * Adds a menu action to a given menu group. * @param group the menu group the action should be added to * @param id the action's identifier * @param action the action itself * @param text text to be displayed in the menu * @param icon icon to be displayed with the menu action (usually displayed befor the text) */ private void addAction(DefaultActionGroup group, String id, AnAction action, String text, Icon icon) { addAction(group, id, action, text, icon, null); } /** * * Adds a menu action to a given menu group. * @param group the menu group the action should be added to * @param id the action's identifier * @param action the action itself * @param text text to be displayed in the menu * @param icon icon to be displayed with the menu action (usually displayed befor the text) * @param constraints constraints telling IntelliJ where to position the menu action */ private void addAction(DefaultActionGroup group, String id, AnAction action, String text, Icon icon, Constraints constraints) { action.getTemplatePresentation().setText(text); if (icon != null) { action.getTemplatePresentation().setIcon(icon); } actionManager.registerAction(id, action); if (constraints == null) { group.add(action); } else { group.add(action, constraints); } } /** * Creates and registers the OpenCms menu for the main menu as an action group */ private void registerMainMenu() { OpenCmsMainMenu openCmsMainMenu = (OpenCmsMainMenu) actionManager.getAction(OPENCMS_MENU_ID); if (openCmsMainMenu == null) { DefaultActionGroup mainMenu = (DefaultActionGroup) actionManager.getAction(IdeActions.GROUP_MAIN_MENU); openCmsMainMenu = OpenCmsMainMenu.getInstance(this); addAction(mainMenu, OPENCMS_MENU_ID, openCmsMainMenu, "_OpenCms", null, new Constraints(Anchor.BEFORE, "HelpMenu")); } } /** * Creates and registers the OpenCms menu for the project popup as an action group */ private void registerProjectPopupMenu() { OpenCmsProjectPopupMenu openCmsProjectPopupMenu = (OpenCmsProjectPopupMenu) actionManager .getAction(PROJECT_POPUP_MENU_ID); if (openCmsProjectPopupMenu == null) { DefaultActionGroup projectPopup = (DefaultActionGroup) actionManager .getAction(IdeActions.GROUP_PROJECT_VIEW_POPUP); openCmsProjectPopupMenu = new OpenCmsProjectPopupMenu(this); addAction(projectPopup, PROJECT_POPUP_MENU_ID, openCmsProjectPopupMenu, "_OpenCms", MENU_ICON, new Constraints(Anchor.BEFORE, "RevealIn")); projectPopup.add(Separator.getInstance(), new Constraints(Anchor.AFTER, PROJECT_POPUP_MENU_ID)); } } /** * Creates and registers the OpenCms menu for the editor popup as an action group */ private void registerEditorPopupMenu() { OpenCmsEditorPopupMenu openCmsEditorPopupMenu = (OpenCmsEditorPopupMenu) actionManager .getAction(EDITOR_POPUP_MENU_ID); if (openCmsEditorPopupMenu == null) { DefaultActionGroup editorPopup = (DefaultActionGroup) actionManager .getAction(IdeActions.GROUP_EDITOR_POPUP); openCmsEditorPopupMenu = new OpenCmsEditorPopupMenu(this); addAction(editorPopup, EDITOR_POPUP_MENU_ID, openCmsEditorPopupMenu, "_OpenCms", MENU_ICON, new Constraints(Anchor.AFTER, "ChangeFileEncodingAction")); editorPopup.addAction(Separator.getInstance(), new Constraints(Anchor.BEFORE, EDITOR_POPUP_MENU_ID)); } } /** * Creates and registers the OpenCms menu for the editor tab popup as an action group */ private void registerEditorTabPopupMenu() { OpenCmsEditorTabPopupMenu openCmsEditorTabPopupMenu = (OpenCmsEditorTabPopupMenu) actionManager .getAction(TAB_POPUP_MENU_ID); if (openCmsEditorTabPopupMenu == null) { // DefaultActionGroup editorTabPopup = (DefaultActionGroup)actionManager.getAction(IdeActions.GROUP_EDITOR_TAB_POPUP); DefaultActionGroup editorTabPopup = (DefaultActionGroup) actionManager .getAction("EditorTabPopupMenuEx"); openCmsEditorTabPopupMenu = new OpenCmsEditorTabPopupMenu(this); editorTabPopup.addAction(Separator.getInstance()); // addAction(editorTabPopup, TAB_POPUP_MENU_ID, openCmsEditorTabPopupMenu, "_OpenCms", MENU_ICON, new Constraints(Anchor.AFTER, "UnsplitAll")); addAction(editorTabPopup, TAB_POPUP_MENU_ID, openCmsEditorTabPopupMenu, "_OpenCms", MENU_ICON, new Constraints(Anchor.BEFORE, "RunContextPopupGroup")); // editorTabPopup.addAction(Separator.getInstance(), new Constraints(Anchor.BEFORE, TAB_POPUP_MENU_ID)); editorTabPopup.addAction(Separator.getInstance(), new Constraints(Anchor.AFTER, TAB_POPUP_MENU_ID)); } } public boolean checkWebappRootConfiguration(boolean showDialog) { boolean configOK = true; OpenCmsPluginConfigurationData config = getPluginConfiguration(); if (config != null && config.isOpenCmsPluginEnabled()) { File file = new File(config.getWebappRoot()); // show an error message if the webapp root folder was not found if (!file.exists()) { configOK = false; if (showDialog) { Messages.showDialog( "The Webapp Root was not found.\nPlease check the OpenCms Webapp Root in the OpenCms Plugin settings.", "OpenCms Plugin - Configuration Error", new String[] { "Ok" }, 0, Messages.getErrorIcon()); } } else { // check if the OpenCms configuration path exists file = new File(config.getWebappRoot() + OpenCmsConfiguration.CONFIGPATH); if (!file.exists()) { configOK = false; if (showDialog) { Messages.showDialog( "The OpenCms configuration was not found.\nPlease check the OpenCms Webapp Root in the OpenCms Plugin settings.", "Error", new String[] { "Ok" }, 0, Messages.getErrorIcon()); } } } } return configOK; } /** * Does some cleanup, called by IntelliJ. */ public void disposeComponent() { project = null; if (openCmsConfiguration != null) { openCmsConfiguration.stopMonitoringConfigurationChanges(); openCmsConfiguration = null; } openCmsModules = null; vfsAdapter = null; pluginConnector = null; toolWindow = null; console = null; actionManager = null; } /** * Returns the component's name. * @return "OpenCmsPlugin.MainComponent" */ @NotNull public String getComponentName() { return "OpenCmsPlugin.MainComponent"; } /** * Returns the IntelliJ project * @return the IntelliJ project */ public Project getProject() { return project; } /** * Returns the helper object to retrieve configuration data from the OpenCms configuration * @return the OpenCms configuration helper object */ public OpenCmsConfiguration getOpenCmsConfiguration() { if (openCmsConfiguration == null) { OpenCmsPluginConfigurationData config = getPluginConfiguration(); openCmsConfiguration = new OpenCmsConfiguration(config); openCmsConfiguration.startMonitoringConfigurationChanges(); } return openCmsConfiguration; } /** * Returns the plugin's project level configuration data * @return the project level configuration data */ public OpenCmsPluginConfigurationData getPluginConfiguration() { if (project != null && project.getComponent(OpenCmsPluginConfigurationComponent.class) != null) { return project.getComponent(OpenCmsPluginConfigurationComponent.class).getState(); } else { return null; } } /** * Returns the container for all OpenCms modules configured in the project * @return the OpenCms module container */ public OpenCmsModules getOpenCmsModules() { return openCmsModules; } /** * refreshes all OpenCms modules (e.g. after configuration changes) */ public void refreshOpenCmsModules() { openCmsModules.refreshAllModules(); } /** * Returns the adapter used to sync the RFS with the OpenCms VFS * @return the VFS adapter for sync actions */ public VfsAdapter getVfsAdapter() { if (vfsAdapter == null) { OpenCmsPluginConfigurationData config = getPluginConfiguration(); if (config != null && config.isOpenCmsPluginEnabled() && config.getPassword() != null && config.getPassword().length() > 0) { vfsAdapter = new VfsAdapter(config.getRepository(), config.getUsername(), config.getPassword()); } } return vfsAdapter; } /** * Returns the connector used to retrieve module or resource information from OpenCms and execute actions in * OpenCms (e.g. publishing) * @return the OpenCms plugin connector for information retrieval and publishing * @deprecated the old connector (via JSP) will be removed once all functionality is moved to the new connector * service (via Servlet) */ @Deprecated public OpenCmsPluginConnector getPluginConnector() { return pluginConnector; } /** * Sets the connector used to retrieve module or resource information from OpenCms and execute actions in * OpenCms (e.g. publishing) * * @param pluginConnector the OpenCms plugin connector for information retrieval and publishing * @deprecated the old connector (via JSP) will be removed once all functionality is moved to the new connector * service (via Servlet) */ @Deprecated public void setPluginConnector(OpenCmsPluginConnector pluginConnector) { this.pluginConnector = pluginConnector; } /** * Returns the IDE connector client that may be used to execute actions on the local OpenCms instance (must be * running) (new with version 1.7). Right now the connector client runs side by side with the old * {@link #pluginConnector} and adds some additional functionality (importing modules). In a future release the * connectorClient is planned to replace the old pluginConnector. * @return the IDE connector client */ public IDEConnectorClient getConnectorClient() { if (connectorClient == null) { initConnectorClient(); } return connectorClient; } /** * Initializes the connector client */ private void initConnectorClient() { OpenCmsPluginConfigurationData config = getPluginConfiguration(); if (config != null && config.isOpenCmsPluginEnabled() && config.isPluginConnectorServiceEnabled() && StringUtils.isNotBlank(config.getConnectorServiceUrl())) { IDEConnectorClientConfiguration clientConfiguration = new IDEConnectorClientConfiguration(); clientConfiguration.setConnectorServiceBaseUrl(config.getConnectorServiceUrl()); connectorClient = new IDEConnectorClient(clientConfiguration); } } /** * Sets the connector client used to access the new IDE Connector Service (e.g. for importing modules) * @param connectorClient */ public void setConnectorClient(IDEConnectorClient connectorClient) { this.connectorClient = connectorClient; } /** * Initializes the plugin's tool window */ private void initToolWindow() { if (project == null) { LOG.info("Unable to initialize the tool window since the project is null"); return; } ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project); if (toolWindowManager == null) { LOG.info("ToolWindowManager could not be retrieved from the project, it may not be registered yet."); return; } toolWindow = toolWindowManager.getToolWindow(OpenCmsPlugin.TOOLWINDOW_ID); if (toolWindow == null) { OpenCmsPluginConfigurationData config = getPluginConfiguration(); toolWindow = toolWindowManager.registerToolWindow(OpenCmsPlugin.TOOLWINDOW_ID, false, ToolWindowAnchor.BOTTOM); toolWindow.setIcon(new ImageIcon(this.getClass().getResource("/icons/opencms_13.png"))); toolWindow.setAvailable(config != null && config.isOpenCmsPluginEnabled(), null); OpenCmsPluginToolWindowFactory toolWindowFactory = new OpenCmsPluginToolWindowFactory(); toolWindowFactory.createToolWindowContent(project, toolWindow); } } /** * Returns the plugin's tool window * @return the plugin's tool window */ public ToolWindow getToolWindow() { if (toolWindow == null) { initToolWindow(); } return toolWindow; } /** * Activates or deactivates the plugin's tool window * @param available <code>true</code> to activate and <code>false</code> to deactivate the tool window */ public void setToolWindowAvailable(boolean available) { ToolWindow toolWindow = getToolWindow(); toolWindow.setAvailable(available, null); } /** * Activates the plugin's tool window to display the console */ public void showConsole() { if (toolWindow == null || !toolWindow.isActive()) { getToolWindow().activate(null); } } /** * Returns the console used to log OpenCms actions like sync or publish * @return the console used to log OpenCms actions like sync or publish */ public OpenCmsToolWindowConsole getConsole() { // if the console has not been initialized ... if (console == null) { initToolWindow(); // ... initialize the tool window (containing the console) } return console; } /** * Sets the console used to log OpenCms actions like sync or publish * @param console the console used to log OpenCms actions like sync or publish */ public void setConsole(OpenCmsToolWindowConsole console) { this.console = console; } }