Skip to content

Commit 7f2162c

Browse files
toddnlmarini
authored andcommitted
Transitioned Polyglot play plugin to guice service.
1 parent c41f0ab commit 7f2162c

File tree

3 files changed

+102
-124
lines changed

3 files changed

+102
-124
lines changed

app/controllers/Files.scala

Lines changed: 81 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Files @Inject() (
4848
contextLDService: ContextLDService,
4949
spaces: SpaceService,
5050
folders: FolderService,
51+
fileConvertService: FileConvertService,
5152
versusService: VersusService,
5253
adminsNotifierService: AdminsNotifierService,
5354
appConfig: AppConfigurationService,
@@ -219,39 +220,31 @@ class Files @Inject() (
219220
}
220221
}
221222

222-
//call Polyglot to get all possible output formats for this file's content type
223-
current.plugin[PolyglotPlugin] match {
224-
case Some(plugin) => {
225-
Logger.debug("Polyglot plugin found")
226-
227-
// Increment view count for file
228-
val (view_count, view_date) = files.incrementViews(id, user)
229-
230-
val fname = file.filename
231-
//use name of the file to get the extension (pdf or txt or jpg) to use an input type for Polyglot
232-
val lastDividerIndex = (fname.replace("/", ".").lastIndexOf(".")) + 1
233-
//drop all elements left of last divider index
234-
val contentTypeEnding = fname.drop(lastDividerIndex)
235-
Logger.debug("file name ends in " + contentTypeEnding)
236-
//get output formats from Polyglot plugin and pass as the last parameter to view
237-
plugin.getOutputFormats(contentTypeEnding).map(outputFormats =>
238-
Ok(views.html.file(file, id.stringify, commentsByFile, previewsWithPreviewer, sectionsWithPreviews,
239-
extractorsActive, decodedDatasetsContaining.toList, foldersContainingFile,
240-
mds, extractionGroups, outputFormats, space, access, folderHierarchy.reverse.toList, decodedSpacesContaining.toList, allDecodedDatasets.toList, view_count, view_date)))
241-
}
242-
case None =>
243-
Logger.debug("Polyglot plugin not found")
244223

245-
// Increment view count for file
246-
val (view_count, view_date) = files.incrementViews(id, user)
224+
// Increment view count for file
225+
val (view_count, view_date) = files.incrementViews(id, user)
226+
227+
val fname = file.filename
228+
//use name of the file to get the extension (pdf or txt or jpg) to use an input type for Polyglot
229+
val lastDividerIndex = (fname.replace("/", ".").lastIndexOf(".")) + 1
230+
//drop all elements left of last divider index
231+
val contentTypeEnding = fname.drop(lastDividerIndex)
232+
Logger.debug("file name ends in " + contentTypeEnding)
233+
234+
//call FileTransferService to get all possible output formats for this file's content type
247235

248-
//passing None as the last parameter (list of output formats)
249-
Future(Ok(views.html.file(file, id.stringify, commentsByFile, previewsWithPreviewer, sectionsWithPreviews,
236+
if (play.Play.application().configuration().getBoolean("fileconvertService")) {
237+
//get output formats from Polyglot plugin and pass as the last parameter to view
238+
fileConvertService.getOutputFormats(contentTypeEnding).map(outputFormats =>
239+
Ok(views.html.file(file, id.stringify, commentsByFile, previewsWithPreviewer, sectionsWithPreviews,
250240
extractorsActive, decodedDatasetsContaining.toList, foldersContainingFile,
251-
mds, extractionGroups, None, space, access, folderHierarchy.reverse.toList, decodedSpacesContaining.toList, allDecodedDatasets.toList, view_count, view_date)))
241+
mds, extractionGroups, outputFormats, space, access, folderHierarchy.reverse.toList, decodedSpacesContaining.toList, allDecodedDatasets.toList, view_count, view_date)))
242+
} else {
243+
Future(Ok(views.html.file(file, id.stringify, commentsByFile, previewsWithPreviewer, sectionsWithPreviews,
244+
extractorsActive, decodedDatasetsContaining.toList, foldersContainingFile,
245+
mds, extractionGroups, None, space, access, folderHierarchy.reverse.toList, decodedSpacesContaining.toList, allDecodedDatasets.toList, view_count, view_date)))
252246
}
253247
}
254-
255248
case None => {
256249
val error_str = s"The file with id ${id} is not found."
257250
Logger.error(error_str)
@@ -738,81 +731,73 @@ class Files @Inject() (
738731
*/
739732
def downloadAsFormat(id: UUID, outputFormat: String) = PermissionAction(Permission.DownloadFiles, Some(ResourceRef(ResourceRef.file, id))).async { implicit request =>
740733
implicit val user = request.user
734+
if (UUID.isValid(id.stringify)) {
735+
files.get(id) match {
736+
case Some(file) => {
737+
//get bytes for file to be converted
738+
files.getBytes(id) match {
739+
case Some((inputStream, filename, contentType, contentLength)) => {
741740

742-
current.plugin[PolyglotPlugin] match {
743-
case Some(plugin) => {
744-
if (UUID.isValid(id.stringify)) {
745-
files.get(id) match {
746-
case Some(file) => {
747-
//get bytes for file to be converted
748-
files.getBytes(id) match {
749-
case Some((inputStream, filename, contentType, contentLength)) => {
750-
751-
//prepare encoded file name for converted file
752-
val lastSeparatorIndex = file.filename.replace("_", ".").lastIndexOf(".")
753-
val outputFileName = file.filename.substring(0, lastSeparatorIndex) + "." + outputFormat
754-
755-
//create local temp file to save polyglot output
756-
val tempFileName = "temp_converted_file." + outputFormat
757-
val tempFile: java.io.File = new java.io.File(tempFileName)
758-
tempFile.deleteOnExit()
759-
760-
val outputStream: OutputStream = new BufferedOutputStream(new FileOutputStream(tempFile))
761-
762-
val polyglotUser: Option[String] = configuration.getString("polyglot.username")
763-
val polyglotPassword: Option[String] = configuration.getString("polyglot.password")
764-
val polyglotConvertURL: Option[String] = configuration.getString("polyglot.convertURL")
765-
766-
if (polyglotConvertURL.isDefined && polyglotUser.isDefined && polyglotPassword.isDefined) {
767-
files.incrementDownloads(id, user)
768-
769-
//first call to Polyglot to get url of converted file
770-
plugin.getConvertedFileURL(filename, inputStream, outputFormat)
771-
.flatMap {
772-
convertedFileURL =>
773-
val triesLeft = 30
774-
//Cponverted file is initially empty. Have to wait for Polyglot to finish conversion.
775-
//keep checking until file exists or until too many tries
776-
//returns future success only if file is found and downloaded
777-
plugin.checkForFileAndDownload(triesLeft, convertedFileURL, outputStream)
778-
}.map {
779-
x =>
780-
//successfuly completed future - get here only after polyglotPlugin.getConvertedFileURL is done executing
781-
Ok.chunked(Enumerator.fromStream(new FileInputStream(tempFileName)))
782-
.withHeaders(CONTENT_TYPE -> "some-content-Type")
783-
.withHeaders(CONTENT_DISPOSITION -> (FileUtils.encodeAttachment(outputFileName, request.headers.get("user-agent").getOrElse(""))))
784-
}.recover {
785-
case t =>
786-
Logger.debug("Failed: " + t.getMessage())
787-
BadRequest("Error: " + t.getMessage())
788-
}
789-
} //end of if defined config params
790-
else {
791-
Logger.error("Could not get configuration parameters.")
792-
Future(BadRequest("Could not get configuration parameters."))
793-
}
794-
} //end of case Some
795-
case None => {
796-
Logger.error("Error getting file " + id)
797-
Future(BadRequest("File with this id not found"))
741+
//prepare encoded file name for converted file
742+
val lastSeparatorIndex = file.filename.replace("_", ".").lastIndexOf(".")
743+
val outputFileName = file.filename.substring(0, lastSeparatorIndex) + "." + outputFormat
744+
745+
//create local temp file to save polyglot output
746+
val tempFileName = "temp_converted_file." + outputFormat
747+
val tempFile: java.io.File = new java.io.File(tempFileName)
748+
tempFile.deleteOnExit()
749+
750+
val outputStream: OutputStream = new BufferedOutputStream(new FileOutputStream(tempFile))
751+
752+
val fileConvertUser: Option[String] = configuration.getString("fileconvert.username")
753+
val fileConvertPassword: Option[String] = configuration.getString("fileconvert.password")
754+
val fileConvertConvertURL: Option[String] = configuration.getString("fileconvert.convertURL")
755+
756+
if (fileConvertConvertURL.isDefined && fileConvertUser.isDefined && fileConvertPassword.isDefined) {
757+
files.incrementDownloads(id, user)
758+
759+
//first call to Polyglot to get url of converted file
760+
fileConvertService.getConvertedFileURL(filename, inputStream, outputFormat)
761+
.flatMap {
762+
convertedFileURL =>
763+
val triesLeft = 30
764+
//Cponverted file is initially empty. Have to wait for Polyglot to finish conversion.
765+
//keep checking until file exists or until too many tries
766+
//returns future success only if file is found and downloaded
767+
fileConvertService.checkForFileAndDownload(triesLeft, convertedFileURL, outputStream)
768+
}.map {
769+
x =>
770+
//successfuly completed future - get here only after polyglotPlugin.getConvertedFileURL is done executing
771+
Ok.chunked(Enumerator.fromStream(new FileInputStream(tempFileName)))
772+
.withHeaders(CONTENT_TYPE -> "some-content-Type")
773+
.withHeaders(CONTENT_DISPOSITION -> (FileUtils.encodeAttachment(outputFileName, request.headers.get("user-agent").getOrElse(""))))
774+
}.recover {
775+
case t =>
776+
Logger.debug("Failed: " + t.getMessage())
777+
BadRequest("Error: " + t.getMessage())
798778
}
779+
} //end of if defined config params
780+
else {
781+
Logger.error("Could not get configuration parameters.")
782+
Future(BadRequest("Could not get configuration parameters."))
799783
}
800-
}
784+
} //end of case Some
801785
case None => {
802-
//File could not be found
803-
Logger.error(s"Error getting the file with id $id.")
804-
Future(BadRequest("Invalid file ID"))
786+
Logger.error("Error getting file " + id)
787+
Future(BadRequest("File with this id not found"))
805788
}
806789
}
807-
} //end of if (UUID.isValid(id.stringify))
808-
else {
809-
Logger.error(s"The given id $id is not a valid ObjectId.")
810-
Future(BadRequest(toJson(s"The given id $id is not a valid ObjectId.")))
811790
}
812-
} //end of case Some(plugin)
813-
case None =>
814-
Logger.debug("Polyglot plugin not found")
815-
Future(Ok("Plugin not found"))
791+
case None => {
792+
//File could not be found
793+
Logger.error(s"Error getting the file with id $id.")
794+
Future(BadRequest("Invalid file ID"))
795+
}
796+
}
797+
} //end of if (UUID.isValid(id.stringify))
798+
else {
799+
Logger.error(s"The given id $id is not a valid ObjectId.")
800+
Future(BadRequest(toJson(s"The given id $id is not a valid ObjectId.")))
816801
}
817802
}
818803

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,20 @@ import org.apache.commons.io.IOUtils
1616
import com.ning.http.client.Realm.AuthScheme
1717

1818
/**
19-
* Polyglot Plugin
19+
* File Convert Service
2020
*
2121
*/
22-
class PolyglotPlugin(application: Application) extends Plugin {
22+
class FileConvertService(application: Application) {
2323

24-
val polyglotUser: Option[String] = configuration.getString("polyglot.username")
25-
val polyglotPassword: Option[String] = configuration.getString("polyglot.password")
26-
val polyglotConvertURL: Option[String] = configuration.getString("polyglot.convertURL")
27-
val polyglotInputsURL: Option[String] = configuration.getString("polyglot.inputsURL")
24+
val fileConvertUser: Option[String] = configuration.getString("fileconvert.username")
25+
val fileConvertPassword: Option[String] = configuration.getString("fileconvert.password")
26+
val fileConvertConvertURL: Option[String] = configuration.getString("fileconvert.convertURL")
27+
val fileConvertInputsURL: Option[String] = configuration.getString("fileconvert.inputsURL")
2828

2929
//table to store output formats for each input format
3030
//store them in memory to avoind making a request to Polyglot each time
3131
val formatsTable = scala.collection.mutable.HashMap.empty[String, List[String]]
3232

33-
override def onStart() {
34-
Logger.debug("Starting Polyglot Plugin")
35-
}
36-
37-
override def onStop() {
38-
Logger.debug("Stopping Polyglot Plugin")
39-
}
40-
4133
//using code from https://www.playframework.com/documentation/2.2.x/ScalaWS
4234
//Processing large responses
4335
def fromStream(stream: OutputStream): Iteratee[Array[Byte], Unit] = Cont {
@@ -60,20 +52,20 @@ class PolyglotPlugin(application: Application) extends Plugin {
6052
def checkForFileAndDownload(triesLeft: Int, url: String, outputStream: OutputStream): Future[Unit] =
6153
{
6254
//check that credentials are set in config file
63-
if ( !polyglotUser.isDefined || !polyglotPassword.isDefined) {
55+
if ( !fileConvertUser.isDefined || !fileConvertPassword.isDefined) {
6456
throw new RuntimeException("Polyglot credentials not defined.")
6557
}
6658

6759
if (triesLeft == 0) Future.failed(throw new RuntimeException("Converted file not found."))
6860

69-
else WS.url(url).withAuth(polyglotUser.get, polyglotPassword.get, AuthScheme.BASIC).get flatMap { res =>
61+
else WS.url(url).withAuth(fileConvertUser.get, fileConvertPassword.get, AuthScheme.BASIC).get flatMap { res =>
7062
if (res.status == 200) {
7163
//this is the callback, runs after file exists is TRUE
7264
Logger.debug("File exists on polyglot. Will download now.")
7365
//file exists on Polyglot, begin download using iteratee
7466
//following example in https://www.playframework.com/documentation/2.2.x/ScalaWS Processing large responses
7567
val result = WS.url(url)
76-
.withAuth(polyglotUser.get, polyglotPassword.get, AuthScheme.BASIC)
68+
.withAuth(fileConvertUser.get, fileConvertPassword.get, AuthScheme.BASIC)
7769
.get { xx => fromStream(outputStream) }
7870
.flatMap(_.run)
7971
//Returning result. When it is mapped in the controller, the successful future is AFTER file has been downloaded on the Clowder server.
@@ -90,7 +82,7 @@ class PolyglotPlugin(application: Application) extends Plugin {
9082
*/
9183
def getConvertedFileURL(filename: String, inputStream: java.io.InputStream, outputFormat: String): Future[String] = {
9284
//check that Polyglot credentials are defined
93-
if (!polyglotConvertURL.isDefined || !polyglotUser.isDefined || !polyglotPassword.isDefined) {
85+
if (!fileConvertConvertURL.isDefined || !fileConvertUser.isDefined || !fileConvertPassword.isDefined) {
9486
throw new RuntimeException("Polyglot credentials not defined.")
9587
}
9688

@@ -107,8 +99,8 @@ class PolyglotPlugin(application: Application) extends Plugin {
10799
val reqContentType = reqEntity.getContentType
108100

109101
// Now just send the data to the WS API
110-
val response = WS.url(polyglotConvertURL.get + outputFormat)
111-
.withAuth(polyglotUser.get, polyglotPassword.get, AuthScheme.BASIC)
102+
val response = WS.url(fileConvertConvertURL.get + outputFormat)
103+
.withAuth(fileConvertUser.get, fileConvertPassword.get, AuthScheme.BASIC)
112104
.post(bytes)(Writeable.wBytes, ContentTypeOf(Some(reqContentType)))
113105

114106
//get the url for the converted file on Polyglot
@@ -149,10 +141,10 @@ class PolyglotPlugin(application: Application) extends Plugin {
149141
*/
150142
def getOutputFormatsPolyglot(inputType: String): Future[Option[List[String]]] = {
151143
//proceed only if received all the config params
152-
if (polyglotInputsURL.isDefined && polyglotUser.isDefined && polyglotPassword.isDefined) {
144+
if (fileConvertInputsURL.isDefined && fileConvertUser.isDefined && fileConvertPassword.isDefined) {
153145
//call polyglot server with authentication
154-
WS.url(polyglotInputsURL.get + inputType)
155-
.withAuth(polyglotUser.get, polyglotPassword.get, AuthScheme.BASIC)
146+
WS.url(fileConvertInputsURL.get + inputType)
147+
.withAuth(fileConvertUser.get, fileConvertPassword.get, AuthScheme.BASIC)
156148
.get
157149
.map {
158150
case response =>

conf/application.conf

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,16 +426,17 @@ downloadDatasetBagIt = false
426426
stagingArea = false
427427

428428
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
429-
# Polyglot
429+
# FileConvertService
430430
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
431+
fileconvertService = false
431432
#url to get all outputs for given input
432-
polyglot.inputsURL="http://dap-dev.ncsa.illinois.edu:8184/inputs/"
433+
fileconvert.inputsURL="http://dap-dev.ncsa.illinois.edu:8184/inputs/"
433434
#url to convert a file
434-
polyglot.convertURL="http://dap-dev.ncsa.illinois.edu:8184/convert/"
435+
fileconvert.convertURL="http://dap-dev.ncsa.illinois.edu:8184/convert/"
435436
#for connecting to polyglog server
436-
polyglot.username = "browndog.user"
437+
fileconvert.username = "browndog.user"
437438
# DO NOT check in the password. The user needs to enter the correct pwd here.
438-
polyglot.password = ""
439+
fileconvert.password = ""
439440

440441
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
441442
# Staging Area

0 commit comments

Comments
 (0)