/* * Copyright 2003-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.plugins.projectplugins; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.project.Project; import com.intellij.util.containers.HashMap; import com.intellij.util.xmlb.annotations.Tag; import jetbrains.mps.ide.ThreadUtils; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.ide.tools.BaseTool; import jetbrains.mps.plugins.custom.BaseCustomProjectPlugin; import jetbrains.mps.plugins.prefs.BaseProjectPrefsComponent; import jetbrains.mps.plugins.relations.RelationDescriptor; import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import jetbrains.mps.plugins.tool.BaseGeneratedTool; import jetbrains.mps.plugins.projectplugins.BaseProjectPlugin.PluginState; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.module.ModelAccess; import java.util.ArrayList; import java.util.Collections; import java.util.List; public abstract class BaseProjectPlugin implements PersistentStateComponent<PluginState> { private static final Logger LOG = LogManager.getLogger(BaseProjectPlugin.class); private Project myProject; private List<BaseTool> myTools = new ArrayList<BaseTool>(); private EDTAccessor<List<BaseTool>> myInitializedTools = new EDTAccessor<List<BaseTool>>(new ArrayList<BaseTool>()); private List<BaseCustomProjectPlugin> myCustomPlugins = new ArrayList<BaseCustomProjectPlugin>(); private List<BaseProjectPrefsComponent> myPrefsComponents = new ArrayList<BaseProjectPrefsComponent>(); private List<RelationDescriptor> myTabDescriptors = new ArrayList<RelationDescriptor>(); public Project getProject() { return myProject; } //------------------stuff to generate----------------------- protected List<RelationDescriptor> initTabbedEditors(Project project) { return new ArrayList<RelationDescriptor>(); } //remove after 3.3 protected List<BaseGeneratedTool> initAllTools(Project project) { return new ArrayList<BaseGeneratedTool>(); } protected List<BaseTool> initAllTools1(Project project) { return new ArrayList<BaseTool>(); } protected List<BaseProjectPrefsComponent> createPreferencesComponents(Project project) { return new ArrayList<BaseProjectPrefsComponent>(); } protected List<BaseCustomProjectPlugin> initCustomParts(Project project) { return new ArrayList<BaseCustomProjectPlugin>(); } @NotNull private ModelAccess getModelAccess() { ModelAccess modelAccess = ProjectHelper.getModelAccess(myProject); assert modelAccess != null; return modelAccess; } public final void init(@NotNull final Project project) { myProject = project; initTabbedEditors1(project); initCustomParts1(project); initTools1(); createPrefComponents1(); registerPrefsAndTools(); } private void createPrefComponents1() { try { myPrefsComponents = createPreferencesComponents(myProject); } catch (Throwable t) { LOG.error("Exception on project preference components init:", t); } } protected void initTools1() { try { myTools.addAll(initAllTools(myProject)); myTools.addAll(initAllTools1(myProject)); } catch (Throwable t) { LOG.error("Exception on tools init:", t); } } protected void initTabbedEditors1(Project project) { try { myTabDescriptors = initTabbedEditors(project); } catch (Throwable t) { LOG.error("Exception on tabbed editors init:", t); } } protected void initCustomParts1(Project project) { try { myCustomPlugins = initCustomParts(project); } catch (Throwable t) { LOG.error("Exception on custom project plugins init:", t); } } private void registerPrefsAndTools() { final List<BaseTool> toolsToInit = new ArrayList<BaseTool>(myTools); final List<BaseProjectPrefsComponent> prefsToInit = new ArrayList<BaseProjectPrefsComponent>(myPrefsComponents); for (BaseTool tool : toolsToInit) { try { tool.init(myProject); tool.register(); } catch (Throwable t) { LOG.error("Exception on a tool init: " + tool, t); } myInitializedTools.get().add(tool); } for (BaseProjectPrefsComponent component : prefsToInit) { try { component.init(); } catch (Throwable t) { LOG.error("Exception on a pref component init: " + component, t); } } } public final void dispose() { disposePrefsToolsAndCustomParts(); disposeTabbedEditors(); } private void disposeTabbedEditors() { myTabDescriptors.clear(); } private void disposePrefsToolsAndCustomParts() { disposePrefComponents(myPrefsComponents); disposeTools(myTools); disposeCustomPlugins(myCustomPlugins); myPrefsComponents.clear(); myTools.clear(); myCustomPlugins.clear(); } private void disposeCustomPlugins(final List<BaseCustomProjectPlugin> customPluginsToDispose) { for (BaseCustomProjectPlugin customPlugin : customPluginsToDispose) { try { customPlugin.dispose(); } catch (Throwable t) { LOG.error("Exception on the custom project plugin component dispose: " + customPlugin, t); } } } private void disposeTools(List<BaseTool> toolsToDispose) { for (BaseTool tool : toolsToDispose) { if (myInitializedTools.get().contains(tool)) { try { tool.unregister(); tool.dispose(); } catch (Throwable t) { LOG.error("Exception on a tool dispose: " + tool, t); } finally { myInitializedTools.get().remove(tool); } } } } private void disposePrefComponents(List<BaseProjectPrefsComponent> prefsComponentsToDispose) { for (BaseProjectPrefsComponent component : prefsComponentsToDispose) { try { component.dispose(); } catch (Throwable t) { LOG.error("Exception on a project preference component dispose: " + component, t); } } } //------------------tools stuff----------------------- public List<BaseProjectPrefsComponent> getPrefsComponents() { return Collections.unmodifiableList(myPrefsComponents); } public List<BaseTool> getTools() { return Collections.unmodifiableList(myTools); } public List<RelationDescriptor> getTabDescriptors() { return Collections.unmodifiableList(myTabDescriptors); } //----------------STATE STUFF------------------------ @Override public PluginState getState() { PluginState state = new PluginState(); for (BaseProjectPrefsComponent component : myPrefsComponents) { try { Element componentState = component.getState(); state.myComponentsState.add(new ComponentState(component.getClass().getName(), componentState)); } catch (Throwable t) { LOG.error("", t); } } return state; } @Override public void loadState(PluginState state) { HashMap<String, BaseProjectPrefsComponent> components = new HashMap<String, BaseProjectPrefsComponent>(); for (BaseProjectPrefsComponent component : myPrefsComponents) { components.put(component.getClass().getName(), component); } for (ComponentState componentState : state.myComponentsState) { if (componentState.second == null) return; try { BaseProjectPrefsComponent component = components.get(componentState.first); if (component != null) { component.loadState(componentState.second); } } catch (Throwable t) { LOG.error("", t); } } } public static class PluginState { public List<ComponentState> myComponentsState = new ArrayList<ComponentState>(); } public static class ComponentState { public String first; @Tag(value = "params") public Element second; public ComponentState() { } public ComponentState(String first, Element second) { this.first = first; this.second = second; } } private static class EDTAccessor<T> { private T myT; public EDTAccessor(T t) { myT = t; } public T get() { ThreadUtils.assertEDT(); return myT; } } }