/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.ext.java.client.tree.library; import com.google.common.annotations.Beta; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.web.bindery.event.shared.EventBus; import com.google.web.bindery.event.shared.HandlerRegistration; import org.eclipse.che.api.promises.client.Function; import org.eclipse.che.api.promises.client.FunctionException; import org.eclipse.che.api.promises.client.Promise; import org.eclipse.che.api.promises.client.js.Promises; import org.eclipse.che.ide.api.data.tree.HasAction; import org.eclipse.che.ide.api.data.tree.Node; import org.eclipse.che.ide.api.data.tree.settings.NodeSettings; import org.eclipse.che.ide.api.editor.EditorAgent; import org.eclipse.che.ide.api.editor.EditorPartPresenter; import org.eclipse.che.ide.api.event.FileEvent; import org.eclipse.che.ide.api.event.FileEvent.FileEventHandler; import org.eclipse.che.ide.api.resources.ResourceChangedEvent; import org.eclipse.che.ide.api.resources.ResourceChangedEvent.ResourceChangedHandler; import org.eclipse.che.ide.api.resources.ResourceDelta; import org.eclipse.che.ide.api.resources.VirtualFile; import org.eclipse.che.ide.api.theme.Style; import org.eclipse.che.ide.ext.java.client.JavaResources; import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService; import org.eclipse.che.ide.ext.java.shared.JarEntry; import org.eclipse.che.ide.ext.java.shared.dto.ClassContent; import org.eclipse.che.ide.project.node.SyntheticNode; import org.eclipse.che.ide.project.shared.NodesResources; import org.eclipse.che.ide.resource.Path; import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation; import javax.validation.constraints.NotNull; import java.util.Collections; import java.util.List; import static java.util.Collections.singletonList; import static org.eclipse.che.ide.api.resources.ResourceDelta.REMOVED; /** * It might be used for any jar content. * * @author Vlad Zhukovskiy */ @Beta public class JarFileNode extends SyntheticNode<JarEntry> implements VirtualFile, HasAction, FileEventHandler, ResourceChangedHandler { private final int libId; private final Path project; private final JavaResources javaResources; private final NodesResources nodesResources; private final JavaNavigationService service; private final EditorAgent editorAgent; private final EventBus eventBus; private HandlerRegistration fileEventHandlerRegistration; private HandlerRegistration resourceChangeHandlerRegistration; private boolean contentGenerated; @Inject public JarFileNode(@Assisted JarEntry jarEntry, @Assisted int libId, @Assisted Path project, @Assisted NodeSettings nodeSettings, JavaResources javaResources, NodesResources nodesResources, JavaNavigationService service, EditorAgent editorAgent, EventBus eventBus) { super(jarEntry, nodeSettings); this.libId = libId; this.project = project; this.javaResources = javaResources; this.nodesResources = nodesResources; this.service = service; this.editorAgent = editorAgent; this.eventBus = eventBus; getAttributes().put(CUSTOM_BACKGROUND_FILL, singletonList(Style.theme.projectExplorerReadonlyItemBackground())); } /** {@inheritDoc} */ @NotNull @Override protected Promise<List<Node>> getChildrenImpl() { return Promises.resolve(Collections.<Node>emptyList()); } /** {@inheritDoc} */ @Override public void actionPerformed() { if (fileEventHandlerRegistration == null) { fileEventHandlerRegistration = eventBus.addHandler(FileEvent.TYPE, this); } editorAgent.openEditor(this); } /** {@inheritDoc} */ @Override public void updatePresentation(@NotNull NodePresentation presentation) { presentation.setPresentableText(getDisplayName()); presentation.setPresentableIcon(isClassFile() ? javaResources.javaFile() : nodesResources.file()); } /** {@inheritDoc} */ @NotNull @Override public String getName() { return getData().getName(); } /** {@inheritDoc} */ @Override public boolean isLeaf() { return true; } @Override public Path getLocation() { return Path.valueOf(getData().getPath()); } /** {@inheritDoc} */ @Override public String getDisplayName() { if (isClassFile()) { return getData().getName().substring(0, getData().getName().lastIndexOf(".class")); } else { return getData().getName(); } } /** {@inheritDoc} */ @Override public boolean isReadOnly() { return true; } /** {@inheritDoc} */ @Override public String getContentUrl() { return null; } public Path getProjectLocation() { return project; } /** {@inheritDoc} */ @Override public Promise<String> getContent() { if (libId != -1) { return service.getContent(project, libId, Path.valueOf(getData().getPath())).then(new Function<ClassContent, String>() { @Override public String apply(ClassContent result) throws FunctionException { JarFileNode.this.contentGenerated = result.isGenerated(); return result.getContent(); } }); } else { return service.getContent(project, getData().getPath()).then(new Function<ClassContent, String>() { @Override public String apply(ClassContent result) throws FunctionException { JarFileNode.this.contentGenerated = result.isGenerated(); return result.getContent(); } }); } } /** {@inheritDoc} */ @Override public Promise<Void> updateContent(String content) { throw new IllegalStateException("Update content on class file is not supported."); } private boolean isClassFile() { return getData().getName().endsWith(".class"); } public boolean isContentGenerated() { return contentGenerated; } @Override public Path getProject() { return project; } @Override public void onFileOperation(FileEvent event) { Path filePath = event.getFile().getLocation(); Path currentPath = getLocation(); if (!filePath.equals(currentPath)) { return; } switch (event.getOperationType()) { case OPEN: { if (resourceChangeHandlerRegistration == null) { resourceChangeHandlerRegistration = eventBus.addHandler(ResourceChangedEvent.getType(), this); } break; } case CLOSE: { if (resourceChangeHandlerRegistration != null) { resourceChangeHandlerRegistration.removeHandler(); resourceChangeHandlerRegistration = null; } break; } } } @Override public void onResourceChanged(ResourceChangedEvent event) { ResourceDelta delta = event.getDelta(); Path resourceLocation = delta.getResource().getLocation(); if (REMOVED == delta.getKind() && project.equals(resourceLocation)) { EditorPartPresenter editorPart = editorAgent.getOpenedEditor(getLocation()); editorAgent.closeEditor(editorPart); removeHandlers(); } } private void removeHandlers() { if (fileEventHandlerRegistration != null) { fileEventHandlerRegistration.removeHandler(); fileEventHandlerRegistration = null; } if (resourceChangeHandlerRegistration != null) { resourceChangeHandlerRegistration.removeHandler(); resourceChangeHandlerRegistration = null; } } }