Grails Plugin Get Plugin's Root or Installed Directory - grails

I'm writing a plugin and I'm trying to write a file inside of the Plugin's root or installed directory (not sure what to refer to this to). I can't seem to figure out how to get a hold of this value. Doing System.properties['base.dir'] will result in the implementing Grails project's root directory. So right now I have two directories:
C:/PluginProject/
C:/GrailsAppThatUsesPlugin/
It's my understanding that when this becomes a distributed plugin a user will similarly have two directories:
GRAILS_HOME/grails-version/projects/projectName/plugins/myPlugin/
C:/GrailsAppThatUsesPlugin/
Inside of my plugin project I need to create a file. It needs to be inside of my plugin because the file I'm writing needs to reference other files that my plugin provides. The few things that I've tried that haven't worked are:
System.properties['base.dir']
new File("")
In a groovy script within a plugin you can simply refer to pluginNamePluginDir but I'm trying to access this from a POGO.
Looking at all of the System.properties none of them have the plugin directory
grailsApplication doesn't seem to contain this type of information either.
Any help is greatly appreciated.

This worked for me (both in-place and regular plug-ins):
import org.codehaus.groovy.grails.plugins.GrailsPluginUtils
GrailsPluginUtils.pluginInfos.find { it.name == pluginName }.pluginDir

You can use this:
import org.codehaus.groovy.grails.plugins.PluginManagerHolder
def pluginManager = PluginManagerHolder.pluginManager
def plugin = pluginManager.getGrailsPlugin(pluginName)
def pluginDir = plugin.descriptor.file.parentFile
The plugin name has to be of the form 'spring-security-core', not 'springSecurityCore'

Related

Read files of directory using Job DSL (similar to readFilesFromDirectory)

In the Job DSL, there is the method readFileFromWorkspace(), which makes it possible to read a files content from the workspace.
Now it would like to have something like readFilesFromDirectory() which gives me all files in some directory.
The goal is to make it possible to choose from different ansible playbooks:
choiceParam('PLAYBOOK_FILE', ['playbook1.yml', 'playbook2.yml'])
and to populate this list with existing files from a directory. Is something like this possible?
Well, shortly after asking this question, I found the solution.
So the Hudson API can be used:
hudson.FilePath workspace =
hudson.model.Executor.currentExecutor().getCurrentWorkspace()
def resultList = workspace.list().findAll { it.name ==~ /deploy.*\.yml/ }

Reading Grails configs from groovy

I just tried to read a grails config from groovy. The ConfigSlurper is easy to use, but since it executes the config, it needs all dependencies in place. In my case, it complains about a missing log4j class.
Even when I import this class into my ConfigSlurper script, the config itself runs into this problem.
Any Idea how I could make the log4j classes accessible to the config?
Update: now that I have a proper keyboard in front of me, I can elaborate on my problem:
I have grails configurations which configure log4j as described in the docs:
import org.apache.log4j.*
log4j = {
appenders {
appender new RollingFileAppender(
name: "myAppender",
maxFileSize: 1024,
file: "/tmp/logs/myApp.log"
)
}
}
Then I tried to parse them like this:
def file = new File(<config location>)
def config = new ConfigSlurper().parse(file.toURL())
and the Slurper threw an exception...
I've found two solutions:
First, the documents show a way how to configure a rollingFileAppender without instantiating one: http://grails.org/doc/2.3.7/guide/conf.html .
Second, I managed to fix my original problem with a
#Grab('log4j:log4j:')
in front of my script - not a good solution if you are behind a firewall...
As Jeff already stated, it should also be possible to put the right jar file in the classpath, but I have to say that I often struggle with the cp :-( and when I tried to put the log4j.jar in the .groovy folder, I didn't succeed - but I guess this was because of an inproper groovy installation.

Add logging to an external pluggable script

As described in Can't call one closure from another, I am using a pluggable script from within a Grails app.
Unfortunately, I've found that I can't use log4j from within these scripts. I am forced to use println.
I tried using
import org.apache.commons.logging.LogFactory
def Log log = LogFactory.getLog(getClass())
but I got no output. When I print out the result of the call to getClass(), I get something like
myscript$_run_closure5
So I'm thinking the issue is that there is no configuration in my Grails Config.groovy file for this class.
Is there a way for me to programmatically add these pluggable scripts to the log4j configuration? Keep in mind that I do not know in advance what the names of the scripts are, so this has to happen at runtime.
Consider the following code:
import org.apache.log4j.Logger
// ...
Logger log = Logger.getLogger('MyPlugin')
new File( grailsApplication.config.externalFiles ).eachFile { file ->
Binding binding = new Binding()
binding.variables.log = log
GroovyShell shell = new GroovyShell(binding)
shell.evaluate(file)
strategies.put( binding.variables.key, binding.variables )
}
Explanation:
It is not obligatory to pass class name to getLogger, it can be actually any string. You just need to make sure that this string is matched in log4j.properties of the main program.
You pass once created log to plugin scripts via binding variable "log". Then plugin scripts can access it simply as log.info('test123')
My personal recommendation would be to use logback instead of log4j. Both libraries were developed by the same guy and it is stated that logback supersedes log4j.

How to know if a grails plugin is running standalone or when the plugin is installed into the application

Basically I want to retrieve the same value provided by the "pluginContextPath" variable used in a gsp but in a groovy class.
class {
String pluginCtx = $pluginContextPath
byte[] logo = grailsApplication.getParentContext().servletContext.getResource("${pluginCtx}images/myImage.jpg").bytes;
}
I know that I cannot use the $pluginContextPath variable in a groovy class, but I tried using something suggested in post but it gives me the dir full path
GrailsPluginUtils.pluginInfos.find { it.name == pluginName }.pluginDir
but what i want is what the pluginContextPath variable does
"When you run the plugin in development mode the link to the resource will resolve to something like /js/mycode.js. However, when the plugin is installed into an application the path will automatically change to something like /plugin/example-0.1/js/mycode.js and Grails will deal with making sure the resources are in the right place."

deleting plugins views (gsp) when building the war

We are using various plugins in our grails application (like logging, spring security core, ui, acl and many others). Now these plugins come with default gsps (in the views folder of each plugin).
I want to build a WAR without including the views of any plugin. So when the war is built right now it creates the plugins folder which contains views folder which come by default with the plugin, these views are introducing a lot of vulnerabilities and so I want to exclude the plugins views.
I am trying this right now in BuildConfig.groovy like below:
grails.project.dependency.resolution = {
grails.war.resources = { stagingDir ->
println "Customized delete started..."
delete{fileset dir: "${stagingDir}/WEB-INF/plugins/logging-0.1/grails-app/views/"}
delete{fileset dir: "${stagingDir}/WEB-INF/plugins/spring-security-ui-0.1.2/grails-app/views/"}
}
}
But the problem is the code tries to delete the views when they are not yet created by the war building process. Hence I get a file not found error for those plugins views.
Where should I write the code to delete the plugins views so that they are already created and available to delete when building the WAR, or how do I not include the plugins views in the WAR?
Thanks in advance..
Priyank
I answered this question on the Grails mailing list.
http://grails.1312388.n4.nabble.com/deleting-plugins-views-gsp-when-building-the-war-td4560517.html
(The answer hasn't yet shown up in nabble)
You can remove/add files from/to a war file in the eventCreateWarStart
event specified in scripts/_Events.groovy file.
This might work:
filename: scripts/_Events.groovy
eventCreateWarStart = { warName, stagingDir ->
Ant.delete(dir: "${stagingDir}/WEB-INF/plugins/logging-0.1/grails-app/views")
Ant.delete(dir: "${stagingDir}/WEB-INF/classes", includes:"gsp_logging*.*")
Ant.delete(dir: "${stagingDir}/WEB-INF/plugins/spring-security-ui-0.1.2/grails-app/views")
Ant.delete(dir: "${stagingDir}/WEB-INF/classes", includes:"gsp_springSecurityUi*.*")
}
I'm not sure if you could also remove plugin Controller classes without problems. We've used Filter classes to "disable" controllers provided by plugins.
As a side-note you can disable "development-only" plugins in the production environment by using the yet undocumented "grails.plugins.excludes" feature:
Example:
in Config.groovy:
import grails.util.Environment
if(Environment.current == Environment.PRODUCTION) {
grails.plugin.excludes = ['somePluginName']
}

Resources