mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 19:02:13 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
Generated
+3
-3
@@ -1,13 +1,13 @@
|
||||
<component name="libraryTable">
|
||||
<library name="jna">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/jna-utils.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/jna.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/jna-platform.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jna-src.zip!/src" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jna-src.zip!/contrib/platform/src" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jna.zip!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jna-platform.zip!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
Generated
+11
-6
@@ -10,12 +10,17 @@
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-0.0.6/jsch-agent-proxy-core/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-0.0.6/jsch-agent-proxy-pageant/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-0.0.6/jsch-agent-proxy-sshagent/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-0.0.6/jsch-agent-proxy-usocket-nc/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-0.0.6/jsch-agent-proxy-usocket-jna/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-0.0.6/jsch-agent-proxy-connector-factory/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/examples/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-connector-factory/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-core/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-jsch/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-pageant/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-sshagent/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-sshj/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-svnkit-trilead-ssh2/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-usocket-jna/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-usocket-junixsocket/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/jsch-agent-proxy.zip!/jsch-agent-proxy-usocket-nc/src/main/java" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
Generated
+2
-2
@@ -1,11 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="pty4j">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.4.22.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/pty4j-0.4.23.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.4.22-src.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/pty4j-0.4.23-src.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@
|
||||
<include name="guava*.jar"/>
|
||||
<include name="picocontainer.jar"/>
|
||||
<include name="jna.jar"/>
|
||||
<include name="jna-utils.jar"/>
|
||||
<include name="jna-platform.jar"/>
|
||||
<include name="oromatcher.jar"/>
|
||||
<include name="snappy-in-java-*.jar"/>
|
||||
<include name="cli-parser-*.jar"/>
|
||||
|
||||
@@ -199,10 +199,10 @@ libraryLicense(name: "javawriter", libraryName: "javawriter", license: "Apache 2
|
||||
libraryLicense(name: "JGoodies Forms", libraryName: "jgoodies-forms", version: "1.1-preview 2006-05-04 11:55:37", license: "BSD ", url: "http://www.jgoodies.com/freeware/forms/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
|
||||
libraryLicense(name: "JGoodies Looks", libraryName: "jgoodies-looks", version: "2.4.2", license: "BSD ", url: "http://www.jgoodies.com/freeware/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
|
||||
libraryLicense(name: "JGoodies Common", libraryName: "jgoodies-common", version: "1.2.1", license: "BSD ", url: "http://www.jgoodies.com/freeware/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
|
||||
libraryLicense(name: "JNA", libraryName: "jna", version: "3.4.0", license: "LGPL 2.1", url: "https://jna.dev.java.net/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php")
|
||||
libraryLicense(name: "JNA", libraryName: "jna", version: "4.1.0", license: "LGPL 2.1", url: "https://jna.dev.java.net/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php")
|
||||
libraryLicense(name: "JSch", libraryName: "JSch", version: "0.1.52", license: "BSD", url: "http://www.jcraft.com/jsch/", licenseUrl: "http://www.jcraft.com/jsch/LICENSE.txt")
|
||||
libraryLicense(name: "jsch-agent-proxy", libraryName: "jsch-agent-proxy", version: "0.0.6", license: "BSD", url: "https://github.com/ymnk/jsch-agent-proxy", licenseUrl: "https://github.com/ymnk/jsch-agent-proxy/blob/master/LICENSE.txt")
|
||||
libraryLicense(name: "jsch-agent-proxy for svnkit trilead", libraryName: "jsch.agentproxy.svnkit-trilead-ssh2.jar", version: "0.0.6", license: "BSD", url: "https://github.com/ymnk/jsch-agent-proxy", licenseUrl: "https://github.com/ymnk/jsch-agent-proxy/blob/master/LICENSE.txt")
|
||||
libraryLicense(name: "jsch-agent-proxy", libraryName: "jsch-agent-proxy", version: "0.0.7", license: "BSD", url: "https://github.com/ymnk/jsch-agent-proxy", licenseUrl: "https://github.com/ymnk/jsch-agent-proxy/blob/master/LICENSE.txt")
|
||||
libraryLicense(name: "jsch-agent-proxy for svnkit trilead", libraryName: "jsch.agentproxy.svnkit-trilead-ssh2.jar", version: "0.0.7", license: "BSD", url: "https://github.com/ymnk/jsch-agent-proxy", licenseUrl: "https://github.com/ymnk/jsch-agent-proxy/blob/master/LICENSE.txt")
|
||||
libraryLicense(name: "JUnit", libraryName: "JUnit3", version: "3.8.1", license: "CPL 1.0", url: "http://junit.org/")
|
||||
libraryLicense(name: "JUnit", libraryName: "JUnit4", version: "4.11", license: "CPL 1.0", url: "http://junit.org/")
|
||||
libraryLicense(name: "Log4j", libraryName: "Log4J", version: "1.2.17", license: "Apache 2.0", url: "http://logging.apache.org/log4j/1.2/index.html", licenseUrl: "http://logging.apache.org/license.html")
|
||||
@@ -242,7 +242,7 @@ libraryLicense(name: "Saxon-6.5.5", version: "6.5.5", license: "Mozilla Public L
|
||||
libraryLicense(name: "Sonatype Nexus: Indexer", libraryName: "nexus-indexer-1.2.3.jar", version: "1.2.3", license: "Eclipse Public License v1.0", url: "http://nexus.sonatype.org/", licenseUrl: "http://www.eclipse.org/org/documents/epl-v10.html")
|
||||
libraryLicense(name: "Sonatype Nexus: Indexer", libraryName: "nexus-indexer-3.0.4.jar", version: "3.0.4", license: "Eclipse Public License v1.0", url: "http://nexus.sonatype.org/", licenseUrl: "http://www.eclipse.org/org/documents/epl-v10.html")
|
||||
libraryLicense(name: "Sonatype Nexus Indexer Artifact", libraryName: "nexus-indexer-artifact-1.0.1.jar", version: "1.0.1", license: "Eclipse Public License v1.0", url: "http://nexus.sonatype.org/", licenseUrl: "http://www.eclipse.org/org/documents/epl-v10.html")
|
||||
libraryLicense(name: "SVNKit", libraryName: "svnkit.jar", version: "1.7.11", license: "link (commercial license)", url: "http://www.svnkit.com/", licenseUrl: "http://svnkit.com/license.html")
|
||||
libraryLicense(name: "SVNKit", libraryName: "svnkit.jar", version: "1.8.7", license: "link (commercial license)", url: "http://www.svnkit.com/", licenseUrl: "http://svnkit.com/license.html")
|
||||
libraryLicense(name: "Sequence", libraryName: "sequence-library.jar", version: "bundled with SVNKit", license: "BSD (see LICENSE.txt in sequence-library.jar)", url:"http://www.syntevo.com")
|
||||
libraryLicense(name: "swingx", libraryName: "swingx", version: "1.6.2", license: "LGPL 2.1", url: "http://java.net/downloads/swingx/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php")
|
||||
libraryLicense(name: "TestNG", version: "6.9 snapshot", license: "Apache 2.0", url: "http://testng.org/doc/", licenseUrl: "http://code.google.com/p/testng/")
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
<orderEntry type="module" module-name="jps-model-impl" />
|
||||
<orderEntry type="module" module-name="java-analysis-impl" />
|
||||
<orderEntry type="module" module-name="built-in-server" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
package org.jetbrains.builtInWebServer;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.artifacts.ArtifactManager;
|
||||
import com.intellij.util.PairFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
final class ArtifactWebServerRootsProvider extends PrefixlessWebServerRootsProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public PathInfo resolve(@NotNull String path, @NotNull Project project, @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver) {
|
||||
for (Artifact artifact : ArtifactManager.getInstance(project).getArtifacts()) {
|
||||
VirtualFile root = artifact.getOutputFile();
|
||||
if (root != null) {
|
||||
VirtualFile file = root.findFileByRelativePath(path);
|
||||
if (file != null) {
|
||||
return new PathInfo(file, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project) {
|
||||
for (Artifact artifact : ArtifactManager.getInstance(project).getArtifacts()) {
|
||||
VirtualFile root = artifact.getOutputFile();
|
||||
if (root != null && VfsUtilCore.isAncestor(root, file, true)) {
|
||||
return new PathInfo(file, root);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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 org.jetbrains.builtInWebServer
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.packaging.artifacts.ArtifactManager
|
||||
|
||||
internal class ArtifactWebServerRootsProvider : PrefixlessWebServerRootsProvider() {
|
||||
override fun resolve(path: String, project: Project, resolver: FileResolver): PathInfo? {
|
||||
for (artifact in ArtifactManager.getInstance(project).artifacts) {
|
||||
val root = artifact.outputFile ?: continue
|
||||
return resolver.resolve(path, root)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getPathInfo(file: VirtualFile, project: Project): PathInfo? {
|
||||
for (artifact in ArtifactManager.getInstance(project).artifacts) {
|
||||
val root = artifact.outputFile ?: continue
|
||||
if (VfsUtilCore.isAncestor(root, file, true)) {
|
||||
return PathInfo(null, file, root)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ package com.intellij.debugger.jdi;
|
||||
import com.intellij.debugger.engine.DebugProcess;
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.jdi.VirtualMachineProxy;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -278,6 +279,14 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy {
|
||||
return myVirtualMachine.eventRequestManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #mirrorOfVoid()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public VoidValue mirrorOf() throws EvaluateException {
|
||||
return mirrorOfVoid();
|
||||
}
|
||||
|
||||
public VoidValue mirrorOfVoid() {
|
||||
return myVirtualMachine.mirrorOfVoid();
|
||||
}
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ public class TestDiscoveryExtension extends RunConfigurationExtension {
|
||||
|
||||
@Override
|
||||
public boolean isListenerDisabled(RunConfigurationBase configuration, Object listener, RunnerSettings runnerSettings) {
|
||||
return !(listener instanceof TestDiscoveryListener) || runnerSettings != null || !isApplicableFor(configuration);
|
||||
return listener instanceof TestDiscoveryListener && (runnerSettings != null || !isApplicableFor(configuration));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -79,7 +79,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(element);
|
||||
final PsiElement firstChild = element.getFirstChild();
|
||||
if (interfaceMethod != null && firstChild != null) {
|
||||
return createSuperMethodLineMarkerInfo(firstChild, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_ALL);
|
||||
return createSuperMethodLineMarkerInfo(firstChild, AllIcons.Gutter.ImplementingFunctional, Pass.UPDATE_ALL);
|
||||
}
|
||||
|
||||
if (myDaemonSettings.SHOW_METHOD_SEPARATORS && firstChild == null) {
|
||||
|
||||
@@ -114,7 +114,7 @@ public class JavaDocExternalFilter extends AbstractExternalFilter {
|
||||
String builtInServer = "http://localhost:" + BuiltInServerOptions.getInstance().getEffectiveBuiltInServerPort() + "/" + myProject.getName() + "/";
|
||||
if (docURL.startsWith(builtInServer)) {
|
||||
int refPosition = docURL.lastIndexOf('#');
|
||||
VirtualFile file = WebServerPathToFileManager.getInstance(myProject).get(
|
||||
VirtualFile file = WebServerPathToFileManager.getInstance(myProject).findVirtualFile(
|
||||
docURL.substring(builtInServer.length(), refPosition < builtInServer.length() ? docURL.length() : refPosition)
|
||||
);
|
||||
if (file != null) {
|
||||
|
||||
@@ -1004,7 +1004,7 @@ public class ControlFlowUtil {
|
||||
if (isLeaf(nextOffset)) {
|
||||
exitPoints[offset].add(offset);
|
||||
}
|
||||
else {
|
||||
else if (exitPoints[nextOffset] != null) {
|
||||
exitPoints[offset].addAll(exitPoints[nextOffset].toArray());
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -30,8 +30,8 @@ jgoodies-common-1.2.1.jar
|
||||
jgoodies-forms.jar
|
||||
jgoodies-looks-2.4.2.jar
|
||||
jh.jar
|
||||
jna-utils.jar
|
||||
jna.jar
|
||||
jna-platform.jar
|
||||
jsch-0.1.52.jar
|
||||
jsch.agentproxy.connector-factory.jar
|
||||
jsch.agentproxy.core.jar
|
||||
@@ -56,7 +56,7 @@ oromatcher.jar
|
||||
picocontainer.jar
|
||||
protobuf-2.5.0.jar
|
||||
proxy-vole_20131209.jar
|
||||
pty4j-0.4.22.jar
|
||||
pty4j-0.4.23.jar
|
||||
purejavacomm.jar
|
||||
resolver.jar
|
||||
rhino-js-1_7R4.jar
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -197,7 +197,7 @@ public class Main {
|
||||
// always delete previous patch copy
|
||||
File patchCopy = new File(tempDir, patchFileName + "_copy");
|
||||
File log4jCopy = new File(tempDir, "log4j.jar." + platform + "_copy");
|
||||
File jnaUtilsCopy = new File(tempDir, "jna-utils.jar." + platform + "_copy");
|
||||
File jnaUtilsCopy = new File(tempDir, "jna-platform.jar." + platform + "_copy");
|
||||
File jnaCopy = new File(tempDir, "jna.jar." + platform + "_copy");
|
||||
if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy) || !FileUtilRt.delete(jnaUtilsCopy) || !FileUtilRt.delete(jnaCopy)) {
|
||||
throw new IOException("Cannot delete temporary files in " + tempDir);
|
||||
@@ -209,8 +209,8 @@ public class Main {
|
||||
File log4j = new File(PathManager.getLibPath(), "log4j.jar");
|
||||
if (!log4j.exists()) throw new IOException("Log4J is missing: " + log4j);
|
||||
|
||||
File jnaUtils = new File(PathManager.getLibPath(), "jna-utils.jar");
|
||||
if (!jnaUtils.exists()) throw new IOException("jna-utils.jar is missing: " + jnaUtils);
|
||||
File jnaUtils = new File(PathManager.getLibPath(), "jna-platform.jar");
|
||||
if (!jnaUtils.exists()) throw new IOException("jna-platform.jar is missing: " + jnaUtils);
|
||||
|
||||
File jna = new File(PathManager.getLibPath(), "jna.jar");
|
||||
if (!jna.exists()) throw new IOException("jna is missing: " + jna);
|
||||
|
||||
@@ -10,5 +10,7 @@
|
||||
<orderEntry type="module" module-name="core-api" />
|
||||
<orderEntry type="library" name="Netty" level="project" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="module" module-name="platform-api" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,59 +0,0 @@
|
||||
package org.jetbrains.builtInWebServer;
|
||||
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PathInfo {
|
||||
private final VirtualFile child;
|
||||
private final VirtualFile root;
|
||||
private final boolean isLibrary;
|
||||
|
||||
String moduleName;
|
||||
|
||||
private String computedPath;
|
||||
|
||||
public PathInfo(@NotNull VirtualFile child, @NotNull VirtualFile root, @Nullable String moduleName, boolean isLibrary) {
|
||||
this.child = child;
|
||||
this.root = root;
|
||||
this.moduleName = moduleName;
|
||||
this.isLibrary = isLibrary;
|
||||
}
|
||||
|
||||
public PathInfo(@NotNull VirtualFile child, @NotNull VirtualFile root) {
|
||||
this(child, root, null, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile getChild() {
|
||||
return child;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getModuleName() {
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPath() {
|
||||
if (computedPath == null) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (moduleName != null) {
|
||||
builder.append(moduleName).append('/');
|
||||
}
|
||||
|
||||
if (isLibrary) {
|
||||
builder.append(root.getName()).append('/');
|
||||
}
|
||||
|
||||
computedPath = builder.append(VfsUtilCore.getRelativePath(child, root, '/')).toString();
|
||||
}
|
||||
return computedPath;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.jetbrains.builtInWebServer
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import java.io.File
|
||||
|
||||
class PathInfo(val ioFile: File?, val file: VirtualFile?, val root: VirtualFile, moduleName: String? = null, private val isLibrary: Boolean = false) {
|
||||
var moduleName: String? = moduleName
|
||||
set
|
||||
|
||||
val path: String by lazy {
|
||||
val builder = StringBuilder()
|
||||
if (moduleName != null) {
|
||||
builder.append(moduleName).append('/')
|
||||
}
|
||||
|
||||
if (isLibrary) {
|
||||
builder.append(root.name).append('/')
|
||||
}
|
||||
|
||||
if (file == null) {
|
||||
builder.append(FileUtilRt.getRelativePath(FileUtilRt.toSystemIndependentName(ioFile!!.path), root.path, '/')).toString()
|
||||
}
|
||||
else {
|
||||
builder.append(VfsUtilCore.getRelativePath(file, root, '/')).toString()
|
||||
}
|
||||
}
|
||||
|
||||
val isValid: Boolean
|
||||
get() = if (ioFile == null) file!!.isValid else ioFile.exists()
|
||||
|
||||
val name: String
|
||||
get() = if (ioFile == null) file!!.name else ioFile.name
|
||||
|
||||
val fileType: FileType
|
||||
get() = if (ioFile == null) file!!.fileType else FileTypeManager.getInstance().getFileTypeByFileName(ioFile.name)
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ public abstract class WebServerRootsProvider {
|
||||
public abstract PathInfo resolve(@NotNull String path, @NotNull Project project);
|
||||
|
||||
@Nullable
|
||||
public abstract PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project);
|
||||
public abstract PathInfo getPathInfo(@NotNull VirtualFile file, @NotNull Project project);
|
||||
|
||||
public boolean isClearCacheOnFileContentChanged(@NotNull VirtualFile file) {
|
||||
return false;
|
||||
|
||||
@@ -21,26 +21,16 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.util.SystemInfoRt
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtilRt
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.PathUtilRt
|
||||
import com.intellij.util.UriUtil
|
||||
import com.intellij.util.io.URLUtil
|
||||
import com.intellij.util.net.NetUtils
|
||||
import io.netty.buffer.ByteBufUtf8Writer
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.ChannelFutureListener
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.handler.codec.http.*
|
||||
import io.netty.handler.stream.ChunkedStream
|
||||
import org.jetbrains.builtInWebServer.ssi.SsiExternalResolver
|
||||
import org.jetbrains.builtInWebServer.ssi.SsiProcessor
|
||||
import io.netty.handler.codec.http.FullHttpRequest
|
||||
import io.netty.handler.codec.http.HttpHeaderNames
|
||||
import io.netty.handler.codec.http.HttpMethod
|
||||
import io.netty.handler.codec.http.QueryStringDecoder
|
||||
import org.jetbrains.ide.HttpRequestHandler
|
||||
import org.jetbrains.io.FileResponses
|
||||
import org.jetbrains.io.Responses
|
||||
import org.jetbrains.io.Responses.addKeepAliveIfNeed
|
||||
import java.io.File
|
||||
import java.net.InetAddress
|
||||
import java.net.UnknownHostException
|
||||
|
||||
@@ -124,7 +114,7 @@ class BuiltInWebServer : HttpRequestHandler() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun isSupported(request: FullHttpRequest) = super.isSupported(request) || request.method() === HttpMethod.POST
|
||||
override fun isSupported(request: FullHttpRequest) = super.isSupported(request) || request.method() == HttpMethod.POST
|
||||
|
||||
override fun process(urlDecoder: QueryStringDecoder, request: FullHttpRequest, context: ChannelHandlerContext): Boolean {
|
||||
var host = request.headers().getAsString(HttpHeaderNames.HOST)
|
||||
@@ -156,12 +146,12 @@ class BuiltInWebServer : HttpRequestHandler() {
|
||||
}
|
||||
}
|
||||
|
||||
public fun compareNameAndProjectBasePath(projectName: String, project: Project): Boolean {
|
||||
fun compareNameAndProjectBasePath(projectName: String, project: Project): Boolean {
|
||||
val basePath = project.basePath
|
||||
return basePath != null && basePath.length() > projectName.length() && basePath.endsWith(projectName) && basePath.charAt(basePath.length() - projectName.length() - 1) == '/'
|
||||
}
|
||||
|
||||
public fun findIndexFile(basedir: VirtualFile): VirtualFile? {
|
||||
fun findIndexFile(basedir: VirtualFile): VirtualFile? {
|
||||
val children = basedir.children
|
||||
if (children == null || children.isEmpty()) {
|
||||
return null
|
||||
@@ -189,7 +179,7 @@ public fun findIndexFile(basedir: VirtualFile): VirtualFile? {
|
||||
return null
|
||||
}
|
||||
|
||||
public fun isOwnHostName(host: String): Boolean {
|
||||
fun isOwnHostName(host: String): Boolean {
|
||||
if (NetUtils.isLocalhost(host)) {
|
||||
return true
|
||||
}
|
||||
@@ -208,93 +198,4 @@ public fun isOwnHostName(host: String): Boolean {
|
||||
catch (ignored: UnknownHostException) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private class StaticFileHandler : WebServerFileHandler() {
|
||||
private var ssiProcessor: SsiProcessor? = null
|
||||
|
||||
override fun process(file: VirtualFile, canonicalRequestPath: CharSequence, project: Project, request: FullHttpRequest, channel: Channel, isCustomHost: Boolean): Boolean {
|
||||
if (file.isInLocalFileSystem) {
|
||||
val nameSequence = file.nameSequence
|
||||
//noinspection SpellCheckingInspection
|
||||
if (StringUtilRt.endsWithIgnoreCase(nameSequence, ".shtml") || StringUtilRt.endsWithIgnoreCase(nameSequence, ".stm") || StringUtilRt.endsWithIgnoreCase(nameSequence, ".shtm")) {
|
||||
processSsi(file, canonicalRequestPath, project, request, channel, isCustomHost)
|
||||
return true
|
||||
}
|
||||
|
||||
val ioFile = VfsUtilCore.virtualToIoFile(file)
|
||||
if (hasAccess(ioFile)) {
|
||||
FileResponses.sendFile(request, channel, ioFile)
|
||||
}
|
||||
else {
|
||||
Responses.sendStatus(HttpResponseStatus.FORBIDDEN, channel, request)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val response = FileResponses.prepareSend(request, channel, file.timeStamp, file.path) ?: return true
|
||||
|
||||
val keepAlive = addKeepAliveIfNeed(response, request)
|
||||
if (request.method() !== HttpMethod.HEAD) {
|
||||
HttpUtil.setContentLength(response, file.length)
|
||||
}
|
||||
|
||||
channel.write(response)
|
||||
|
||||
if (request.method() != HttpMethod.HEAD) {
|
||||
channel.write(ChunkedStream(file.inputStream))
|
||||
}
|
||||
|
||||
val future = channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT)
|
||||
if (!keepAlive) {
|
||||
future.addListener(ChannelFutureListener.CLOSE)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun processSsi(file: VirtualFile, canonicalRequestPath: CharSequence, project: Project, request: FullHttpRequest, channel: Channel, isCustomHost: Boolean) {
|
||||
var path = PathUtilRt.getParentPath(canonicalRequestPath.toString())
|
||||
if (!isCustomHost) {
|
||||
// remove project name - SSI resolves files only inside current project
|
||||
path = path.substring(path.indexOf('/', 1) + 1)
|
||||
}
|
||||
|
||||
if (ssiProcessor == null) {
|
||||
ssiProcessor = SsiProcessor(false)
|
||||
}
|
||||
|
||||
val buffer = channel.alloc().ioBuffer()
|
||||
val keepAlive: Boolean
|
||||
var releaseBuffer = true
|
||||
try {
|
||||
val lastModified = ssiProcessor!!.process(SsiExternalResolver(project, request, path, file.parent), VfsUtilCore.loadText(file), file.timeStamp, ByteBufUtf8Writer(buffer))
|
||||
|
||||
val response = FileResponses.prepareSend(request, channel, lastModified, file.path) ?: return
|
||||
|
||||
keepAlive = addKeepAliveIfNeed(response, request)
|
||||
if (request.method() !== HttpMethod.HEAD) {
|
||||
HttpUtil.setContentLength(response, buffer.readableBytes().toLong())
|
||||
}
|
||||
|
||||
channel.write(response)
|
||||
|
||||
if (request.method() !== HttpMethod.HEAD) {
|
||||
releaseBuffer = false
|
||||
channel.write(buffer)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (releaseBuffer) {
|
||||
buffer.release()
|
||||
}
|
||||
}
|
||||
|
||||
val future = channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT)
|
||||
if (!keepAlive) {
|
||||
future.addListener(ChannelFutureListener.CLOSE)
|
||||
}
|
||||
}
|
||||
|
||||
// deny access to .htaccess files
|
||||
private fun hasAccess(result: File) = !result.isDirectory && result.canRead() && !(result.isHidden || result.name.startsWith(".ht"))
|
||||
}
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 org.jetbrains.builtInWebServer;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.io.Responses;
|
||||
|
||||
final class DefaultWebServerPathHandler extends WebServerPathHandler {
|
||||
@Override
|
||||
public boolean process(@NotNull String path,
|
||||
@NotNull Project project,
|
||||
@NotNull FullHttpRequest request,
|
||||
@NotNull ChannelHandlerContext context,
|
||||
@Nullable String projectName,
|
||||
@NotNull String decodedRawPath,
|
||||
boolean isCustomHost) {
|
||||
Channel channel = context.channel();
|
||||
WebServerPathToFileManager pathToFileManager = WebServerPathToFileManager.getInstance(project);
|
||||
VirtualFile result = pathToFileManager.pathToFileCache.getIfPresent(path);
|
||||
boolean indexUsed = false;
|
||||
if (result == null || !result.isValid()) {
|
||||
result = pathToFileManager.findByRelativePath(project, path);
|
||||
if (result == null) {
|
||||
if (path.isEmpty()) {
|
||||
Responses.sendStatus(HttpResponseStatus.NOT_FOUND, channel, "Index file doesn't exist.", request);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (result.isDirectory()) {
|
||||
if (!endsWithSlash(decodedRawPath)) {
|
||||
redirectToDirectory(request, channel, isCustomHost ? path : (projectName + '/' + path));
|
||||
return true;
|
||||
}
|
||||
|
||||
result = BuiltInWebServerPackage.findIndexFile(result);
|
||||
if (result == null) {
|
||||
Responses.sendStatus(HttpResponseStatus.NOT_FOUND, channel, "Index file doesn't exist.", request);
|
||||
return true;
|
||||
}
|
||||
indexUsed = true;
|
||||
}
|
||||
|
||||
pathToFileManager.pathToFileCache.put(path, result);
|
||||
}
|
||||
else if (!path.endsWith(result.getName())) {
|
||||
if (endsWithSlash(decodedRawPath)) {
|
||||
indexUsed = true;
|
||||
}
|
||||
else {
|
||||
// FallbackResource feature in action, /login requested, /index.php retrieved, we must not redirect /login to /login/
|
||||
if (path.endsWith(result.getParent().getName())) {
|
||||
redirectToDirectory(request, channel, isCustomHost ? path : (projectName + '/' + path));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder canonicalRequestPath = new StringBuilder();
|
||||
canonicalRequestPath.append('/');
|
||||
if (!isCustomHost) {
|
||||
canonicalRequestPath.append(projectName).append('/');
|
||||
}
|
||||
canonicalRequestPath.append(path);
|
||||
if (indexUsed) {
|
||||
canonicalRequestPath.append('/').append(result.getName());
|
||||
}
|
||||
|
||||
for (WebServerFileHandler fileHandler : WebServerFileHandler.EP_NAME.getExtensions()) {
|
||||
try {
|
||||
if (fileHandler.process(result, canonicalRequestPath, project, request, channel, isCustomHost)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
BuiltInWebServer.LOG.error(e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 org.jetbrains.builtInWebServer
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.util.PathUtilRt
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.handler.codec.http.FullHttpRequest
|
||||
import io.netty.handler.codec.http.HttpResponseStatus
|
||||
import org.jetbrains.io.Responses
|
||||
|
||||
private class DefaultWebServerPathHandler : WebServerPathHandler() {
|
||||
override fun process(path: String,
|
||||
project: Project,
|
||||
request: FullHttpRequest,
|
||||
context: ChannelHandlerContext,
|
||||
projectName: String?,
|
||||
decodedRawPath: String,
|
||||
isCustomHost: Boolean): Boolean {
|
||||
val channel = context.channel()
|
||||
val pathToFileManager = WebServerPathToFileManager.getInstance(project)
|
||||
var pathInfo = pathToFileManager.pathToInfoCache.getIfPresent(path)
|
||||
var indexUsed = false
|
||||
if (pathInfo == null || !pathInfo.isValid) {
|
||||
pathInfo = pathToFileManager.doFindByRelativePath(path)
|
||||
if (pathInfo == null) {
|
||||
if (path.isEmpty()) {
|
||||
Responses.sendStatus(HttpResponseStatus.NOT_FOUND, channel, "Index file doesn't exist.", request)
|
||||
return true
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
else {
|
||||
var virtualFile = pathInfo.file
|
||||
val isDirectory = if (virtualFile == null) pathInfo.ioFile!!.isDirectory else virtualFile.isDirectory
|
||||
if (isDirectory) {
|
||||
if (!WebServerPathHandler.endsWithSlash(decodedRawPath)) {
|
||||
WebServerPathHandler.redirectToDirectory(request, channel, if (isCustomHost) path else (projectName + '/' + path))
|
||||
return true
|
||||
}
|
||||
|
||||
if (virtualFile == null) {
|
||||
virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(pathInfo.ioFile!!)
|
||||
}
|
||||
|
||||
virtualFile = if (virtualFile == null) null else findIndexFile(virtualFile)
|
||||
if (virtualFile == null) {
|
||||
Responses.sendStatus(HttpResponseStatus.NOT_FOUND, channel, "Index file doesn't exist.", request)
|
||||
return true
|
||||
}
|
||||
indexUsed = true
|
||||
}
|
||||
}
|
||||
|
||||
pathToFileManager.pathToInfoCache.put(path, pathInfo)
|
||||
}
|
||||
else if (!path.endsWith(pathInfo.name)) {
|
||||
if (WebServerPathHandler.endsWithSlash(decodedRawPath)) {
|
||||
indexUsed = true
|
||||
}
|
||||
else {
|
||||
// FallbackResource feature in action, /login requested, /index.php retrieved, we must not redirect /login to /login/
|
||||
if (path.endsWith(PathUtilRt.getFileName(PathUtilRt.getParentPath(pathInfo.path)))) {
|
||||
WebServerPathHandler.redirectToDirectory(request, channel, if (isCustomHost) path else (projectName + '/' + path))
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val canonicalRequestPath = StringBuilder()
|
||||
canonicalRequestPath.append('/')
|
||||
if (!isCustomHost) {
|
||||
canonicalRequestPath.append(projectName).append('/')
|
||||
}
|
||||
canonicalRequestPath.append(path)
|
||||
if (indexUsed) {
|
||||
canonicalRequestPath.append('/').append(pathInfo.name)
|
||||
}
|
||||
|
||||
for (fileHandler in WebServerFileHandler.EP_NAME.extensions) {
|
||||
try {
|
||||
if (fileHandler.process(pathInfo, canonicalRequestPath, project, request, channel, isCustomHost)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
BuiltInWebServer.LOG.error(e)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
+41
-60
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.jetbrains.builtInWebServer
|
||||
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
@@ -34,7 +33,6 @@ import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.JarFileSystem
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.PairFunction
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.intellij.util.Processor
|
||||
|
||||
@@ -43,18 +41,11 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
var effectivePath = path
|
||||
if (PlatformUtils.isIntelliJ()) {
|
||||
val index = effectivePath.indexOf('/')
|
||||
if (index > 0 && !effectivePath.regionMatches(0, project.getName(), 0, index, !SystemInfo.isFileSystemCaseSensitive)) {
|
||||
if (index > 0 && !effectivePath.regionMatches(0, project.name, 0, index, !SystemInfo.isFileSystemCaseSensitive)) {
|
||||
val moduleName = effectivePath.substring(0, index)
|
||||
val token = ReadAction.start()
|
||||
val module: Module?
|
||||
try {
|
||||
module = ModuleManager.getInstance(project).findModuleByName(moduleName)
|
||||
}
|
||||
finally {
|
||||
token.finish()
|
||||
}
|
||||
val module = runReadAction { ModuleManager.getInstance(project).findModuleByName(moduleName) }
|
||||
|
||||
if (module != null && !module.isDisposed()) {
|
||||
if (module != null && !module.isDisposed) {
|
||||
effectivePath = effectivePath.substring(index + 1)
|
||||
val resolver = WebServerPathToFileManager.getInstance(project).getResolver(effectivePath)
|
||||
|
||||
@@ -74,7 +65,7 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
}
|
||||
}
|
||||
|
||||
val modules = runReadAction { ModuleManager.getInstance(project).getModules() }
|
||||
val modules = runReadAction { ModuleManager.getInstance(project).modules }
|
||||
val resolver = WebServerPathToFileManager.getInstance(project).getResolver(effectivePath)
|
||||
for (rootProvider in RootProvider.values()) {
|
||||
val result = findByRelativePath(project, effectivePath, modules, rootProvider, resolver)
|
||||
@@ -85,63 +76,57 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
return findInLibraries(project, modules, effectivePath, resolver)
|
||||
}
|
||||
|
||||
override fun getRoot(file: VirtualFile, project: Project): PathInfo? {
|
||||
override fun getPathInfo(file: VirtualFile, project: Project): PathInfo? {
|
||||
runReadAction {
|
||||
val directoryIndex = DirectoryIndex.getInstance(project)
|
||||
val info = directoryIndex.getInfoForFile(file)
|
||||
// we serve excluded files
|
||||
if (!info.isExcluded() && !info.isInProject()) {
|
||||
if (!info.isExcluded && !info.isInProject) {
|
||||
// javadoc jars is "not under project", but actually is, so, let's check project library table
|
||||
return if (file.getFileSystem() === JarFileSystem.getInstance()) getInfoForDocJar(file, project) else null
|
||||
return if (file.fileSystem == JarFileSystem.getInstance()) getInfoForDocJar(file, project) else null
|
||||
}
|
||||
|
||||
var root = info.getSourceRoot()
|
||||
var root = info.sourceRoot
|
||||
val isLibrary: Boolean
|
||||
if (root == null) {
|
||||
root = info.getContentRoot()
|
||||
root = info.contentRoot
|
||||
if (root == null) {
|
||||
root = info.getLibraryClassRoot()
|
||||
root = info.libraryClassRoot
|
||||
isLibrary = true
|
||||
|
||||
assert(root != null) { file.getPresentableUrl() }
|
||||
assert(root != null) { file.presentableUrl }
|
||||
}
|
||||
else {
|
||||
isLibrary = false
|
||||
}
|
||||
}
|
||||
else {
|
||||
isLibrary = info.isInLibrarySource()
|
||||
isLibrary = info.isInLibrarySource
|
||||
}
|
||||
|
||||
var module = info.getModule()
|
||||
var module = info.module
|
||||
if (isLibrary && module == null) {
|
||||
for (entry in directoryIndex.getOrderEntries(info)) {
|
||||
if (entry is ModuleLibraryOrderEntryImpl) {
|
||||
module = entry.getOwnerModule()
|
||||
module = entry.ownerModule
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PathInfo(file, root!!, getModuleNameQualifier(project, module), isLibrary)
|
||||
return PathInfo(null, file, root!!, getModuleNameQualifier(project, module), isLibrary)
|
||||
}
|
||||
}
|
||||
|
||||
private enum class RootProvider {
|
||||
SOURCE {
|
||||
override fun getRoots(rootManager: ModuleRootManager): Array<VirtualFile> {
|
||||
return rootManager.getSourceRoots()
|
||||
}
|
||||
override fun getRoots(rootManager: ModuleRootManager) = rootManager.sourceRoots
|
||||
},
|
||||
CONTENT {
|
||||
override fun getRoots(rootManager: ModuleRootManager): Array<VirtualFile> {
|
||||
return rootManager.getContentRoots()
|
||||
}
|
||||
override fun getRoots(rootManager: ModuleRootManager) = rootManager.contentRoots
|
||||
},
|
||||
EXCLUDED {
|
||||
override fun getRoots(rootManager: ModuleRootManager): Array<VirtualFile> {
|
||||
return rootManager.getExcludeRoots()
|
||||
}
|
||||
override fun getRoots(rootManager: ModuleRootManager) = rootManager.excludeRoots
|
||||
};
|
||||
|
||||
public abstract fun getRoots(rootManager: ModuleRootManager): Array<VirtualFile>
|
||||
@@ -167,7 +152,7 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun findInModuleLibraries(path: String, module: Module, resolver: PairFunction<String, VirtualFile, VirtualFile>): PathInfo? {
|
||||
private fun findInModuleLibraries(path: String, module: Module, resolver: FileResolver): PathInfo? {
|
||||
val index = path.indexOf('/')
|
||||
if (index <= 0) {
|
||||
return null
|
||||
@@ -178,7 +163,7 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
return result.get()
|
||||
}
|
||||
|
||||
private fun findInLibraries(project: Project, modules: Array<Module>, path: String, resolver: PairFunction<String, VirtualFile, VirtualFile>): PathInfo? {
|
||||
private fun findInLibraries(project: Project, modules: Array<Module>, path: String, resolver: FileResolver): PathInfo? {
|
||||
val index = path.indexOf('/')
|
||||
if (index < 0) {
|
||||
return null
|
||||
@@ -189,14 +174,14 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
runReadAction {
|
||||
val result = Ref.create<PathInfo>()
|
||||
for (module in modules) {
|
||||
if (!module.isDisposed()) {
|
||||
if (!module.isDisposed) {
|
||||
if (findInModuleLibraries(resolver, libraryFileName, relativePath, result, module)) {
|
||||
return result.get()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (library in LibraryTablesRegistrar.getInstance().getLibraryTable(project).getLibraries()) {
|
||||
for (library in LibraryTablesRegistrar.getInstance().getLibraryTable(project).libraries) {
|
||||
val pathInfo = findInLibrary(libraryFileName, relativePath, library, resolver)
|
||||
if (pathInfo != null) {
|
||||
return pathInfo
|
||||
@@ -207,24 +192,22 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun findInModuleLibraries(resolver: PairFunction<String, VirtualFile, VirtualFile>, libraryFileName: String, relativePath: String, result: Ref<PathInfo>, module: Module): Boolean {
|
||||
private fun findInModuleLibraries(resolver: FileResolver, libraryFileName: String, relativePath: String, result: Ref<PathInfo>, module: Module): Boolean {
|
||||
ModuleRootManager.getInstance(module).orderEntries().forEachLibrary(object : Processor<Library> {
|
||||
override fun process(library: Library): Boolean {
|
||||
result.set(findInLibrary(libraryFileName, relativePath, library, resolver))
|
||||
return result.isNull()
|
||||
return result.isNull
|
||||
}
|
||||
})
|
||||
return !result.isNull()
|
||||
return !result.isNull
|
||||
}
|
||||
|
||||
private fun findInLibrary(libraryFileName: String, relativePath: String, library: Library, resolver: PairFunction<String, VirtualFile, VirtualFile>): PathInfo? {
|
||||
for (rootType in ORDER_ROOT_TYPES.getValue()) {
|
||||
private fun findInLibrary(libraryFileName: String, relativePath: String, library: Library, resolver: FileResolver): PathInfo? {
|
||||
for (rootType in ORDER_ROOT_TYPES.value) {
|
||||
for (root in library.getFiles(rootType)) {
|
||||
if (StringUtil.equalsIgnoreCase(root.getNameSequence(), libraryFileName)) {
|
||||
val file = resolver.`fun`(relativePath, root)
|
||||
if (file != null) {
|
||||
return PathInfo(file, root, null, true)
|
||||
}
|
||||
if (StringUtil.equalsIgnoreCase(root.nameSequence, libraryFileName)) {
|
||||
val result = resolver.resolve(relativePath, root, isLibrary = true) ?: continue
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,7 +224,7 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
override fun process(library: Library): Boolean {
|
||||
for (root in library.getFiles(javaDocRootType)) {
|
||||
if (VfsUtilCore.isAncestor(root, file, false)) {
|
||||
result = PathInfo(file, root, getModuleNameQualifier(project, module), true)
|
||||
result = PathInfo(null, file, root, getModuleNameQualifier(project, module), true)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -252,8 +235,8 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
val processor = LibraryProcessor()
|
||||
runReadAction {
|
||||
val moduleManager = ModuleManager.getInstance(project)
|
||||
for (module in moduleManager.getModules()) {
|
||||
if (module.isDisposed()) {
|
||||
for (module in moduleManager.modules) {
|
||||
if (module.isDisposed) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -265,7 +248,7 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
}
|
||||
|
||||
processor.module = null
|
||||
for (library in LibraryTablesRegistrar.getInstance().getLibraryTable(project).getLibraries()) {
|
||||
for (library in LibraryTablesRegistrar.getInstance().getLibraryTable(project).libraries) {
|
||||
if (!processor.process(library)) {
|
||||
return processor.result
|
||||
}
|
||||
@@ -276,25 +259,23 @@ class DefaultWebServerRootsProvider : WebServerRootsProvider() {
|
||||
}
|
||||
|
||||
private fun getModuleNameQualifier(project: Project, module: Module?): String? {
|
||||
if (module != null && PlatformUtils.isIntelliJ() && !(module.getName().equals(project.getName(), ignoreCase = true) || compareNameAndProjectBasePath(module.getName(), project))) {
|
||||
return module.getName()
|
||||
if (module != null && PlatformUtils.isIntelliJ() && !(module.name.equals(project.name, ignoreCase = true) || compareNameAndProjectBasePath(module.name, project))) {
|
||||
return module.name
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun findByRelativePath(path: String, roots: Array<VirtualFile>, resolver: PairFunction<String, VirtualFile, VirtualFile>, moduleName: String?): PathInfo? {
|
||||
private fun findByRelativePath(path: String, roots: Array<VirtualFile>, resolver: FileResolver, moduleName: String?): PathInfo? {
|
||||
for (root in roots) {
|
||||
val file = resolver.`fun`(path, root)
|
||||
if (file != null) {
|
||||
return PathInfo(file, root, moduleName, false)
|
||||
}
|
||||
val result = resolver.resolve(path, root, moduleName) ?: continue
|
||||
return result
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun findByRelativePath(project: Project, path: String, modules: Array<Module>, rootProvider: RootProvider, resolver: PairFunction<String, VirtualFile, VirtualFile>): PathInfo? {
|
||||
private fun findByRelativePath(project: Project, path: String, modules: Array<Module>, rootProvider: RootProvider, resolver: FileResolver): PathInfo? {
|
||||
for (module in modules) {
|
||||
if (!module.isDisposed()) {
|
||||
if (!module.isDisposed) {
|
||||
val moduleRootManager = ModuleRootManager.getInstance(module)
|
||||
val result = findByRelativePath(path, rootProvider.getRoots(moduleRootManager), resolver, null)
|
||||
if (result != null) {
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package org.jetbrains.builtInWebServer;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PairFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class PrefixlessWebServerRootsProvider extends WebServerRootsProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public final PathInfo resolve(@NotNull String path, @NotNull Project project) {
|
||||
return resolve(path, project, WebServerPathToFileManager.getInstance(project).getResolver(path));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract PathInfo resolve(@NotNull String path, @NotNull Project project, @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.builtInWebServer
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
abstract class PrefixlessWebServerRootsProvider : WebServerRootsProvider() {
|
||||
override final fun resolve(path: String, project: Project) = resolve(path, project, WebServerPathToFileManager.getInstance(project).getResolver(path))
|
||||
|
||||
abstract fun resolve(path: String, project: Project, resolver: FileResolver): PathInfo?
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package org.jetbrains.builtInWebServer
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtilRt
|
||||
import com.intellij.util.PathUtilRt
|
||||
import io.netty.buffer.ByteBufUtf8Writer
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.ChannelFutureListener
|
||||
import io.netty.handler.codec.http.*
|
||||
import io.netty.handler.stream.ChunkedStream
|
||||
import org.jetbrains.builtInWebServer.ssi.SsiExternalResolver
|
||||
import org.jetbrains.builtInWebServer.ssi.SsiProcessor
|
||||
import org.jetbrains.io.FileResponses
|
||||
import org.jetbrains.io.Responses
|
||||
import java.io.File
|
||||
|
||||
private class StaticFileHandler : WebServerFileHandler() {
|
||||
private var ssiProcessor: SsiProcessor? = null
|
||||
|
||||
override fun process(pathInfo: PathInfo, canonicalRequestPath: CharSequence, project: Project, request: FullHttpRequest, channel: Channel, isCustomHost: Boolean): Boolean {
|
||||
if (pathInfo.ioFile != null || pathInfo.file!!.isInLocalFileSystem) {
|
||||
val ioFile = pathInfo.ioFile ?: File(pathInfo.file!!.path)
|
||||
|
||||
val nameSequence = pathInfo.name
|
||||
//noinspection SpellCheckingInspection
|
||||
if (StringUtilRt.endsWithIgnoreCase(nameSequence, ".shtml") || StringUtilRt.endsWithIgnoreCase(nameSequence, ".stm") || StringUtilRt.endsWithIgnoreCase(nameSequence, ".shtm")) {
|
||||
processSsi(ioFile, canonicalRequestPath, project, request, channel, isCustomHost)
|
||||
return true
|
||||
}
|
||||
|
||||
if (hasAccess(ioFile)) {
|
||||
FileResponses.sendFile(request, channel, ioFile)
|
||||
}
|
||||
else {
|
||||
Responses.sendStatus(HttpResponseStatus.FORBIDDEN, channel, request)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val file = pathInfo.file!!
|
||||
val response = FileResponses.prepareSend(request, channel, file.timeStamp, file.path) ?: return true
|
||||
|
||||
val keepAlive = Responses.addKeepAliveIfNeed(response, request)
|
||||
if (request.method() != HttpMethod.HEAD) {
|
||||
HttpUtil.setContentLength(response, file.length)
|
||||
}
|
||||
|
||||
channel.write(response)
|
||||
|
||||
if (request.method() != HttpMethod.HEAD) {
|
||||
channel.write(ChunkedStream(file.inputStream))
|
||||
}
|
||||
|
||||
val future = channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT)
|
||||
if (!keepAlive) {
|
||||
future.addListener(ChannelFutureListener.CLOSE)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun processSsi(file: File, canonicalRequestPath: CharSequence, project: Project, request: FullHttpRequest, channel: Channel, isCustomHost: Boolean) {
|
||||
var path = PathUtilRt.getParentPath(canonicalRequestPath.toString())
|
||||
if (!isCustomHost) {
|
||||
// remove project name - SSI resolves files only inside current project
|
||||
path = path.substring(path.indexOf('/', 1) + 1)
|
||||
}
|
||||
|
||||
if (ssiProcessor == null) {
|
||||
ssiProcessor = SsiProcessor(false)
|
||||
}
|
||||
|
||||
val buffer = channel.alloc().ioBuffer()
|
||||
val keepAlive: Boolean
|
||||
var releaseBuffer = true
|
||||
try {
|
||||
val lastModified = ssiProcessor!!.process(SsiExternalResolver(project, request, path, file.parentFile), FileUtil.loadFile(file), file.lastModified(), ByteBufUtf8Writer(buffer))
|
||||
val response = FileResponses.prepareSend(request, channel, lastModified, file.path) ?: return
|
||||
keepAlive = Responses.addKeepAliveIfNeed(response, request)
|
||||
if (request.method() != HttpMethod.HEAD) {
|
||||
HttpUtil.setContentLength(response, buffer.readableBytes().toLong())
|
||||
}
|
||||
|
||||
channel.write(response)
|
||||
|
||||
if (request.method() != HttpMethod.HEAD) {
|
||||
releaseBuffer = false
|
||||
channel.write(buffer)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (releaseBuffer) {
|
||||
buffer.release()
|
||||
}
|
||||
}
|
||||
|
||||
val future = channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT)
|
||||
if (!keepAlive) {
|
||||
future.addListener(ChannelFutureListener.CLOSE)
|
||||
}
|
||||
}
|
||||
|
||||
// deny access to .htaccess files
|
||||
private fun hasAccess(result: File) = !result.isDirectory && result.canRead() && !(result.isHidden || result.name.startsWith(".ht"))
|
||||
}
|
||||
+1
-2
@@ -17,7 +17,6 @@ package org.jetbrains.builtInWebServer;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -27,7 +26,7 @@ import java.io.IOException;
|
||||
public abstract class WebServerFileHandler {
|
||||
static final ExtensionPointName<WebServerFileHandler> EP_NAME = ExtensionPointName.create("org.jetbrains.webServerFileHandler");
|
||||
|
||||
public abstract boolean process(@NotNull VirtualFile file,
|
||||
public abstract boolean process(@NotNull PathInfo pathInfo,
|
||||
@NotNull CharSequence canonicalRequestPath,
|
||||
@NotNull Project project,
|
||||
@NotNull FullHttpRequest request,
|
||||
|
||||
-142
@@ -1,142 +0,0 @@
|
||||
package org.jetbrains.builtInWebServer;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.intellij.ProjectTopics;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootAdapter;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.util.PairFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Implement {@link WebServerRootsProvider} to add your provider
|
||||
*/
|
||||
public class WebServerPathToFileManager {
|
||||
private static final PairFunction<String, VirtualFile, VirtualFile> RELATIVE_PATH_RESOLVER = new PairFunction<String, VirtualFile, VirtualFile>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public VirtualFile fun(String path, VirtualFile parent) {
|
||||
return parent.findFileByRelativePath(path);
|
||||
}
|
||||
};
|
||||
|
||||
private static final PairFunction<String, VirtualFile, VirtualFile> EMPTY_PATH_RESOLVER = new PairFunction<String, VirtualFile, VirtualFile>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public VirtualFile fun(String path, VirtualFile parent) {
|
||||
return BuiltInWebServerPackage.findIndexFile(parent);
|
||||
}
|
||||
};
|
||||
|
||||
private final Project project;
|
||||
|
||||
final Cache<String, VirtualFile> pathToFileCache = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(10, TimeUnit.MINUTES).build();
|
||||
// time to expire should be greater than pathToFileCache
|
||||
private final Cache<VirtualFile, PathInfo> fileToRoot = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(11, TimeUnit.MINUTES).build();
|
||||
|
||||
public static WebServerPathToFileManager getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, WebServerPathToFileManager.class);
|
||||
}
|
||||
|
||||
public WebServerPathToFileManager(@NotNull Application application, @NotNull Project project) {
|
||||
this.project = project;
|
||||
application.getMessageBus().connect(project).subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
for (VFileEvent event : events) {
|
||||
if (event instanceof VFileContentChangeEvent) {
|
||||
VirtualFile file = ((VFileContentChangeEvent)event).getFile();
|
||||
for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
|
||||
if (rootsProvider.isClearCacheOnFileContentChanged(file)) {
|
||||
clearCache();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
clearCache();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
|
||||
@Override
|
||||
public void rootsChanged(ModuleRootEvent event) {
|
||||
clearCache();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearCache() {
|
||||
pathToFileCache.invalidateAll();
|
||||
fileToRoot.invalidateAll();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VirtualFile get(@NotNull String path) {
|
||||
return get(path, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VirtualFile get(@NotNull String path, boolean cacheResult) {
|
||||
VirtualFile result = pathToFileCache.getIfPresent(path);
|
||||
if (result == null || !result.isValid()) {
|
||||
result = findByRelativePath(project, path);
|
||||
if (cacheResult && result != null && result.isValid()) {
|
||||
pathToFileCache.put(path, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getPath(@NotNull VirtualFile file) {
|
||||
PathInfo pathInfo = getRoot(file);
|
||||
return pathInfo == null ? null : pathInfo.getPath();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PathInfo getRoot(@NotNull VirtualFile child) {
|
||||
PathInfo result = fileToRoot.getIfPresent(child);
|
||||
if (result == null) {
|
||||
for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
|
||||
result = rootsProvider.getRoot(child, project);
|
||||
if (result != null) {
|
||||
fileToRoot.put(child, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
VirtualFile findByRelativePath(@NotNull Project project, @NotNull String path) {
|
||||
for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
|
||||
PathInfo result = rootsProvider.resolve(path, project);
|
||||
if (result != null) {
|
||||
fileToRoot.put(result.getChild(), result);
|
||||
return result.getChild();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PairFunction<String, VirtualFile, VirtualFile> getResolver(@NotNull String path) {
|
||||
return path.isEmpty() ? EMPTY_PATH_RESOLVER : RELATIVE_PATH_RESOLVER;
|
||||
}
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
package org.jetbrains.builtInWebServer
|
||||
|
||||
import com.google.common.cache.CacheBuilder
|
||||
import com.intellij.ProjectTopics
|
||||
import com.intellij.openapi.application.Application
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ModuleRootAdapter
|
||||
import com.intellij.openapi.roots.ModuleRootEvent
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Implement [WebServerRootsProvider] to add your provider
|
||||
*/
|
||||
class WebServerPathToFileManager(application: Application, private val project: Project) {
|
||||
val pathToInfoCache = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(10, TimeUnit.MINUTES).build<String, PathInfo>()
|
||||
// time to expire should be greater than pathToFileCache
|
||||
private val virtualFileToPathInfo = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(11, TimeUnit.MINUTES).build<VirtualFile, PathInfo>()
|
||||
|
||||
init {
|
||||
application.messageBus.connect(project).subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener.Adapter() {
|
||||
override fun after(events: List<VFileEvent>) {
|
||||
for (event in events) {
|
||||
if (event is VFileContentChangeEvent) {
|
||||
val file = event.file
|
||||
for (rootsProvider in WebServerRootsProvider.EP_NAME.extensions) {
|
||||
if (rootsProvider.isClearCacheOnFileContentChanged(file)) {
|
||||
clearCache()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
clearCache()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
project.messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootAdapter() {
|
||||
override fun rootsChanged(event: ModuleRootEvent) {
|
||||
clearCache()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun clearCache() {
|
||||
pathToInfoCache.invalidateAll()
|
||||
virtualFileToPathInfo.invalidateAll()
|
||||
}
|
||||
|
||||
@JvmOverloads fun findVirtualFile(path: String, cacheResult: Boolean = true): VirtualFile? {
|
||||
val pathInfo = getPathInfo(path, cacheResult) ?: return null
|
||||
return pathInfo.file ?: return LocalFileSystem.getInstance().findFileByIoFile(pathInfo.ioFile!!)
|
||||
}
|
||||
|
||||
fun getPathInfo(path: String, cacheResult: Boolean = true): PathInfo? {
|
||||
var pathInfo = pathToInfoCache.getIfPresent(path)
|
||||
if (pathInfo == null || !pathInfo.isValid) {
|
||||
pathInfo = doFindByRelativePath(path)
|
||||
if (cacheResult && pathInfo != null && pathInfo.isValid) {
|
||||
pathToInfoCache.put(path, pathInfo)
|
||||
}
|
||||
}
|
||||
return pathInfo
|
||||
}
|
||||
|
||||
fun getPath(file: VirtualFile) = getPathInfo(file)?.path
|
||||
|
||||
private fun getPathInfo(child: VirtualFile): PathInfo? {
|
||||
var result = virtualFileToPathInfo.getIfPresent(child)
|
||||
if (result == null) {
|
||||
for (infoProvider in WebServerRootsProvider.EP_NAME.extensions) {
|
||||
result = infoProvider.getPathInfo(child, project)
|
||||
if (result != null) {
|
||||
virtualFileToPathInfo.put(child, result)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
internal fun doFindByRelativePath(path: String): PathInfo? {
|
||||
for (rootsProvider in WebServerRootsProvider.EP_NAME.extensions) {
|
||||
val result = rootsProvider.resolve(path, project)
|
||||
if (result != null) {
|
||||
if (result.file != null) {
|
||||
virtualFileToPathInfo.put(result.file, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getResolver(path: String) = if (path.isEmpty()) EMPTY_PATH_RESOLVER else RELATIVE_PATH_RESOLVER
|
||||
|
||||
companion object {
|
||||
private val RELATIVE_PATH_RESOLVER = object : FileResolver {
|
||||
override fun resolve(path: String, root: VirtualFile, moduleName: String?, isLibrary: Boolean): PathInfo? {
|
||||
// WEB-17691 built-in server doesn't serve files it doesn't have in the project tree
|
||||
// temp:// reports isInLocalFileSystem == true, but it is not true
|
||||
if (root.isInLocalFileSystem && root.fileSystem == LocalFileSystem.getInstance()) {
|
||||
val file = File(root.path, path)
|
||||
if (file.exists()) {
|
||||
return PathInfo(file, null, root, moduleName, isLibrary)
|
||||
}
|
||||
else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
else {
|
||||
val file = root.findFileByRelativePath(path) ?: return null
|
||||
return PathInfo(null, file, root, moduleName, isLibrary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val EMPTY_PATH_RESOLVER = object : FileResolver {
|
||||
override fun resolve(path: String, root: VirtualFile, moduleName: String?, isLibrary: Boolean): PathInfo? {
|
||||
val file = findIndexFile(root) ?: return null
|
||||
return PathInfo(null, file, root, moduleName, isLibrary)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic fun getInstance(project: Project): WebServerPathToFileManager {
|
||||
return ServiceManager.getService(project, WebServerPathToFileManager::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface FileResolver {
|
||||
fun resolve(path: String, root: VirtualFile, moduleName: String? = null, isLibrary: Boolean = false): PathInfo?
|
||||
}
|
||||
+18
-10
@@ -17,13 +17,14 @@ package org.jetbrains.builtInWebServer.ssi;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import gnu.trove.THashMap;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.builtInWebServer.PathInfo;
|
||||
import org.jetbrains.builtInWebServer.WebServerPathToFileManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -44,12 +45,12 @@ public final class SsiExternalResolver {
|
||||
|
||||
private Map<String, String> variables = new THashMap<String, String>();
|
||||
private final String parentPath;
|
||||
@NotNull private final VirtualFile parentFile;
|
||||
@NotNull private final File parentFile;
|
||||
|
||||
public SsiExternalResolver(@NotNull Project project,
|
||||
@NotNull HttpRequest request,
|
||||
@NotNull String parentPath,
|
||||
@NotNull VirtualFile parentFile) {
|
||||
@NotNull File parentFile) {
|
||||
this.project = project;
|
||||
this.request = request;
|
||||
this.parentPath = parentPath;
|
||||
@@ -75,23 +76,30 @@ public final class SsiExternalResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VirtualFile findFile(@NotNull String originalPath, boolean virtual) {
|
||||
public File findFile(@NotNull String originalPath, boolean virtual) {
|
||||
String path = FileUtil.toCanonicalPath(originalPath, '/');
|
||||
if (!virtual) {
|
||||
return parentFile.findFileByRelativePath(path);
|
||||
return new File(parentFile, path);
|
||||
}
|
||||
|
||||
path = path.charAt(0) == '/' ? path : (parentPath + '/' + path);
|
||||
return WebServerPathToFileManager.getInstance(project).get(path);
|
||||
PathInfo pathInfo = WebServerPathToFileManager.getInstance(project).getPathInfo(path, true);
|
||||
if (pathInfo == null) {
|
||||
return null;
|
||||
}
|
||||
if (pathInfo.getIoFile() != null) {
|
||||
return pathInfo.getIoFile();
|
||||
}
|
||||
return new File(pathInfo.getFile().getPath());
|
||||
}
|
||||
|
||||
public long getFileLastModified(String path, boolean virtual) {
|
||||
VirtualFile file = findFile(path, virtual);
|
||||
return file == null ? 0 : file.getTimeStamp();
|
||||
File file = findFile(path, virtual);
|
||||
return file == null || !file.exists() ? 0 : file.lastModified();
|
||||
}
|
||||
|
||||
public long getFileSize(@NotNull String path, boolean virtual) {
|
||||
VirtualFile file = findFile(path, virtual);
|
||||
return file == null ? -1 : file.getLength();
|
||||
File file = findFile(path, virtual);
|
||||
return file == null || !file.exists() ? -1 : file.length();
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,13 @@
|
||||
package org.jetbrains.builtInWebServer.ssi;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.SmartList;
|
||||
import gnu.trove.THashMap;
|
||||
import io.netty.buffer.ByteBufUtf8Writer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
@@ -109,15 +110,15 @@ public class SsiProcessor {
|
||||
try {
|
||||
boolean virtual = paramName.equalsIgnoreCase("virtual");
|
||||
lastModified = state.ssiExternalResolver.getFileLastModified(substitutedValue, virtual);
|
||||
VirtualFile file = state.ssiExternalResolver.findFile(substitutedValue, virtual);
|
||||
File file = state.ssiExternalResolver.findFile(substitutedValue, virtual);
|
||||
if (file == null) {
|
||||
LOG.warn("#include-- Couldn't find file: " + substitutedValue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
InputStream in = file.getInputStream();
|
||||
InputStream in = new FileInputStream(file);
|
||||
try {
|
||||
writer.write(in, (int)file.getLength());
|
||||
writer.write(in, (int)file.length());
|
||||
}
|
||||
finally {
|
||||
in.close();
|
||||
|
||||
@@ -218,7 +218,7 @@ class OpenFileHttpService extends RestService {
|
||||
}
|
||||
|
||||
if (virtualFile == null) {
|
||||
virtualFile = WebServerPathToFileManager.getInstance(openedProject).get(path);
|
||||
virtualFile = WebServerPathToFileManager.getInstance(openedProject).findVirtualFile(path);
|
||||
}
|
||||
if (virtualFile != null) {
|
||||
project = openedProject;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.jetbrains.io.fastCgi
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.ByteBufAllocator
|
||||
import io.netty.buffer.ByteBufUtil
|
||||
@@ -9,7 +7,7 @@ import io.netty.buffer.ByteBufUtilEx
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.handler.codec.http.FullHttpRequest
|
||||
import io.netty.handler.codec.http.HttpHeaderNames
|
||||
import org.jetbrains.builtInWebServer.WebServerPathToFileManager
|
||||
import org.jetbrains.builtInWebServer.PathInfo
|
||||
import org.jetbrains.io.Responses
|
||||
import java.net.InetSocketAddress
|
||||
import java.util.*
|
||||
@@ -34,11 +32,10 @@ class FastCgiRequest(val requestId: Int, allocator: ByteBufAllocator) {
|
||||
buffer!!.writeZero(5)
|
||||
}
|
||||
|
||||
public fun writeFileHeaders(file: VirtualFile, project: Project, canonicalRequestPath: CharSequence) {
|
||||
val root = WebServerPathToFileManager.getInstance(project).getRoot(file)
|
||||
LOG.assertTrue(root != null)
|
||||
addHeader("DOCUMENT_ROOT", root!!.root.path)
|
||||
addHeader("SCRIPT_FILENAME", file.path)
|
||||
public fun writeFileHeaders(pathInfo: PathInfo, canonicalRequestPath: CharSequence) {
|
||||
val root = pathInfo.root
|
||||
addHeader("DOCUMENT_ROOT", root.path)
|
||||
addHeader("SCRIPT_FILENAME", pathInfo.path)
|
||||
addHeader("SCRIPT_NAME", canonicalRequestPath)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,29 +25,29 @@ class RestApiTest {
|
||||
private val manager = TestManager(projectRule, tempDirManager)
|
||||
|
||||
private val ruleChain = RuleChain(tempDirManager, manager)
|
||||
public Rule fun getChain(): RuleChain = ruleChain
|
||||
@Rule fun getChain() = ruleChain
|
||||
|
||||
Test(timeout = 60000)
|
||||
TestDescriptor(filePath = "", status = 400)
|
||||
public fun fileEmptyRequest() {
|
||||
@Test(timeout = 60000)
|
||||
@TestDescriptor(filePath = "", status = 400)
|
||||
fun fileEmptyRequest() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
Test(timeout = 60000)
|
||||
TestDescriptor(filePath = "foo.txt", relativeToProject = true, status = 200)
|
||||
public fun relativeToProject() {
|
||||
@Test(timeout = 60000)
|
||||
@TestDescriptor(filePath = "foo.txt", relativeToProject = true, status = 200)
|
||||
fun relativeToProject() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
Test(timeout = 60000)
|
||||
TestDescriptor(filePath = "foo.txt", relativeToProject = true, line = 1, status = 200)
|
||||
public fun relativeToProjectWithLine() {
|
||||
@Test(timeout = 60000)
|
||||
@TestDescriptor(filePath = "foo.txt", relativeToProject = true, line = 1, status = 200)
|
||||
fun relativeToProjectWithLine() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
Test(timeout = 60000)
|
||||
TestDescriptor(filePath = "foo.txt", relativeToProject = true, line = 1, column = 13, status = 200)
|
||||
public fun relativeToProjectWithLineAndColumn() {
|
||||
@Test(timeout = 60000)
|
||||
@TestDescriptor(filePath = "foo.txt", relativeToProject = true, line = 1, column = 13, status = 200)
|
||||
fun relativeToProjectWithLineAndColumn() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
@@ -57,26 +57,26 @@ class RestApiTest {
|
||||
doTest()
|
||||
}
|
||||
|
||||
Test(timeout = 60000)
|
||||
TestDescriptor(filePath = "bar/42/foo.txt", doNotCreate = true, status = 404)
|
||||
public fun relativeNonExistent() {
|
||||
@Test(timeout = 60000)
|
||||
@TestDescriptor(filePath = "bar/42/foo.txt", doNotCreate = true, status = 404)
|
||||
fun relativeNonExistent() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
Test(timeout = 60000)
|
||||
TestDescriptor(filePath = "_tmp_", doNotCreate = true, status = 404)
|
||||
public fun absoluteNonExistent() {
|
||||
@Test(timeout = 60000)
|
||||
@TestDescriptor(filePath = "_tmp_", doNotCreate = true, status = 404)
|
||||
fun absoluteNonExistent() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
Test(timeout = 60000)
|
||||
TestDescriptor(filePath = "_tmp_", status = 200)
|
||||
public fun absolute() {
|
||||
@Test(timeout = 60000)
|
||||
@TestDescriptor(filePath = "_tmp_", status = 200)
|
||||
fun absolute() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
private fun doTest() {
|
||||
val serviceUrl = "http://localhost:" + BuiltInServerManager.getInstance().getPort() + "/api/file"
|
||||
val serviceUrl = "http://localhost:${BuiltInServerManager.getInstance().port}/api/file"
|
||||
var url = serviceUrl + (if (manager.filePath == null) "" else ("/${manager.filePath}"))
|
||||
val line = manager.annotation?.line ?: -1
|
||||
if (line != -1) {
|
||||
@@ -89,21 +89,21 @@ class RestApiTest {
|
||||
|
||||
var connection = URL(url).openConnection() as HttpURLConnection
|
||||
val expectedStatus = HttpResponseStatus.valueOf(manager.annotation?.status ?: 200)
|
||||
assertThat(HttpResponseStatus.valueOf(connection.getResponseCode())).isEqualTo(expectedStatus)
|
||||
assertThat(HttpResponseStatus.valueOf(connection.responseCode)).isEqualTo(expectedStatus)
|
||||
|
||||
connection = URL("$serviceUrl?file=${manager.filePath ?: ""}&line=$line&column=$column").openConnection() as HttpURLConnection
|
||||
assertThat(HttpResponseStatus.valueOf(connection.getResponseCode())).isEqualTo(expectedStatus)
|
||||
assertThat(HttpResponseStatus.valueOf(connection.responseCode)).isEqualTo(expectedStatus)
|
||||
|
||||
connection = URL("$serviceUrl").openConnection() as HttpURLConnection
|
||||
connection.setRequestMethod("POST")
|
||||
connection.setDoOutput(true)
|
||||
val writer = JsonWriter(OutputStreamWriter(BufferedOutputStream(connection.getOutputStream()), CharsetToolkit.UTF8_CHARSET))
|
||||
connection.requestMethod = "POST"
|
||||
connection.doOutput = true
|
||||
val writer = JsonWriter(OutputStreamWriter(BufferedOutputStream(connection.outputStream), CharsetToolkit.UTF8_CHARSET))
|
||||
writer.beginObject()
|
||||
writer.name("file").value(manager.filePath)
|
||||
writer.name("line").value(line)
|
||||
writer.name("column").value(column)
|
||||
writer.endObject()
|
||||
writer.close()
|
||||
assertThat(HttpResponseStatus.valueOf(connection.getResponseCode())).isEqualTo(expectedStatus)
|
||||
assertThat(HttpResponseStatus.valueOf(connection.responseCode)).isEqualTo(expectedStatus)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
settingsSavingComponents.add(component)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
if (!(component is JDOMExternalizable || component is PersistentStateComponent<*>)) {
|
||||
return
|
||||
}
|
||||
@@ -88,10 +89,11 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
componentNameIfStateExists = if (component is PersistentStateComponent<*>) {
|
||||
val stateSpec = StoreUtil.getStateSpec(component)
|
||||
doAddComponent(stateSpec.name, component)
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
initPersistentComponent(stateSpec, component as PersistentStateComponent<Any>, null, false)
|
||||
}
|
||||
else {
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
initJdomExternalizable(component as JDOMExternalizable)
|
||||
}
|
||||
}
|
||||
@@ -142,7 +144,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
}
|
||||
|
||||
override TestOnly fun saveApplicationComponent(component: Any) {
|
||||
override @TestOnly fun saveApplicationComponent(component: Any) {
|
||||
val externalizationSession = storageManager.startExternalization() ?: return
|
||||
|
||||
commitComponent(externalizationSession, component, null)
|
||||
@@ -179,6 +181,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
|
||||
private fun commitComponent(session: ExternalizationSession, component: Any, componentName: String?) {
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
if (component is PersistentStateComponent<*>) {
|
||||
val state = component.getState()
|
||||
if (state != null) {
|
||||
@@ -199,7 +202,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
return errors
|
||||
}
|
||||
|
||||
private fun initJdomExternalizable(component: JDOMExternalizable): String? {
|
||||
private fun initJdomExternalizable(@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") component: JDOMExternalizable): String? {
|
||||
val componentName = ComponentManagerImpl.getComponentName(component)
|
||||
doAddComponent(componentName, component)
|
||||
|
||||
@@ -374,7 +377,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
|
||||
override final fun reloadState(componentClass: Class<out PersistentStateComponent<*>>) {
|
||||
val stateSpec = StoreUtil.getStateSpecOrError(componentClass)
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val component = components.get(stateSpec.name) as PersistentStateComponent<Any>?
|
||||
if (component != null) {
|
||||
initPersistentComponent(stateSpec, component, emptySet(), true)
|
||||
@@ -382,7 +385,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
|
||||
private fun reloadState(componentName: String, changedStorages: Set<StateStorage>): Boolean {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val component = components.get(componentName) as PersistentStateComponent<Any>?
|
||||
if (component == null) {
|
||||
return false
|
||||
|
||||
@@ -49,11 +49,9 @@ import gnu.trove.TObjectProcedure
|
||||
import org.jdom.Document
|
||||
import org.jdom.Element
|
||||
import java.io.File
|
||||
import java.io.FilenameFilter
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import java.util.*
|
||||
|
||||
public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val fileSpec: String,
|
||||
private val processor: SchemeProcessor<E>,
|
||||
@@ -80,8 +78,8 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
|
||||
init {
|
||||
if (processor is SchemeExtensionProvider) {
|
||||
schemeExtension = processor.getSchemeExtension()
|
||||
updateExtension = processor.isUpgradeNeeded()
|
||||
schemeExtension = processor.schemeExtension
|
||||
updateExtension = processor.isUpgradeNeeded
|
||||
}
|
||||
else {
|
||||
schemeExtension = FileStorageCoreUtil.DEFAULT_EXT
|
||||
@@ -103,33 +101,33 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
val directory = LocalFileSystem.getInstance().findFileByIoFile(ioDirectory) ?: return
|
||||
|
||||
this.directory = directory
|
||||
directory.getChildren()
|
||||
directory.children
|
||||
if (directory is NewVirtualFile) {
|
||||
directory.markDirty()
|
||||
}
|
||||
|
||||
directory.refresh(true, false, Runnable {
|
||||
directory.refresh(true, false, {
|
||||
addVfsListener(virtualFileTrackerDisposable)
|
||||
})
|
||||
}
|
||||
|
||||
private fun addVfsListener(virtualFileTrackerDisposable: Disposable?) {
|
||||
service<VirtualFileTracker>().addTracker("${LocalFileSystem.PROTOCOL_PREFIX}${ioDirectory.getAbsolutePath().replace(File.separatorChar, '/')}", object : VirtualFileAdapter() {
|
||||
service<VirtualFileTracker>().addTracker("${LocalFileSystem.PROTOCOL_PREFIX}${ioDirectory.absolutePath.replace(File.separatorChar, '/')}", object : VirtualFileAdapter() {
|
||||
override fun contentsChanged(event: VirtualFileEvent) {
|
||||
if (event.getRequestor() != null || !isMy(event)) {
|
||||
if (event.requestor != null || !isMy(event)) {
|
||||
return
|
||||
}
|
||||
|
||||
val oldScheme = findExternalizableSchemeByFileName(event.getFile().getName())
|
||||
val oldScheme = findExternalizableSchemeByFileName(event.file.name)
|
||||
var oldCurrentScheme: T? = null
|
||||
if (oldScheme != null) {
|
||||
oldCurrentScheme = currentScheme
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
removeScheme(oldScheme as T)
|
||||
processor.onSchemeDeleted(oldScheme)
|
||||
}
|
||||
|
||||
val newScheme = readSchemeFromFile(event.getFile(), false)
|
||||
val newScheme = readSchemeFromFile(event.file, false)
|
||||
if (newScheme != null) {
|
||||
processor.initScheme(newScheme)
|
||||
processor.onSchemeAdded(newScheme)
|
||||
@@ -140,20 +138,20 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
|
||||
private fun updateCurrentScheme(oldCurrentScheme: T?, newCurrentScheme: E? = null) {
|
||||
if (oldCurrentScheme != currentScheme && currentScheme == null) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
setCurrent(newCurrentScheme as T? ?: schemes.firstOrNull())
|
||||
}
|
||||
}
|
||||
|
||||
override fun fileCreated(event: VirtualFileEvent) {
|
||||
if (event.getRequestor() != null) {
|
||||
if (event.requestor != null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (event.getFile().isDirectory()) {
|
||||
if (event.file.isDirectory) {
|
||||
val dir = getDirectory()
|
||||
if (event.getFile() == dir) {
|
||||
for (file in dir!!.getChildren()) {
|
||||
if (event.file == dir) {
|
||||
for (file in dir.children) {
|
||||
if (isMy(file)) {
|
||||
schemeCreatedExternally(file)
|
||||
}
|
||||
@@ -161,7 +159,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
}
|
||||
else if (isMy(event)) {
|
||||
schemeCreatedExternally(event.getFile())
|
||||
schemeCreatedExternally(event.file)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,21 +172,21 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
|
||||
override fun fileDeleted(event: VirtualFileEvent) {
|
||||
if (event.getRequestor() != null) {
|
||||
if (event.requestor != null) {
|
||||
return
|
||||
}
|
||||
|
||||
var oldCurrentScheme = currentScheme
|
||||
if (event.getFile().isDirectory()) {
|
||||
if (event.file.isDirectory) {
|
||||
val dir = directory
|
||||
if (event.getFile() == dir) {
|
||||
if (event.file == dir) {
|
||||
directory = null
|
||||
removeExternalizableSchemes()
|
||||
}
|
||||
}
|
||||
else if (isMy(event)) {
|
||||
val scheme = findExternalizableSchemeByFileName(event.getFile().getName()) ?: return
|
||||
@suppress("UNCHECKED_CAST")
|
||||
val scheme = findExternalizableSchemeByFileName(event.file.name) ?: return
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
removeScheme(scheme as T)
|
||||
processor.onSchemeDeleted(scheme)
|
||||
}
|
||||
@@ -201,7 +199,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
override fun loadBundledScheme(resourceName: String, requestor: Any, convertor: ThrowableConvertor<Element, T, Throwable>) {
|
||||
try {
|
||||
val url = if (requestor is AbstractExtensionPointBean)
|
||||
requestor.getLoaderForClass().getResource(resourceName)
|
||||
requestor.loaderForClass.getResource(resourceName)
|
||||
else
|
||||
DecodeDefaultsUtil.getDefaults(requestor, resourceName)
|
||||
if (url == null) {
|
||||
@@ -212,17 +210,17 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
val element = JDOMUtil.load(URLUtil.openStream(url))
|
||||
val scheme = convertor.convert(element)
|
||||
if (scheme is ExternalizableScheme) {
|
||||
val fileName = PathUtilRt.getFileName(url.getPath())
|
||||
val fileName = PathUtilRt.getFileName(url.path)
|
||||
val extension = getFileExtension(fileName, true)
|
||||
val info = ExternalInfo(fileName.substring(0, fileName.length() - extension.length()), extension)
|
||||
info.hash = JDOMUtil.getTreeHash(element, true)
|
||||
info.schemeName = scheme.getName()
|
||||
@suppress("UNCHECKED_CAST")
|
||||
info.schemeName = scheme.name
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val oldInfo = schemeToInfo.put(scheme as E, info)
|
||||
LOG.assertTrue(oldInfo == null)
|
||||
val oldScheme = readOnlyExternalizableSchemes.put(scheme.getName(), scheme)
|
||||
val oldScheme = readOnlyExternalizableSchemes.put(scheme.name, scheme)
|
||||
if (oldScheme != null) {
|
||||
LOG.warn("Duplicated scheme ${scheme.getName()} - old: $oldScheme, new $scheme")
|
||||
LOG.warn("Duplicated scheme ${scheme.name} - old: $oldScheme, new $scheme")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,9 +246,9 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
}
|
||||
|
||||
private fun isMy(event: VirtualFileEvent) = isMy(event.getFile())
|
||||
private fun isMy(event: VirtualFileEvent) = isMy(event.file)
|
||||
|
||||
private fun isMy(file: VirtualFile) = StringUtilRt.endsWithIgnoreCase(file.getNameSequence(), schemeExtension)
|
||||
private fun isMy(file: VirtualFile) = StringUtilRt.endsWithIgnoreCase(file.nameSequence, schemeExtension)
|
||||
|
||||
override fun loadSchemes(): Collection<E> {
|
||||
val newSchemesOffset = schemes.size()
|
||||
@@ -264,17 +262,17 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
}
|
||||
else {
|
||||
ioDirectory.listFiles(FilenameFilter({ parent, name -> canRead(name) }))?.let {
|
||||
ioDirectory.listFiles({ parent, name -> canRead(name) })?.let {
|
||||
for (file in it) {
|
||||
if (file.isDirectory()) {
|
||||
if (file.isDirectory) {
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
loadScheme(file.getName(), file.inputStream(), true)
|
||||
loadScheme(file.name, file.inputStream(), true)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
LOG.error("Cannot read scheme ${file.getPath()}", e)
|
||||
LOG.error("Cannot read scheme ${file.path}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +280,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
|
||||
val list = SmartList<E>()
|
||||
for (i in newSchemesOffset..schemes.size() - 1) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val scheme = schemes[i] as E
|
||||
processor.initScheme(scheme)
|
||||
list.add(scheme)
|
||||
@@ -301,7 +299,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
// todo check is bundled/read-only schemes correctly handled
|
||||
for (i in schemes.indices.reversed()) {
|
||||
val scheme = schemes.get(i)
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (scheme is ExternalizableScheme && getState(scheme as E) != BaseSchemeProcessor.State.NON_PERSISTENT) {
|
||||
if (scheme == currentScheme) {
|
||||
currentScheme = null
|
||||
@@ -315,7 +313,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
|
||||
private fun findExternalizableSchemeByFileName(fileName: String): E? {
|
||||
for (scheme in schemes) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (scheme is ExternalizableScheme && fileName == "${scheme.fileName}$schemeExtension") {
|
||||
return scheme as E
|
||||
}
|
||||
@@ -324,7 +322,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
|
||||
private fun isOverwriteOnLoad(existingScheme: E): Boolean {
|
||||
if (readOnlyExternalizableSchemes.get(existingScheme.getName()) === existingScheme) {
|
||||
if (readOnlyExternalizableSchemes.get(existingScheme.name) === existingScheme) {
|
||||
// so, bundled scheme is shadowed
|
||||
return true
|
||||
}
|
||||
@@ -337,7 +335,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
private fun loadScheme(fileName: CharSequence, input: InputStream, duringLoad: Boolean): E? {
|
||||
try {
|
||||
val element = JDOMUtil.load(input)
|
||||
@suppress("DEPRECATED_SYMBOL_WITH_MESSAGE", "UNCHECKED_CAST")
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE", "UNCHECKED_CAST")
|
||||
val scheme = (if (processor is BaseSchemeProcessor<*>) {
|
||||
processor.readScheme(element, duringLoad) as E?
|
||||
}
|
||||
@@ -353,9 +351,9 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
return null
|
||||
}
|
||||
|
||||
val existingScheme = findSchemeByName(scheme.getName())
|
||||
val existingScheme = findSchemeByName(scheme.name)
|
||||
if (existingScheme != null) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (existingScheme is ExternalizableScheme && isOverwriteOnLoad(existingScheme as E)) {
|
||||
removeScheme(existingScheme)
|
||||
}
|
||||
@@ -367,7 +365,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
else {
|
||||
// We don't load scheme with duplicated name - if we generate unique name for it, it will be saved then with new name.
|
||||
// It is not what all can expect. Such situation in most cases indicates error on previous level, so, we just warn about it.
|
||||
LOG.warn("Scheme file \"$fileName\" is not loaded because defines duplicated name \"${scheme.getName()}\"")
|
||||
LOG.warn("Scheme file \"$fileName\" is not loaded because defines duplicated name \"${scheme.name}\"")
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -383,9 +381,9 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
info.setFileNameWithoutExtension(fileNameWithoutExtension, extension)
|
||||
}
|
||||
info.hash = JDOMUtil.getTreeHash(element, true)
|
||||
info.schemeName = scheme.getName()
|
||||
info.schemeName = scheme.name
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (duringLoad) {
|
||||
schemes.add(scheme as T)
|
||||
}
|
||||
@@ -406,13 +404,13 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
private fun canRead(name: CharSequence) = updateExtension && StringUtilRt.endsWithIgnoreCase(name, DEFAULT_EXT) || StringUtilRt.endsWithIgnoreCase(name, schemeExtension)
|
||||
|
||||
private fun readSchemeFromFile(file: VirtualFile, duringLoad: Boolean): E? {
|
||||
val fileName = file.getNameSequence()
|
||||
if (file.isDirectory() || !canRead(fileName)) {
|
||||
val fileName = file.nameSequence
|
||||
if (file.isDirectory || !canRead(fileName)) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
return loadScheme(fileName, file.getInputStream(), duringLoad)
|
||||
return loadScheme(fileName, file.inputStream, duringLoad)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
LOG.error("Cannot read scheme $fileName", e)
|
||||
@@ -425,7 +423,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
val nameGenerator = UniqueNameGenerator()
|
||||
val schemesToSave = SmartList<E>()
|
||||
for (scheme in schemes) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (scheme is ExternalizableScheme) {
|
||||
val state = getState(scheme as E)
|
||||
if (state == BaseSchemeProcessor.State.NON_PERSISTENT) {
|
||||
@@ -454,7 +452,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
}
|
||||
|
||||
if (!filesToDelete.isEmpty()) {
|
||||
if (!filesToDelete.isEmpty) {
|
||||
deleteFiles(errors)
|
||||
// remove empty directory only if some file was deleted - avoid check on each save
|
||||
if (!hasSchemes && (provider == null || !provider.enabled)) {
|
||||
@@ -466,14 +464,14 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
private fun removeDirectoryIfEmpty(errors: MutableList<Throwable>) {
|
||||
ioDirectory.listFiles()?.let {
|
||||
for (file in it) {
|
||||
if (!file.isHidden()) {
|
||||
LOG.info("Directory ${ioDirectory.getName()} is not deleted: at least one file ${file.getName()} exists")
|
||||
if (!file.isHidden) {
|
||||
LOG.info("Directory ${ioDirectory.name} is not deleted: at least one file ${file.name} exists")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG.info("Remove schemes directory ${ioDirectory.getName()}")
|
||||
LOG.info("Remove schemes directory ${ioDirectory.name}")
|
||||
directory = null
|
||||
|
||||
var deleteUsingIo = !useVfs
|
||||
@@ -504,7 +502,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
(processor as BaseSchemeProcessor<E>).getState(scheme)
|
||||
}
|
||||
else {
|
||||
@suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
if (processor.shouldBeSaved(scheme)) BaseSchemeProcessor.State.POSSIBLY_CHANGED else BaseSchemeProcessor.State.NON_PERSISTENT
|
||||
}
|
||||
}
|
||||
@@ -521,7 +519,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
|
||||
var fileNameWithoutExtension = currentFileNameWithoutExtension
|
||||
if (fileNameWithoutExtension == null || isRenamed(scheme)) {
|
||||
fileNameWithoutExtension = nameGenerator.generateUniqueName(FileUtil.sanitizeFileName(scheme.getName(), false))
|
||||
fileNameWithoutExtension = nameGenerator.generateUniqueName(FileUtil.sanitizeFileName(scheme.name, false))
|
||||
}
|
||||
|
||||
val newHash = JDOMUtil.getTreeHash(element!!, true)
|
||||
@@ -530,7 +528,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
|
||||
// save only if scheme differs from bundled
|
||||
val bundledScheme = readOnlyExternalizableSchemes.get(scheme.getName())
|
||||
val bundledScheme = readOnlyExternalizableSchemes.get(scheme.name)
|
||||
if (bundledScheme != null && schemeToInfo.get(bundledScheme)?.hash == newHash) {
|
||||
externalInfo?.scheduleDelete()
|
||||
return
|
||||
@@ -560,7 +558,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
if (useVfs) {
|
||||
var file: VirtualFile? = null
|
||||
var dir = getDirectory()
|
||||
if (dir == null || !dir.isValid()) {
|
||||
if (dir == null || !dir.isValid) {
|
||||
dir = createDir(ioDirectory, this)
|
||||
directory = dir
|
||||
}
|
||||
@@ -588,14 +586,14 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
if (renamed) {
|
||||
externalInfo!!.scheduleDelete()
|
||||
}
|
||||
FileUtil.writeToFile(File(ioDirectory, fileName), byteOut.getInternalBuffer(), 0, byteOut.size())
|
||||
FileUtil.writeToFile(File(ioDirectory, fileName), byteOut.internalBuffer, 0, byteOut.size())
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (renamed) {
|
||||
externalInfo!!.scheduleDelete()
|
||||
}
|
||||
provider!!.write(providerPath, byteOut.getInternalBuffer(), byteOut.size(), roamingType)
|
||||
provider!!.write(providerPath, byteOut.internalBuffer, byteOut.size(), roamingType)
|
||||
}
|
||||
|
||||
if (externalInfo == null) {
|
||||
@@ -606,7 +604,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
externalInfo.setFileNameWithoutExtension(fileNameWithoutExtension, schemeExtension)
|
||||
}
|
||||
externalInfo.hash = newHash
|
||||
externalInfo.schemeName = scheme.getName()
|
||||
externalInfo.schemeName = scheme.name
|
||||
}
|
||||
|
||||
private fun ExternalInfo.scheduleDelete() {
|
||||
@@ -615,7 +613,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
|
||||
private fun isRenamed(scheme: ExternalizableScheme): Boolean {
|
||||
val info = schemeToInfo.get(scheme)
|
||||
return info != null && scheme.getName() != info.schemeName
|
||||
return info != null && scheme.name != info.schemeName
|
||||
}
|
||||
|
||||
private fun deleteFiles(errors: MutableList<Throwable>) {
|
||||
@@ -640,8 +638,8 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
if (!deleteUsingIo) {
|
||||
var token: AccessToken? = null
|
||||
try {
|
||||
for (file in dir!!.getChildren()) {
|
||||
if (filesToDelete.contains(file.getName())) {
|
||||
for (file in dir!!.children) {
|
||||
if (filesToDelete.contains(file.name)) {
|
||||
if (token == null) {
|
||||
token = WriteAction.start()
|
||||
}
|
||||
@@ -712,13 +710,13 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
|
||||
private fun retainExternalInfo(newSchemes: List<T>) {
|
||||
if (schemeToInfo.isEmpty()) {
|
||||
if (schemeToInfo.isEmpty) {
|
||||
return
|
||||
}
|
||||
|
||||
schemeToInfo.retainEntries(object : TObjectObjectProcedure<E, ExternalInfo> {
|
||||
override fun execute(scheme: E, info: ExternalInfo): Boolean {
|
||||
if (readOnlyExternalizableSchemes.get(scheme.getName()) == scheme) {
|
||||
if (readOnlyExternalizableSchemes.get(scheme.name) == scheme) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -742,16 +740,16 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
var toReplace = -1
|
||||
for (i in schemes.indices) {
|
||||
val existing = schemes.get(i)
|
||||
if (existing.getName() == scheme.getName()) {
|
||||
if (existing.name == scheme.name) {
|
||||
if (!Comparing.equal<Class<out Scheme>>(existing.javaClass, scheme.javaClass)) {
|
||||
LOG.warn("'${scheme.getName()}' ${existing.javaClass.getSimpleName()} replaced with ${scheme.javaClass.getSimpleName()}")
|
||||
LOG.warn("'${scheme.name}' ${existing.javaClass.simpleName} replaced with ${scheme.javaClass.simpleName}")
|
||||
}
|
||||
|
||||
toReplace = i
|
||||
if (replaceExisting && existing is ExternalizableScheme) {
|
||||
val oldInfo = schemeToInfo.remove(existing)
|
||||
if (oldInfo != null && scheme is ExternalizableScheme && !schemeToInfo.containsKey(scheme)) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
schemeToInfo.put(scheme as E, oldInfo)
|
||||
}
|
||||
}
|
||||
@@ -765,7 +763,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
schemes.set(toReplace, scheme)
|
||||
}
|
||||
else {
|
||||
scheme.renameScheme(UniqueNameGenerator.generateUniqueName(scheme.getName(), collectExistingNames(schemes)))
|
||||
scheme.renameScheme(UniqueNameGenerator.generateUniqueName(scheme.name, collectExistingNames(schemes)))
|
||||
schemes.add(scheme)
|
||||
}
|
||||
|
||||
@@ -780,7 +778,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
private fun collectExistingNames(schemes: Collection<T>): Collection<String> {
|
||||
val result = THashSet<String>(schemes.size())
|
||||
for (scheme in schemes) {
|
||||
result.add(scheme.getName())
|
||||
result.add(scheme.name)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -802,7 +800,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
|
||||
override fun findSchemeByName(schemeName: String): T? {
|
||||
for (scheme in schemes) {
|
||||
if (scheme.getName() == schemeName) {
|
||||
if (scheme.name == schemeName) {
|
||||
return scheme
|
||||
}
|
||||
}
|
||||
@@ -822,7 +820,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
override fun removeScheme(scheme: T) {
|
||||
for (i in schemes.size() - 1 downTo 0) {
|
||||
val s = schemes.get(i)
|
||||
if (scheme.getName() == s.getName()) {
|
||||
if (scheme.name == s.name) {
|
||||
if (currentScheme == s) {
|
||||
currentScheme = null
|
||||
}
|
||||
@@ -843,7 +841,7 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
|
||||
val names = ArrayList<String>(schemes.size())
|
||||
for (scheme in schemes) {
|
||||
names.add(scheme.getName())
|
||||
names.add(scheme.name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
@@ -870,9 +868,9 @@ public class SchemeManagerImpl<T : Scheme, E : ExternalizableScheme>(private val
|
||||
}
|
||||
|
||||
private fun ExternalizableScheme.renameScheme(newName: String) {
|
||||
if (newName != getName()) {
|
||||
setName(newName)
|
||||
LOG.assertTrue(newName == getName())
|
||||
if (newName != name) {
|
||||
name = newName
|
||||
LOG.assertTrue(newName == name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -885,15 +883,11 @@ private inline fun MutableList<Throwable>.catch(runnable: () -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
inline val Scheme.name: String
|
||||
get() = getName()
|
||||
|
||||
|
||||
fun createDir(ioDir: File, requestor: Any): VirtualFile {
|
||||
ioDir.mkdirs()
|
||||
val parentFile = ioDir.getParent()
|
||||
val parentVirtualFile = (if (parentFile == null) null else VfsUtil.createDirectoryIfMissing(parentFile)) ?: throw IOException(ProjectBundle.message("project.configuration.save.file.not.found", parentFile))
|
||||
return getFile(ioDir.getName(), parentVirtualFile, requestor)
|
||||
return getFile(ioDir.name, parentVirtualFile, requestor)
|
||||
}
|
||||
|
||||
fun getFile(fileName: String, parent: VirtualFile, requestor: Any): VirtualFile {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 582 B |
Binary file not shown.
|
After Width: | Height: | Size: 310 B |
@@ -246,8 +246,9 @@ public abstract class RunConfigurationProducer<T extends RunConfiguration> {
|
||||
@Nullable
|
||||
public RunConfiguration createLightConfiguration(@NotNull final ConfigurationContext context) {
|
||||
RunConfiguration configuration = myConfigurationFactory.createTemplateConfiguration(context.getProject());
|
||||
final Ref<PsiElement> ref = new Ref<PsiElement>(context.getPsiLocation());
|
||||
try {
|
||||
if (!setupConfigurationFromContext((T)configuration, context, new Ref<PsiElement>(context.getPsiLocation()))) {
|
||||
if (!setupConfigurationFromContext((T)configuration, context, ref)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,9 +230,12 @@ public class RenameProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
|
||||
private boolean findRenamedVariables(final List<UsageInfo> variableUsages) {
|
||||
for (final AutomaticRenamer automaticVariableRenamer : myRenamers) {
|
||||
for (Iterator<AutomaticRenamer> iterator = myRenamers.iterator(); iterator.hasNext(); ) {
|
||||
AutomaticRenamer automaticVariableRenamer = iterator.next();
|
||||
if (!automaticVariableRenamer.hasAnythingToRename()) continue;
|
||||
if (!showAutomaticRenamingDialog(automaticVariableRenamer)) return false;
|
||||
if (!showAutomaticRenamingDialog(automaticVariableRenamer)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
final Runnable runnable = new Runnable() {
|
||||
|
||||
+1
-1
@@ -241,7 +241,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
final AutomaticRenamingDialog renamingDialog = new AutomaticRenamingDialog(myProject, renamer);
|
||||
if (!renamingDialog.showAndGet()) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -24,7 +24,9 @@ import com.sun.jna.win32.StdCallLibrary;
|
||||
import com.sun.jna.win32.W32APIFunctionMapper;
|
||||
import com.sun.jna.win32.W32APITypeMapper;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.sun.jna.Library.OPTION_FUNCTION_MAPPER;
|
||||
@@ -123,8 +125,15 @@ public class WindowsCryptUtils {
|
||||
DATA_BLOB pDataOut);
|
||||
|
||||
class DATA_BLOB extends Structure implements Structure.ByReference {
|
||||
private static final List __FIELDS = Arrays.asList("cbData", "pbData");
|
||||
|
||||
public W32API.DWORD cbData;
|
||||
public Pointer pbData;
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return __FIELDS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@ public final class EditorUtil {
|
||||
* @return true if the editor is in fact an ordinary file editor;
|
||||
* false if the editor is part of EditorTextField, CommitMessage and etc.
|
||||
*/
|
||||
public static boolean isRealFileEditor(@NotNull Editor editor) {
|
||||
return TextEditorProvider.getInstance().getTextEditor(editor) instanceof TextEditorImpl;
|
||||
public static boolean isRealFileEditor(@Nullable Editor editor) {
|
||||
return editor != null && TextEditorProvider.getInstance().getTextEditor(editor) instanceof TextEditorImpl;
|
||||
}
|
||||
|
||||
public static int getLastVisualLineColumnNumber(@NotNull Editor editor, final int line) {
|
||||
|
||||
+16
-1
@@ -40,6 +40,8 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
private final Map<String, SMTestProxy> myRunningTestsFullNameToProxy = new HashMap<String, SMTestProxy>();
|
||||
private final Set<AbstractTestProxy> myFailedTestsSet = new HashSet<AbstractTestProxy>();
|
||||
private final TestSuiteStack mySuitesStack;
|
||||
private final Set<SMTestProxy> myCurrentChildren = new LinkedHashSet<SMTestProxy>();
|
||||
private boolean myGetChildren = true;
|
||||
private final SMTestProxy.SMRootTestProxy myTestsRootNode;
|
||||
|
||||
private boolean myIsTestingFinished;
|
||||
@@ -231,6 +233,15 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
}
|
||||
|
||||
parentSuite.addChild(testProxy);
|
||||
|
||||
if (myTreeBuildBeforeStart && myGetChildren) {
|
||||
for (SMTestProxy proxy : parentSuite.getChildren()) {
|
||||
if (!proxy.isFinal()) {
|
||||
myCurrentChildren.add(proxy);
|
||||
}
|
||||
}
|
||||
myGetChildren = false;
|
||||
}
|
||||
}
|
||||
|
||||
// adds to running tests map
|
||||
@@ -264,6 +275,7 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
parentSuite.addChild(newSuite);
|
||||
}
|
||||
|
||||
myGetChildren = true;
|
||||
mySuitesStack.pushSuite(newSuite);
|
||||
|
||||
//Progress started
|
||||
@@ -277,7 +289,8 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
|
||||
private SMTestProxy findChildByName(SMTestProxy parentSuite, String fullName) {
|
||||
if (myTreeBuildBeforeStart) {
|
||||
for (SMTestProxy proxy : parentSuite.getChildren()) {
|
||||
final Collection<? extends SMTestProxy> children = myGetChildren ? parentSuite.getChildren() : myCurrentChildren;
|
||||
for (SMTestProxy proxy : children) {
|
||||
if (fullName.equals(proxy.getName()) && !proxy.isFinal()) {
|
||||
return proxy;
|
||||
}
|
||||
@@ -303,6 +316,7 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
testProxy.setDuration(duration);
|
||||
testProxy.setFinished();
|
||||
myRunningTestsFullNameToProxy.remove(fullTestName);
|
||||
myCurrentChildren.remove(testProxy);
|
||||
|
||||
//fire events
|
||||
fireOnTestFinished(testProxy);
|
||||
@@ -317,6 +331,7 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
|
||||
final SMTestProxy mySuite = mySuitesStack.popSuite(suiteName);
|
||||
if (mySuite != null) {
|
||||
mySuite.setFinished();
|
||||
myCurrentChildren.clear();
|
||||
|
||||
//fire events
|
||||
fireOnSuiteFinished(mySuite);
|
||||
|
||||
+22
-9
@@ -412,13 +412,15 @@ public class SMTestProxy extends AbstractTestProxy {
|
||||
* @param duration In milliseconds
|
||||
*/
|
||||
public void setDuration(final long duration) {
|
||||
invalidateCachedDurationForContainerSuites();
|
||||
|
||||
if (!isSuite()) {
|
||||
invalidateCachedDurationForContainerSuites(duration - (myDuration != null ? myDuration : 0));
|
||||
myDurationIsCached = true;
|
||||
myDuration = (duration >= 0) ? duration : null;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
invalidateCachedDurationForContainerSuites(-1);
|
||||
}
|
||||
|
||||
// Not allow to directly set duration for suites.
|
||||
// It should be the sum of children. This requirement is only
|
||||
@@ -782,17 +784,28 @@ public class SMTestProxy extends AbstractTestProxy {
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively invalidates cached duration for container(parent) suites
|
||||
* Recursively invalidates cached duration for container(parent) suites or updates their value
|
||||
* @param duration
|
||||
*/
|
||||
private void invalidateCachedDurationForContainerSuites() {
|
||||
// Invalidates duration of this suite
|
||||
myDuration = null;
|
||||
myDurationIsCached = false;
|
||||
private void invalidateCachedDurationForContainerSuites(long duration) {
|
||||
if (duration >= 0) {
|
||||
if (myDuration == null) {
|
||||
myDuration = duration;
|
||||
}
|
||||
else {
|
||||
myDuration += duration;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Invalidates duration of this suite
|
||||
myDuration = null;
|
||||
myDurationIsCached = false;
|
||||
}
|
||||
|
||||
// Invalidates duration of container suite
|
||||
final SMTestProxy containerSuite = getParent();
|
||||
if (containerSuite != null) {
|
||||
containerSuite.invalidateCachedDurationForContainerSuites();
|
||||
containerSuite.invalidateCachedDurationForContainerSuites(duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,7 +814,7 @@ public class SMTestProxy extends AbstractTestProxy {
|
||||
while (parent != null && !(parent instanceof SMRootTestProxy)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return parent instanceof SMRootTestProxy ? (SMRootTestProxy)parent : null;
|
||||
return parent != null ? (SMRootTestProxy)parent : null;
|
||||
}
|
||||
|
||||
public static class SMRootTestProxy extends SMTestProxy implements TestProxyRoot {
|
||||
|
||||
@@ -283,32 +283,24 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
EdtTestUtil.runInEdtAndWait(new ThrowableRunnable<Throwable>() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LightPlatformTestCase.super.setUp();
|
||||
initApplication();
|
||||
ApplicationInfoImpl.setInPerformanceTest(isPerformanceTest());
|
||||
public void run() throws Exception {
|
||||
LightPlatformTestCase.super.setUp();
|
||||
initApplication();
|
||||
ApplicationInfoImpl.setInPerformanceTest(isPerformanceTest());
|
||||
|
||||
ourApplication.setDataProvider(LightPlatformTestCase.this);
|
||||
LightProjectDescriptor descriptor = new SimpleLightProjectDescriptor(getModuleType(), getProjectJDK());
|
||||
doSetup(descriptor, configureLocalInspectionTools(), getTestRootDisposable());
|
||||
InjectedLanguageManagerImpl.pushInjectors(getProject());
|
||||
ourApplication.setDataProvider(LightPlatformTestCase.this);
|
||||
LightProjectDescriptor descriptor = new SimpleLightProjectDescriptor(getModuleType(), getProjectJDK());
|
||||
doSetup(descriptor, configureLocalInspectionTools(), getTestRootDisposable());
|
||||
InjectedLanguageManagerImpl.pushInjectors(getProject());
|
||||
|
||||
storeSettings();
|
||||
storeSettings();
|
||||
|
||||
myThreadTracker = new ThreadTracker();
|
||||
ModuleRootManager.getInstance(ourModule).orderEntries().getAllLibrariesAndSdkClassesRoots();
|
||||
VirtualFilePointerManagerImpl filePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance();
|
||||
filePointerManager.storePointers();
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
myThreadTracker = new ThreadTracker();
|
||||
ModuleRootManager.getInstance(ourModule).orderEntries().getAllLibrariesAndSdkClassesRoots();
|
||||
VirtualFilePointerManagerImpl filePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance();
|
||||
filePointerManager.storePointers();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -264,18 +264,25 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
|
||||
|
||||
@NotNull
|
||||
public static Project createProject(@NotNull String path, String creationPlace) {
|
||||
return createProject(path, creationPlace, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Project createProject(@NotNull String path, String creationPlace, boolean clearVfs) {
|
||||
String fileName = PathUtilRt.getFileName(path);
|
||||
String projectName = FileUtilRt.getNameWithoutExtension(fileName);
|
||||
VirtualFile projectBase = LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(fileName.endsWith(
|
||||
ProjectFileType.DOT_DEFAULT_EXTENSION) ? PathUtilRt.getParentPath(path) : path));
|
||||
if (projectBase != null) {
|
||||
// must be leftovers from the previous test run
|
||||
for (VirtualFile file : ((NewVirtualFile)projectBase).iterInDbChildren()) {
|
||||
delete(file);
|
||||
if (clearVfs) {
|
||||
VirtualFile projectBase = LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(fileName.endsWith(
|
||||
ProjectFileType.DOT_DEFAULT_EXTENSION) ? PathUtilRt.getParentPath(path) : path));
|
||||
if (projectBase != null) {
|
||||
// must be leftovers from the previous test run
|
||||
for (VirtualFile file : ((NewVirtualFile)projectBase).iterInDbChildren()) {
|
||||
delete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String projectName = FileUtilRt.getNameWithoutExtension(fileName);
|
||||
Project project = ProjectManagerEx.getInstanceEx().newProject(projectName, path, false, false);
|
||||
assert project != null;
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ public abstract class UsefulTestCase extends TestCase {
|
||||
super.setUp();
|
||||
|
||||
if (shouldContainTempFiles()) {
|
||||
String testName = getTestName(true);
|
||||
String testName = FileUtil.sanitizeFileName(getTestName(true));
|
||||
if (StringUtil.isEmptyOrSpaces(testName)) testName = "";
|
||||
testName = new File(testName).getName(); // in case the test name contains file separators
|
||||
File tempDirectory = FileUtil.createTempDirectory(new File(ORIGINAL_TEMP_DIR), TEMP_DIR_MARKER + testName, "");
|
||||
|
||||
@@ -72,7 +72,7 @@ public class ProjectRule() : ExternalResource() {
|
||||
val buffer = ByteArrayOutputStream()
|
||||
java.lang.Throwable(projectPath).printStackTrace(PrintStream(buffer))
|
||||
|
||||
val project = PlatformTestCase.createProject(projectPath, "Light project: $buffer") as ProjectEx
|
||||
val project = PlatformTestCase.createProject(projectPath, "Light project: $buffer", false) as ProjectEx
|
||||
Disposer.register(ApplicationManager.getApplication(), Disposable {
|
||||
try {
|
||||
disposeProject()
|
||||
|
||||
@@ -557,6 +557,7 @@ public class AllIcons {
|
||||
public static final Icon Colors = IconLoader.getIcon("/gutter/colors.png"); // 12x12
|
||||
public static final Icon ExtAnnotation = IconLoader.getIcon("/gutter/extAnnotation.png"); // 12x12
|
||||
public static final Icon ImplementedMethod = IconLoader.getIcon("/gutter/implementedMethod.png"); // 12x12
|
||||
public static final Icon ImplementingFunctional = IconLoader.getIcon("/gutter/implementingFunctional.png"); // 12x12
|
||||
public static final Icon ImplementingMethod = IconLoader.getIcon("/gutter/implementingMethod.png"); // 12x12
|
||||
public static final Icon OverridenMethod = IconLoader.getIcon("/gutter/overridenMethod.png"); // 12x12
|
||||
public static final Icon OverridingMethod = IconLoader.getIcon("/gutter/overridingMethod.png"); // 12x12
|
||||
|
||||
@@ -439,7 +439,7 @@ public class PathManager {
|
||||
THashSet.class, // trove4j
|
||||
PicoContainer.class, // PicoContainer
|
||||
TypeMapper.class, // JNA
|
||||
FileUtils.class, // JNA (jna-utils)
|
||||
FileUtils.class, // JNA (jna-platform)
|
||||
PatternMatcher.class, // OROMatcher
|
||||
Snappy.class // Snappy
|
||||
};
|
||||
|
||||
@@ -23,6 +23,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -350,6 +352,8 @@ public class Foundation {
|
||||
}
|
||||
|
||||
public static class NSRect extends Structure implements Structure.ByValue {
|
||||
private static final List __FIELDS = Arrays.asList("origin", "size");
|
||||
|
||||
public NSPoint origin;
|
||||
public NSSize size;
|
||||
|
||||
@@ -357,9 +361,16 @@ public class Foundation {
|
||||
origin = new NSPoint(x, y);
|
||||
size = new NSSize(w, h);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return __FIELDS;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NSPoint extends Structure implements Structure.ByValue {
|
||||
private static final List __FIELDS = Arrays.asList("x", "y");
|
||||
|
||||
public CGFloat x;
|
||||
public CGFloat y;
|
||||
|
||||
@@ -372,9 +383,16 @@ public class Foundation {
|
||||
this.x = new CGFloat(x);
|
||||
this.y = new CGFloat(y);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return __FIELDS;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NSSize extends Structure implements Structure.ByValue {
|
||||
private static final List __FIELDS = Arrays.asList("width", "height");
|
||||
|
||||
public CGFloat width;
|
||||
public CGFloat height;
|
||||
|
||||
@@ -387,6 +405,11 @@ public class Foundation {
|
||||
this.width = new CGFloat(width);
|
||||
this.height = new CGFloat(height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return __FIELDS;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CGFloat implements NativeMapped {
|
||||
|
||||
@@ -46,9 +46,9 @@ import kotlin.properties.Delegates
|
||||
|
||||
val PLUGIN_NAME: String = "Settings Repository"
|
||||
|
||||
val LOG: Logger = Logger.getInstance(IcsManager::class.java)
|
||||
internal val LOG: Logger = Logger.getInstance(IcsManager::class.java)
|
||||
|
||||
val icsManager by Delegates.lazy {
|
||||
val icsManager by lazy(LazyThreadSafetyMode.NONE) {
|
||||
ApplicationLoadListener.EP_NAME.findExtension(IcsApplicationLoadListener::class.java).icsManager
|
||||
}
|
||||
|
||||
@@ -101,15 +101,15 @@ class IcsManager(dir: File) {
|
||||
}
|
||||
}, settings.commitDelay)
|
||||
|
||||
private volatile var autoCommitEnabled = true
|
||||
private @Volatile var autoCommitEnabled = true
|
||||
|
||||
volatile var repositoryActive = false
|
||||
@Volatile var repositoryActive = false
|
||||
|
||||
val autoSyncManager = AutoSyncManager(this)
|
||||
private val syncManager = SyncManager(this, autoSyncManager)
|
||||
|
||||
private fun scheduleCommit() {
|
||||
if (autoCommitEnabled && !ApplicationManager.getApplication()!!.isUnitTestMode()) {
|
||||
if (autoCommitEnabled && !ApplicationManager.getApplication()!!.isUnitTestMode) {
|
||||
commitAlarm.cancelAndRequest()
|
||||
}
|
||||
}
|
||||
@@ -160,13 +160,13 @@ class IcsManager(dir: File) {
|
||||
fun beforeApplicationLoaded(application: Application) {
|
||||
repositoryActive = repositoryManager.isRepositoryExists()
|
||||
|
||||
(application.stateStore.getStateStorageManager() as StateStorageManagerImpl).streamProvider = ApplicationLevelProvider()
|
||||
(application.stateStore.stateStorageManager as StateStorageManagerImpl).streamProvider = ApplicationLevelProvider()
|
||||
|
||||
autoSyncManager.registerListeners(application)
|
||||
|
||||
application.getMessageBus().connect().subscribe(ProjectLifecycleListener.TOPIC, object : ProjectLifecycleListener.Adapter() {
|
||||
application.messageBus.connect().subscribe(ProjectLifecycleListener.TOPIC, object : ProjectLifecycleListener.Adapter() {
|
||||
override fun beforeProjectLoaded(project: Project) {
|
||||
if (project.isDefault()) {
|
||||
if (project.isDefault) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ class IcsApplicationLoadListener : ApplicationLoadListener {
|
||||
private set
|
||||
|
||||
override fun beforeApplicationLoaded(application: Application, configPath: String) {
|
||||
if (application.isUnitTestMode()) {
|
||||
if (application.isUnitTestMode) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ class IcsApplicationLoadListener : ApplicationLoadListener {
|
||||
Pair("_unknown/\$APP_CONFIG$", "_unknown")
|
||||
))) {
|
||||
// schedule push to avoid merge conflicts
|
||||
application.invokeLater(Runnable { icsManager.autoSyncManager.autoSync(force = true) })
|
||||
application.invokeLater({ icsManager.autoSyncManager.autoSync(force = true) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,19 +35,19 @@ import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier
|
||||
import java.util.concurrent.Future
|
||||
|
||||
class AutoSyncManager(private val icsManager: IcsManager) {
|
||||
private volatile var autoSyncFuture: Future<*>? = null
|
||||
private @Volatile var autoSyncFuture: Future<*>? = null
|
||||
|
||||
fun waitAutoSync(indicator: ProgressIndicator) {
|
||||
val autoFuture = autoSyncFuture
|
||||
if (autoFuture != null) {
|
||||
if (autoFuture.isDone()) {
|
||||
if (autoFuture.isDone) {
|
||||
autoSyncFuture = null
|
||||
}
|
||||
else if (autoSyncFuture != null) {
|
||||
LOG.info("Wait for auto sync future")
|
||||
indicator.setText("Wait for auto sync completion")
|
||||
while (!autoFuture.isDone()) {
|
||||
if (indicator.isCanceled()) {
|
||||
indicator.text = "Wait for auto sync completion"
|
||||
while (!autoFuture.isDone) {
|
||||
if (indicator.isCanceled) {
|
||||
return
|
||||
}
|
||||
Thread.sleep(5)
|
||||
@@ -65,21 +65,21 @@ class AutoSyncManager(private val icsManager: IcsManager) {
|
||||
}
|
||||
|
||||
fun registerListeners(project: Project) {
|
||||
project.getMessageBus().connect().subscribe(Notifications.TOPIC, object : NotificationsAdapter() {
|
||||
project.messageBus.connect().subscribe(Notifications.TOPIC, object : NotificationsAdapter() {
|
||||
override fun notify(notification: Notification) {
|
||||
if (!icsManager.repositoryActive || project.isDisposed()) {
|
||||
if (!icsManager.repositoryActive || project.isDisposed) {
|
||||
return
|
||||
}
|
||||
|
||||
if (when {
|
||||
notification.getGroupId() == VcsBalloonProblemNotifier.NOTIFICATION_GROUP.getDisplayId() -> {
|
||||
val message = notification.getContent()
|
||||
notification.groupId == VcsBalloonProblemNotifier.NOTIFICATION_GROUP.displayId -> {
|
||||
val message = notification.content
|
||||
message.startsWith("VCS Update Finished") ||
|
||||
message == VcsBundle.message("message.text.file.is.up.to.date") ||
|
||||
message == VcsBundle.message("message.text.all.files.are.up.to.date")
|
||||
}
|
||||
|
||||
notification.getGroupId() == VcsNotifier.NOTIFICATION_GROUP_ID.getDisplayId() && notification.getTitle() == "Push successful" -> true
|
||||
notification.groupId == VcsNotifier.NOTIFICATION_GROUP_ID.displayId && notification.title == "Push successful" -> true
|
||||
|
||||
else -> false
|
||||
}) {
|
||||
@@ -95,7 +95,7 @@ class AutoSyncManager(private val icsManager: IcsManager) {
|
||||
}
|
||||
|
||||
var future = autoSyncFuture
|
||||
if (future != null && !future.isDone()) {
|
||||
if (future != null && !future.isDone) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ class AutoSyncManager(private val icsManager: IcsManager) {
|
||||
sync(app, onAppExit)
|
||||
return
|
||||
}
|
||||
else if (app.isDisposeInProgress()) {
|
||||
else if (app.isDisposeInProgress) {
|
||||
// will be handled by applicationExiting listener
|
||||
return
|
||||
}
|
||||
@@ -145,7 +145,7 @@ class AutoSyncManager(private val icsManager: IcsManager) {
|
||||
app.invokeAndWait({
|
||||
catchAndLog {
|
||||
val updateResult = updater.merge()
|
||||
if (!onAppExit && !app.isDisposeInProgress() && updateResult != null && updateStoragesFromStreamProvider(app.stateStore as ComponentStoreImpl, updateResult, app.getMessageBus())) {
|
||||
if (!onAppExit && !app.isDisposeInProgress && updateResult != null && updateStoragesFromStreamProvider(app.stateStore as ComponentStoreImpl, updateResult, app.messageBus)) {
|
||||
// force to avoid saveAll & confirmation
|
||||
app.exit(true, true, true, true)
|
||||
}
|
||||
@@ -160,7 +160,7 @@ class AutoSyncManager(private val icsManager: IcsManager) {
|
||||
}
|
||||
}
|
||||
|
||||
inline fun catchAndLog(runnable: () -> Unit) {
|
||||
inline internal fun catchAndLog(runnable: () -> Unit) {
|
||||
try {
|
||||
runnable()
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@ import com.intellij.openapi.util.Computable
|
||||
import com.intellij.util.messages.MessageBus
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import gnu.trove.THashSet
|
||||
import java.util.LinkedHashSet
|
||||
import java.util.*
|
||||
|
||||
class SyncManager(private val icsManager: IcsManager, private val autoSyncManager: AutoSyncManager) {
|
||||
volatile var writeAndDeleteProhibited = false
|
||||
@Volatile var writeAndDeleteProhibited = false
|
||||
private set
|
||||
|
||||
public fun sync(syncType: SyncType, project: Project? = null, localRepositoryInitializer: (() -> Unit)? = null): UpdateResult? {
|
||||
@@ -47,7 +47,7 @@ class SyncManager(private val icsManager: IcsManager, private val autoSyncManage
|
||||
writeAndDeleteProhibited = true
|
||||
ProgressManager.getInstance().run(object : Task.Modal(project, IcsBundle.message("task.sync.title"), true) {
|
||||
override fun run(indicator: ProgressIndicator) {
|
||||
indicator.setIndeterminate(true)
|
||||
indicator.isIndeterminate = true
|
||||
|
||||
autoSyncManager.waitAutoSync(indicator)
|
||||
|
||||
@@ -73,7 +73,7 @@ class SyncManager(private val icsManager: IcsManager, private val autoSyncManage
|
||||
}
|
||||
}
|
||||
|
||||
if (indicator.isCanceled()) {
|
||||
if (indicator.isCanceled) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ class SyncManager(private val icsManager: IcsManager, private val autoSyncManage
|
||||
icsManager.repositoryActive = true
|
||||
if (updateResult != null) {
|
||||
val app = ApplicationManager.getApplication()
|
||||
restartApplication = updateStoragesFromStreamProvider(app.stateStore as ComponentStoreImpl, updateResult!!, app.getMessageBus())
|
||||
restartApplication = updateStoragesFromStreamProvider(app.stateStore as ComponentStoreImpl, updateResult!!, app.messageBus)
|
||||
}
|
||||
if (!restartApplication && syncType == SyncType.OVERWRITE_LOCAL) {
|
||||
(SchemesManagerFactory.getInstance() as SchemeManagerFactoryBase).process {
|
||||
@@ -140,7 +140,7 @@ class SyncManager(private val icsManager: IcsManager, private val autoSyncManage
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateStoragesFromStreamProvider(store: ComponentStoreImpl, updateResult: UpdateResult, messageBus: MessageBus): Boolean {
|
||||
internal fun updateStoragesFromStreamProvider(store: ComponentStoreImpl, updateResult: UpdateResult, messageBus: MessageBus): Boolean {
|
||||
val changedComponentNames = LinkedHashSet<String>()
|
||||
val (changed, deleted) = (store.storageManager as StateStorageManagerImpl).getCachedFileStorages(updateResult.changed, updateResult.deleted)
|
||||
if (changed.isEmpty() && deleted.isEmpty()) {
|
||||
|
||||
Binary file not shown.
@@ -1,4 +1,5 @@
|
||||
This is a README.txt file for SQLJet v1.0.4.
|
||||
This is a README.txt file for SQLJet (c) 2009-2013 TMate Software.
|
||||
|
||||
SQLJet is a pure Java (tm) embedded database management engine with SQLite format support.
|
||||
|
||||
1. DESCRIPTION
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -42,6 +42,7 @@ public class SvnKitBrowseClient extends BaseSvnClient implements BrowseClient {
|
||||
SVNLogClient client = getLogClient();
|
||||
ISVNDirEntryHandler wrappedHandler = wrapHandler(handler);
|
||||
|
||||
client.setIgnoreExternals(true);
|
||||
try {
|
||||
if (target.isFile()) {
|
||||
client.doList(target.getFile(), target.getPegRevision(), notNullize(revision), true, toDepth(depth), SVNDirEntry.DIRENT_ALL, wrappedHandler);
|
||||
|
||||
@@ -9,9 +9,12 @@ import org.jetbrains.idea.svn.api.Depth;
|
||||
import org.jetbrains.idea.svn.api.ProgressTracker;
|
||||
import org.jetbrains.idea.svn.commandLine.SvnBindException;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb;
|
||||
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
|
||||
import org.tmatesoft.svn.core.internal.wc2.compat.SvnCodec;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNUpdateClient;
|
||||
import org.tmatesoft.svn.core.wc2.SvnCheckout;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
@@ -49,21 +52,59 @@ public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClien
|
||||
|
||||
SVNUpdateClient client = myVcs.getSvnKitManager().createUpdateClient();
|
||||
|
||||
if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
|
||||
client.getOperationsFactory().setPrimaryWcGeneration(SvnWcGeneration.V16);
|
||||
}
|
||||
|
||||
client.setIgnoreExternals(ignoreExternals);
|
||||
client.setEventHandler(toEventHandler(handler));
|
||||
|
||||
try {
|
||||
client.doCheckout(source.getURL(), destination, source.getPegRevision(), revision, toDepth(depth), force);
|
||||
runCheckout(client, format, source, destination, revision, depth, force);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is mostly inlined {@code SVNUpdateClient.doCheckout()} - to allow specifying necessary working copy format. Otherwise, if only
|
||||
* {@link SvnWcGeneration} is used - either svn 1.6 or svn 1.8 working copy will be created.
|
||||
* <p/>
|
||||
* See also http://issues.tmatesoft.com/issue/SVNKIT-495 for more details.
|
||||
*/
|
||||
private static void runCheckout(@NotNull SVNUpdateClient client,
|
||||
@NotNull WorkingCopyFormat format,
|
||||
@NotNull SvnTarget source,
|
||||
@NotNull File destination,
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable Depth depth,
|
||||
boolean force) throws SVNException {
|
||||
SvnCheckout checkoutOperation = createCheckoutOperation(client, format);
|
||||
|
||||
checkoutOperation.setUpdateLocksOnDemand(client.isUpdateLocksOnDemand());
|
||||
checkoutOperation.setSource(SvnTarget.fromURL(source.getURL(), source.getPegRevision()));
|
||||
checkoutOperation.setSingleTarget(SvnTarget.fromFile(destination));
|
||||
checkoutOperation.setRevision(revision);
|
||||
checkoutOperation.setDepth(toDepth(depth));
|
||||
checkoutOperation.setAllowUnversionedObstructions(force);
|
||||
checkoutOperation.setIgnoreExternals(client.isIgnoreExternals());
|
||||
checkoutOperation.setExternalsHandler(SvnCodec.externalsHandler(client.getExternalsHandler()));
|
||||
|
||||
checkoutOperation.run();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static SvnCheckout createCheckoutOperation(@NotNull SVNUpdateClient client, @NotNull WorkingCopyFormat format) {
|
||||
if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
|
||||
client.getOperationsFactory().setPrimaryWcGeneration(SvnWcGeneration.V16);
|
||||
}
|
||||
|
||||
SvnCheckout checkoutOperation = client.getOperationsFactory().createCheckout();
|
||||
|
||||
if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
|
||||
checkoutOperation.setTargetWorkingCopyFormat(ISVNWCDb.WC_FORMAT_17);
|
||||
}
|
||||
|
||||
return checkoutOperation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WorkingCopyFormat> getSupportedFormats() throws VcsException {
|
||||
return SUPPORTED_FORMATS;
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
QuerySet is parametrized with model object
|
||||
"""
|
||||
class QuerySet(object):
|
||||
def __init__(self):
|
||||
def __init__(self, model=None, query=None, using=None, hints=None):
|
||||
"""
|
||||
:rtype: QuerySet[T]
|
||||
:rtype: django.db.models.QuerySet[T]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ label.debugger.general.configurable.skip.constructors=Skip &constructors
|
||||
label.debugger.general.configurable.skip.classLoaders=Skip class l&oaders
|
||||
label.debugger.general.configurable.skip.simple.getters=Skip simple &getters
|
||||
label.debugger.general.configurable.step.filters.list.header=Do not step &into the classes
|
||||
label.debugger.general.configurable.evaluate.finally.on.pop=Evaluate finally blocks on pop frame:
|
||||
label.debugger.general.configurable.evaluate.finally.on.pop=Evaluate finally blocks on pop frame and early return:
|
||||
label.debugger.general.configurable.evaluate.finally.always=&Always
|
||||
label.debugger.general.configurable.evaluate.finally.never=N&ever
|
||||
label.debugger.general.configurable.evaluate.finally.ask=As&k
|
||||
|
||||
@@ -21,6 +21,9 @@ import com.sun.jna.platform.win32.WinDef;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.sun.jna.ptr.LongByReference;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public interface Win32RestartManager extends Library {
|
||||
|
||||
Win32RestartManager INSTANCE = (Win32RestartManager) Native.loadLibrary("Rstrtmgr", Win32RestartManager.class);
|
||||
@@ -30,11 +33,21 @@ public interface Win32RestartManager extends Library {
|
||||
int CCH_RM_MAX_SVC_NAME = 63;
|
||||
|
||||
class RmUniqueProcess extends Structure {
|
||||
private static final List __FIELDS = Arrays.asList("dwProcessId", "ProcessStartTime");
|
||||
|
||||
public int dwProcessId;
|
||||
public WinBase.FILETIME ProcessStartTime;
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return __FIELDS;
|
||||
}
|
||||
}
|
||||
|
||||
class RmProcessInfo extends Structure {
|
||||
private static final List __FIELDS = Arrays.asList(
|
||||
"Process", "strAppName", "strServiceShortName", "ApplicationType", "AppStatus", "TSSessionId", "bRestartable");
|
||||
|
||||
public RmUniqueProcess Process;
|
||||
public char[] strAppName = new char[CCH_RM_MAX_APP_NAME + 1];
|
||||
public char[] strServiceShortName = new char[CCH_RM_MAX_SVC_NAME + 1];
|
||||
@@ -42,6 +55,11 @@ public interface Win32RestartManager extends Library {
|
||||
public WinDef.LONG AppStatus;
|
||||
public int TSSessionId;
|
||||
public boolean bRestartable;
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return __FIELDS;
|
||||
}
|
||||
}
|
||||
|
||||
int RmGetList(int dwSessionHandle,
|
||||
|
||||
Reference in New Issue
Block a user