Netty example

This commit is contained in:
Alex Tkachman
2012-02-06 16:32:04 +02:00
parent 964b66ecb1
commit 9d69c62a6c
13 changed files with 1295 additions and 141 deletions
-141
View File
@@ -1,141 +0,0 @@
import java.util.concurrent.Executors
import java.net.InetSocketAddress
import java.net.URLDecoder
import java.io.*
import org.jboss.netty.bootstrap.ServerBootstrap
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory
import org.jboss.netty.channel.*
import org.jboss.netty.handler.codec.http.*
import org.jboss.netty.handler.stream.ChunkedWriteHandler
import org.jboss.netty.handler.codec.frame.TooLongFrameException
import org.jboss.netty.buffer.ChannelBuffers
import org.jboss.netty.util.CharsetUtil
import org.jboss.netty.handler.codec.http.HttpResponseStatus.*
import netty.*
import jlstring.*
package jlstring {
fun String.replace(c: Char, by: Char) : String = (this as java.lang.String).replace(c, by) as String
fun String.contains(s: String) : Boolean = (this as java.lang.String).contains(s as java.lang.CharSequence)
fun java.lang.String.plus(s: Any?) : String = (this as String) + s.toString()
}
package netty {
fun ChannelPipeline.with(op: fun ChannelPipeline.() ) : ChannelPipeline {
this.op()
return this
}
fun HttpResponse.set(header: String, value: Any?) : Unit {
setHeader(header, value)
}
fun HttpResponse.setContent(content: Any?) : Unit {
setContent(ChannelBuffers.copiedBuffer(content.toString() as java.lang.String, CharsetUtil.UTF_8))
}
fun ChannelHandlerContext.sendError(status: HttpResponseStatus?) {
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, status)
response["Content-Type"] = "text/plain; charset=UTF-8"
response.setContent("Failure: " + status.toString() + "\r\n")
// Close the connection as soon as the error message is sent.
this.getChannel()?.write(response)?.addListener(ChannelFutureListener.CLOSE)
}
fun String.decodeURI(encoding : String) : String? {
try {
return URLDecoder.decode(this, encoding)
}
catch (e : UnsupportedEncodingException) {
return null
}
}
fun String.sanitizeUri() : String? {
val path = decodeURI("UTF-8") ?: decodeURI("ISO-8859-1")
if (path == null)
throw Error()
val localizedPath : String = path.replace('/', File.separatorChar)
return if (localizedPath.contains(File.separator + ".") ||
localizedPath.contains("." + File.separator) ||
localizedPath.startsWith(".") || endsWith("."))
null
else
localizedPath
}
class StandardPipelineFactory(val config: fun ChannelPipeline.():Unit) : ChannelPipelineFactory {
override fun getPipeline() : ChannelPipeline {
val pipeline = DefaultChannelPipeline().with {
addLast("decoder", HttpRequestDecoder())
addLast("aggregator", HttpChunkAggregator(65536))
addLast("encoder", HttpResponseEncoder())
addLast("chunkedWriter", ChunkedWriteHandler())
}
pipeline.config () // can not move it inside with{} because of codegen bug
return pipeline
}
}
fun ServerBootstrap.configPipeline(config: fun ChannelPipeline.(): Unit) =
setPipelineFactory(
StandardPipelineFactory(config)
)
}
fun main(args : Array<String>) {
val bootstrap = ServerBootstrap(
NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()
)
)
bootstrap.configPipeline {
addLast("handler", HttpStaticFileServerHandler(args[0]))
}
bootstrap.bind(InetSocketAddress(8080))
}
class HttpStaticFileServerHandler(val rootDir: String) : SimpleChannelUpstreamHandler() {
fun messageReceived(ctx : ChannelHandlerContext, e : MessageEvent) {
val request = e.getMessage() as HttpRequest
if (request.getMethod() != HttpMethod.GET) {
ctx.sendError(METHOD_NOT_ALLOWED);
return;
}
val path = request.getUri()?.sanitizeUri()
if (path == null) {
ctx.sendError(FORBIDDEN);
return;
}
val file = File(rootDir + File.separator + path)
if (file.isHidden() || !file.exists()) {
ctx.sendError(NOT_FOUND)
return
}
if (!file.isFile()) {
ctx.sendError(FORBIDDEN)
return
}
var raf = RandomAccessFile(file, "r")
val fileLength = raf.length()
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, OK)
response["Content-Length"] = fileLength
val ch = e.getChannel()
ch?.write(response)
ch?.write(DefaultFileRegion(raf.getChannel(), 0, fileLength))
}
}
Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="file://$MODULE_DIR$/lib" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$MODULE_DIR$/lib" />
</SOURCES>
<jarDirectory url="file://$MODULE_DIR$/lib" recursive="false" />
<jarDirectory url="file://$MODULE_DIR$/lib" recursive="false" type="SOURCES" />
</library>
</orderEntry>
<orderEntry type="library" name="KotlinRuntime" level="project" />
</component>
</module>
+178
View File
@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AntConfiguration">
<defaultAnt bundledAnt="true" />
</component>
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="?*.properties" />
<entry name="?*.xml" />
<entry name="?*.gif" />
<entry name="?*.png" />
<entry name="?*.jpeg" />
<entry name="?*.jpg" />
<entry name="?*.html" />
<entry name="?*.dtd" />
<entry name="?*.tld" />
<entry name="?*.ftl" />
</wildcardResourcePatterns>
<annotationProcessing enabled="false" useClasspath="true" />
</component>
<component name="CopyrightManager" default="">
<module2copyright />
</component>
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/nettyserver.iml" filepath="$PROJECT_DIR$/nettyserver.iml" />
</modules>
</component>
<component name="ProjectResources">
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
<component name="libraryTable">
<library name="KotlinRuntime">
<CLASSES>
<root url="jar://$PROJECT_DIR$/../../../dist/kotlinc/lib/kotlin-runtime.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
</project>
+750
View File
@@ -0,0 +1,750 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="40c9d6f7-e35c-44cc-8793-ac1acc607a7b" name="Default" comment="" />
<ignored path="nettyserver.iws" />
<ignored path=".idea/workspace.xml" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
</component>
<component name="DaemonCodeAnalyzer">
<disable_hints />
</component>
<component name="DebuggerManager">
<line_breakpoints>
<breakpoint url="file://$PROJECT_DIR$/src/Main.kt" line="22" class="Class at Main.kt:22" package="">
<option name="ENABLED" value="true" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
</line_breakpoints>
<breakpoint_any>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
</breakpoint_any>
<breakpoint_rules />
<ui_properties />
</component>
<component name="FavoritesManager">
<favorites_list name="nettyserver" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="HttpHandler.kt" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/HttpHandler.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="41" column="0" selection-start="1324" selection-end="1324" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="RestProcessor.kt" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/RestProcessor.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="36" column="0" selection-start="1181" selection-end="1181" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="StaticFileProcessor.kt" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/StaticFileProcessor.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="3" column="0" selection-start="98" selection-end="98" vertical-scroll-proportion="0.06838906">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="Request.kt" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Request.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="59" column="4" selection-start="2104" selection-end="2104" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="HttpMessage.java" pinned="false" current="false" current-in-tab="false">
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/handler/codec/http/HttpMessage.java">
<provider selected="true" editor-type-id="text-editor">
<state line="92" column="18" selection-start="2935" selection-end="2935" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="Main.kt" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Main.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="22" column="0" selection-start="679" selection-end="679" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="ChannelBuffers.java" pinned="false" current="false" current-in-tab="false">
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/buffer/ChannelBuffers.java">
<provider selected="true" editor-type-id="text-editor">
<state line="107" column="30" selection-start="4011" selection-end="4011" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="ChannelBuffer.java" pinned="false" current="false" current-in-tab="false">
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/buffer/ChannelBuffer.java">
<provider selected="true" editor-type-id="text-editor">
<state line="1710" column="0" selection-start="68976" selection-end="68976" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="AbstractChannelBuffer.java" pinned="false" current="false" current-in-tab="false">
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/buffer/AbstractChannelBuffer.java">
<provider selected="true" editor-type-id="text-editor">
<state line="536" column="18" selection-start="14864" selection-end="14864" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="index.html" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/static/index.html">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="-0.0">
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindManager">
<FindUsagesManager>
<setting name="OPEN_NEW_TAB" value="false" />
</FindUsagesManager>
</component>
<component name="IdeDocumentHistory">
<option name="changedFiles">
<list>
<option value="$PROJECT_DIR$/src/StaticFileProcessor.kt" />
<option value="$PROJECT_DIR$/src/Netty.kt" />
<option value="$PROJECT_DIR$/src/Request.kt" />
<option value="$PROJECT_DIR$/src/Main.kt" />
<option value="$PROJECT_DIR$/static/index.html" />
<option value="$PROJECT_DIR$/src/HttpHandler.kt" />
<option value="$PROJECT_DIR$/src/RestProcessor.kt" />
</list>
</option>
</component>
<component name="ProjectFrameBounds">
<option name="x" value="1" />
<option name="y" value="22" />
<option name="width" value="1411" />
<option name="height" value="826" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectReloadState">
<option name="STATE" value="0" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1" splitterProportion="0.5">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
</navigator>
<panes>
<pane id="Scope">
<subPane subId="Project Files">
<PATH>
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="PackagesPane" />
<pane id="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="nettyserver" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="nettyserver" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="nettyserver" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="nettyserver" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="nettyserver" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="static" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="nettyserver" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="nettyserver" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
<property name="GoToFile.includeJavaFiles" value="false" />
<property name="project.structure.last.edited" value="Modules" />
<property name="GoToClass.toSaveIncludeLibraries" value="false" />
<property name="project.structure.proportion" value="0.15" />
<property name="MemberChooser.sorted" value="false" />
<property name="recentsLimit" value="5" />
<property name="MemberChooser.showClasses" value="true" />
<property name="GoToClass.includeLibraries" value="false" />
<property name="project.structure.side.proportion" value="0.2" />
<property name="MemberChooser.copyJavadoc" value="false" />
<property name="dynamic.classpath" value="false" />
</component>
<component name="RunManager" selected="Kotlin.org.jetbrains.kotlin.examples.netty">
<configuration default="false" name="org.jetbrains.kotlin.examples.netty" type="JetRunConfigurationType" factoryName="Kotlin" temporary="true">
<option name="MAIN_CLASS_NAME" value="org.jetbrains.kotlin.examples.netty.namespace" />
<option name="VM_PARAMETERS" value="" />
<option name="PROGRAM_PARAMETERS" value="./static" />
<option name="WORKING_DIRECTORY" value="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="nettyserver" />
<envs />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="" />
<option name="TRANSPORT" value="0" />
<option name="LOCAL" value="true" />
</RunnerSettings>
<RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Debug" />
<ConfigurationWrapper RunnerId="Run" />
<method />
</configuration>
<configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
<module name="" />
<option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m" />
<option name="PROGRAM_PARAMETERS" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Remote" factoryName="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
<option name="SHMEM_ADDRESS" value="javadebug" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="JetRunConfigurationType" factoryName="Kotlin">
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="nettyserver" />
<envs />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<module name="" />
<option name="MAIN_CLASS_NAME" />
<option name="HTML_FILE_NAME" />
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<option name="VM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="TestNG" factoryName="TestNG">
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="SUITE_NAME" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="GROUP_NAME" />
<option name="TEST_OBJECT" value="CLASS" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="OUTPUT_DIRECTORY" />
<option name="ANNOTATION_TYPE" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<option name="USE_DEFAULT_REPORTERS" value="false" />
<option name="PROPERTIES_FILE" />
<envs />
<properties />
<listeners />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="" />
<envs />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="JUnit" factoryName="JUnit">
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<envs />
<patterns />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="Kotlin.org.jetbrains.kotlin.examples.netty" />
</list>
<configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
<Host>localhost</Host>
<Port>5050</Port>
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="40c9d6f7-e35c-44cc-8793-ac1acc607a7b" name="Default" comment="" />
<created>1328521187492</created>
<updated>1328521187492</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="1" y="22" width="1411" height="826" extended-state="0" />
<editor active="false" />
<layout>
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32956153" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39886847" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="CodeWindow" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294204" sideWeight="0.67043847" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32956153" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Gradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="true" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.24944974" sideWeight="0.60113156" order="0" side_tool="false" content_ui="combo" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32956153" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="ResolveWindow" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
</layout>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="VcsManagerConfiguration">
<option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="true" />
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="true" />
<option name="CHECK_NEW_TODO" value="true" />
<option name="myTodoPanelSettings">
<value>
<are-packages-shown value="false" />
<are-modules-shown value="false" />
<flatten-packages value="false" />
<is-autoscroll-to-source value="false" />
</value>
</option>
<option name="PERFORM_UPDATE_IN_BACKGROUND" value="true" />
<option name="PERFORM_COMMIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_EDIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_CHECKOUT_IN_BACKGROUND" value="true" />
<option name="PERFORM_ADD_REMOVE_IN_BACKGROUND" value="true" />
<option name="PERFORM_ROLLBACK_IN_BACKGROUND" value="false" />
<option name="CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND" value="false" />
<option name="ENABLE_BACKGROUND_PROCESSES" value="false" />
<option name="CHANGED_ON_SERVER_INTERVAL" value="60" />
<option name="SHOW_ONLY_CHANGED_IN_SELECTION_DIFF" value="true" />
<option name="CHECK_COMMIT_MESSAGE_SPELLING" value="true" />
<option name="DEFAULT_PATCH_EXTENSION" value="patch" />
<option name="SHORT_DIFF_HORISONTALLY" value="true" />
<option name="SHORT_DIFF_EXTRA_LINES" value="2" />
<option name="SOFT_WRAPS_IN_SHORT_DIFF" value="true" />
<option name="INCLUDE_TEXT_INTO_PATCH" value="false" />
<option name="INCLUDE_TEXT_INTO_SHELF" value="false" />
<option name="CREATE_PATCH_EXPAND_DETAILS_DEFAULT" value="true" />
<option name="SHOW_FILE_HISTORY_DETAILS" value="true" />
<option name="FORCE_NON_EMPTY_COMMENT" value="false" />
<option name="LAST_COMMIT_MESSAGE" />
<option name="MAKE_NEW_CHANGELIST_ACTIVE" value="false" />
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="false" />
<option name="CHECK_FILES_UP_TO_DATE_BEFORE_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_FILE_COMMIT" value="false" />
<option name="FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION" value="0.8" />
<option name="FILE_HISTORY_DIALOG_SPLITTER_PROPORTION" value="0.5" />
<option name="ACTIVE_VCS_NAME" />
<option name="UPDATE_GROUP_BY_PACKAGES" value="false" />
<option name="UPDATE_GROUP_BY_CHANGELIST" value="false" />
<option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
<option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
</component>
<component name="antWorkspaceConfiguration">
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
<option name="FILTER_TARGETS" value="false" />
</component>
<component name="editorHistoryManager">
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/handler/codec/http/DefaultHttpMessage.java">
<provider selected="true" editor-type-id="text-editor">
<state line="97" column="16" selection-start="2835" selection-end="2835" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Netty.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="28" column="29" selection-start="1155" selection-end="1155" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/handler/codec/http/HttpResponseStatus.java">
<provider selected="true" editor-type-id="text-editor">
<state line="442" column="13" selection-start="13864" selection-end="13864" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/handler/codec/http/DefaultHttpResponse.java">
<provider selected="true" editor-type-id="text-editor">
<state line="42" column="24" selection-start="1490" selection-end="1490" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/channel/ChannelFuture.java">
<provider selected="true" editor-type-id="text-editor">
<state line="327" column="0" selection-start="13131" selection-end="13131" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/handler/codec/http/HttpRequest.java">
<provider selected="true" editor-type-id="text-editor">
<state line="36" column="44" selection-start="1319" selection-end="1319" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/handler/codec/http/HttpMessage.java">
<provider selected="true" editor-type-id="text-editor">
<state line="92" column="18" selection-start="2935" selection-end="2935" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/buffer/ChannelBuffers.java">
<provider selected="true" editor-type-id="text-editor">
<state line="107" column="30" selection-start="4011" selection-end="4011" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/buffer/AbstractChannelBuffer.java">
<provider selected="true" editor-type-id="text-editor">
<state line="536" column="18" selection-start="14864" selection-end="14864" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final-sources.jar!/org/jboss/netty/buffer/ChannelBuffer.java">
<provider selected="true" editor-type-id="text-editor">
<state line="1710" column="0" selection-start="68976" selection-end="68976" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Main.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="22" column="0" selection-start="679" selection-end="679" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Request.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="59" column="4" selection-start="2104" selection-end="2104" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/static/index.html">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="-0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/HttpHandler.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="41" column="0" selection-start="1324" selection-end="1324" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/RestProcessor.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="36" column="0" selection-start="1181" selection-end="1181" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/StaticFileProcessor.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="3" column="0" selection-start="98" selection-end="98" vertical-scroll-proportion="0.06838906">
<folding />
</state>
</provider>
</entry>
</component>
<component name="masterDetails">
<states>
<state key="ArtifactsStructureConfigurable.UI">
<settings>
<artifact-editor />
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="FacetStructureConfigurable.UI">
<settings>
<last-edited>No facets are configured</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="GlobalLibrariesConfigurable.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="JdkListConfigurable.UI">
<settings>
<last-edited>1.6</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ModuleStructureConfigurable.UI">
<settings>
<last-edited>nettyserver</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ProjectJDKs.UI">
<settings>
<last-edited>1.6</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ProjectLibrariesConfigurable.UI">
<settings>
<last-edited>KotlinRuntime</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>
@@ -0,0 +1,41 @@
package org.jetbrains.kotlin.examples.netty
import org.jboss.netty.channel.SimpleChannelUpstreamHandler
import java.util.LinkedList
import org.jboss.netty.channel.ChannelHandlerContext
import org.jboss.netty.channel.MessageEvent
import org.jboss.netty.handler.codec.http.HttpResponseStatus.*
import org.jboss.netty.handler.codec.http.HttpMethod
import org.jboss.netty.handler.codec.http.HttpResponseStatus
class HttpHandler(config: HttpHandler.() -> Unit) : SimpleChannelUpstreamHandler() {
private var processors = LinkedList<Processor>();
var onNotFound : (RequestResponse)->Any? = { request -> request.setError(NOT_FOUND) };
{
this.bind(config)()
}
fun messageReceived(ctx : ChannelHandlerContext, e : MessageEvent) {
val request = RequestResponse(e)
for(processor in processors) {
if(processor.tryToProcess(request)) {
request.write()
return
}
}
(onNotFound)(request)
}
fun static(prefix: String = "/", directory: String) {
processors.add(StaticFileProcessor(prefix, directory))
}
fun rest(prefix: String, config: RestBuilder.()->Any?) {
val builder = RestBuilder()
(builder.bind(config))()
processors.add(RestProcessor(prefix, builder))
}
}
+40
View File
@@ -0,0 +1,40 @@
package org.jetbrains.kotlin.examples.netty
import org.jboss.netty.handler.codec.http.HttpResponseStatus
import org.jboss.netty.handler.codec.http.DefaultHttpResponse
import org.jboss.netty.handler.codec.http.HttpVersion
import org.jboss.netty.buffer.ChannelBuffers
import java.nio.charset.Charset
fun main(args : Array<String>) {
if(args.size == 0) {
println("Please provide command line argument <path to static resources>")
System.exit(1)
}
else {
println("Please open http://localhost:8080/index.html page in your browser")
}
httpServer(8080) {
static(directory = args[0])
rest("/sayhello") {
GET {
response.content = "Hello, World!"
}
POST {
response.content = "You said: ${request.getContent().sure().toString(Charset.defaultCharset())}"
}
}
onNotFound = { requestResponse ->
when(requestResponse.path) {
"/prototype.js" -> {
requestResponse.redirect("https://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js")
}
else ->
requestResponse.setError(HttpResponseStatus.FORBIDDEN)
}
}
}
}
+66
View File
@@ -0,0 +1,66 @@
package org.jetbrains.kotlin.examples.netty
import java.util.concurrent.Executors
import java.net.*
import java.io.*
import org.jboss.netty.bootstrap.ServerBootstrap
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory
import org.jboss.netty.channel.*
import org.jboss.netty.handler.codec.http.*
import org.jboss.netty.handler.stream.ChunkedWriteHandler
import org.jboss.netty.handler.codec.frame.TooLongFrameException
import org.jboss.netty.buffer.ChannelBuffers
import org.jboss.netty.util.CharsetUtil
import org.jboss.netty.handler.codec.http.HttpResponseStatus.*
import org.jboss.netty.bootstrap.ServerBootstrap
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory
import org.jboss.netty.channel.*
import org.jboss.netty.handler.codec.http.*
import org.jboss.netty.handler.stream.ChunkedWriteHandler
import org.jboss.netty.handler.codec.frame.TooLongFrameException
import org.jboss.netty.buffer.ChannelBuffers
import org.jboss.netty.util.CharsetUtil
import org.jboss.netty.handler.codec.http.HttpResponseStatus.*
import java.util.LinkedList
// This is workaround for compiler bug
fun <T> T.bind(op: T.()->Any?) = { op() }
fun HttpResponse.set(header: String, value: Any?) : Unit {
setHeader(header, value)
}
var HttpResponse.content : Any?
get() = throw UnsupportedOperationException()
set(c: Any?) {
val buffer = ChannelBuffers.copiedBuffer(c.toString(), CharsetUtil.UTF_8).sure()
setContent(buffer)
setHeader("Content-Length", buffer.readableBytes())
}
fun ServerBootstrap.configPipeline(config: ChannelPipeline.() -> Unit) = setPipelineFactory(object: ChannelPipelineFactory {
override fun getPipeline() : ChannelPipeline {
val pipeline = DefaultChannelPipeline()
pipeline.bind(config) ()
return pipeline
}
})
fun httpServer(port: Int, handler: HttpHandler.() -> Unit) {
val bootstrap = ServerBootstrap(
NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()
)
)
bootstrap.configPipeline {
addLast("decoder", HttpRequestDecoder())
addLast("aggregator", HttpChunkAggregator(65536))
addLast("encoder", HttpResponseEncoder())
addLast("chunkedWriter", ChunkedWriteHandler())
addLast("handler", HttpHandler(handler))
}
bootstrap.bind(InetSocketAddress(port))
}
+80
View File
@@ -0,0 +1,80 @@
package org.jetbrains.kotlin.examples.netty
import org.jboss.netty.channel.SimpleChannelUpstreamHandler
import java.util.LinkedList
import org.jboss.netty.channel.ChannelHandlerContext
import org.jboss.netty.channel.MessageEvent
import org.jboss.netty.handler.codec.http.HttpResponseStatus.*
import org.jboss.netty.handler.codec.http.HttpRequest
import org.jboss.netty.channel.Channel
import org.jboss.netty.handler.codec.http.HttpResponseStatus
import org.jboss.netty.handler.codec.http.DefaultHttpResponse
import org.jboss.netty.channel.ChannelFutureListener
import org.jboss.netty.handler.codec.http.HttpVersion
import java.io.File
import java.io.UnsupportedEncodingException
import java.net.URLDecoder
import org.jboss.netty.handler.codec.http.HttpHeaders.*
import org.jboss.netty.handler.codec.http.HttpMessage
import org.jboss.netty.channel.ChannelFuture
class RequestResponse(e: MessageEvent) {
val request = e.getMessage() as HttpRequest
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN)
val channel = e.getChannel().sure()
val path = request.getUri().sure().sanitizeUri()
fun setError(status: HttpResponseStatus?) {
response.setStatus(status)
response["Content-Type"] = "text/plain; charset=UTF-8"
response.content = "Failure: " + status.toString() + "\r\n"
}
fun redirect(path: String) {
response.setStatus(HttpResponseStatus.MOVED_PERMANENTLY)
response["Location"] = path
response["Content-Length"] = 0
channel.write(response)
}
fun ok() : RequestResponse {
response.setStatus(HttpResponseStatus.OK)
return this
}
fun write() =
if(response.getStatus().sure().getCode() >= 400) {
channel.write(response).sure().addListener(ChannelFutureListener.CLOSE)
}
else {
channel.write(response)
}
}
fun String.sanitizeUri() : String {
val path = decodeURI("UTF-8") ?: decodeURI("ISO-8859-1") ?: throw Error()
val localizedPath = path.replace('/', File.separatorChar)
return if (localizedPath.contains(File.separator + ".") ||
localizedPath.contains("." + File.separator) ||
localizedPath.startsWith(".") || localizedPath.endsWith("."))
throw Error()
else
localizedPath
}
fun String.decodeURI(encoding : String) : String? {
try {
return URLDecoder.decode(this, encoding)
}
catch (e : UnsupportedEncodingException) {
return null
}
}
trait Processor {
fun tryToProcess(request: RequestResponse) : Boolean
}
@@ -0,0 +1,37 @@
package org.jetbrains.kotlin.examples.netty
import org.jboss.netty.handler.codec.http.HttpMethod
import org.jboss.netty.handler.codec.http.HttpResponseStatus
class RestBuilder() {
var onGet : (RequestResponse.()->Any?)? = null
var onPost : (RequestResponse.()->Any?)? = null
fun GET(handler: RequestResponse.()->Unit) {
onGet = handler
}
fun POST(handler: RequestResponse.()->Unit) {
onPost = handler
}
}
class RestProcessor(val prefix: String, val builder: RestBuilder) : Processor {
override fun tryToProcess(request: RequestResponse): Boolean {
if(request.path.startsWith(prefix)) {
if(request.request.getMethod() == HttpMethod.GET && builder.onGet != null) {
request.ok()
request.(builder.onGet.sure())()
}
else if(request.request.getMethod() == HttpMethod.POST && builder.onPost != null) {
request.ok()
request.(builder.onPost.sure())()
}
else {
request.setError(HttpResponseStatus.METHOD_NOT_ALLOWED)
}
return true;
}
return false
}
}
@@ -0,0 +1,46 @@
package org.jetbrains.kotlin.examples.netty
import org.jboss.netty.handler.codec.http.HttpMethod
import java.io.File
import java.io.RandomAccessFile
import org.jboss.netty.handler.codec.http.DefaultHttpResponse
import org.jboss.netty.channel.DefaultFileRegion
import org.jboss.netty.handler.codec.http.HttpVersion
import org.jboss.netty.handler.codec.http.HttpResponseStatus.*
class StaticFileProcessor(val prefix: String, val root: String) : Processor {
override fun tryToProcess(request: RequestResponse) : Boolean {
if(request.path.startsWith(prefix)) {
return request.processStaticFile()
}
return false;
}
fun RequestResponse.processStaticFile() : Boolean {
val file = File(root + File.separator + path.substring(prefix.length))
if(!file.exists())
return false;
if (request.getMethod() != HttpMethod.GET) {
setError(METHOD_NOT_ALLOWED);
return true;
}
if (file.isHidden() || !file.isFile()) {
setError(FORBIDDEN)
return true
}
var raf = RandomAccessFile(file, "r")
val fileLength = raf.length()
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, OK)
response["Content-Length"] = fileLength
channel.write(response)
channel.write(DefaultFileRegion(raf.getChannel(), 0, fileLength))
return true;
}
}
@@ -0,0 +1,31 @@
<html>
<head>
<script src="/prototype.js" ></script>
<script language="javascript">
function onLoad() {
new Ajax.Request('/sayhello', {
method: 'get',
onSuccess: function(transport) {
$('notice').update(transport.responseText)
}
});
}
function sayHello() {
new Ajax.Request('/sayhello', {
method: 'post',
postBody: $('input').value,
onSuccess: function(transport) {
var div = document.createElement('div')
div.innerHTML = transport.responseText
$('interactions').insert(div)
}
});
}
</script>
</head>
<body onload="onLoad()">
<div id="notice"><i>Waiting...</i></div>
<input type="text" id="input"><button onclick="sayHello();">Say Hello</button>
<div id="interactions"></div>
</body>
</html>