001package org.apache.archiva.common.plexusbridge; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import com.google.inject.AbstractModule; 023import org.apache.maven.bridge.MavenRepositorySystem; 024import org.codehaus.plexus.DefaultContainerConfiguration; 025import org.codehaus.plexus.DefaultPlexusContainer; 026import org.codehaus.plexus.PlexusConstants; 027import org.codehaus.plexus.PlexusContainerException; 028import org.codehaus.plexus.classworlds.ClassWorld; 029import org.codehaus.plexus.classworlds.realm.ClassRealm; 030import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 031import org.eclipse.sisu.inject.TypeArguments; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034import org.springframework.stereotype.Service; 035 036import javax.annotation.PostConstruct; 037import javax.inject.Inject; 038import java.lang.reflect.Method; 039import java.net.URL; 040import java.net.URLClassLoader; 041import java.util.List; 042import java.util.Map; 043 044/** 045 * Simple component which will initiate the plexus shim component 046 * to see plexus components inside a guice container.<br> 047 * So move all of this here to be able to change quickly if needed. 048 * 049 * @author Olivier Lamy 050 */ 051@Service( "plexusSisuBridge" ) 052public class PlexusSisuBridge 053{ 054 055 private MavenRepositorySystem mavenRepositorySystem = new MavenRepositorySystem(); 056 057 private Logger log = LoggerFactory.getLogger( getClass() ); 058 059 private boolean containerAutoWiring = true; 060 061 private String containerClassPathScanning = PlexusConstants.SCANNING_INDEX;// PlexusConstants.SCANNING_ON; 062 063 private String containerComponentVisibility = PlexusConstants.REALM_VISIBILITY; 064 065 private URL overridingComponentsXml; 066 067 private ClassRealm containerRealm; 068 069 private DefaultPlexusContainer plexusContainer; 070 071 class InternalBinder extends AbstractModule { 072 073 @Override 074 protected void configure( ) 075 { 076 bind( MavenRepositorySystem.class ).toInstance( mavenRepositorySystem ); 077 // bind(TypeArguments.implicitKey( MavenRepositorySystem.class )).to(MavenRepositorySystem.class); 078 } 079 } 080 081 @PostConstruct 082 public void initialize() 083 throws PlexusSisuBridgeException 084 { 085 DefaultContainerConfiguration conf = new DefaultContainerConfiguration(); 086 087 conf.setAutoWiring( containerAutoWiring ); 088 conf.setClassPathScanning( containerClassPathScanning ); 089 conf.setComponentVisibility( containerComponentVisibility ); 090 091 conf.setContainerConfigurationURL( overridingComponentsXml ); 092 093 ClassWorld classWorld = new ClassWorld(); 094 095 ClassLoader tccl = Thread.currentThread().getContextClassLoader(); 096 097 containerRealm = new ClassRealm( classWorld, "maven", tccl ); 098 099 // olamy hackhish but plexus-sisu need a URLClassLoader with URL filled 100 101 if ( tccl instanceof URLClassLoader ) 102 { 103 URL[] urls = ( (URLClassLoader) tccl ).getURLs(); 104 for ( URL url : urls ) 105 { 106 containerRealm.addURL( url ); 107 log.debug("Added url {}", url); 108 } 109 } 110 111 conf.setRealm( containerRealm ); 112 113 //conf.setClassWorld( classWorld ); 114 115 ClassLoader ori = Thread.currentThread().getContextClassLoader(); 116 117 try 118 { 119 Thread.currentThread().setContextClassLoader( containerRealm ); 120 InternalBinder binder = new InternalBinder( ); 121 plexusContainer = new DefaultPlexusContainer( conf, binder ); 122 123 } 124 catch ( PlexusContainerException e ) 125 { 126 throw new PlexusSisuBridgeException( e.getMessage(), e ); 127 } catch (Throwable ex) { 128 log.error("PlexusSisuBridge initialization failed {}", ex.getMessage(), ex); 129 throw new PlexusSisuBridgeException( ex.getMessage(), ex ); 130 } 131 finally 132 { 133 Thread.currentThread().setContextClassLoader( ori ); 134 } 135 } 136 137 138 private URL[] getClassLoaderURLs( ClassLoader classLoader ) 139 { 140 try 141 { 142 // can be WebappClassLoader when using tomcat maven plugin 143 //java.net.URL[] getURLs 144 Method method = classLoader.getClass().getMethod( "getURLs", new Class[]{ } ); 145 if ( method != null ) 146 { 147 return (URL[]) method.invoke( classLoader ); 148 } 149 } 150 catch ( Exception e ) 151 { 152 log.info( "ignore issue trying to find url[] from classloader {}", e.getMessage() ); 153 } 154 return new URL[]{ }; 155 } 156 157 public <T> T lookup( Class<T> clazz ) 158 throws PlexusSisuBridgeException 159 { 160 ClassLoader ori = Thread.currentThread().getContextClassLoader(); 161 try 162 { 163 Thread.currentThread().setContextClassLoader( containerRealm ); 164 return plexusContainer.lookup( clazz ); 165 } 166 catch ( ComponentLookupException e ) 167 { 168 throw new PlexusSisuBridgeException( e.getMessage(), e ); 169 } 170 finally 171 { 172 Thread.currentThread().setContextClassLoader( ori ); 173 } 174 } 175 176 public <T> T lookup( Class<T> clazz, String hint ) 177 throws PlexusSisuBridgeException 178 { 179 ClassLoader ori = Thread.currentThread().getContextClassLoader(); 180 181 try 182 { 183 Thread.currentThread().setContextClassLoader( containerRealm ); 184 return plexusContainer.lookup( clazz, hint ); 185 } 186 catch ( ComponentLookupException e ) 187 { 188 throw new PlexusSisuBridgeException( e.getMessage(), e ); 189 } 190 finally 191 { 192 Thread.currentThread().setContextClassLoader( ori ); 193 } 194 } 195 196 public <T> List<T> lookupList( Class<T> clazz ) 197 throws PlexusSisuBridgeException 198 { 199 ClassLoader ori = Thread.currentThread().getContextClassLoader(); 200 201 try 202 { 203 Thread.currentThread().setContextClassLoader( containerRealm ); 204 return plexusContainer.lookupList( clazz ); 205 } 206 catch ( ComponentLookupException e ) 207 { 208 throw new PlexusSisuBridgeException( e.getMessage(), e ); 209 } 210 finally 211 { 212 Thread.currentThread().setContextClassLoader( ori ); 213 } 214 } 215 216 public <T> Map<String, T> lookupMap( Class<T> clazz ) 217 throws PlexusSisuBridgeException 218 { 219 ClassLoader ori = Thread.currentThread().getContextClassLoader(); 220 221 try 222 { 223 Thread.currentThread().setContextClassLoader( containerRealm ); 224 return plexusContainer.lookupMap( clazz ); 225 } 226 catch ( ComponentLookupException e ) 227 { 228 throw new PlexusSisuBridgeException( e.getMessage(), e ); 229 } 230 finally 231 { 232 Thread.currentThread().setContextClassLoader( ori ); 233 } 234 } 235}