Gradle plugin copy file from plugin jar - plugins

I'm creating my first gradle plugin. I'm trying to copy a file from the distribution jar into a directory I've created at the project. Although the file exists inside the jar, I can't copy it to the directory.
This is my task code:
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
class InitTask extends DefaultTask {
File baseDir;
private void copyEnvironment(File environments) {
String resource = getClass().getResource("/environments/development.properties").getFile();
File input = new File(resource);
File output = new File(environments, "development.properties");
try {
copyFile(input, output);
}
catch (IOException e) {
e.printStackTrace();
}
}
void copyFile(File sourceFile, File destFile) {
destFile << sourceFile.text
}
#TaskAction
void createDirectories() {
logger.info "Creating directory."
File environments = new File(baseDir, "environments");
File scripts = new File(baseDir, "scripts");
File drivers = new File(baseDir, "drivers");
[environments, scripts, drivers].each {
it.mkdirs();
}
copyEnvironment(environments);
logger.info "Directory created at '${baseDir.absolutePath}'."
}
}
And this is the error I'm getting:
:init
java.io.FileNotFoundException: file:/path-to-jar/MyJar.jar!/environments/development.properties (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at groovy.util.CharsetToolkit.<init>(CharsetToolkit.java:69)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.newReader(DefaultGroovyMethods.java:15706)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.getText(DefaultGroovyMethods.java:14754)
at org.codehaus.groovy.runtime.dgm$352.doMethodInvoke(Unknown Source)
at org.codehaus.groovy.reflection.GeneratedMetaMethod$Proxy.doMethodInvoke(GeneratedMetaMethod.java:70)
at groovy.lang.MetaClassImpl$GetBeanMethodMetaProperty.getProperty(MetaClassImpl.java:3465)
at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:61)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
at br.com.smartcoders.migration.tasks.InitTask.copyFile(InitTask.groovy:29)
Just to emphasize, the development.properties is inside the environments directory inside the MyJar.jar

getClass().getResource() returns a URL. To access that URL, you'll have to read it directly (e.g. with url.text) rather than first converting it to a String/File. Or you can use getClass().getResourceAsStream().text, which is probably more accurate. In both cases you can optionally specify the file encoding.

Kotlin DSL answer!
For cases like this it is good to have extensions:
fun Any.getResource(filename: String): File? {
val input = this::class.java.classLoader.getResourceAsStream(filename) ?: return null
val tempFile = File.createTempFile(
filename.substringBeforeLast('.'),
"." + filename.substringAfterLast('.')
)
tempFile.deleteOnExit()
tempFile.writer().use { output ->
input.bufferedReader().use { input ->
output.write(input.readText())
}
}
return tempFile
}

Related

How to get the configuration file path within JAR file for KafkaProducer SSL setup?

I have a JAR file with below structure:
example.jar
|
+-org
| +-springframework
| +-boot
| +-loader.jar
+-BOOT-INF
+-classes
| +- kafka
| truststore.jks ==> I want to get the path here
+-lib
+-dependency1.jar
How can I get the configuration file path, only path (string) of 'kafka/truststore.jks' file ?
Because I am applying the SSL for KafkaProducer, I using below code and it work fine on local:
#Value("classpath:kafka/truststore.jks")
private org.springframework.core.io.Resource sslTruststoreResource;
...
String sslTruststoreLocation = sslTruststoreResource.getFile().getAbsolutePath(); // ==\> ***it throw FileNotFoundException here on deployed Server, local env run fine !***
Map\<String, Object\> config = Maps.newHashMap();
config.put("ssl.truststore.location", sslTruststoreLocation);
but when I deploy on Server, it throw FileNotFoundException :(
After many days to research, I found that the sslTruststoreResource.getFile() will be fail for JAR file case as mentioned at here
The sslTruststoreResource.getInputStream() or sslTruststoreResource.getFilename() are ok for JAR file but they are not path I need for kafka configuration.
In my project, the 'truststore.jks' file is located as below:
src
-- java
-- resources
. -- kafka
-- truststore.jks
So, is there any solution for my issue ? Thank you.
I tried to use ClassPathResource, ResourcePatternResolver but they not working
After many ways I still could not get the path from JKS file then I copy it to another path out of jar file where my code can refer to its path
final String FILE_NAME = env.getProperty("kafka.metadata.ssl.truststore.location");
String sslTruststoreLocation = "*-imf-kafka-client.truststore.jks";
try {
InputStream is = getClass().getClassLoader().getResourceAsStream(FILE_NAME);
// Get the destination path where contains JKS file
final String HOME_DIR = System.getProperty("user.home");
final Path destPath = Paths.get(HOME_DIR, "tmp");
if (!Files.isDirectory(destPath)) {
Files.createDirectories(destPath);
}
// Copy JKS file to destination path
sslTruststoreLocation = destPath.toFile().getAbsolutePath() + "/" + FILE_NAME;
File uploadedFile = new File(sslTruststoreLocation);
if(!uploadedFile.exists()) {
uploadedFile.getParentFile().mkdirs();
uploadedFile.createNewFile();
FileCopyUtils.copy(is, new FileOutputStream(sslTruststoreLocation));
log.debug("Copied {} file from resources dir to {} done !", FILE_NAME, sslTruststoreLocation);
}
config.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG, sslTruststoreLocation);
} catch (IOException e) {
final String message = "The " + sslTruststoreLocation + " file not found to construct a KafkaProducer";
log.error(message);
}
Looks like this is a known issue in Kafka.
Spring Boot propose a workaround similar to yours.

Not able to remove folder name inspite of delting all files inside it in spark

I am deleting output folders before running my spark job .
Sometime it deletes it but sometime it delete all the files inside it but top level folder still remains .
I have sub folders kind of structure .
This is how i am deleting the folders .
def DeleteDescrFolder(fs: org.apache.hadoop.fs.FileSystem, descrFileURL: String) = {
val bDescr = fs.exists(new Path(descrFileURL))
if (true.equals(bDescr)) {
val outputFile = fs.globStatus(new Path(descrFileURL))
for (DeleteFilePath <- outputFile) {
fs.delete(DeleteFilePath.getPath)
}
println("Descr File is delete from " + descrFileURL)
} else {
println(descrFileURL + "Decsr Does not Exist")
}
}
How can i remove folder name also ?
You are deleting the files inside the folder specified. Try the following code which will delete the folder as well
def DeleteDescrFolder(fs: org.apache.hadoop.fs.FileSystem, descrFileURL: String) = {
if (fs.exists(new Path(descrFileURL))) {
try{
fs.delete(new Path(descrFileURL),true)
println("Descr folder is deleted " + descrFileURL)
}catch{case e: Exception =>
print("exeption "+e)
}
} else {
println(descrFileURL + "Decsr Does not Exist")
}
}

Exception occurred during file download in Firebase

Hi am trying to download .zip file from firebase storage using code
FirebaseStorage httpsReference = FirebaseStorage.getInstance();
StorageReference reference = httpsReference.getReferenceFromUrl(Constants.FIREBASE_ST_URL);
StorageReference referenceNew = reference.child("ImageSets").child(post.get("SetName") + ".zip");
Log.d("log_tag", "ZIP URL referenceNew : " + referenceNew.toString());
//**this is log result** gs://memory-matcch.appspot.com/ImageSets/set_2.zip
referenceNew.getFile(file).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Log.d("log_tag", "ZIP FILE onSuccess : " + Uri.fromFile(file) + "\nPath : " + file.getPath() + "\nAbsolute : " + file.getAbsolutePath());
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
and this is fire base rule
this is firebase storage
and I am getting this error
Exception occurred during file download
java.io.IOException: open failed: ENOENT (No such file or directory)
at java.io.File.createNewFile(File.java:939)
at com.google.firebase.storage.FileDownloadTask.run(Unknown Source)
at com.google.firebase.storage.StorageTask$8.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at java.io.File.createNewFile(File.java:932)
at com.google.firebase.storage.FileDownloadTask.run(Unknown Source) 
at com.google.firebase.storage.StorageTask$8.run(Unknown Source) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
at java.lang.Thread.run(Thread.java:818) 
I want to do this without login in fire base as I ant that user can download zip without login also.
.getFile(file) seems to be your problem--what is file? This download the zip to your local filesystem, and it appears, as the exception states, "No such file or directory".
Try getBytes() or getStream() to download in memory, or pick a valid file to write to.
You just need to provide two-arguments first File or second Name in which you want to give that file
Like:
storageRefrence.getFile(fileDirectory, fileName).addOnCompleteListener(new ...);

Resource does not have neither a source nor a target path. Impossible to add it to the bundle

I am trying to read .xlsx file with rules using kie api 6.
However I get this exception
java.lang.RuntimeException: Resource does not have neither a source nor a target path. Impossible to add it to the bundle. P
lease set either the source or target name of the resource before adding it.null
at org.drools.compiler.kie.builder.impl.KieFileSystemImpl.write(KieFileSystemImpl.java:83)
at com.project.watch.validator.RuleValidator.isValidRuleKieNew(RuleValidator.java:71)
at com.project.watch.validator.RuleValidator.isValidRule(RuleValidator.java:37)
at com.project.watch.core.WatchDir$ValidateFileRunnable.run(WatchDir.java:177)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:
178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
The code looks like this
try {
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem();
kfs.write(ks.getResources().newInputStreamResource(Files.newInputStream(p, StandardOpenOption.READ)));
KieBuilder kb = ks.newKieBuilder(kfs);
if (kb.getResults().getMessages(Level.ERROR).size() != 0) {
logger.lifecycle("Invalid file: {}.", kb.getResults().getMessages());
return false;
}
} catch (Exception e) {
logger.lifecycle("UNEXPECTED ERROR DURING VALIDATION -------------- ", e);
return false;
}
logger.lifecycle("Valid file: {}.", p);
return true;
}
It fails on kfs.write by the way.
I also checked the path to file by displaying it in console
Attempt to process rule file: D:\PROJECT_FOLDER\project\src\testInteg\resources\rules\rule.xlsx
and it is a correct path.
What's the problem? I am using 6.3 Final version.
I recommend this mantra, assuming your String p contains the path name as shown:
FileInputStream fis = new FileInputStream( p );
kfs.write( "src/main/resources/rule.xslx",
kieServices.getResources().newInputStreamResource( fis ) );
There are some other forms for write to the KieFileSystem, but I find that this is easy to use. You may derive the rule.xslx from p, using Java's API for path names.

How To Use I18N Messages In A Grails Plugin

I've added a new exception to my plugin:
class UnzipException extends RuntimeException {
String message
String defaultMessage
String fileName
}
. . .
else {
throw new UnzipException(
message:"grailsant.unzipexception.badfile",
defaultMessage: "Invalid zip file: ${zipFile}",
fileName: zipFile)
}
...
And in the plugin's messages.properties I have:
grailsant.unzipexception.badfile=Invalid zip file: {0}
Two questions:
How do I get {0} filled in with fileName?
Can an application override the grailsant.unzipexception.badfile message?
(1) It seems like this has to be done by app:
try {
. . .
} catch (org.grails.plugins.grailsant.UnzipException e) {
flash.message = e.message
flash.args = [e.fileName]
flash.defaultMessage = e.defaultMessage
}
(2) Yep, if the message.properties in the app has the same key as the plugin, the app's values will be used.