/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.scanner.embedder;
import org.apache.maven.execution.MavenExecutionRequestPopulator;
import org.apache.tools.ant.AntClassLoader;
import org.codehaus.plexus.ContainerConfiguration;
import org.codehaus.plexus.DefaultContainerConfiguration;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.eclipse.aether.RepositorySystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonatype.plexus.components.cipher.PlexusCipher;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
public class MavenEmbedderUtils {
private static final Logger log = LoggerFactory.getLogger( MavenEmbedderUtils.class );
private static boolean isIBM_JVM = System.getProperty("java.vendor").toLowerCase().contains("ibm");
private MavenEmbedderUtils() { }
public static boolean enforceWiredComponentProvider = false; // for test purposes only
public static ComponentProvider buildComponentProvider(ClassLoader mavenClassLoader, ClassLoader parent, MavenRequest mavenRequest) throws MavenEmbedderException {
if (enforceWiredComponentProvider || MavenEmbedderUtils.class.getClassLoader().getClass().toString().contains( "Bundle" )) {
log.debug( "In OSGi: using programmatically wired maven parser" );
return new WiredComponentProvider();
}
log.debug( "Not in OSGi: using plexus based maven parser" );
return new PlexusComponentProvider( mavenClassLoader, parent, mavenRequest );
}
public static ClassRealm buildClassRealm(File mavenHome, ClassWorld world, ClassLoader parentClassLoader )
throws MavenEmbedderException {
if ( mavenHome == null ) {
throw new IllegalArgumentException( "mavenHome cannot be null" );
}
if ( !mavenHome.exists() ) {
throw new IllegalArgumentException( "mavenHome '" + mavenHome.getPath() + "' doesn't seem to exist on this node (or you don't have sufficient rights to access it)" );
}
File libDirectory = new File( mavenHome, "lib" );
if ( !libDirectory.exists() ) {
throw new IllegalArgumentException( mavenHome.getPath() + " doesn't have a 'lib' subdirectory - thus cannot be a valid maven installation!" );
}
File[] jarFiles = libDirectory.listFiles( new FilenameFilter()
{
public boolean accept( File dir, String name ) {
return name.endsWith( ".jar" );
}
} );
AntClassLoader antClassLoader = new AntClassLoader( Thread.currentThread().getContextClassLoader(), false );
for ( File jarFile : jarFiles ) {
antClassLoader.addPathComponent( jarFile );
}
if (world == null) {
world = new ClassWorld();
}
ClassRealm classRealm = createClassRealm( world, "plexus.core", parentClassLoader == null ? antClassLoader : parentClassLoader );
for ( File jarFile : jarFiles ) {
try {
classRealm.addURL( jarFile.toURI().toURL() );
} catch ( MalformedURLException e ) {
throw new MavenEmbedderException( e.getMessage(), e );
}
}
return classRealm;
}
public static PlexusContainer buildPlexusContainer(File mavenHome, MavenRequest mavenRequest) throws MavenEmbedderException {
ClassWorld world = new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader());
ClassRealm classRealm = MavenEmbedderUtils.buildClassRealm( mavenHome, world, Thread.currentThread().getContextClassLoader() );
DefaultContainerConfiguration conf = new DefaultContainerConfiguration();
conf.setContainerConfigurationURL( mavenRequest.getOverridingComponentsXml() )
.setRealm( classRealm )
.setClassWorld(world)
.setClassPathScanning(mavenRequest.getContainerClassPathScanning())
.setComponentVisibility(mavenRequest.getContainerComponentVisibility());
return buildPlexusContainer(mavenRequest,conf);
}
public static PlexusContainer buildPlexusContainer(ClassLoader mavenClassLoader, ClassLoader parent, MavenRequest mavenRequest) throws MavenEmbedderException {
DefaultContainerConfiguration conf = new DefaultContainerConfiguration();
conf.setAutoWiring( mavenRequest.isContainerAutoWiring() )
.setClassPathScanning( mavenRequest.getContainerClassPathScanning() )
.setComponentVisibility( mavenRequest.getContainerComponentVisibility() )
.setContainerConfigurationURL(mavenRequest.getOverridingComponentsXml());
ClassWorld classWorld = new ClassWorld();
ClassRealm parentRealm = createParentRealm(classWorld, parent,
MavenExecutionRequestPopulator.class,
RepositorySystem.class,
PlexusCipher.class);
ClassRealm classRealm = createClassRealm( classWorld, "maven", mavenClassLoader );
classRealm.setParentRealm( parentRealm );
conf.setRealm( classRealm );
conf.setClassWorld( classWorld );
return buildPlexusContainer(mavenRequest,conf);
}
private static ClassRealm createParentRealm(ClassWorld classWorld, ClassLoader parent, Class... requiredClasses) {
ClassLoader parentCL = parent == null ? Thread.currentThread().getContextClassLoader() : parent;
Set<ClassLoader> usedCLs = new HashSet<ClassLoader>();
usedCLs.add(parentCL);
ClassRealm parentRealm = createClassRealm( classWorld, "maven-parent", parentCL);
int i = 1;
ClassRealm lastParent = parentRealm;
for ( Class c : requiredClasses ) {
if ( usedCLs.add(c.getClassLoader()) ) {
ClassRealm newParent = createClassRealm( classWorld, "maven-parent" + i++, c.getClassLoader() );
lastParent.setParentRealm( newParent );
lastParent = newParent;
}
}
return parentRealm;
}
private static PlexusContainer buildPlexusContainer(MavenRequest mavenRequest,ContainerConfiguration containerConfiguration )
throws MavenEmbedderException {
try {
DefaultPlexusContainer plexusContainer = new DefaultPlexusContainer( containerConfiguration );
if (mavenRequest.getMavenLoggerManager() != null) {
plexusContainer.setLoggerManager( mavenRequest.getMavenLoggerManager() );
}
if (mavenRequest.getLoggingLevel() > 0) {
plexusContainer.getLoggerManager().setThreshold( mavenRequest.getLoggingLevel() );
}
return plexusContainer;
} catch ( PlexusContainerException e ) {
throw new MavenEmbedderException( e.getMessage(), e );
}
}
private static ClassRealm createClassRealm(ClassWorld world, String id, ClassLoader baseClassLoader) {
return isIBM_JVM ? new IBMClassRealm(world, id, baseClassLoader) : new ClassRealm(world, id, baseClassLoader);
}
public static class IBMClassRealm extends ClassRealm {
public IBMClassRealm(ClassWorld world, String id, ClassLoader baseClassLoader) {
super(world, id, baseClassLoader);
}
@Override
public Enumeration findResources(String name) throws IOException {
return getParent().getResources(name);
}
}
}