Is it possible to run maven plugin from java class? - java

Need to run maven jaxb2 plugin from my app, at run-time. Is it possible?

Maybe i have done something that could help you:
/**
* #author swoeste
*
*/
public class MavenExecutor {
private final File configuration;
private final ClassWorld classWorld;
/**
* Constructor for a new maven executor.
*
* #param aConfiguration
*/
public MavenExecutor( final File aConfiguration ) {
this.configuration = aConfiguration;
this.classWorld = new ClassWorld( "plexus.core", this.getClass().getClassLoader() ); //$NON-NLS-1$
}
/**
* This method is used to perform a mvn command on the given pom. The original
* command must be given, also the sub folder and the marker folder in the working directory. The working directory
* and the configuration file will be added before execution.
*
* #param cmd the mvn command to execute
* #param pom the absolute path to a maven pom file
* #param output the absolute path to the working directory
* #param folder the output sub folder of the working directory
* #param marker the marker sub folder of the working directory
* #return
*/
public int unpack( final String cmd, final File pom, final File output, final String folder, final String marker ) {
final List<String> commands = new ArrayList<String>( //
Arrays.asList( cmd.split( ConfigurationConstants.MAVEN_DELIMITER ) ) );
commands.add( "-DoutputDirectory=" + output.getAbsolutePath() + folder ); //$NON-NLS-1$
commands.add( "-DmarkersDirectory=" + output.getAbsolutePath() + marker ); //$NON-NLS-1$
commands.add( "-gs=\"" + this.configuration.getAbsolutePath() + "\"" ); //$NON-NLS-1$//$NON-NLS-2$
commands.add( "-f=\"" + pom.getAbsolutePath() + "\"" ); //$NON-NLS-1$ //$NON-NLS-2$
return MavenCli.doMain( commands.toArray( new String[commands.size()] ), this.classWorld );
}
}
I dont know what exactly you want to do, but if you want to execute a maven plugin on a maven project the above code will work. In my case i execute a mvn dependency:unpack-dependencies command on a project.
To get the above working you need this dependency:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>3.0.3</version>
</dependency>
PS: A good resource for information about how to execute maven things from java is the implementation of the m2eclipse plugin ;)

I you really need that, of course you can. Just download sources of the plugin and look inside what's going on there. You can instantiate a proper Mojo (class that implements plugin's goal) and execute it. However, usually plugins' goals depend heavily on Maven project context that might be really hard to provide (or even mock somehow) so Mojo was able to execute without errors.
I don't know your specific situation, but I'm 99% sure that it would be really more sensible to write own implementation of something you want to achieve, potentially based on stuff you found in the plugin's source code (to not write everything on your own).

Related

Look for previous working directory to implement "cd -"

I am currently implementing a shell with limited functionality using Java programming language. The scope of the shell has restricted requirement too. The task is to model a Unix shell as much as I can.
When I am implementing the cd command option, I reference a Basic Shell Commands page, it mentions that a cd is able to go back to the last directory I am in with the command "cd -".
As I am given only a interface with the method public String execute(File presentWorkingDirectory, String stdin).
I will like to know if there is API call from Java which I can retrieve the previous working directory, or if there any implementation for this command?
I know one of the simple implementation is to declare a variable to store the previous working directory. However I am currently having the shell itself (the one that take in the command with options), and each time a command tool is executed, a new thread is created. Hence I do not think it is advisable for the "main" thread to store the previous working directory.
Update (6-Mar-'14): Thank for the suggestion! I have now discussed with the coder for shell, and have added an additional variable to store the previous working directory. Below is the sample code for sharing:
public class CdTool extends ATool implements ICdTool {
private static String previousDirectory;
//Constructor
/**
* Create a new CdTool instance so that it represents an unexecuted cd command.
*
* #param arguments
* the argument that is to be passed in to execute the command
*/
public CdTool(final String[] arguments) {
super(arguments);
}
/**
* Executes the tool with arguments provided in the constructor
*
* #param workingDir
* the current working directory path
*
* #param stdin
* the additional input from the stdin
*
* #return the message to be shown on the shell, null if there is no error
* from the command
*/
#Override
public String execute(final File workingDir, final String stdin) {
setStatusCode(0);
String output = "";
final String newDirectory;
if(this.args[0] == "-" && previousDirectory != null){
newDirectory = previousDirectory;
}
else{
newDirectory = this.args[0];
}
if( !newDirectory.equals(workingDir) &&
changeDirectory(newDirectory) == null){
setStatusCode(DIRECTORY_ERROR_CODE);
output = DIRECTORY_ERROR_MSG;
}
else{
previousDirectory = workingDir.getAbsolutePath();
output = changeDirectory(newDirectory).getAbsolutePath();
}
return output;
}
}
P.S: Please note that this is not the full implementation of the code, and this is not the full functionality of cd.
Real shell (at least Bash) shell stores current working directory path in PWD environment variable and old working directory path in OLDPWD. Rewriting PWD does not change your working directory, but rewriting OLDPWD really changes where cd - will take you.
Try this:
cd /tmp
echo "$OLDPWD" # /home/palec
export OLDPWD='/home'
cd - # changes working directory to /home
I don’t know how you implement the shell functionality (namely how you represent current working directory; usually it’s an inherent property of the process, implemented by the kernel) but I think that you really have to keep the old working directory in an extra variable.
By the way shell also forks for each command executed (except for the internal ones). Current working directory is a property of a process. When a command is started, it can change its inner current working directory, but it does not affect the shell’s one. Only cd command (which is internal) can change shell’s current working directory.
If you want to keep more than one working directory just create a LinkedList where you add each new presentWorkingDirectory at the and and if you want to return use linkedList.popLast to get the last workingDirectory.

Eclipse: saved LaunchConfiguration overrides LaunchType

Not sure if it will be Eclipse or Eclipse-plugin-dev answer.
In open-source Nodeclipse project plugin.xml defines that .coffee file can be launched as coffee, coffee --compile or Node with monitor (There are 3 defined LaunchShortcuts).
First time it work fine, but then consequent launches only repeat previous LaunchType. I have found that deleting saved LaunchConfiguration (from Run -> Run Configurations) will let it run again (and then only as this type again)
The code in question is LaunchShortcut (see snippet below), however there is no any if checking, so this behavior should be deeper in Eclipse org.eclipse.debug module.
How can saved LaunchConfiguration override LaunchType ?
/**
* Launch an file,using the file information, which means using default
* launch configurations.
*
* #param file
* #param mode
*/
private void launchFile(IFile file, String mode) throws CoreException {
// check for an existing launch config for the file
String path = file.getFullPath().toString();
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type = launchManager.getLaunchConfigurationType(Constants.LAUNCH_CONFIGURATION_TYPE_ID);
ILaunchConfiguration configuration = createLaunchConfiguration(type, path, file);
DebugUITools.launch(configuration, mode);
// then execution goes in LaunchConfigurationDelegate.java launch() method
}
/**
* Create a new configuration and set useful data.
*
* #param type
* #param path
* #param file
* #return
* #throws CoreException
*/
private ILaunchConfiguration createLaunchConfiguration(ILaunchConfigurationType type, String path, IFile file) throws CoreException {
String configname = file.getFullPath().toString().replace('/', '-');
if(configname.startsWith("-")) {
configname = configname.substring(1);
}
ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(type);
for(ILaunchConfiguration config : configs) {
if(configname.equals(config.getName())) {
return config;
}
}
// create a new configuration for the file
ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null, configname);
workingCopy.setAttribute(Constants.KEY_FILE_PATH, path);
setMoreAttributes(workingCopy);
return workingCopy.doSave();
}
protected void setMoreAttributes(ILaunchConfigurationWorkingCopy workingCopy) {
// stub for extension
}
Help! The code snippet is maybe not enough to answer the question, but references files and everything is in Github repository. The question was raised, because I am not sure if it is possible at all to have many Run Configuration for the same file. Then code snippets doesn't matter at all.
Update: Looking after a while at plugin.xml defines that .coffee file can be launched , I noticed that I am actually using the same <configurationType
id= "org.nodeclipse.debug.launch.LaunchConfigurationType" > in all 5 cases. However adding unique LaunchConfigurationType id for every launch makes no difference.
You can create the launch configuration with this:
Creating a Java application launch configuration
Launch groups can also be setle with this help:
Launch Group
Until here Im pretty sure you have knowledge about, so lets keep moving; You can have different launch configuration for the same file, thats handled with the launch group tool, what I dont get is if you want those different configuration for the same environment or not.
Also here Launch Configuration Types and here Adding launchers to the platform you cand find information about the struct of the launch type file
To finish here Interface ILaunchConfigurationTabGroup is the interface of the launch type tab group;
My Suggestion in codelines:
<extension point="org.eclipse.debug.ui.launchConfigurationTabGroups">
<launchConfigurationTabGroup
<"launchConfigurationType1"
<"/launchConfigurationType1">
<"launchConfigurationType2"
<"/launchConfigurationType2">
//and so on...
</launchConfigurationTabGroup>
</extension>

this.getClass().getResource("").getPath() returns an incorrect path

I am currently making a small simple Java program for my Computer Science Final, which needs to get the path of the current running class. The class files are in the C:\2013\game\ folder.
To get this path, I call this code segment in my main class constructor:
public game(){
String testPath = this.getClass().getResource("").getPath();
//Rest of game
}
However, this command instead returns this String: "/" despite the correct output being "C:/2013/game"
Additionally, I attempted to rectify this by using this code:
public game(){
String testPath = this.getClass().getClassLoader().getResource("").getPath();
}
This returns a NullPointerException, which originates from the fact that getClassLoader() returns null, despite working on my Eclipse IDE. Any Ideas?
If you want to load a file in the same path as the code then I suggest you put it in the same root folder as the code and not the same path as the class.
Reason : class can be inside a jar, data file can be put in same jar but its more difficult to edit and update then.
Also suggest you see the preferences class suggested in comments : http://www.javacodegeeks.com/2011/09/use-javautilprefspreferences-instead-of.html though in some cases I think its okay to have your own data/ excel/csv/ java.util.Properties file
Not sure about why it is working in eclipse but I would suggest you focus on running it from a command prompt/ terminal as that is the 'real mode' when it goes live
You could just ask for your class
String s = getClass().getName();
int i = s.lastIndexOf(".");
if(i > -1) s = s.substring(i + 1);
s = s + ".class";
System.out.println("name " +s);
Object testPath = this.getClass().getResource(s);
System.out.println(testPath);
This will give you
name TstPath.class
file:/java/Projects/tests3b/build/classes/s/TstPath.class
Which is my eclipse build path ...
need to parse this to get the path where the class was loaded.
Remember:
App could be started from elsewhere
class can be in jar then path will be different (will point to a jar and file inside that
classpaths can be many at runtime and point 1
a class might be made at runtime via network/ Proxy / injection etc and thus not have a file source, so this is not a generic solution.
think what you want to acheive at a higher level and post that question. meaning why do you want this path?
do you want the app path :-
File f = new File("./");
f.getCanonicalPath();//...
So an app can be started from folder c:\app1\run\
The jar could be at c:\app1\libsMain\myapp.jar
and a helper jar could be at c:\commonlibs\set1
So this will only tell you where the JVM found your class, that may or maynot be what you need.
if inside a jar will give you some thing like this in unix or windows
jar:file:c:\app\my.jar!/s/TstPath.class
If package is s and class is TstPath, you can be sure this will work as the class has to be there ...
now to parse this you can look for your class name and remove / or \ till you get path you want. String lastIndexOf will help
You can use :
URL classURL = getClass().getProtectionDomain().getCodeSource().getLocation();
The call to getResource([String]) requires a path relative to the folder that contains the class it is being called from. So, if you have the following, anything you pass into MyClass.class.getResource([path]); must be a valid path relative to the com/putable/ package folder and it must point to a real file:
package com.putable;
public class MyClass{}
Using the empty string simply isn't valid, because there can never be a file name that equals the empty string. But, you could do getResource(getClass().getSimpleName()). Just remove the file name from the end of the path returned by that call and you will have the class directory you want.
ClassLoader loader = Test.class.getClassLoader();
System.out.println(loader.getResource("Test.class"));
also
Test.class.getProtectionDomain().getCodeSource().getLocation().getPath());
Try this.
import java.io.File;
public class TT {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String path = TT.class.getResource("").getPath();
File file = new File(path);
System.out.println(file.getAbsolutePath());
}
}
Try use this code
public game()
{
String className = this.getClass().getSimpleName();
String testPath = this.getClass().getResource(className+".class");
System.out.println("Current Running Location is :"+testPath);
}
visit the link for more information
Find where java class is loaded from
Print out absolute path for a file in your classpath i.e. build/resources/main/someFileInClassPath.txt Disclaimer, this is similar to another solution on this page that used TT.class..., but this did not work for me instead TT..getClassLoader()... did work for me.
import java.io.File;
public class TT {
/**
* #param args
*/
public static void main(String[] args) {
String path = TT.getClassLoader().getResource("someFileInClassPath.txt").getPath();
File file = new File(path);
System.out.println(file.getAbsolutePath());
}
}
Because you used class.getResource(filePath).getpath() in a *.jar file. So the path includes "!". If you want to get content of file in *.jar file, use the following code:
MyClass.class.getResourceAsStream("/path/fileName")

java class file constructor of SslSelectChannelConnector.class not being called

I m trying to run i-jetty in eclipse using the m2e (maven) plugin. The source code of file IJettyService.java at line 530 gives makes this call
SslSelectChannelConnector sslConnector = new SslSelectChannelConnector(sslContextFactory);
Eclipse IDE here complains
The constructor SslSelectChannelConnector(SslContextFactory) is
undefined
so I used a decompiler and found out that it does exists.
/* ------------------------------------------------------------ */
public SslSelectChannelConnector()
{
this(new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH));
setSoLingerTime(30000);
}
/* ------------------------------------------------------------ */
/** Construct with explicit SslContextFactory.
* The SslContextFactory passed is added via {#link #addBean(Object)} so that
* it's lifecycle may be managed with {#link AggregateLifeCycle}.
* #param sslContextFactory
*/
public SslSelectChannelConnector(SslContextFactory sslContextFactory)
{
_sslContextFactory = sslContextFactory;
addBean(_sslContextFactory);
setUseDirectBuffers(false);
setSoLingerTime(30000);
}
I don't understand why its behaving this way . Did anyone came across similar problem?
from what you posted here this should work. maybe you have an older version of the jetty library on your classpath? try new SslSelectChannelConnector( null ) and see what happens.

Dynamically adding mojo-generated code to source path

I have authored a mojo that generates code and sticks it under {root}/target/generated-sources/foo. When I execute:
mvn clean install
I get errors indicating that the generated sources are not being included in the build path (the generated files are there, but not being picked up in the compile phase). I understand from this answer that I need to dynamically add {root}/target/generated-sources/foo as a source directory for the POM. Problem is, I haven't been able to track down any information on how to do this.
As a backup plan, I intend to use the Build Helper Maven Plugin, but I was hoping to do this automatically in my mojo if possible.
I prefer to add this to my Mojo:
/**
* The current project representation.
* #parameter expression="${project}"
* #required
* #readonly
*/
private MavenProject project;
/**
* Directory wherein generated source will be put; main, test, site, ... will be added implictly.
* #parameter expression="${outputDir}" default-value="${project.build.directory}/src-generated"
* #required
*/
private File outputDir;
Obviously you can change the default-value to match your own pattern.
And then in the execute() method:
if (!settings.isInteractiveMode()) {
LOG.info("Adding " + outputDir.getAbsolutePath() + " to compile source root");
}
project.addCompileSourceRoot(outputDir.getAbsolutePath());

Categories

Resources