Add basic support for Java 7 NIO file systems (#20293)

This commit is contained in:
Michał Kiędyś 2016-04-25 19:25:26 +10:00 committed by Konrad Malawski
parent 6d399a308e
commit b983f19c1f
23 changed files with 286 additions and 124 deletions

View file

@ -5,6 +5,7 @@
package akka.http.javadsl.model;
import java.io.File;
import java.nio.file.Path;
import akka.http.impl.util.JavaAccessors;
import akka.http.scaladsl.model.HttpEntity;
@ -42,14 +43,30 @@ public final class HttpEntities {
return HttpEntity$.MODULE$.apply((akka.http.scaladsl.model.ContentType) contentType, bytes);
}
/**
* @deprecated Will be removed in Akka 3.x, use {@link #create(ContentType, Path)} instead.
*/
@Deprecated
public static UniversalEntity create(ContentType contentType, File file) {
return JavaAccessors.HttpEntity(contentType, file);
}
public static UniversalEntity create(ContentType contentType, Path file) {
return JavaAccessors.HttpEntity(contentType, file);
}
/**
* @deprecated Will be removed in Akka 3.x, use {@link #create(ContentType, Path, int)} instead.
*/
@Deprecated
public static UniversalEntity create(ContentType contentType, File file, int chunkSize) {
return HttpEntity$.MODULE$.apply((akka.http.scaladsl.model.ContentType) contentType, file, chunkSize);
}
public static UniversalEntity create(ContentType contentType, Path file, int chunkSize) {
return HttpEntity$.MODULE$.fromPath((akka.http.scaladsl.model.ContentType) contentType, file, chunkSize);
}
public static HttpEntity.Default create(ContentType contentType, long contentLength, Source<ByteString, Object> data) {
return new akka.http.scaladsl.model.HttpEntity.Default((akka.http.scaladsl.model.ContentType) contentType, contentLength, data.asScala());
}

View file

@ -5,12 +5,17 @@
package akka.http.javadsl.model;
import akka.util.ByteString;
import java.io.File;
import java.nio.file.Path;
import java.util.Optional;
/**
* The base type for an Http message (request or response).
*
* INTERNAL API: this trait will be changed in binary-incompatible ways for classes that are derived from it!
* Do not implement this interface outside the Akka code base!
*
* Binary compatibility is only maintained for callers of this traits interface.
*/
public interface HttpMessage {
/**
@ -103,9 +108,17 @@ public interface HttpMessage {
/**
* Returns a copy of Self message with a new entity.
*
* @deprecated Will be removed in Akka 3.x, use {@link #withEntity(ContentType, Path)} instead.
*/
@Deprecated
Self withEntity(ContentType type, File file);
/**
* Returns a copy of Self message with a new entity.
*/
Self withEntity(ContentType type, Path file);
/**
* Returns a copy of Self message with a new entity.
*/

View file

@ -5,6 +5,7 @@
package akka.http.impl.util
import java.io.File
import java.nio.file.Path
import JavaMapping.Implicits._
import akka.http.javadsl.model._
@ -28,4 +29,8 @@ object JavaAccessors {
/** INTERNAL API */
def HttpEntity(contentType: ContentType, file: File): UniversalEntity =
model.HttpEntity(contentType.asScala, file)
/** INTERNAL API */
def HttpEntity(contentType: ContentType, file: Path): UniversalEntity =
model.HttpEntity.fromPath(contentType.asScala, file)
}

View file

@ -10,12 +10,13 @@ import akka.http.impl.model.JavaInitialization
import language.implicitConversions
import java.io.File
import java.nio.file.{ Path, Files }
import java.lang.{ Iterable JIterable}
import scala.util.control.NonFatal
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.collection.immutable
import akka.util.{Unsafe, ByteString}
import akka.util.ByteString
import akka.stream.scaladsl._
import akka.stream.stage._
import akka.stream._
@ -242,11 +243,22 @@ object HttpEntity {
*
* If the given `chunkSize` is -1 the default chunk size is used.
*/
def apply(contentType: ContentType, file: File, chunkSize: Int = -1): UniversalEntity = {
val fileLength = file.length
@deprecated("Use `fromPath` instead", "2.4.5")
def apply(contentType: ContentType, file: File, chunkSize: Int = -1): UniversalEntity =
fromPath(contentType, file.toPath, chunkSize)
/**
* Returns either the empty entity, if the given file is empty, or a [[HttpEntity.Default]] entity
* consisting of a stream of [[akka.util.ByteString]] instances each containing `chunkSize` bytes
* (except for the final ByteString, which simply contains the remaining bytes).
*
* If the given `chunkSize` is -1 the default chunk size is used.
*/
def fromPath(contentType: ContentType, file: Path, chunkSize: Int = -1): UniversalEntity = {
val fileLength = Files.size(file)
if (fileLength > 0)
HttpEntity.Default(contentType, fileLength,
if (chunkSize > 0) FileIO.fromFile(file, chunkSize) else FileIO.fromFile(file))
if (chunkSize > 0) FileIO.fromPath(file, chunkSize) else FileIO.fromPath(file))
else empty(contentType)
}

View file

@ -4,6 +4,8 @@
package akka.http.scaladsl.model
import java.io.File
import java.nio.file.Path
import java.lang.{ Iterable JIterable }
import java.util.Optional
@ -107,7 +109,10 @@ sealed trait HttpMessage extends jm.HttpMessage {
withEntity(HttpEntity(contentType.asInstanceOf[ContentType.NonBinary], string))
def withEntity(contentType: jm.ContentType, bytes: Array[Byte]): Self = withEntity(HttpEntity(contentType.asInstanceOf[ContentType], bytes))
def withEntity(contentType: jm.ContentType, bytes: ByteString): Self = withEntity(HttpEntity(contentType.asInstanceOf[ContentType], bytes))
def withEntity(contentType: jm.ContentType, file: java.io.File): Self = withEntity(HttpEntity(contentType.asInstanceOf[ContentType], file))
@deprecated("Use withEntity(ContentType, Path) instead", "2.4.5")
def withEntity(contentType: jm.ContentType, file: File): Self = withEntity(HttpEntity(contentType.asInstanceOf[ContentType], file))
def withEntity(contentType: jm.ContentType, file: Path): Self = withEntity(HttpEntity.fromPath(contentType.asInstanceOf[ContentType], file))
import collection.JavaConverters._
/** Java API */

View file

@ -3,8 +3,8 @@
*/
package akka.http.scaladsl.model
import java.io.File
import java.nio.file.Path
import java.util.Optional
import akka.http.impl.util.Util
import scala.concurrent.duration.FiniteDuration
@ -344,8 +344,18 @@ object Multipart {
* To create an instance with several parts or for multiple files, use
* `FormData(BodyPart.fromFile("field1", ...), BodyPart.fromFile("field2", ...)`
*/
@deprecated("Use `fromPath` instead", "2.4.5")
def fromFile(name: String, contentType: ContentType, file: File, chunkSize: Int = -1): Multipart.FormData =
Multipart.FormData(Source.single(Multipart.FormData.BodyPart.fromFile(name, contentType, file, chunkSize)))
fromPath(name, contentType, file.toPath, chunkSize)
/**
* Creates a FormData instance that contains a single part backed by the given file.
*
* To create an instance with several parts or for multiple files, use
* `FormData(BodyPart.fromPath("field1", ...), BodyPart.fromPath("field2", ...)`
*/
def fromPath(name: String, contentType: ContentType, file: Path, chunkSize: Int = -1): Multipart.FormData =
Multipart.FormData(Source.single(Multipart.FormData.BodyPart.fromPath(name, contentType, file, chunkSize)))
/**
* Strict [[FormData]].
@ -432,8 +442,15 @@ object Multipart {
/**
* Creates a BodyPart backed by a File that will be streamed using a FileSource.
*/
@deprecated("Use `fromPath` instead", since = "2.4.5")
def fromFile(name: String, contentType: ContentType, file: File, chunkSize: Int = -1): BodyPart =
BodyPart(name, HttpEntity(contentType, file, chunkSize), Map("filename" -> file.getName))
fromPath(name, contentType, file.toPath, chunkSize)
/**
* Creates a BodyPart backed by a file that will be streamed using a FileSource.
*/
def fromPath(name: String, contentType: ContentType, file: Path, chunkSize: Int = -1): BodyPart =
BodyPart(name, HttpEntity.fromPath(contentType, file, chunkSize), Map("filename" -> file.getFileName.toString))
def unapply(value: BodyPart): Option[(String, BodyPartEntity, Map[String, String], immutable.Seq[HttpHeader])] =
Some((value.name, value.entity, value.additionalDispositionParams, value.additionalHeaders))