Maven: How to check if an artifact exists? - maven-2

How do I check from within a Mojo if an artifact already exists in the local repository?
I'm installing large binaries into the local Maven repository and I need to know if they already exist before attempting to download them.

Solved with the help of http://docs.codehaus.org/display/MAVENUSER/Mojo+Developer+Cookbook
/**
* The local maven repository.
*
* #parameter expression="${localRepository}"
* #required
* #readonly
*/
#SuppressWarnings("UWF_UNWRITTEN_FIELD")
private ArtifactRepository localRepository;
/**
* #parameter default-value="${project.remoteArtifactRepositories}"
* #required
* #readonly
*/
private List<?> remoteRepositories;
/**
* Resolves Artifacts in the local repository.
*
* #component
*/
private ArtifactResolver artifactResolver;
/**
* #component
*/
private ArtifactFactory artifactFactory;
[...]
Artifact artifact = artifactFactory.createArtifactWithClassifier(groupId, artifactId, version, packagingType, classifier);
boolean artifactExists;
try
{
// Downloads the remote artifact, if necessary
artifactResolver.resolve(artifact, remoteRepositories, localRepository);
artifactExists = true;
}
catch (ArtifactResolutionException e)
{
throw new MojoExecutionException("", e);
}
catch (ArtifactNotFoundException e)
{
artifactExists = false;
}
if (artifactExists)
System.out.println("Artifact found at: " + artifact.getFile());
If you want to check if a remote artifact exists without downloading it, you can use the Aether library to do the following (based on http://dev.eclipse.org/mhonarc/lists/aether-users/msg00127.html):
MavenDefaultLayout defaultLayout = new MavenDefaultLayout();
RemoteRepository centralRepository = new RemoteRepository.Builder("central", "default", "http://repo1.maven.org/maven2/").build();
URI centralUri = URI.create(centralRepository.getUrl());
URI artifactUri = centralUri.resolve(defaultLayout.getPath(artifact));
HttpURLConnection connection = (HttpURLConnection) artifactUri.toURL().openConnection();
connection.setRequestMethod("HEAD");
connection.connect();
boolean artifactExists = connection.getResponseCode() != 404;
With following dependency: org.eclipse.aether:aether-util:0.9.0.M2 and following imports:
import java.net.HttpURLConnection;
import java.net.URI;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.util.repository.layout.MavenDefaultLayout;

Since the answer which is accepted as correct, is no longer pointing to valid URL-s and because I know a better way, I am posting a new answer.
There's the wagon-maven-plugin, which has an exist goal. The documentation is a bit inaccurate, but you can use that.
Code-wise, you can have a look at the DefaultWagonDownload class' exists method:
/**
*
* #param wagon - a Wagon instance
* #param resource - Remote resource to check
* #throws WagonException
*/
public boolean exists( Wagon wagon, String resource )
throws WagonException
{
return wagon.resourceExists( resource );
}

If you expect your artifacts being present in a remote maven repository, I'd suggest you simply use the copy mojo of the maven-dependency-plugin.
It will use normal maven resolution mechanism for retrieving artifacts so will not download something that is already in the local repository.
In a plugin, when using maven 2 (not sure about maven3) you can use the mojo executor to call a mojo from within you code easily.

Related

After log4j changes Hive -e returns additional warning which has impact on the scripts - WARN JNDI lookup class is not available because this JRE

In project we use some technical scripts in python with usage of Subprocess to extract some data from hive, run msck repair table etc ( I know we should switch to beeline :p) unfortunately after the issue with log4j in every output we started to get something like this:
WARN JNDI lookup class is not available because this JRE does not support JNDI. JNDI string lookups will not be available, continuing configuration. Ignoring java.lang.ClassNotFoundException: org.apache.logging.log4j.core.lookup.JndiLookup
Our Infra team is not allowing us so far to introduce any changes in the log4j properties.
As we have multiple technical scripts in many places we would like to find simple solution for time being (till we can fix it on infra level).
Tried:
usage hive -s
settings hive.root.looger to console (I think somehow log4j does not understand this is warning)
Guys does anyone know how we can fix it (preferably during runtime)
Thanks!
One way to fix this is to patch your log4j-core with a nerfed version of JndiLookup rather then removing the class entirely with zip -d .... A simple version of that class could look something like this:
package org.apache.logging.log4j.core.lookup;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
#Plugin(name = "jndi", category = StrLookup.CATEGORY)
public class JndiLookup extends AbstractLookup {
#Override
public String lookup(final LogEvent event, final String key) {
return null;
}
}
Here's a gist with a bash script that automates the compile and replace process:
https://gist.github.com/xyu/348e9cecf25e09bef997a58e1901481b
I looked at what changes were introduced to JndiLookup.java from version 2.0 through 2.14.1 (just before the 2.15 release). No significant changes. It appears regardless of what log4j2 version your application is using you can craft a JndiLookup.java mock class that simply calls LOGGER.warn and nothing else when JndiLookup.lookup is called. You would then replace JndiLookup.class instead of removing it from the jar. The class will load, but do nothing of meaning besides give you a log message you can monitor in your application logs, if doing so adds value.
$git diff rel/2.0 rel/2.14.1 log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java
index 77749e015..30e65ad24 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java
## -16,53 +16,47 ##
*/
package org.apache.logging.log4j.core.lookup;
-import javax.naming.Context;
-import javax.naming.InitialContext;
+import java.util.Objects;
+
import javax.naming.NamingException;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.util.Closer;
+import org.apache.logging.log4j.core.net.JndiManager;
+import org.apache.logging.log4j.status.StatusLogger;
/**
* Looks up keys from JNDI resources.
*/
-#Plugin(name = "jndi", category = "Lookup")
-public class JndiLookup implements StrLookup {
+#Plugin(name = "jndi", category = StrLookup.CATEGORY)
+public class JndiLookup extends AbstractLookup {
- /** JNDI resourcce path prefix used in a J2EE container */
- static final String CONTAINER_JNDI_RESOURCE_PATH_PREFIX = "java:comp/env/";
+ private static final Logger LOGGER = StatusLogger.getLogger();
+ private static final Marker LOOKUP = MarkerManager.getMarker("LOOKUP");
- /**
- * Looks up the value of the JNDI resource.
- * #param key the JNDI resource name to be looked up, may be null
- * #return The value of the JNDI resource.
- */
- #Override
- public String lookup(final String key) {
- return lookup(null, key);
- }
+ /** JNDI resource path prefix used in a J2EE container */
+ static final String CONTAINER_JNDI_RESOURCE_PATH_PREFIX = "java:comp/env/";
/**
* Looks up the value of the JNDI resource.
* #param event The current LogEvent (is ignored by this StrLookup).
* #param key the JNDI resource name to be looked up, may be null
- * #return The value of the JNDI resource.
+ * #return The String value of the JNDI resource.
*/
#Override
public String lookup(final LogEvent event, final String key) {
if (key == null) {
return null;
}
-
- Context ctx = null;
- try {
- ctx = new InitialContext();
- return (String) ctx.lookup(convertJndiName(key));
+ final String jndiName = convertJndiName(key);
+ try (final JndiManager jndiManager = JndiManager.getDefaultManager()) {
+ return Objects.toString(jndiManager.lookup(jndiName), null);
} catch (final NamingException e) {
+ LOGGER.warn(LOOKUP, "Error looking up JNDI resource [{}].", jndiName, e);
return null;
- } finally {
- Closer.closeSilently(ctx);
}
}
## -73,11 +67,10 ## public class JndiLookup implements StrLookup {
* #param jndiName The name of the resource.
* #return The fully qualified name to look up.
*/
- private String convertJndiName(String jndiName) {
+ private String convertJndiName(final String jndiName) {
if (!jndiName.startsWith(CONTAINER_JNDI_RESOURCE_PATH_PREFIX) && jndiName.indexOf(':') == -1) {
- jndiName = CONTAINER_JNDI_RESOURCE_PATH_PREFIX + jndiName;
+ return CONTAINER_JNDI_RESOURCE_PATH_PREFIX + jndiName;
}
-
return jndiName;
}
}

Symfony3 Profiler Storage

in the Docs
http://symfony.com/doc/master/cookbook/profiler/storage.html
you still can find Information about Profiler Storage.
I just checked the code and could not find any clues how to set a custom storage.
I also find no Documentation stating this except some #legacy notes in the Original Source at 2.8.
Is there a Reason why this was removed?
I was using redis to store this data with a lifetime of eta 1hour.
Now I need to run a manual cleanup to whipe all files in that directory.
If anybody has some clues or hints on helping me with this issue are appreceated ^^
Chris
Thanks to the Tip of Matteo I was able to solve this quite flexible.
The Team of Symfony removed this, because it was hard coded into the Profiler Subsystem.
Instead of fixing this by adding a class parameter I had to solve it. :)
Ok, here is the code, If somebody needs this to.
First of all we need the Original Classes from Symfony 2.7 (at least I reused them as I only need the Redis Option ( I use it, because I can Compress the data using igbinary)
Next you need to implement a Compiler Pass.
namespace AcmeBunlde\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class ProfilerCompilerPass implements CompilerPassInterface
{
/**
* You can modify the container here before it is dumped to PHP code.
*
* #param ContainerBuilder $container
*/
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('profiler');
$definition->addArgument('%acmebundle.profiler.defaultEnabled%');
$definition->addArgument('%acmebundle.profiler.class%');
$definition->addArgument('%acmebundle.profiler.dsn%');
$definition->addArgument('%acmebundle.profiler.username%');
$definition->addArgument('%acmebundle.profiler.password%');
$definition->addArgument('%acmebundle.profiler.ttl%');
$definition->setClass('acmebundle\Profiler\Profiler');
}
}
This needs to be loaded inside the Bundle Loader:
public function build(ContainerBuilder $container)
{
...
$container->addCompilerPass(new ProfilerCompilerPass());
}
After this we need to add the Configuration for the New Profiler Storage in the DependencyInjection Folder.
namespace AcmeBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
* #author Chris
*/
class Configuration implements ConfigurationInterface
/**
* {#inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('library');
$rootNode
->children()
->arrayNode('profiler')
->addDefaultsIfNotSet()
->children()
->booleanNode('defaultStorage')
->defaultTrue()
->end()
->scalarNode('class')
->defaultValue('')
->end()
->scalarNode('dsn')
->defaultValue('')
->end()
->scalarNode('username')
->defaultValue('')
->end()
->scalarNode('password')
->defaultValue('')
->end()
->scalarNode('ttl')
->defaultValue('3600')
->end()
->end()
->end();
return $treeBuilder();
}
}
Now set the Default Values in The Dependency Injection Bundle Loader
<?php
namespace AcmeBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html}
* #author Chris
*/
class AcmeExtension extends Extension
{
/**
* {#inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
...
$container->setParameter('acmebundle.profiler.defaultEnabled',$config['profiler']['defaultStorage']);
$container->setParameter('acmebundle.profiler.class',$config['profiler']['class']);
$container->setParameter('acmebundle.profiler.dsn',$config['profiler']['dsn']);
$container->setParameter('acmebundle.profiler.username',$config['profiler']['username']);
$container->setParameter('acmebundle.profiler.password',$config['profiler']['password']);
$container->setParameter('acmebundle.profiler.ttl',$config['profiler']['ttl']);
...
}
...
}
As Last Step you need to build a basic container for adding the new Profiler Handler.
I have choosen to implement it not to complex:
<?php
namespace AcmeBundle\Profiler;
use Psr\Log\LoggerInterface;
use \Symfony\Component\HttpKernel\Profiler\Profiler as ProfilerSrc;
use Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface;
/**
* Profiler.
*/
class Profiler extends ProfilerSrc
{
public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger, $defaultEnabled=true,$class=null,$dsn=null,$username=null,$password=null,$ttl=3600)
{
if($defaultEnabled!==true)
{
$storage = new $class($dsn,$username,$password,$ttl);
}
parent::__construct($storage , $logger);
}
}
I have also added a Library to define the Constructor of the Storage Interface.
<?php
namespace AcmeBundle\Profiler;
use Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface as ProfilerStorageSource;
interface ProfilerStorageInterface extends ProfilerStorageSource
{
/**
* ProfilerStorageInterface constructor.
*
* #param $dsn
* #param $username
* #param $password
* #param $ttl
*/
public function __construct($dsn,$username,$password,$ttl);
}
All you need to do now is to define some Options in your config_dev.yml file.
acmebundle:
profiler:
defaultEnabled: false
class:CLASSNAME INCLUDING NAMESPACE
dsn: redis://localhost/1
username:
password
ttl: 3600
with defaultEnabled = true you can reenable to Original Handler.
the rest is, I believe self explaining.
username + password is from the original feature set.
(ttl == lifetime)
I hope this helps somebody else as well :)
Is marked as deprecated since 2.8 with the suppression in the 3.0. I can't find any motivation about in the PR. The doc is not yet updated as you mention.
The only suggestion is about a comment in this issue:
If you want to use your own implementation of a profiler storage,
then just override the profile.storage service.
Hope this help

Eclipse: Within a plug-in, how to access another plug-ins preference store?

I have an Eclipse plug-in with a checkbox in the plug-in's preference page.
This checkbox is used for enabling and disabling an editor, which is being launched from this plug-in.
However, the problem is, I would also like to be able to enable and disable this 'editor-launch' from another plug-in, by having actions which change the value of the checkbox in the above mentioned preference page.
Here's the problem, how do I access that local preference store from another plug-in?
I've tried things like..
View myView = (View) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView("ViewID");
But this 'myView' always seems to be null.. And also, what would I do with the view since it's the Plug-in I want.
Platform.getBundle('bundleName')...
Same here, want the Plugin, not the bundle corresponding to is.
No matter what I try nothing seems to work.
Does anyone have any ideas?
There are two ways of doing this:
Please refer to http://www.vogella.com/tutorials/EclipsePreferences/article.html#preferences_pluginaccess
Using .getPluginPreferences(). For example, there is a plugin class "com.xxx.TestPlugin" which extends org.eclipse.ui.plugin.AbstractUIPlugin.Plugin, in order to get access to the preferences of TestPlugin. The plugin code could be below:
public class TestPlugin extends AbstractUIPlugin {
private static TestPlugin plugin;
public static final String PREF_TEST = "test_preference";
/**
* The constructor.
*/
public TestPlugin() {
plugin = this;
}
/**
* This method is called upon plug-in activation
*/
public void start(BundleContext context) throws Exception {
super.start(context);
}
/**
* This method is called when the plug-in is stopped
*/
public void stop(BundleContext context) throws Exception {
super.stop(context);
plugin = null;
}
/**
* Returns the shared instance.
*/
public static TestPlugin getDefault() {
return plugin;
}
}
To access the preference of TestPlugin, the code could be:
TestPlugin.getDefault().getPluginPreferences().getDefaultBoolean(TestPlugin.PREF_TEST);
Or have a look at this answer: Writing Eclipse plugin to modify Editor Preferences
This thread recommend the use of a Service tracker:
ServiceTracker tracker = new ServiceTracker(ToolkitPlugin.getDefault().getBundle().getBundleContext(),
IProxyService.class.getName(), null);
tracker.open();
proxyService = (IProxyService) tracker.getService();
proxyService.addProxyChangeListener(this);
This may work.
Prefs stores are found per plugin. This is one way to get a prefs store for the plugin whose activator class is ActivatorA.
IPreferenceStore store = ActivatorA.getDefault().getPreferenceStore();
If you want another plugin to refer to the same store, perhaps you could expose some api on ActivatorA for it to get there, e.g.
public IPreferenceStore getSharedPrefs() {
return ActivatorA.getDefault().getPreferenceStore();
}
The second plugin would find the shared store by doing this
IPreferenceStore sharedPrefs = ActivatorA.getSharedPrefs();
Good luck.

How to Take Taking online Hot Backup of lucene FileDirecotry index?

I am thinking of adding JMX bean for taking hot backup of lucene index.
LuceneMBean mbean = new LuceneMBeanImpl();
ObjectName name = new ObjectName("indexing.index:type=lucene");
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
mbs.registerMBean(mbean, name);
LuceneMBean will have method called backupIndex(String directory).
I have gone through lucene docs and I found out copy() method of Directory. If I have Writer Open on directory will this method will work? Basically my code snippet is like follows :
public class LuceneMBeanImpl implements LuceneMBean{
public void backupIndex(String directory){
Directory fileDirectory = FSDirectory.getDirectory(directory);
Directory.copy(masterDirectory, fileDirectory,false);
}
}
I think an open Writer should be okay, but you definitely can't copy while another thread is modifying the index, or you may get a FileNotFoundException. From the source:
/**
* Copy contents of a directory src to a directory dest.
* If a file in src already exists in dest then the
* one in dest will be blindly overwritten.
*
* <p><b>NOTE:</b> the source directory cannot change
* while this method is running. Otherwise the results
* are undefined and you could easily hit a
* FileNotFoundException.
*
* #param src source directory
* #param dest destination directory
* #param closeDirSrc if <code>true</code>, call {#link #close()} method on source directory
* #throws IOException
*/
public static void copy(Directory src, Directory dest, boolean closeDirSrc) throws IOException {

Collapsing parent POM into the child

Given a maven project with a parent POM - including mostly plugin and dependency versions - how can I generate a POM which takes the information from the parent, places it into the child and removes the reference to the parent?
Ideally this would be done with the maven-assembly-plugin.
Update: I need this done automatically, since manually it's boring and tedious.
Update 2: I'm preparing the source code for an external and want to deliver only one project, not the whole family.
I had a similar issue a while back, you can avoid Maven substituting for the properties and resolving paths etc. by defining a new Maven plugin to do the following.
Resolve each parent using the standard artifact factory
Read each pom file (without resolving it) using the MavenXpp3Reader
Merge the unresolved projects
Write the merged project to a file
Here is some test code I used to prove the process for myself, you'd obviously need to wrap this up in a Maven plugin and bind that to some phase of your process. The resolved pom is output to the output directory (i.e. target) with the name resolved-pom.xml by default, these two properties can be overridden with the usual Maven plugin configuration approach by setting the "outputDir" and/or "pomfileName" properties.
package name.seller.rich;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Stack;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.inheritance.ModelInheritanceAssembler;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* #goal output-project
* #phase process-resources
* #requiresProject true
*/
public class OutputResolvedProjectMojo extends AbstractMojo {
/**
* Used to look up overlay the parent models on the project's model.
*
* #parameter expression=
* "${component.org.apache.maven.project.inheritance.ModelInheritanceAssembler}"
* #required
* #readonly
*/
private ModelInheritanceAssembler modelInheritanceAssembler;
/**
* Used to look up Artifacts in the remote repository.
*
* #parameter expression=
* "${component.org.apache.maven.artifact.factory.ArtifactFactory}"
* #required
* #readonly
*/
protected org.apache.maven.artifact.factory.ArtifactFactory factory;
/**
* Used to look up Artifacts in the remote repository.
*
* #parameter expression=
* "${component.org.apache.maven.artifact.resolver.ArtifactResolver}"
* #required
* #readonly
*/
protected org.apache.maven.artifact.resolver.ArtifactResolver artifactResolver;
/**
* List of Remote Repositories used by the resolver
*
* #parameter expression="${project.remoteArtifactRepositories}"
* #readonly
* #required
*/
protected java.util.List remoteRepos;
/**
* Location of the local repository.
*
* #parameter expression="${localRepository}"
* #readonly
* #required
*/
protected org.apache.maven.artifact.repository.ArtifactRepository local;
/**
* #parameter expression="${project}"
* #required
* #readonly
*/
private MavenProject mavenProject;
/**
* The directory to output the resolved project to.
*
* #parameter expression="${project.build.directory}"
*/
private File outputDir;
/**
* The directory to output the resolved project to.
*
* #parameter expression="resolved-pom.xml"
*/
private String pomfileName;
public void execute() throws MojoExecutionException, MojoFailureException {
MavenProject parentProject = mavenProject.getParent();
// get the unresolved project by reading the file
MavenProject bareProject = readBareProject(mavenProject.getFile());
Stack hierarchy = new Stack();
hierarchy.push(bareProject);
try {
while (parentProject != null) {
try {
// get Maven to resolve the parent artifact (download if
// needed)
Artifact pomArtifact = this.factory.createArtifact(
parentProject.getGroupId(), parentProject
.getArtifactId(), parentProject
.getVersion(), "", "pom");
artifactResolver.resolve(pomArtifact, this.remoteRepos,
this.local);
// get the file from the local repository and read the bare
// project
File parentPomFile = pomArtifact.getFile();
parentProject = readBareProject(parentPomFile);
hierarchy.push(parentProject);
parentProject = parentProject.getParent();
} catch (ArtifactResolutionException e) {
getLog().error("can't resolve parent pom", e);
} catch (ArtifactNotFoundException e) {
getLog().error("can't resolve parent pom", e);
}
}
// merge each model starting with the oldest ancestors
MavenProject currentParent = (MavenProject) hierarchy.pop();
MavenProject currentProject = null;
while (hierarchy.size() != 0) {
currentProject = (MavenProject) hierarchy.pop();
modelInheritanceAssembler.assembleModelInheritance(
currentProject.getModel(), currentParent.getModel());
currentParent = currentProject;
}
// spit the merged model to the output file.
Writer writer = getWriter(outputDir, pomfileName);
if (writer != null) {
currentProject.writeModel(writer);
writer.close();
}
} catch (IOException e) {
getLog().error("can't write resolved pom", e);
}
}
/**
* Creates and returns a writer for outputting the project to a pom file.
*
* #param logDir
* the directory to output the file to.
* #param logFileName
* name of the log file
* #return the writer.
* #throws IOException
* if the writer cannot be created.
*/
private Writer getWriter(final File logDir, final String logFileName)
throws IOException {
if (!logDir.exists()) {
logDir.mkdirs();
}
File pomLog = new File(logDir, logFileName);
if (!pomLog.exists()) {
pomLog.createNewFile();
}
return new FileWriter(pomLog);
}
/**
* Read the mavenProject without resolving any inherited settings.
*
* #return the MavenProject for the project's POM
* #throws MojoExecutionException
* if the POM can't be parsed.
*/
MavenProject readBareProject(final File file) {
MavenXpp3Reader reader = new MavenXpp3Reader();
Model model = null;
try {
model = reader.read(new FileReader(file));
} catch (IOException e) {
getLog().error("can't read pom file", e);
} catch (XmlPullParserException e) {
getLog().error("can't read pom file", e);
}
return new MavenProject(model);
}
}
Would mvn help:effective-pom do what you need? You can send the output to a file with -Doutput=new-pom.xml.
If you don't want a parent you can try the BOM (Bill of materials) pattern and select that pom for import in your dependancy management section.
Since you want no references to anything else, you will need to build an app to parse the xml from the "parents" and then write them to the target pom file in the dependencies section. I don't think there is any plugin to do what you want since it seems to go against the very core of how maven is supposed to help you. The whole point of maven is so that you can include all your dependancies using inheritance or importing them with the import scope.
Another option, but I think you've excluded it, is to maintain your releasable POM file separately. Though I think you may find an easier time with this if you reference LATEST or SNAPSHOTS and then use the release plugin to resolve them to released versions.