├── .gitignore ├── META-INF └── plugin.xml ├── README.md ├── lib ├── curator-client-2.12.0.jar ├── curator-framework-2.12.0.jar ├── guava-16.0.1.jar ├── slf4j-api-1.7.20.jar └── zookeeper-3.4.11.jar ├── src └── main │ ├── java │ └── org │ │ └── mvnsearch │ │ └── intellij │ │ └── plugin │ │ └── zookeeper │ │ ├── ZkConfigPersistence.java │ │ ├── ZkNodePathReferenceContributor.java │ │ ├── ZkProjectComponent.java │ │ ├── actions │ │ ├── CopyNodePathAction.java │ │ ├── CreateNodeAction.java │ │ ├── DeleteNodeAction.java │ │ ├── OpenZkNodeInEditorAction.java │ │ ├── UpdateZkNodeAction.java │ │ └── ZkTreeRefreshAction.java │ │ ├── ui │ │ ├── ZkConfigurable.form │ │ ├── ZkNode.java │ │ ├── ZkProjectConfigurable.java │ │ └── ZkTreeModel.java │ │ └── vfs │ │ ├── ZkNodeVirtualFile.java │ │ └── ZkVirtualFileSystem.java │ └── resources │ └── icons │ └── zookeeper_small.png └── zookeeper-intellij.iml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | *.class 4 | 5 | # Mobile Tools for Java (J2ME) 6 | .mtj.tmp/ 7 | 8 | # Package Files # 9 | *.war 10 | *.ear 11 | 12 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 13 | hs_err_pid* 14 | 15 | 16 | ### JetBrains template 17 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 18 | 19 | *.iml 20 | 21 | ## Directory-based project format: 22 | .idea/ 23 | # if you remove the above rule, at least ignore the following: 24 | 25 | # User-specific stuff: 26 | # .idea/workspace.xml 27 | # .idea/tasks.xml 28 | # .idea/dictionaries 29 | 30 | # Sensitive or high-churn files: 31 | # .idea/dataSources.ids 32 | # .idea/dataSources.xml 33 | # .idea/sqlDataSources.xml 34 | # .idea/dynamic.xml 35 | # .idea/uiDesigner.xml 36 | 37 | # Gradle: 38 | # .idea/gradle.xml 39 | # .idea/libraries 40 | 41 | # Mongo Explorer plugin: 42 | # .idea/mongoSettings.xml 43 | 44 | ## File-based project format: 45 | *.ipr 46 | *.iws 47 | 48 | ## Plugin-specific files: 49 | 50 | # IntelliJ 51 | /out/ 52 | 53 | # mpeltonen/sbt-idea plugin 54 | .idea_modules/ 55 | 56 | # JIRA plugin 57 | atlassian-ide-plugin.xml 58 | 59 | # Crashlytics plugin (for Android Studio and IntelliJ) 60 | com_crashlytics_export_strings.xml 61 | crashlytics.properties 62 | crashlytics-build.properties 63 | 64 | 65 | -------------------------------------------------------------------------------- /META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | zookeeper 4 | ZooKeeper 5 | 0.0.14 6 | 7 | Jacky Chan 8 | 9 | 10 | 11 | Manage ZooKeeper in IntelliJ IDEA. 12 |
13 | After install ZooKeeper plugin, please open "Preferences" to set connection information in "ZooKeeper" item, 14 | then you will find a "ZooKeeper" tool windown, click "ZooKeeper" tool window to visit ZK file system. 15 |
16 | 26 | ]]> 27 |
28 | 29 | 30 | 46 | ]]> 47 | 48 | 49 | 50 | 51 | 52 | 54 | 55 | com.intellij.modules.lang 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.mvnsearch.intellij.plugin.zookeeper.ZkProjectComponent 65 | 66 | 67 | 68 | 69 | 70 | 72 | 73 | 74 | 76 | 77 | 79 | 80 | 82 | 83 | 85 | 86 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 96 | 97 | 98 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | IntelliJ IDEA ZooKeeper Plugin 2 | ======================================= 3 | ZooKeeper plugin for IntelliJ IDEA, and you can operate ZooKeeper directly in IDEA. 4 | 5 | ### Features 6 | 7 | * ZooKeeper configuration for project: enable, host, port 8 | * ZeeKeeper tool window to display ZooKeeper file system tree 9 | * Double click to open node editor for ZooKeeper node 10 | * Update node value by editor popup menu 11 | * Right click ZK tree node to popup operation menu 12 | * Create Node: path support, such as com/xxx/yyy 13 | * Delete Node: rmr support 14 | * Refresh ZK tree on tool window bar 15 | * Diff with ZK Node 16 | * namespace filter 17 | * encoding support 18 | * multi ip 19 | * directory node edit 20 | 21 | ### RoadMap 22 | 23 | * Code completion for Curator(forPath, Reference, quick lookup) and ZooKeeper Client 24 | * Dump ZK: find file support 25 | * Local History 26 | * zip support(such as *.xml.zip with one file) 27 | -------------------------------------------------------------------------------- /lib/curator-client-2.12.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linux-china/zookeeper-intellij/dd9ac9cf2e5a3d43a37c78fcabb6e06152d7118b/lib/curator-client-2.12.0.jar -------------------------------------------------------------------------------- /lib/curator-framework-2.12.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linux-china/zookeeper-intellij/dd9ac9cf2e5a3d43a37c78fcabb6e06152d7118b/lib/curator-framework-2.12.0.jar -------------------------------------------------------------------------------- /lib/guava-16.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linux-china/zookeeper-intellij/dd9ac9cf2e5a3d43a37c78fcabb6e06152d7118b/lib/guava-16.0.1.jar -------------------------------------------------------------------------------- /lib/slf4j-api-1.7.20.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linux-china/zookeeper-intellij/dd9ac9cf2e5a3d43a37c78fcabb6e06152d7118b/lib/slf4j-api-1.7.20.jar -------------------------------------------------------------------------------- /lib/zookeeper-3.4.11.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linux-china/zookeeper-intellij/dd9ac9cf2e5a3d43a37c78fcabb6e06152d7118b/lib/zookeeper-3.4.11.jar -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/ZkConfigPersistence.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper; 2 | 3 | import com.intellij.openapi.components.*; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.openapi.util.text.StringUtil; 6 | import com.intellij.util.xmlb.XmlSerializerUtil; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | /** 10 | * zookeeper configuration persistence 11 | * 12 | * @author linux_china 13 | */ 14 | @State(name = "ZooKeeperConfig", storages = {@Storage(StoragePathMacros.WORKSPACE_FILE)}) 15 | public class ZkConfigPersistence implements PersistentStateComponent { 16 | public String host; 17 | public Integer port; 18 | public String charset; 19 | public String whitePaths; 20 | public boolean enabled; 21 | public boolean tooltip; 22 | 23 | public static ZkConfigPersistence getInstance(Project project) { 24 | return ServiceManager.getService(project, ZkConfigPersistence.class); 25 | } 26 | 27 | @Nullable 28 | public ZkConfigPersistence getState() { 29 | return this; 30 | } 31 | 32 | public void loadState(ZkConfigPersistence state) { 33 | XmlSerializerUtil.copyBean(state, this); 34 | } 35 | 36 | public boolean isAvailable() { 37 | return enabled && StringUtil.isNotEmpty(host); 38 | } 39 | 40 | public String getZkUrl() { 41 | if (host.contains(":")) { 42 | return host; 43 | } else if (host.contains(",")) { 44 | return host.replaceAll("[\\s,]+", ":" + port + ","); 45 | } else { 46 | return host + ":" + port; 47 | } 48 | } 49 | 50 | public String getFirstServer() { 51 | String zkUrl = getZkUrl(); 52 | if (zkUrl.contains(",")) { 53 | return zkUrl.substring(0, zkUrl.indexOf(",")); 54 | } 55 | return zkUrl; 56 | } 57 | 58 | public String getTitle() { 59 | String zkUrl = getZkUrl(); 60 | if (zkUrl.contains(",")) { 61 | return zkUrl.substring(0, zkUrl.indexOf(",")); 62 | } 63 | return zkUrl; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/ZkNodePathReferenceContributor.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.openapi.vfs.VirtualFile; 5 | import com.intellij.patterns.PsiJavaElementPattern; 6 | import com.intellij.patterns.PsiMethodPattern; 7 | import com.intellij.patterns.StringPattern; 8 | import com.intellij.psi.*; 9 | import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet; 10 | import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl; 11 | import com.intellij.util.ProcessingContext; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.mvnsearch.intellij.plugin.zookeeper.vfs.ZkVirtualFileSystem; 14 | 15 | import java.util.ArrayList; 16 | import java.util.Collection; 17 | 18 | import static com.intellij.patterns.PsiJavaPatterns.*; 19 | import static com.intellij.patterns.StandardPatterns.string; 20 | 21 | /** 22 | * zookeeper node path reference contributor 23 | * 24 | * @author linux_china 25 | */ 26 | public class ZkNodePathReferenceContributor extends PsiReferenceContributor { 27 | 28 | public void registerReferenceProviders(PsiReferenceRegistrar registrar) { 29 | final StringPattern methodName = string().oneOf("forPath"); 30 | final PsiMethodPattern method = psiMethod().withName(methodName); 31 | final PsiJavaElementPattern.Capture javaFile 32 | = literalExpression().and(psiExpression().methodCallParameter(0, method)); 33 | registrar.registerReferenceProvider(javaFile, new PsiReferenceProvider() { 34 | @NotNull 35 | @Override 36 | public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) { 37 | return new FileReferenceSet(element) { 38 | @Override 39 | protected Collection getExtraContexts() { 40 | Project project = element.getProject(); 41 | final ArrayList result = new ArrayList(); 42 | ZkVirtualFileSystem fileSystem = ZkProjectComponent.getInstance(project).getFileSystem(); 43 | PsiLiteralExpression literalExpression = (PsiLiteralExpression) element; 44 | String innerText = ((PsiLiteralExpressionImpl) literalExpression).getInnerText(); 45 | if (innerText == null) { 46 | innerText = ""; 47 | } 48 | innerText = innerText.replace("IntellijIdeaRulezzz", ""); 49 | if (innerText.isEmpty()) { 50 | innerText = "/"; 51 | } 52 | final PsiManager psiManager = element.getManager(); 53 | VirtualFile rootDirectory = fileSystem.findFileByPath(innerText); 54 | if (rootDirectory != null) { 55 | if (rootDirectory.isDirectory()) { 56 | result.add(psiManager.findDirectory(rootDirectory)); 57 | } else { 58 | result.add(psiManager.findFile(rootDirectory)); 59 | } 60 | } 61 | return result; 62 | } 63 | }.getAllReferences(); 64 | } 65 | }); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/ZkProjectComponent.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper; 2 | 3 | import com.intellij.ide.ui.customization.CustomizationUtil; 4 | import com.intellij.openapi.actionSystem.ActionGroup; 5 | import com.intellij.openapi.actionSystem.ActionManager; 6 | import com.intellij.openapi.actionSystem.ActionPlaces; 7 | import com.intellij.openapi.components.ProjectComponent; 8 | import com.intellij.openapi.fileEditor.OpenFileDescriptor; 9 | import com.intellij.openapi.fileTypes.FileType; 10 | import com.intellij.openapi.fileTypes.FileTypeManager; 11 | import com.intellij.openapi.fileTypes.FileTypes; 12 | import com.intellij.openapi.project.Project; 13 | import com.intellij.openapi.ui.SimpleToolWindowPanel; 14 | import com.intellij.openapi.util.IconLoader; 15 | import com.intellij.openapi.vfs.VirtualFile; 16 | import com.intellij.openapi.wm.ToolWindow; 17 | import com.intellij.openapi.wm.ToolWindowAnchor; 18 | import com.intellij.openapi.wm.ToolWindowManager; 19 | import com.intellij.ui.DoubleClickListener; 20 | import com.intellij.ui.components.JBScrollPane; 21 | import com.intellij.ui.content.Content; 22 | import com.intellij.ui.content.ContentManager; 23 | import com.intellij.ui.treeStructure.Tree; 24 | import com.intellij.util.IconUtil; 25 | import org.apache.curator.framework.CuratorFramework; 26 | import org.apache.curator.framework.CuratorFrameworkFactory; 27 | import org.apache.curator.retry.ExponentialBackoffRetry; 28 | import org.apache.zookeeper.common.IOUtils; 29 | import org.jdesktop.swingx.renderer.DefaultTreeRenderer; 30 | import org.jdesktop.swingx.renderer.WrappingIconPanel; 31 | import org.jetbrains.annotations.NotNull; 32 | import org.mvnsearch.intellij.plugin.zookeeper.ui.ZkNode; 33 | import org.mvnsearch.intellij.plugin.zookeeper.ui.ZkTreeModel; 34 | import org.mvnsearch.intellij.plugin.zookeeper.vfs.ZkVirtualFileSystem; 35 | 36 | import javax.swing.*; 37 | import javax.swing.tree.TreePath; 38 | import javax.swing.tree.TreeSelectionModel; 39 | import java.awt.*; 40 | import java.awt.event.MouseEvent; 41 | import java.io.ByteArrayOutputStream; 42 | import java.net.Socket; 43 | import java.util.Arrays; 44 | 45 | /** 46 | * Zoo Keeper project component 47 | * 48 | * @author linux_china 49 | */ 50 | public class ZkProjectComponent extends DoubleClickListener implements ProjectComponent { 51 | private Project project; 52 | private CuratorFramework curator; 53 | private Tree zkTree; 54 | private ZkVirtualFileSystem fileSystem; 55 | private final Icon rootIcon = IconLoader.findIcon("/icons/zookeeper_small.png"); 56 | 57 | public ZkProjectComponent(Project project) { 58 | this.project = project; 59 | } 60 | 61 | public static ZkProjectComponent getInstance(Project project) { 62 | return project.getComponent(ZkProjectComponent.class); 63 | } 64 | 65 | public void initComponent() { 66 | 67 | } 68 | 69 | public void disposeComponent() { 70 | 71 | } 72 | 73 | @NotNull 74 | public String getComponentName() { 75 | return "ZkProjectComponent"; 76 | } 77 | 78 | public void projectOpened() { 79 | initZk(); 80 | if (this.curator != null) { 81 | initToolWindow(); 82 | } 83 | } 84 | 85 | public void initToolWindow() { 86 | final ZkConfigPersistence config = ZkConfigPersistence.getInstance(project); 87 | ToolWindow toolWindow = ToolWindowManager.getInstance(project).registerToolWindow("ZooKeeper", false, ToolWindowAnchor.LEFT); 88 | toolWindow.setTitle("ZooKeeper"); 89 | toolWindow.setIcon(rootIcon); 90 | ZkNode.ROOT_NAME = config.getTitle(); 91 | zkTree = new Tree(new ZkTreeModel(curator, config.whitePaths)); 92 | ToolTipManager.sharedInstance().registerComponent(zkTree); 93 | zkTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 94 | this.installOn(zkTree); 95 | CustomizationUtil.installPopupHandler(zkTree, "ZK.OperationMenu", ActionPlaces.UNKNOWN); 96 | zkTree.setCellRenderer(new DefaultTreeRenderer() { 97 | @Override 98 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { 99 | Component component = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); 100 | if (value instanceof ZkNode && component instanceof WrappingIconPanel) { 101 | ZkNode node = (ZkNode) value; 102 | WrappingIconPanel wrappingPanel = (WrappingIconPanel) component; 103 | if (node.isRoot()) { 104 | wrappingPanel.setIcon(rootIcon); 105 | } else if (node.isLeaf()) { 106 | FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(node.getName()); 107 | Icon icon = fileType.getIcon(); 108 | if (node.isBinary()) { 109 | icon = FileTypes.ARCHIVE.getIcon(); 110 | } else if (fileType.getName().equalsIgnoreCase(FileTypes.UNKNOWN.getName())) { 111 | icon = FileTypes.PLAIN_TEXT.getIcon(); 112 | } 113 | if (node.isEphemeral() && icon != null) { 114 | icon = IconLoader.getTransparentIcon(icon); 115 | } 116 | wrappingPanel.setIcon(icon); 117 | } 118 | if (config.tooltip) { 119 | wrappingPanel.setToolTipText(node.getTooltip()); 120 | } 121 | } 122 | 123 | return component; 124 | } 125 | }); 126 | final ContentManager contentManager = toolWindow.getContentManager(); 127 | SimpleToolWindowPanel panel = new SimpleToolWindowPanel(true); 128 | JBScrollPane jbScrollPane = new JBScrollPane(zkTree); 129 | panel.add(jbScrollPane); 130 | panel.setToolbar(createToolBar()); 131 | final Content content = contentManager.getFactory().createContent(panel, null, false); 132 | contentManager.addContent(content); 133 | } 134 | 135 | private JComponent createToolBar() { 136 | ActionGroup actionGroup = (ActionGroup) ActionManager.getInstance().getAction("ZK.Toolbar"); 137 | String place = ActionPlaces.EDITOR_TOOLBAR; 138 | JPanel toolBarPanel = new JPanel(new GridLayout()); 139 | toolBarPanel.add(ActionManager.getInstance().createActionToolbar(place, actionGroup, true).getComponent()); 140 | return toolBarPanel; 141 | } 142 | 143 | public void projectClosed() { 144 | if (curator != null) { 145 | this.curator.close(); 146 | } 147 | } 148 | 149 | protected boolean onDoubleClick(MouseEvent mouseEvent) { 150 | Tree source = (Tree) mouseEvent.getSource(); 151 | TreePath treePath = source.getSelectionPath(); 152 | ZkNode selectedNode = (ZkNode) treePath.getLastPathComponent(); 153 | if (selectedNode.isLeaf() && !selectedNode.isBinary()) { 154 | VirtualFile file = fileSystem.findFileByPath(selectedNode.getFilePath()); 155 | if (file != null && project != null) { 156 | new OpenFileDescriptor(project, file).navigate(true); 157 | } 158 | } 159 | return true; 160 | } 161 | 162 | public ZkVirtualFileSystem getFileSystem() { 163 | return fileSystem; 164 | } 165 | 166 | public Tree getZkTree() { 167 | return zkTree; 168 | } 169 | 170 | public void reloadZkTree() { 171 | ZkNode.ROOT_NAME = ZkConfigPersistence.getInstance(project).getTitle(); 172 | if (curator == null) { 173 | initZk(); 174 | } 175 | if (curator != null) { 176 | zkTree.setModel(new ZkTreeModel(curator, ZkConfigPersistence.getInstance(project).whitePaths)); 177 | zkTree.updateUI(); 178 | } 179 | } 180 | 181 | public CuratorFramework getCurator() { 182 | return curator; 183 | } 184 | 185 | public void initZk() { 186 | if (this.curator != null) { 187 | this.curator.close(); 188 | } 189 | ZkConfigPersistence config = ZkConfigPersistence.getInstance(project); 190 | if (config.isAvailable() && ruok(config.getFirstServer())) { 191 | this.curator = CuratorFrameworkFactory.newClient(config.getZkUrl(), new ExponentialBackoffRetry(1000, 0, 1000)); 192 | curator.start(); 193 | this.fileSystem = new ZkVirtualFileSystem(curator, ZkConfigPersistence.getInstance(project).charset); 194 | } 195 | } 196 | 197 | public boolean ruok(String server) { 198 | try { 199 | String[] parts = server.split(":"); 200 | Socket sock = new Socket(parts[0], Integer.valueOf(parts[1])); 201 | sock.getOutputStream().write("ruok".getBytes()); 202 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 203 | IOUtils.copyBytes(sock.getInputStream(), bos, 1000); 204 | if (!sock.isClosed()) { 205 | sock.close(); 206 | } 207 | return "imok".equals(new String(bos.toByteArray())); 208 | } catch (Exception e) { 209 | return false; 210 | } 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/actions/CopyNodePathAction.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.actions; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.project.Project; 6 | import com.intellij.openapi.wm.impl.status.StatusBarUtil; 7 | import com.intellij.ui.treeStructure.Tree; 8 | import org.mvnsearch.intellij.plugin.zookeeper.ZkProjectComponent; 9 | import org.mvnsearch.intellij.plugin.zookeeper.ui.ZkNode; 10 | 11 | import javax.swing.tree.TreePath; 12 | import java.awt.*; 13 | import java.awt.datatransfer.Clipboard; 14 | import java.awt.datatransfer.ClipboardOwner; 15 | import java.awt.datatransfer.StringSelection; 16 | import java.awt.datatransfer.Transferable; 17 | 18 | /** 19 | * copy zk node path action 20 | * 21 | * @author linux_china 22 | */ 23 | public class CopyNodePathAction extends AnAction implements ClipboardOwner { 24 | public void actionPerformed(final AnActionEvent anActionEvent) { 25 | Project project = anActionEvent.getProject(); 26 | ZkProjectComponent zkProjectComponent = ZkProjectComponent.getInstance(project); 27 | Tree zkTree = zkProjectComponent.getZkTree(); 28 | TreePath treePath = zkTree.getSelectionPath(); 29 | ZkNode currentNode = (ZkNode) treePath.getLastPathComponent(); 30 | if (currentNode != null) { 31 | String filePath = currentNode.getFilePath(); 32 | StringSelection stringSelection = new StringSelection(filePath); 33 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 34 | clipboard.setContents(stringSelection, this); 35 | StatusBarUtil.setStatusBarInfo(project, "'" + filePath + "' has been copied into clipboard!"); 36 | } 37 | } 38 | 39 | public void lostOwnership(Clipboard clipboard, Transferable transferable) { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/actions/CreateNodeAction.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.actions; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.fileEditor.OpenFileDescriptor; 6 | import com.intellij.openapi.fileTypes.FileType; 7 | import com.intellij.openapi.fileTypes.FileTypeManager; 8 | import com.intellij.openapi.fileTypes.FileTypes; 9 | import com.intellij.openapi.ui.DialogBuilder; 10 | import com.intellij.openapi.ui.DialogWrapper; 11 | import com.intellij.openapi.util.text.StringUtil; 12 | import com.intellij.openapi.vfs.VirtualFile; 13 | import com.intellij.ui.treeStructure.Tree; 14 | import org.apache.curator.framework.CuratorFramework; 15 | import org.mvnsearch.intellij.plugin.zookeeper.ZkProjectComponent; 16 | import org.mvnsearch.intellij.plugin.zookeeper.ui.ZkNode; 17 | import org.mvnsearch.intellij.plugin.zookeeper.vfs.ZkNodeVirtualFile; 18 | 19 | import javax.swing.*; 20 | import javax.swing.tree.TreePath; 21 | 22 | /** 23 | * create zk node action 24 | * 25 | * @author linux_china 26 | */ 27 | public class CreateNodeAction extends AnAction { 28 | public void actionPerformed(final AnActionEvent anActionEvent) { 29 | final DialogBuilder builder = new DialogBuilder(anActionEvent.getProject()); 30 | builder.setTitle("Create Node"); 31 | final JTextField jTextField = new JTextField(); 32 | builder.setPreferredFocusComponent(jTextField); 33 | builder.setCenterPanel(jTextField); 34 | builder.setOkOperation(new Runnable() { 35 | public void run() { 36 | String nodeName = jTextField.getText(); 37 | if (StringUtil.isNotEmpty(nodeName)) { 38 | if (nodeName.startsWith("/")) { 39 | nodeName = nodeName.substring(1); 40 | } 41 | if (nodeName.endsWith("/")) { 42 | nodeName = nodeName.substring(0, nodeName.length() - 1); 43 | } 44 | ZkProjectComponent zkProjectComponent = ZkProjectComponent.getInstance(anActionEvent.getProject()); 45 | Tree zkTree = zkProjectComponent.getZkTree(); 46 | TreePath treePath = zkTree.getSelectionPath(); 47 | CuratorFramework curator = zkProjectComponent.getCurator(); 48 | ZkNode currentNode = (ZkNode) treePath.getLastPathComponent(); 49 | try { 50 | //create recursively support 51 | String[] parts = nodeName.split("/"); 52 | ZkNode newNode = null; 53 | for (String part : parts) { 54 | newNode = currentNode.getSubNode(part); 55 | // check exists 56 | if (curator.checkExists().forPath(newNode.getFilePath()) == null) { 57 | if (nodeName.endsWith(".zip")) { 58 | String entryName = nodeName.replace(".zip", ""); 59 | curator.create().forPath(newNode.getFilePath(), ZkNodeVirtualFile.zip(entryName, "".getBytes())); 60 | } else { 61 | curator.create().forPath(newNode.getFilePath(), "".getBytes()); 62 | } 63 | } 64 | currentNode = newNode; 65 | } 66 | zkTree.updateUI(); 67 | zkTree.expandPath(treePath); 68 | if (newNode != null) { 69 | FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(nodeName); 70 | if (!fileType.getName().equals(FileTypes.UNKNOWN.getName())) { 71 | VirtualFile virtualFile = zkProjectComponent.getFileSystem().findFileByPath(newNode.getFilePath()); 72 | if (anActionEvent.getProject() != null && virtualFile != null) { 73 | new OpenFileDescriptor(anActionEvent.getProject(), virtualFile).navigate(true); 74 | } 75 | } 76 | } 77 | } catch (Exception ignore) { 78 | ignore.printStackTrace(); 79 | } 80 | } 81 | builder.getDialogWrapper().close(DialogWrapper.OK_EXIT_CODE); 82 | } 83 | }); 84 | builder.showModal(true); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/actions/DeleteNodeAction.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.actions; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.project.Project; 6 | import com.intellij.openapi.ui.DialogBuilder; 7 | import com.intellij.openapi.ui.DialogWrapper; 8 | import com.intellij.openapi.wm.impl.status.StatusBarUtil; 9 | import com.intellij.ui.treeStructure.Tree; 10 | import org.apache.curator.framework.CuratorFramework; 11 | import org.mvnsearch.intellij.plugin.zookeeper.ZkProjectComponent; 12 | import org.mvnsearch.intellij.plugin.zookeeper.ui.ZkNode; 13 | 14 | import javax.swing.*; 15 | import javax.swing.tree.TreePath; 16 | 17 | /** 18 | * delete zk node action 19 | * 20 | * @author linux_china 21 | */ 22 | public class DeleteNodeAction extends AnAction { 23 | public void actionPerformed(final AnActionEvent anActionEvent) { 24 | final Project project = anActionEvent.getProject(); 25 | final ZkProjectComponent zkProjectComponent = ZkProjectComponent.getInstance(project); 26 | final Tree zkTree = zkProjectComponent.getZkTree(); 27 | TreePath treePath = zkTree.getSelectionPath(); 28 | final ZkNode currentNode = (ZkNode) treePath.getLastPathComponent(); 29 | final DialogBuilder builder = new DialogBuilder(project); 30 | builder.setTitle("Delete Node"); 31 | final JLabel jTextField = new JLabel("Path: " + currentNode.getFilePath()); 32 | builder.setCenterPanel(jTextField); 33 | builder.setOkOperation(new Runnable() { 34 | public void run() { 35 | CuratorFramework curator = zkProjectComponent.getCurator(); 36 | try { 37 | curator.delete().deletingChildrenIfNeeded().forPath(currentNode.getFilePath()); 38 | zkTree.updateUI(); 39 | } catch (Exception ignore) { 40 | 41 | } 42 | builder.getDialogWrapper().close(DialogWrapper.OK_EXIT_CODE); 43 | StatusBarUtil.setStatusBarInfo(project, "'" + currentNode.getFilePath() + "' has been deleted!"); 44 | } 45 | }); 46 | builder.showModal(true); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/actions/OpenZkNodeInEditorAction.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.actions; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.fileEditor.FileEditorManager; 6 | import com.intellij.ui.treeStructure.Tree; 7 | import org.mvnsearch.intellij.plugin.zookeeper.ZkProjectComponent; 8 | import org.mvnsearch.intellij.plugin.zookeeper.ui.ZkNode; 9 | import org.mvnsearch.intellij.plugin.zookeeper.vfs.ZkNodeVirtualFile; 10 | 11 | import javax.swing.tree.TreePath; 12 | 13 | /** 14 | * open zk node in editor action 15 | * 16 | * @author linux_china 17 | */ 18 | public class OpenZkNodeInEditorAction extends AnAction { 19 | 20 | public void actionPerformed(AnActionEvent actionEvent) { 21 | ZkProjectComponent zkProjectComponent = ZkProjectComponent.getInstance(actionEvent.getProject()); 22 | Tree zkTree = zkProjectComponent.getZkTree(); 23 | TreePath treePath = zkTree.getSelectionPath(); 24 | ZkNode zkNode = (ZkNode) treePath.getLastPathComponent(); 25 | FileEditorManager fileEditorManager = FileEditorManager.getInstance(actionEvent.getProject()); 26 | ZkNodeVirtualFile virtualFile = (ZkNodeVirtualFile) zkProjectComponent.getFileSystem().findFileByPath(zkNode.getFilePath()); 27 | if (virtualFile != null) { 28 | virtualFile.setLeaf(); 29 | fileEditorManager.openFile(virtualFile, true); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/actions/UpdateZkNodeAction.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.actions; 2 | 3 | import com.intellij.openapi.actionSystem.CommonDataKeys; 4 | import com.intellij.openapi.actionSystem.DataContext; 5 | import com.intellij.openapi.editor.Editor; 6 | import com.intellij.openapi.editor.actionSystem.EditorAction; 7 | import com.intellij.openapi.editor.actionSystem.EditorActionHandler; 8 | import com.intellij.openapi.project.Project; 9 | import com.intellij.openapi.vfs.VirtualFile; 10 | import com.intellij.openapi.wm.impl.status.StatusBarUtil; 11 | import org.mvnsearch.intellij.plugin.zookeeper.ZkProjectComponent; 12 | import org.mvnsearch.intellij.plugin.zookeeper.vfs.ZkNodeVirtualFile; 13 | 14 | /** 15 | * update zoo keeper node action 16 | * 17 | * @author linux_china 18 | */ 19 | public class UpdateZkNodeAction extends EditorAction { 20 | 21 | public UpdateZkNodeAction() { 22 | super(new EditorActionHandler() { 23 | @Override 24 | public void execute(Editor editor, DataContext dataContext) { 25 | VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext); 26 | if (virtualFile != null && virtualFile instanceof ZkNodeVirtualFile) { 27 | ZkNodeVirtualFile nodeFile = (ZkNodeVirtualFile) virtualFile; 28 | String nodeContent = editor.getDocument().getText(); 29 | Project project = CommonDataKeys.PROJECT.getData(dataContext); 30 | ZkProjectComponent zkProjectComponent = ZkProjectComponent.getInstance(project); 31 | try { 32 | if (nodeFile.isSingleFileZip()) { 33 | zkProjectComponent.getCurator().setData().forPath(nodeFile.getFilePath(), 34 | ZkNodeVirtualFile.zip(nodeFile.getName().replace(".zip", ""), nodeContent.getBytes())); 35 | } else { 36 | zkProjectComponent.getCurator().setData().forPath(nodeFile.getFilePath(), nodeContent.getBytes()); 37 | } 38 | StatusBarUtil.setStatusBarInfo(project, "'" + nodeFile.getFilePath() + "' has been updated!"); 39 | } catch (Exception e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | } 44 | 45 | @Override 46 | public boolean isEnabled(Editor editor, DataContext dataContext) { 47 | VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext); 48 | return virtualFile instanceof ZkNodeVirtualFile; 49 | } 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/actions/ZkTreeRefreshAction.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.actions; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.ui.treeStructure.Tree; 6 | import org.mvnsearch.intellij.plugin.zookeeper.ZkProjectComponent; 7 | 8 | import javax.swing.tree.TreePath; 9 | 10 | /** 11 | * Refresh Zoo Keeper Tree 12 | * 13 | * @author linux_china 14 | */ 15 | public class ZkTreeRefreshAction extends AnAction { 16 | public void actionPerformed(AnActionEvent anActionEvent) { 17 | ZkProjectComponent zkProjectComponent = ZkProjectComponent.getInstance(anActionEvent.getProject()); 18 | Tree zkTree = zkProjectComponent.getZkTree(); 19 | TreePath treePath = zkTree.getSelectionPath(); 20 | zkTree.updateUI(); 21 | if (treePath != null) { 22 | zkTree.expandPath(treePath); 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/ui/ZkConfigurable.form: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
99 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/ui/ZkNode.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.ui; 2 | 3 | import com.intellij.openapi.fileTypes.FileTypes; 4 | import org.apache.zookeeper.data.Stat; 5 | 6 | import java.util.Arrays; 7 | import java.util.Date; 8 | 9 | /** 10 | * ZooKeeper Node 11 | * 12 | * @author linux_china 13 | */ 14 | public class ZkNode { 15 | private static java.util.List binaryExtNames = Arrays.asList("pb", "bin", "msgpack"); 16 | 17 | public static String ROOT_NAME = "/"; 18 | private String path; 19 | private String name; 20 | private Stat stat; 21 | 22 | public ZkNode(String path, String name) { 23 | this.path = path; 24 | this.name = name; 25 | } 26 | 27 | public boolean isLeaf() { 28 | return stat != null && stat.getNumChildren() == 0; 29 | } 30 | 31 | public boolean isRoot() { 32 | return path.equals("/") && name == null; 33 | } 34 | 35 | public boolean isEphemeral() { 36 | return stat != null && stat.getEphemeralOwner() > 0; 37 | } 38 | 39 | public int getChildrenCount() { 40 | return stat != null ? stat.getNumChildren() : 0; 41 | } 42 | 43 | public boolean isFilled() { 44 | return stat != null; 45 | } 46 | 47 | public String getPath() { 48 | return path; 49 | } 50 | 51 | public void setPath(String path) { 52 | this.path = path; 53 | } 54 | 55 | public String getName() { 56 | return name; 57 | } 58 | 59 | public void setName(String name) { 60 | this.name = name; 61 | } 62 | 63 | public String getFilePath() { 64 | if (name == null) { 65 | return path; 66 | } else { 67 | if (path.endsWith("/")) { 68 | return path + name; 69 | } else { 70 | return path + "/" + name; 71 | } 72 | } 73 | } 74 | 75 | public ZkNode getSubNode(String subNodeName) { 76 | return new ZkNode(getFilePath(), subNodeName); 77 | } 78 | 79 | public Stat getStat() { 80 | return stat; 81 | } 82 | 83 | public void setStat(Stat stat) { 84 | this.stat = stat; 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return name == null ? ROOT_NAME : name; 90 | } 91 | 92 | public boolean isBinary() { 93 | String extName = null; 94 | if (name.contains(".")) { 95 | extName = name.substring(name.lastIndexOf(".") + 1); 96 | } 97 | return extName != null && binaryExtNames.contains(extName.toLowerCase()); 98 | } 99 | 100 | public String getTooltip() { 101 | return "cZxid = " + stat.getCzxid() + "\n" + 102 | "ctime = " + new Date(stat.getCtime()) + "\n" + 103 | "mZxid = " + stat.getMzxid() + "\n" + 104 | "mtime = " + new Date(stat.getMtime()) + "\n" + 105 | "pZxid = " + stat.getPzxid() + "\n" + 106 | "cversion = " + stat.getCversion() + "\n" + 107 | "dataVersion = " + stat.getVersion() + "\n" + 108 | "aclVersion = " + stat.getAversion() + "\n" + 109 | "ephemeralOwner = " + stat.getEphemeralOwner() + "\n" + 110 | "dataLength =" + stat.getDataLength() + " \n" + 111 | "numChildren = " + stat.getNumChildren(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/ui/ZkProjectConfigurable.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.ui; 2 | 3 | import com.intellij.openapi.options.Configurable; 4 | import com.intellij.openapi.options.ConfigurationException; 5 | import com.intellij.openapi.project.Project; 6 | import com.intellij.openapi.util.text.StringUtil; 7 | import com.intellij.openapi.wm.ToolWindowManager; 8 | import org.jetbrains.annotations.Nls; 9 | import org.jetbrains.annotations.Nullable; 10 | import org.mvnsearch.intellij.plugin.zookeeper.ZkConfigPersistence; 11 | import org.mvnsearch.intellij.plugin.zookeeper.ZkProjectComponent; 12 | 13 | import javax.swing.*; 14 | 15 | /** 16 | * Zoo Keeper application configurable 17 | * 18 | * @author linux_china 19 | */ 20 | public class ZkProjectConfigurable implements Configurable { 21 | private Project project; 22 | private JPanel root; 23 | private JTextField hostTextField; 24 | private JTextField portTextField; 25 | private JTextField pathsTextField; 26 | private JCheckBox enableZooKeeperCheckBox; 27 | private JTextField charsetTextField; 28 | private JCheckBox statTooltipCheckBox; 29 | private ZkConfigPersistence config; 30 | 31 | public ZkProjectConfigurable(Project project) { 32 | this.project = project; 33 | this.config = ZkConfigPersistence.getInstance(project); 34 | reset(); 35 | } 36 | 37 | @Nls 38 | public String getDisplayName() { 39 | return "ZooKeeper"; 40 | } 41 | 42 | @Nullable 43 | public String getHelpTopic() { 44 | return null; 45 | } 46 | 47 | @Nullable 48 | public JComponent createComponent() { 49 | return root; 50 | } 51 | 52 | public boolean isModified() { 53 | String newHost = hostTextField.getText().trim(); 54 | String newPort = portTextField.getText().trim(); 55 | String newPath = pathsTextField.getText(); 56 | String newCharset = charsetTextField.getText(); 57 | if (newPath == null) { 58 | newPath = ""; 59 | } else { 60 | newPath = newPath.trim(); 61 | } 62 | return !(newHost.equals(config.host) 63 | && Integer.valueOf(newPort).equals(config.port) 64 | && newCharset.equals(config.charset) 65 | && config.enabled == enableZooKeeperCheckBox.isSelected() 66 | && config.tooltip == statTooltipCheckBox.isSelected() 67 | && (newPath.equals(config.whitePaths))); 68 | } 69 | 70 | public void apply() throws ConfigurationException { 71 | String oldHost = config.host; 72 | config.host = hostTextField.getText().trim(); 73 | config.port = Integer.valueOf(portTextField.getText().trim()); 74 | config.charset = charsetTextField.getText(); 75 | boolean oldEnabled = config.enabled; 76 | config.enabled = enableZooKeeperCheckBox.isSelected(); 77 | config.tooltip = statTooltipCheckBox.isSelected(); 78 | ZkProjectComponent zkProjectComponent = ZkProjectComponent.getInstance(project); 79 | if (!oldEnabled && config.enabled) { 80 | zkProjectComponent.initZk(); 81 | if (ToolWindowManager.getInstance(project).getToolWindow("ZooKeeper") == null) { 82 | zkProjectComponent.initToolWindow(); 83 | } 84 | } 85 | // host changed to init zk again 86 | if (oldHost != null && !oldHost.equals(config.host)) { 87 | zkProjectComponent.initZk(); 88 | } 89 | config.whitePaths = pathsTextField.getText(); 90 | if (config.isAvailable()) { 91 | zkProjectComponent.reloadZkTree(); 92 | } 93 | } 94 | 95 | public void reset() { 96 | hostTextField.setText(config.host); 97 | portTextField.setText(config.port == null ? "2181" : String.valueOf(config.port)); 98 | enableZooKeeperCheckBox.setSelected(config.enabled); 99 | pathsTextField.setText(config.whitePaths); 100 | charsetTextField.setText(config.charset == null ? "UTF-8" : config.charset); 101 | statTooltipCheckBox.setSelected(config.tooltip); 102 | } 103 | 104 | public void disposeUIResources() { 105 | 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/ui/ZkTreeModel.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.ui; 2 | 3 | import com.intellij.openapi.util.text.StringUtil; 4 | import org.apache.curator.framework.CuratorFramework; 5 | import org.apache.zookeeper.data.Stat; 6 | 7 | import javax.swing.event.TreeModelListener; 8 | import javax.swing.tree.TreeModel; 9 | import javax.swing.tree.TreePath; 10 | import java.util.*; 11 | 12 | /** 13 | * zoo keeper tree model 14 | * 15 | * @author linux_china 16 | */ 17 | public class ZkTreeModel implements TreeModel { 18 | private ZkNode root = new ZkNode("/", null); 19 | private CuratorFramework curator; 20 | private List whitePaths; 21 | 22 | public ZkTreeModel(CuratorFramework curator, String whitePaths) { 23 | this.curator = curator; 24 | if (StringUtil.isNotEmpty(whitePaths)) { 25 | this.whitePaths = Arrays.asList(whitePaths.trim().split("[\\s;]+")); 26 | } 27 | } 28 | 29 | public Object getRoot() { 30 | return root; 31 | } 32 | 33 | public Object getChild(Object parent, int i) { 34 | List children = getChildren((ZkNode) parent); 35 | return children.get(i); 36 | } 37 | 38 | public int getChildCount(Object parent) { 39 | ZkNode zkNode = (ZkNode) parent; 40 | if (!zkNode.isFilled()) { 41 | fillZkNode(zkNode); 42 | } 43 | if (!zkNode.isLeaf() && whitePaths != null && !whitePaths.isEmpty()) { 44 | return getChildren(zkNode).size(); 45 | } 46 | return zkNode.getChildrenCount(); 47 | } 48 | 49 | public boolean isLeaf(Object node) { 50 | ZkNode zkNode = (ZkNode) node; 51 | if (!zkNode.isFilled()) { 52 | fillZkNode(zkNode); 53 | } 54 | return zkNode.isLeaf(); 55 | } 56 | 57 | private void fillZkNode(ZkNode zkNode) { 58 | try { 59 | Stat stat = curator.checkExists().forPath(zkNode.getFilePath()); 60 | if (stat != null) { 61 | zkNode.setStat(stat); 62 | } 63 | } catch (Exception ignore) { 64 | 65 | } 66 | } 67 | 68 | public void valueForPathChanged(TreePath treePath, Object o) { 69 | 70 | } 71 | 72 | public int getIndexOfChild(Object parent, Object node) { 73 | List children = getChildren((ZkNode) parent); 74 | for (int i = 0; i < children.size(); i++) { 75 | if (((ZkNode) node).getFilePath().equals(children.get(i).getFilePath())) { 76 | return i; 77 | } 78 | } 79 | return -1; 80 | } 81 | 82 | public void addTreeModelListener(TreeModelListener treeModelListener) { 83 | 84 | } 85 | 86 | public void removeTreeModelListener(TreeModelListener treeModelListener) { 87 | 88 | } 89 | 90 | public List getChildren(ZkNode node) { 91 | List children = new ArrayList(); 92 | if (!node.isFilled()) { 93 | fillZkNode(node); 94 | } 95 | if (node.isLeaf()) { 96 | return children; 97 | } 98 | try { 99 | List nodes = curator.getChildren().forPath(node.getFilePath()); 100 | Collections.sort(nodes, new Comparator() { 101 | public int compare(String s, String s2) { 102 | return s.compareTo(s2); 103 | } 104 | }); 105 | for (int i = 0; i < nodes.size() && i < 100; i++) { 106 | ZkNode zkNode = new ZkNode(node.getFilePath(), nodes.get(i)); 107 | if (isWhitePath(zkNode.getFilePath())) { 108 | children.add(zkNode); 109 | } 110 | } 111 | } catch (Exception ignore) { 112 | } 113 | return children; 114 | } 115 | 116 | private boolean isWhitePath(String filePath) { 117 | if (this.whitePaths != null) { 118 | boolean legal = false; 119 | for (String whitePath : whitePaths) { 120 | if (filePath.startsWith(whitePath)) { 121 | legal = true; 122 | break; 123 | } else if (whitePath.lastIndexOf("/") > 1 && whitePath.startsWith(filePath)) { 124 | legal = true; 125 | break; 126 | } 127 | } 128 | return legal; 129 | } 130 | return true; 131 | } 132 | } -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/vfs/ZkNodeVirtualFile.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.vfs; 2 | 3 | import com.intellij.openapi.fileTypes.FileType; 4 | import com.intellij.openapi.fileTypes.FileTypeManager; 5 | import com.intellij.openapi.fileTypes.FileTypes; 6 | import com.intellij.openapi.vfs.VirtualFile; 7 | import com.intellij.openapi.vfs.VirtualFileEvent; 8 | import com.intellij.openapi.vfs.VirtualFileListener; 9 | import com.intellij.openapi.vfs.VirtualFileSystem; 10 | import com.intellij.util.LocalTimeCounter; 11 | import org.apache.curator.framework.CuratorFramework; 12 | import org.apache.zookeeper.data.Stat; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | import java.io.*; 17 | import java.nio.charset.Charset; 18 | import java.util.List; 19 | import java.util.zip.ZipEntry; 20 | import java.util.zip.ZipInputStream; 21 | import java.util.zip.ZipOutputStream; 22 | 23 | /** 24 | * ZooKeeper node virtual file 25 | * 26 | * @author linux_china 27 | */ 28 | public class ZkNodeVirtualFile extends VirtualFile { 29 | private ZkVirtualFileSystem fileSystem; 30 | private String filePath; 31 | private String fileName; 32 | private boolean isLeaf; 33 | private Stat stat; 34 | private byte[] content; 35 | private VirtualFileListener fileListener = null; 36 | private final long myTimeStamp = System.currentTimeMillis(); 37 | private long myModStamp = LocalTimeCounter.currentTime(); 38 | 39 | public ZkNodeVirtualFile(ZkVirtualFileSystem fileSystem, String filePath) { 40 | this.fileSystem = fileSystem; 41 | this.filePath = filePath; 42 | if (!filePath.equals("/") && filePath.endsWith("/")) { 43 | this.filePath = filePath.substring(0, filePath.length() - 1); 44 | } 45 | fileName = filePath.substring(filePath.lastIndexOf("/") + 1); 46 | try { 47 | this.stat = getCurator().checkExists().forPath(filePath); 48 | this.isLeaf = stat.getNumChildren() == 0; 49 | } catch (Exception ignore) { 50 | 51 | } 52 | } 53 | 54 | public void setLeaf() { 55 | this.isLeaf = true; 56 | } 57 | 58 | public void setFileListener(VirtualFileListener fileListener) { 59 | this.fileListener = fileListener; 60 | } 61 | 62 | @NotNull 63 | public String getName() { 64 | return this.fileName; 65 | } 66 | 67 | @NotNull 68 | public VirtualFileSystem getFileSystem() { 69 | return this.fileSystem; 70 | } 71 | 72 | public String getPath() { 73 | String path = "/"; 74 | if (filePath.lastIndexOf("/") > 0) { 75 | path = filePath.substring(0, filePath.lastIndexOf("/")); 76 | } 77 | return path; 78 | } 79 | 80 | public String getFilePath() { 81 | return filePath; 82 | } 83 | 84 | public boolean isWritable() { 85 | return true; 86 | } 87 | 88 | public boolean isDirectory() { 89 | return !isLeaf; 90 | } 91 | 92 | public boolean isValid() { 93 | return true; 94 | } 95 | 96 | public VirtualFile getParent() { 97 | if ("/".equals(filePath)) { 98 | return null; 99 | } 100 | int slashIndex = filePath.lastIndexOf("/"); 101 | if (slashIndex == 0) { 102 | return new ZkNodeVirtualFile(this.fileSystem, "/"); 103 | } else { 104 | String parentPath = filePath.substring(0, slashIndex); 105 | return new ZkNodeVirtualFile(this.fileSystem, parentPath); 106 | } 107 | } 108 | 109 | public VirtualFile[] getChildren() { 110 | try { 111 | List children = getCurator().getChildren().forPath(filePath); 112 | if (children != null && !children.isEmpty()) { 113 | VirtualFile[] files = new VirtualFile[children.size()]; 114 | for (int i = 0; i < children.size(); i++) { 115 | String childName = children.get(i); 116 | files[i] = new ZkNodeVirtualFile(fileSystem, filePath.endsWith("/") ? filePath + childName : filePath + "/" + childName); 117 | } 118 | return files; 119 | } 120 | } catch (Exception ignore) { 121 | 122 | } 123 | return new VirtualFile[0]; 124 | } 125 | 126 | @NotNull 127 | public OutputStream getOutputStream(final Object requestor, final long newModificationStamp, long newTimeStamp) throws IOException { 128 | return new ByteArrayOutputStream() { 129 | @Override 130 | public void close() { 131 | // disable save to update node operation 132 | //setContent(requestor, toByteArray(), newModificationStamp); 133 | } 134 | }; 135 | } 136 | 137 | @NotNull 138 | public byte[] contentsToByteArray() throws IOException { 139 | checkContent(); 140 | return this.content; 141 | } 142 | 143 | public void checkContent() { 144 | if (content == null) { 145 | try { 146 | this.content = getCurator().getData().storingStatIn(stat).forPath(filePath); 147 | if (isSingleFileZip()) { 148 | this.content = unzip(content); 149 | } 150 | } catch (Exception ignore) { 151 | 152 | } 153 | if (this.content == null) { 154 | content = "".getBytes(); 155 | } 156 | } 157 | } 158 | 159 | public long getTimeStamp() { 160 | return myModStamp; 161 | } 162 | 163 | @Override 164 | public long getModificationStamp() { 165 | return myTimeStamp; 166 | } 167 | 168 | public long getLength() { 169 | checkContent(); 170 | return this.content.length; 171 | } 172 | 173 | public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { 174 | 175 | } 176 | 177 | public InputStream getInputStream() throws IOException { 178 | checkContent(); 179 | return new ByteArrayInputStream(content); 180 | } 181 | 182 | public void setContent(@Nullable Object requestor, byte[] content, long newModificationStamp) { 183 | long oldModstamp = myModStamp; 184 | myModStamp = newModificationStamp; 185 | this.content = content; 186 | try { 187 | getCurator().setData().forPath(this.filePath, content); 188 | } catch (Exception ignore) { 189 | 190 | } 191 | if (fileListener != null) { 192 | fileListener.contentsChanged(new VirtualFileEvent(requestor, this, null, oldModstamp, myModStamp)); 193 | } 194 | } 195 | 196 | @Override 197 | public Charset getCharset() { 198 | return fileSystem.getCharset(); 199 | } 200 | 201 | @NotNull 202 | public FileType getFileType() { 203 | String newFileName = this.fileName; 204 | if (isSingleFileZip()) { 205 | newFileName = newFileName.replace(".zip", ""); 206 | } 207 | FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(newFileName); 208 | if (fileType.getName().equalsIgnoreCase(FileTypes.UNKNOWN.getName())) { 209 | return FileTypes.PLAIN_TEXT; 210 | } 211 | return fileType; 212 | } 213 | 214 | public CuratorFramework getCurator() { 215 | return fileSystem.getCurator(); 216 | } 217 | 218 | public boolean equals(Object obj) { 219 | return obj instanceof ZkNodeVirtualFile && ((ZkNodeVirtualFile) obj).getFilePath().equals(filePath); 220 | } 221 | 222 | @Override 223 | public String toString() { 224 | return this.filePath; 225 | } 226 | 227 | public boolean isSingleFileZip() { 228 | return isLeaf && fileName.endsWith(".zip") && fileName.replace(".zip", "").contains("."); 229 | } 230 | 231 | public static byte[] unzip(byte[] zipContent) throws Exception { 232 | ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipContent)); 233 | zis.getNextEntry(); 234 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 235 | int b; 236 | while ((b = zis.read()) != -1) { 237 | bos.write(b); 238 | } 239 | zis.closeEntry(); 240 | zis.close(); 241 | return bos.toByteArray(); 242 | } 243 | 244 | public static byte[] zip(String name, byte[] content) throws Exception { 245 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 246 | ZipOutputStream zipOutput = new ZipOutputStream(bos); 247 | ZipEntry entry = new ZipEntry(name); 248 | entry.setSize(content.length); 249 | zipOutput.putNextEntry(entry); 250 | zipOutput.write(content); 251 | zipOutput.closeEntry(); 252 | zipOutput.close(); 253 | return bos.toByteArray(); 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/intellij/plugin/zookeeper/vfs/ZkVirtualFileSystem.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.intellij.plugin.zookeeper.vfs; 2 | 3 | import com.intellij.openapi.util.text.StringUtil; 4 | import com.intellij.openapi.vfs.VirtualFile; 5 | import com.intellij.openapi.vfs.VirtualFileListener; 6 | import com.intellij.openapi.vfs.ex.dummy.DummyFileSystem; 7 | import org.apache.curator.framework.CuratorFramework; 8 | import org.jetbrains.annotations.NonNls; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.io.IOException; 13 | import java.nio.charset.Charset; 14 | 15 | /** 16 | * zookeeper virtual file system 17 | * 18 | * @author linux_china 19 | */ 20 | public class ZkVirtualFileSystem extends DummyFileSystem { 21 | public static final String PROTOCOL = "zk"; 22 | private CuratorFramework curator; 23 | private Charset charset = Charset.forName("utf-8"); 24 | 25 | public ZkVirtualFileSystem(CuratorFramework curator, String charsetName) { 26 | this.curator = curator; 27 | if (StringUtil.isEmpty(charsetName)) { 28 | charsetName = "utf-8"; 29 | } 30 | this.charset = Charset.forName(charsetName); 31 | } 32 | 33 | @NotNull 34 | public String getProtocol() { 35 | return PROTOCOL; 36 | } 37 | 38 | public Charset getCharset() { 39 | return this.charset; 40 | } 41 | 42 | @Nullable 43 | public VirtualFile findFileByPath(@NotNull @NonNls String path) { 44 | return new ZkNodeVirtualFile(this, path); 45 | } 46 | 47 | public void refresh(boolean b) { 48 | 49 | } 50 | 51 | @Nullable 52 | public VirtualFile refreshAndFindFileByPath(@NotNull String path) { 53 | return findFileByPath(path); 54 | } 55 | 56 | public void addVirtualFileListener(@NotNull VirtualFileListener virtualFileListener) { 57 | 58 | } 59 | 60 | public void removeVirtualFileListener(@NotNull VirtualFileListener virtualFileListener) { 61 | 62 | } 63 | 64 | public void deleteFile(Object o, @NotNull VirtualFile virtualFile) throws IOException { 65 | try { 66 | getCurator().delete().forPath(virtualFile.getPath()); 67 | } catch (Exception ignore) { 68 | 69 | } 70 | } 71 | 72 | public void moveFile(Object o, @NotNull VirtualFile virtualFile, @NotNull VirtualFile virtualFile2) throws IOException { 73 | try { 74 | byte[] content = getCurator().getData().forPath(virtualFile.getPath()); 75 | getCurator().create().forPath(virtualFile2.getPath(), content); 76 | getCurator().delete().forPath(virtualFile.getPath()); 77 | } catch (Exception ignore) { 78 | 79 | } 80 | } 81 | 82 | public void renameFile(Object o, @NotNull VirtualFile virtualFile, @NotNull String name) throws IOException { 83 | String newFilePath = virtualFile.getPath().substring(0, virtualFile.getPath().indexOf("/")) + "/" + name; 84 | moveFile(o, virtualFile, new ZkNodeVirtualFile(this, newFilePath)); 85 | } 86 | 87 | public VirtualFile createChildFile(Object o, @NotNull VirtualFile virtualFile, @NotNull String fileName) throws IOException { 88 | String filePath = virtualFile.getPath() + "/" + fileName; 89 | try { 90 | getCurator().create().forPath(filePath); 91 | } catch (Exception ignore) { 92 | 93 | } 94 | return new ZkNodeVirtualFile(this, filePath); 95 | } 96 | 97 | @NotNull 98 | public VirtualFile createChildDirectory(Object o, @NotNull VirtualFile virtualFile, @NotNull String directory) throws IOException { 99 | String filePath = virtualFile.getPath() + "/" + directory; 100 | try { 101 | getCurator().create().forPath(filePath); 102 | } catch (Exception ignore) { 103 | 104 | } 105 | return new ZkNodeVirtualFile(this, filePath); 106 | } 107 | 108 | public VirtualFile copyFile(Object o, @NotNull VirtualFile virtualFile, @NotNull VirtualFile virtualFile2, @NotNull String s) throws IOException { 109 | try { 110 | //todo 111 | } catch (Exception ignore) { 112 | 113 | } 114 | return null; 115 | } 116 | 117 | public boolean isReadOnly() { 118 | return false; 119 | } 120 | 121 | public CuratorFramework getCurator() { 122 | return this.curator; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/resources/icons/zookeeper_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linux-china/zookeeper-intellij/dd9ac9cf2e5a3d43a37c78fcabb6e06152d7118b/src/main/resources/icons/zookeeper_small.png -------------------------------------------------------------------------------- /zookeeper-intellij.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 47 | --------------------------------------------------------------------------------