Skip to content

Instantly share code, notes, and snippets.

@adamrabung
Created November 28, 2012 18:34
Show Gist options
  • Save adamrabung/4163100 to your computer and use it in GitHub Desktop.
Save adamrabung/4163100 to your computer and use it in GitHub Desktop.
Implementation of James Roper's Play 2 versioned assets w/o scala 2.10 dependency
package controllers
import play.api.mvc.PathBindable
import play.api.Play
import java.net.JarURLConnection
import Play.current
import java.io.File
import com.google.common.cache.CacheBuilder
import com.google.common.cache.CacheLoader
import java.net.URL
//modified to use guava Cache instead of 2.10 TrieMap
//original: https://github.com/jroper/play-versioned-assets-example/blob/master/app/controllers/VersionedAssets.scala
class AccessTimeCacheLoader extends CacheLoader[URL, Option[Long]] {
@Override
override def load(resource: URL) = resource.getProtocol match {
case "jar" => {
resource.getPath.split('!').drop(1).headOption.flatMap { fileNameInJar =>
Option(resource.openConnection)
.collect { case c: JarURLConnection => c }
.flatMap(c => Option(c.getJarFile.getJarEntry(fileNameInJar.drop(1))))
.map(_.getTime)
.filterNot(_ == 0)
}
}
case _ => None
}
}
object VersionedAssets {
def at(file: VersionedAsset) = Assets.at(file.path, file.file)
}
case class VersionedAsset(file: String, path: String = "/public", versionParam: String = "v")
object VersionedAsset {
private val lastModifieds = CacheBuilder.newBuilder().maximumSize(10000).build(new AccessTimeCacheLoader());
private def lastModifiedFor(resource: java.net.URL): Option[Long] = lastModifieds.get(resource)
implicit def pathBinder = new PathBindable[VersionedAsset] {
def bind(key: String, value: String) = Right(VersionedAsset(value))
def unbind(key: String, value: VersionedAsset) = {
val resourceName = Option(value.path + "/" + value.file).map(name => if (name.startsWith("/")) name else ("/" + name)).get
val modified = Play.resource(resourceName).flatMap { resource =>
resource.getProtocol match {
case file if file == "file" => Some(new File(resource.toURI).lastModified())
case jar if jar == "jar" => lastModifiedFor(resource)
case _ => None
}
}
modified.map(value.file + "?" + value.versionParam + "=" + _).getOrElse(value.file)
}
}
implicit def toVersionedAsset(path: String): VersionedAsset = VersionedAsset(path)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment