// WEB-17839 Internal web server reports 404 when serving files from project with slashes in name
if (decodedPath.regionMatches(1, name, 0, name.length, !SystemInfoRt.isFileSystemCaseSensitive)) {
var emptyPathCandidate = decodedPath.length == (name.length + 1)
- if (emptyPathCandidate || decodedPath.charAt(name.length + 1) == '/') {
+ if (emptyPathCandidate || decodedPath[name.length + 1] == '/') {
projectName = name
offset = name.length + 1
emptyPath = emptyPathCandidate
}
val projectName: String?
- val isIpv6 = host.charAt(0) == '[' && host.length > 2 && host.charAt(host.length - 1) == ']'
+ val isIpv6 = host[0] == '[' && host.length > 2 && host[host.length - 1] == ']'
if (isIpv6) {
host = host.substring(1, host.length - 1)
}
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) == '/'
+ return basePath != null && basePath.length > projectName.length && basePath.endsWith(projectName) && basePath[basePath.length - projectName.length - 1] == '/'
}
fun findIndexFile(basedir: VirtualFile): VirtualFile? {
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
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 lastModified = ssiProcessor!!.process(SsiExternalResolver(project, request, path, file.parentFile), file, ByteBufUtf8Writer(buffer))
val response = FileResponses.prepareSend(request, channel, lastModified, file.path) ?: return
keepAlive = Responses.addKeepAliveIfNeed(response, request)
if (request.method() != HttpMethod.HEAD) {
/**
* The SSIMediator to use when evaluating the expressions.
*/
- private final SsiProcessingState mySsiProcessingState;
+ private final SsiProcessingState ssiProcessingState;
/**
* Creates a new parse tree for the specified expression.
*/
public ExpressionParseTree(String expr, SsiProcessingState ssiProcessingState)
throws ParseException {
- this.mySsiProcessingState = ssiProcessingState;
+ this.ssiProcessingState = ssiProcessingState;
parseExpression(expr);
}
private void pushOpp(OppNode node) {
// If node is null then it's just a group marker
if (node == null) {
- oppStack.add(0, node);
+ oppStack.add(0, null);
return;
}
while (true) {
*/
public String getValue() {
if (resolved == null) {
- resolved = mySsiProcessingState.substituteVariables(value.toString());
+ resolved = ssiProcessingState.substituteVariables(value.toString());
}
return resolved;
}
}
}
catch (PatternSyntaxException e) {
- SsiProcessor.LOG.warn("Invalid expression: " + expr, e);
+ SsiProcessorKt.getLOG().warn("Invalid expression: " + expr, e);
return 0;
}
}
+++ /dev/null
-/*
- * 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.ssi;
-
-import io.netty.buffer.ByteBufUtf8Writer;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-
-public interface SsiCommand {
- long process(@NotNull SsiProcessingState state, @NotNull String commandName, @NotNull List<String> paramNames, @NotNull String[] paramValues, @NotNull ByteBufUtf8Writer writer);
-}
\ No newline at end of file
public class SsiConditional implements SsiCommand {
@SuppressWarnings("SpellCheckingInspection")
@Override
- public long process(@NotNull SsiProcessingState ssiProcessingState, @NotNull String commandName, @NotNull List<String> paramNames, @NotNull String[] paramValues, @NotNull ByteBufUtf8Writer writer) {
+ public long process(@NotNull SsiProcessingState ssiProcessingState, @NotNull String commandName, @NotNull List<? extends String> paramNames, @NotNull String[] paramValues, @NotNull ByteBufUtf8Writer writer) {
// Assume anything using conditionals was modified by it
long lastModified = System.currentTimeMillis();
// Retrieve the current state information
/**
* Retrieves the expression from the specified arguments and performs the necessary evaluation steps.
*/
- private static boolean evaluateArguments(@NotNull List<String> names, @NotNull String[] values, @NotNull SsiProcessingState ssiProcessingState) {
+ private static boolean evaluateArguments(@NotNull List<? extends String> names, @NotNull String[] values, @NotNull SsiProcessingState ssiProcessingState) {
String expression = "expr".equalsIgnoreCase(names.get(0)) ? values[0] : null;
if (expression == null) {
throw new SsiStopProcessingException();
private static final int ONE_MEGABYTE = 1024 * 1024;
@Override
- public long process(@NotNull SsiProcessingState state, @NotNull String commandName, @NotNull List<String> paramNames, @NotNull String[] paramValues, @NotNull ByteBufUtf8Writer writer) {
+ public long process(@NotNull SsiProcessingState state, @NotNull String commandName, @NotNull List<? extends String> paramNames, @NotNull String[] paramValues, @NotNull ByteBufUtf8Writer writer) {
long lastModified = 0;
String configErrMsg = state.configErrorMessage;
for (int i = 0; i < paramNames.size(); i++) {
writer.write(formatSize(state.ssiExternalResolver.getFileSize(substitutedValue, virtual), state.configSizeFmt));
}
else {
- SsiProcessor.LOG.info("#fsize--Invalid attribute: " + paramName);
+ SsiProcessorKt.getLOG().info("#fsize--Invalid attribute: " + paramName);
writer.write(configErrMsg);
}
}
package org.jetbrains.builtInWebServer.ssi
import com.intellij.openapi.diagnostic.Logger
+import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.util.SmartList
+import com.intellij.util.text.CharArrayUtil
import gnu.trove.THashMap
import io.netty.buffer.ByteBufUtf8Writer
+import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.util.*
fun process(state: SsiProcessingState, commandName: String, paramNames: List<String>, paramValues: Array<String>, writer: ByteBufUtf8Writer): Long
}
+class SsiStopProcessingException : RuntimeException()
+
class SsiProcessor(allowExec: Boolean) {
private val commands: MutableMap<String, SsiCommand> = THashMap()
/**
* @return the most current modified date resulting from any SSI commands
*/
- fun process(ssiExternalResolver: SsiExternalResolver, fileContents: String, lastModifiedDate: Long, writer: ByteBufUtf8Writer): Long {
- var resultLastModifiedDate = lastModifiedDate
- val ssiProcessingState = SsiProcessingState(ssiExternalResolver, resultLastModifiedDate)
+ fun process(ssiExternalResolver: SsiExternalResolver, file: File, writer: ByteBufUtf8Writer): Long {
+ val fileContents = FileUtilRt.loadFileText(file)
+ var lastModifiedDate = file.lastModified()
+ val ssiProcessingState = SsiProcessingState(ssiExternalResolver, lastModifiedDate)
var index = 0
var inside = false
val command = StringBuilder()
+ writer.ensureWritable(file.length().toInt())
try {
- while (index < fileContents.length) {
+ while (index < fileContents.size) {
val c = fileContents[index]
if (inside) {
if (c == COMMAND_END[0] && charCmp(fileContents, index, COMMAND_END)) {
val ssiCommand = commands[commandName.toLowerCase(Locale.ENGLISH)]
var errorMessage: String? = null
if (ssiCommand == null) {
- errorMessage = "Unknown command: " + commandName
+ errorMessage = "Unknown command: $commandName"
}
else if (paramValues == null) {
errorMessage = "Error parsing directive parameters."
}
else if (paramNames.size != paramValues.size) {
- errorMessage = "Parameter names count does not match parameter values count on command: " + commandName
+ errorMessage = "Parameter names count does not match parameter values count on command: $commandName"
}
else {
// don't process the command if we are processing conditional commands only and the command is not conditional
if (!ssiProcessingState.conditionalState.processConditionalCommandsOnly || ssiCommand is SsiConditional) {
val newLastModified = ssiCommand.process(ssiProcessingState, commandName, paramNames, paramValues, writer)
- if (newLastModified > resultLastModifiedDate) {
- resultLastModifiedDate = newLastModified
+ if (newLastModified > lastModifiedDate) {
+ lastModifiedDate = newLastModified
}
}
}
}
else {
if (!ssiProcessingState.conditionalState.processConditionalCommandsOnly) {
- writer.write(c.toInt())
+ writer.append(c)
}
index++
}
//If we are here, then we have already stopped processing, so all is good
}
- return resultLastModifiedDate
+ return lastModifiedDate
}
protected fun parseParamNames(command: StringBuilder, start: Int): List<String> {
return if (firstLetter == -1) "" else instruction.substring(firstLetter, lastLetter + 1)
}
- protected fun charCmp(buf: String, index: Int, command: String) = buf.regionMatches(index, command, 0, command.length)
+ protected fun charCmp(buf: CharArray, index: Int, command: String) = CharArrayUtil.regionMatches(buf, index, index + command.length, command)
protected fun isSpace(c: Char) = c == ' ' || c == '\n' || c == '\t' || c == '\r'
+++ /dev/null
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.ssi;
-
-
-/**
- * Exception used to tell SSIProcessor that it should stop processing SSI
- * commands. This is used to mimic the Apache behavior in #set with invalid
- * attributes.
- *
- * @author Paul Speed
- * @author Dan Sandberg
- */
-public class SsiStopProcessingException extends RuntimeException {
-}
\ No newline at end of file
RecordType.END_REQUEST -> {
val appStatus = buffer.readInt()
val protocolStatus = buffer.readUnsignedByte().toInt()
- if (appStatus != 0 || protocolStatus != ProtocolStatus.REQUEST_COMPLETE.ordinal()) {
+ if (appStatus != 0 || protocolStatus != ProtocolStatus.REQUEST_COMPLETE.ordinal) {
LOG.warn("Protocol status $protocolStatus")
dataBuffers.remove(id)
responseHandler.responseReceived(id, null)
}
- else if (protocolStatus == ProtocolStatus.REQUEST_COMPLETE.ordinal()) {
+ else if (protocolStatus == ProtocolStatus.REQUEST_COMPLETE.ordinal) {
responseHandler.responseReceived(id, dataBuffers.remove(id))
}
}
fun getOrCreateStorage(collapsedPath: String,
roamingType: RoamingType = RoamingType.DEFAULT,
storageClass: Class<out StateStorage> = StateStorage::class.java,
- @Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") @SuppressWarnings("deprecation") stateSplitter: Class<out StateSplitter> = StateSplitterEx::class.java): StateStorage {
+ @Suppress("DEPRECATION") @SuppressWarnings("deprecation") stateSplitter: Class<out StateSplitter> = StateSplitterEx::class.java): StateStorage {
val normalizedCollapsedPath = normalizeFileSpec(collapsedPath)
val key = if (storageClass == StateStorage::class.java) normalizedCollapsedPath else storageClass.name
storageLock.withLock {
protected open fun createStateStorage(storageClass: Class<out StateStorage>,
collapsedPath: String,
roamingType: RoamingType,
- @Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") stateSplitter: Class<out StateSplitter>): StateStorage {
+ @Suppress("DEPRECATION") stateSplitter: Class<out StateSplitter>): StateStorage {
if (storageClass != StateStorage::class.java) {
val constructor = storageClass.constructors[0]!!
constructor.isAccessible = true
}
val filePath = expandMacros(collapsedPath)
- @Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
+ @Suppress("DEPRECATION")
if (stateSplitter != StateSplitter::class.java && stateSplitter != StateSplitterEx::class.java) {
val storage = MyDirectoryStorage(this, File(filePath), ReflectionUtil.newInstance(stateSplitter))
virtualFileTracker?.put(filePath, storage)
return storage
}
- private class MyDirectoryStorage(override val storageManager: StateStorageManagerImpl, file: File, @Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") splitter: StateSplitter) :
+ private class MyDirectoryStorage(override val storageManager: StateStorageManagerImpl, file: File, @Suppress("DEPRECATION") splitter: StateSplitter) :
DirectoryBasedStorage(file, splitter, storageManager.pathMacroSubstitutor), StorageVirtualFileTracker.TrackedStorage
private class MyFileStorage(override val storageManager: StateStorageManagerImpl,
}
var saveSessions: MutableList<SaveSession>? = null
- val externalizationSessions = sessions.values()
+ val externalizationSessions = sessions.values
for (session in externalizationSessions) {
val saveSession = session.createSaveSession()
if (saveSession != null) {
override fun getOldStorage(component: Any, componentName: String, operation: StateStorageOperation): StateStorage? {
val oldStorageSpec = getOldStorageSpec(component, componentName, operation) ?: return null
- @Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
+ @Suppress("DEPRECATION")
return getOrCreateStorage(oldStorageSpec, if (component is com.intellij.openapi.util.RoamingTypeDisabled) RoamingType.DISABLED else RoamingType.DEFAULT)
}
fun String.startsWithMacro(macro: String): Boolean {
val i = macro.length
- return length > i && charAt(i) == '/' && startsWith(macro)
+ return length > i && this[i] == '/' && startsWith(macro)
}
\ No newline at end of file
buffer.writeBytes(inputStream, length);
}
+ public void ensureWritable(int minWritableBytes) {
+ buffer.ensureWritable(minWritableBytes);
+ }
+
@Override
public void write(int c) {
- AbstractByteBuf buffer = ByteBufUtilEx.getBuf(this.buffer);
- int writerIndex = this.buffer.writerIndex();
- if (c < 0x80) {
- buffer._setByte(writerIndex++, (byte)c);
- }
- else if (c < 0x800) {
- buffer._setByte(writerIndex++, (byte)(0xc0 | (c >> 6)));
- buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f)));
- }
- else {
- buffer._setByte(writerIndex++, (byte)(0xe0 | (c >> 12)));
- buffer._setByte(writerIndex++, (byte)(0x80 | ((c >> 6) & 0x3f)));
- buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f)));
- }
- this.buffer.writerIndex(writerIndex);
+ buffer.writerIndex(ByteBufUtilEx.writeChar(ByteBufUtilEx.getBuf(buffer), buffer.writerIndex(), c));
}
@Override
// We can use the _set methods as these not need to do any index checks and reference checks.
// This is possible as we called ensureWritable(...) before.
for (int i = start; i < end; i++) {
- char c = seq.charAt(i);
- if (c < 0x80) {
- buffer._setByte(writerIndex++, (byte)c);
- }
- else if (c < 0x800) {
- buffer._setByte(writerIndex++, (byte)(0xc0 | (c >> 6)));
- buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f)));
- }
- else {
- buffer._setByte(writerIndex++, (byte)(0xe0 | (c >> 12)));
- buffer._setByte(writerIndex++, (byte)(0x80 | ((c >> 6) & 0x3f)));
- buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f)));
- }
+ writerIndex = writeChar(buffer, writerIndex, seq.charAt(i));
}
// update the writerIndex without any extra checks for performance reasons
return writerIndex - oldWriterIndex;
}
+ static int writeChar(AbstractByteBuf buffer, int writerIndex, int c) {
+ if (c < 0x80) {
+ buffer._setByte(writerIndex++, (byte)c);
+ }
+ else if (c < 0x800) {
+ buffer._setByte(writerIndex++, (byte)(0xc0 | (c >> 6)));
+ buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f)));
+ }
+ else {
+ buffer._setByte(writerIndex++, (byte)(0xe0 | (c >> 12)));
+ buffer._setByte(writerIndex++, (byte)(0x80 | ((c >> 6) & 0x3f)));
+ buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f)));
+ }
+ return writerIndex;
+ }
+
@SuppressWarnings("SpellCheckingInspection")
public static void readUtf8(@NotNull ByteBuf buf, int byteCount, @NotNull CharBuffer charBuffer) throws IOException {
AbstractByteBuf buffer = getBuf(buf);
}
while (count > 0) {
- if (Character.isDigit(variables.get(count - 1).name.charAt(0))) {
+ if (Character.isDigit(variables.get(count - 1).name[0])) {
break
}
count--
val presentableValue = value.valueString ?: return ""
var endIndex = 0
- while (endIndex < presentableValue.length && !StringUtil.isLineBreak(presentableValue.charAt(endIndex))) {
+ while (endIndex < presentableValue.length && !StringUtil.isLineBreak(presentableValue[endIndex])) {
endIndex++
}
- while (endIndex > 0 && Character.isWhitespace(presentableValue.charAt(endIndex - 1))) {
+ while (endIndex > 0 && Character.isWhitespace(presentableValue[endIndex - 1])) {
endIndex--
}
return presentableValue.substring(0, endIndex)
var i = 0
var j = 0
while (i < string1Length && j < string2Length) {
- var ch1 = string1.charAt(i)
- var ch2 = string2.charAt(j)
+ var ch1 = string1[i]
+ var ch2 = string2[j]
if ((StringUtil.isDecimalDigit(ch1) || ch1 == ' ') && (StringUtil.isDecimalDigit(ch2) || ch2 == ' ')) {
var startNum1 = i
while (ch1 == ' ' || ch1 == '0') {
if (startNum1 >= string1Length) {
break
}
- ch1 = string1.charAt(startNum1)
+ ch1 = string1[startNum1]
}
var startNum2 = j
while (ch2 == ' ' || ch2 == '0') {
if (startNum2 >= string2Length) {
break
}
- ch2 = string2.charAt(startNum2)
+ ch2 = string2[startNum2]
}
i = startNum1
j = startNum2
// find end index of number
- while (i < string1Length && StringUtil.isDecimalDigit(string1.charAt(i))) {
+ while (i < string1Length && StringUtil.isDecimalDigit(string1[i])) {
i++
}
- while (j < string2Length && StringUtil.isDecimalDigit(string2.charAt(j))) {
+ while (j < string2Length && StringUtil.isDecimalDigit(string2[j])) {
j++
}
val lengthDiff = (i - startNum1) - (j - startNum2)
}
while (startNum1 < i) {
// compare numbers with equal digit count
- val diff = string1.charAt(startNum1) - string2.charAt(startNum2)
+ val diff = string1[startNum1] - string2[startNum2]
if (diff != 0) {
return diff
}
val list = XValueChildrenList(to - from)
var getterOrSetterContext: VariableContext? = null
for (i in from..to - 1) {
- val variable = variables.get(i)
+ val variable = variables[i]
val normalizedName = if (memberFilter == null) variable.name else memberFilter.rawNameToSource(variable)
list.add(VariableView(normalizedName, variable, variableContext))
if (variable is ObjectProperty) {
}
if (compact) {
- if (length != 0 && charAt(length - 1) != ' ') {
+ if (length != 0 && this[length - 1] != ' ') {
append('\t')
}
append(name)