gradle - how to access file remotely - gradle

A few months ago i read the gradle manual and i thought i was able to reference a file remotely. So hosted with http. For example here is a sample json file hosted somewhere on the internet :
http://techslides.com/demos/samples/sample.json
so a simple task i want to achieve is to read this file in gradle and print out the output as a proof of concept.
Thus, in my build.gradle file i put the following:
allprojects {
afterEvaluate { project ->
FileCollection collection = files('http://techslides.com/demos/samples/sample.json')
if (!collection.isEmpty()) {
File file = collection.getSingleFile();
println 'this is the file'+ file.text;
}
}
}
but i am getting the following error:
Error:(51, 0) Cannot convert URL 'http://techslides.com/demos/samples/sample.json' to a file.

You can read only file URL with File like file:/path/to/file
To download a text file and read it line by line, you can convert it to an URL object and read it with a Reader :
def line
'http://techslides.com/demos/samples/sample.json'.toURL().withReader { reader ->
while (line = reader.readLine()) {
println line
}
}

Related

Setting file permissions dynamically in a gradle Copy task

I'm trying to get around a problem where a dependency in my build is a zip file that contains some read only files. When I extract that zip as part of my build I end out with read only files in a staging folder and they prevent the task running in the future since they cannot be overwritten.
Until there's a way to force overwrite in a gradle copy task I've been trying to find a way to change the file mode of the read-only files in a way that doesn't remove the execute bit from those files that need it.
I've come up with this:
task stageZip(type: Copy) {
from({ zipTree(zipFile) })
into stagingFolder
eachFile {
println "${it.name}, oldMode: ${Integer.toOctalString(it.mode)}, newMode: ${Integer.toOctalString(it.mode | 0200)}"
fileMode it.mode | 0200
}
}
But this doesn't work. If I comment out the fileMode line then the println correctly lists the old and new file modes with the write bit enabled for all files. If I leave the code as is, then all the files in the zip get extracted with the newMode of the first file.
This doesn't seem like this is an unreasonable thing to try and do, but I'm obviously doing something wrong. Any suggestions?
Based on this thread, consider the Sync task. Specifically:
task stageZip(type: Sync) {
from zipTree('data/data.zip')
into 'staging'
fileMode 0644
}
I've put a working example (as I understand the question) here.
Here is a method that answers the question about file permissions. The example is posted to GitHub here.
First, consider a method to add w to a file:
import java.nio.file.*
import java.nio.file.attribute.PosixFilePermission
def addWritePerm = { file ->
println "TRACER adding 'w' to : " + file.absolutePath
def path = Paths.get(file.absolutePath)
def perms = Files.getPosixFilePermissions(path)
perms << PosixFilePermission.OWNER_WRITE
Files.setPosixFilePermissions(path, perms)
}
then, the Gradle task could be as follows:
project.ext.stagingFolder = 'staging'
project.ext.zipFile = 'data/data.zip'
task stageZip(type: Copy) {
from({ zipTree(project.ext.zipFile) })
into project.ext.stagingFolder
doLast {
new File(project.ext.stagingFolder).eachFileRecurse { def file ->
if (! file.canWrite()) {
addWritePerm(file)
}
}
}
}
eachFile {
file -> file.setMode(file.getMode() | 0200)
}
Worked for me in an rpm task which works with copyspec

How to replace in log4j2.xml with Gradle?

I want to replace a value in our log4j2.xml with Gradle during build. I found a way to do that:
task reaplaceInLogFile {
String apiSuffix = System.properties['apiSuffix'] ?: ''
println "In my task"
String contents = file('src/main/resources/log4j2.xml').getText( 'UTF-8' )
println "File found"
contents = contents.replaceAll( "svc0022_operations", "svc0022_operations${apiSuffix}")
new File( 'src/main/resources/log4j2.xml' ).write( contents, 'UTF-8' )
}
However, this changes also the source file permanently and I do not want to do that. I want to change the log4j2.xml that will be included in the build zip only. I know I can use something like this:
tasks.withType(com.mulesoft.build.MuleZip) { task ->
String apiSuffix = System.properties['apiSuffix'] ?: ''
task.eachFile {
println name
if (name == 'mule-app.properties') {
println "Expanding properties for API Version suffix: ${apiSuffix}"
filter { String line ->
line.startsWith("${serviceId}.api.suffix") ? "${serviceId}.api.suffix=${apiSuffix}" : line
}
}
But I do not know what is the type of the log4j2 file. If there is another way to do that I will be thankful!
We are using Mule gradle plugin.
The Type is not the type of the log4j2 file, but the type of the task that creates the ZIP or wherever your log4j2 file is packaged into. If the log4j2 file is included in the ZIP that is generated by a MuleZip task, then you can simply add another if-branch for the log4j2 file.
But actually it is probably better to just edit the concrete task that packages up the log4j2 file into some archive instead of all tasks of the same type.
Besides that you should be able to use filesMatching instead of eachFile with an if I think.

Reading includes from idl file in custom task

I want to make my gradle build inteligent when building my model.
To acquire this I was planning to read schema files, acquire what is included and then build firstly included models (if they are not present).
I'm pretty new to Groovy and Gradle, so please that into account.
What I have:
build.gradle file on root directory, including n subdirectories (subprojects added to settings.gradle). I have only one gradle build file, because I defined tasks like:
subprojects {
task init
task includeDependencies(type: checkDependencies)
task build
task dist
(...)
}
I will return to checkDependencies shortly.
Schema files located externally, which I can see.
Each of them have from 0 to 3 lines of code, that say about dependencies and looks like that:
#include "ModelDir/ModelName.idl"
In my build.gradle I created task that should open, and read those dependencies, preferably return them:
class parsingIDL extends DefaultTask{
String idlFileName="*def file name*"
def regex = ~/#include .*\/(\w*).idl/
#Task Action
def checkDependencies(){
File idlFile= new File(idlFileName)
if(!idlFile.exists()){
logger.error("File not found)
} else {
idlFile.eachLine{ line ->
def dep = []
def matcher = regex.matcher(line)
(...)*
}
}
}
}
What should I have in (...)* to find all dependencies and how should I define, that for example
subprojectA::build.dependsOn([subprojectB::dist, subprojectC::dist])?
All I could find on internet created dep, that outputted given:
[]
[]
[modelName]
[]
[]
(...)

Issue with Gradle task to write file

I am developing an Android application where I have a directory of JSON files and I want to create a gradle task that will combine all these files into a single JSON file.
This is the gradle task I have so far but does not create the file:
// Task that combines all JSON files in ../libraries into src/main/res/raw/libraries.json
task combineJSonFiles {
String content = ""
FileTree tree = fileTree(dir: '../libraries', include: '**/*.json')
tree.each {File file ->
content += file.getText()
}
println "[" + content.substring(0, content.length()-1) + "]" // prints out the correct contents
File libraries = file("../app/src/main/res/raw/libraries.json")
println libraries.getProperties()
}
I print out the properties and I am not sure why these are the property values:
{directory=false, canonicalFile=/Users/michaelcarrano/AndroidStudioProjects/detective_droid/app/src/main/res/raw/libraries.json, file=false, freeSpace=0, canonicalPath=/Users/michaelcarrano/AndroidStudioProjects/detective_droid/app/src/main/res/raw/libraries.json, usableSpace=0, hidden=false, totalSpace=0, path=/Users/michaelcarrano/AndroidStudioProjects/detective_droid/app/src/main/res/raw/libraries.json, name=libraries.json, prefixLength=1, absolute=true, class=class java.io.File, parentFile=/Users/michaelcarrano/AndroidStudioProjects/detective_droid/app/src/main/res/raw, absolutePath=/Users/michaelcarrano/AndroidStudioProjects/detective_droid/app/src/main/res/raw/libraries.json, absoluteFile=/Users/michaelcarrano/AndroidStudioProjects/detective_droid/app/src/main/res/raw/libraries.json, parent=/Users/michaelcarrano/AndroidStudioProjects/detective_droid/app/src/main/res/raw}
Any help is appreciated as I have not seemed to figure this out even after reading the documentation. http://www.gradle.org/docs/current/userguide/working_with_files.html
I am just posting the code for the task that now works:
task combineJSonFiles {
String content = ""
FileTree tree = fileTree(dir: '../libraries', include: '**/*.json')
tree.each {File file ->
content += file.getText()
}
def libraries = new File("app/src/main/res/raw/libraries.json")
libraries.text = "[" + content.substring(0, content.length()-1) + "]"
}
My issue was trying to use Java.io.File and having the wrong directory path set for my file.
Creating an instance of java.io.File in Groovy/Java does not create the file on disk. You will need to write something to it. Check out this tutorial for working with files in Groovy.
Also you have put your task implementation in a task configuration block, rather than a task action. This means your code will not be running when you are expecting - it will run every time you run gradle rather than when you run this task. You need to put your code in a doLast block

How to execute a shell command for each file in a Gradle file collection?

I've recently been directed to implement all build/release engineering jobs in Gradle.
So I'm new to Gradle and some things which are drop-dead obvious at a shell prompt are just hard to fathom in this brave new world.
My build creates a set of jar files.
I need to execute a shell task for each one of them
Something similar to:
task findBugs (type:Exec, dependsOn: fb23) {commandLine 'java', '-jar',
'./findBugs/findbugs.jar', '-textui', '-progress', '-xml', '-output',
'TrustManagerService.xml', 'TrustManagerService.jar'}
(I can't usethe FindBugs plug-in because we're in JDK8 - so I'm running FindBugs externally from a preview version...)
I can get a file collection and iterate over the file names with something like:
FileTree iotTree = fileTree(dir: '.')
iotTree.include '*.jar'
iotTree.each {
File file -> println file.name
println 'A file'
}
or
def iotJars = files(file('./jars').listFiles())
println ''
println iotJars
iotJars.each { File file -> println 'The next file is: ' + file.name }
But for the life of me I can't see how to execute a shell command for each filename returned...
Thoughts on the most straightforward way to do this??
By the way - what's the best way to include the line breaks in the code listing - I had to return and add CRs to each line to get them to break...:(
You can use the execute method on a String to execute a shell command.
Here is an example task:
task executeExample << {
FileTree ioTree = fileTree(dir: ".")
ioTree.each { f ->
def proc = "ls -l ${f}".execute();
proc.waitFor();
println "return code: ${ proc.exitValue()}"
println "stderr: ${proc.err.text}"
println "stdout: ${proc.in.text}"
}
}

Resources