This project has retired. For details please refer to its Attic page.
Source code
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}