001    package 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    
022    import org.codehaus.plexus.DefaultContainerConfiguration;
023    import org.codehaus.plexus.DefaultPlexusContainer;
024    import org.codehaus.plexus.PlexusConstants;
025    import org.codehaus.plexus.PlexusContainerException;
026    import org.codehaus.plexus.classworlds.ClassWorld;
027    import org.codehaus.plexus.classworlds.realm.ClassRealm;
028    import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
029    import org.slf4j.Logger;
030    import org.slf4j.LoggerFactory;
031    import org.springframework.stereotype.Service;
032    
033    import javax.annotation.PostConstruct;
034    import java.lang.reflect.Method;
035    import java.net.URL;
036    import java.net.URLClassLoader;
037    import java.util.List;
038    import java.util.Map;
039    
040    /**
041     * Simple component which will initiate the plexus shim component
042     * to see plexus components inside a guice container.<br/>
043     * So move all of this here to be able to change quickly if needed.
044     *
045     * @author Olivier Lamy
046     */
047    @Service( "plexusSisuBridge" )
048    public class PlexusSisuBridge
049    {
050    
051        private Logger log = LoggerFactory.getLogger( getClass() );
052    
053        private boolean containerAutoWiring = true;
054    
055        private String containerClassPathScanning = PlexusConstants.SCANNING_ON;
056    
057        private String containerComponentVisibility = PlexusConstants.REALM_VISIBILITY;
058    
059        private URL overridingComponentsXml;
060    
061        private ClassRealm containerRealm;
062    
063        private DefaultPlexusContainer plexusContainer;
064    
065        @PostConstruct
066        public void initialize()
067            throws PlexusSisuBridgeException
068        {
069            DefaultContainerConfiguration conf = new DefaultContainerConfiguration();
070    
071            conf.setAutoWiring( containerAutoWiring );
072            conf.setClassPathScanning( containerClassPathScanning );
073            conf.setComponentVisibility( containerComponentVisibility );
074    
075            conf.setContainerConfigurationURL( overridingComponentsXml );
076    
077            ClassWorld classWorld = new ClassWorld();
078    
079            ClassLoader tccl = Thread.currentThread().getContextClassLoader();
080    
081            containerRealm = new ClassRealm( classWorld, "maven", tccl );
082    
083            // olamy hackhish but plexus-sisu need a URLClassLoader with URL filled
084    
085            if ( tccl instanceof URLClassLoader )
086            {
087                URL[] urls = ( (URLClassLoader) tccl ).getURLs();
088                for ( URL url : urls )
089                {
090                    containerRealm.addURL( url );
091                }
092            }
093    
094            conf.setRealm( containerRealm );
095    
096            //conf.setClassWorld( classWorld );
097    
098            ClassLoader ori = Thread.currentThread().getContextClassLoader();
099    
100            try
101            {
102                Thread.currentThread().setContextClassLoader( containerRealm );
103                plexusContainer = new DefaultPlexusContainer( conf );
104            }
105            catch ( PlexusContainerException e )
106            {
107                throw new PlexusSisuBridgeException( e.getMessage(), e );
108            }
109            finally
110            {
111                Thread.currentThread().setContextClassLoader( ori );
112            }
113        }
114    
115    
116        private URL[] getClassLoaderURLs( ClassLoader classLoader )
117        {
118            try
119            {
120                // can be WebappClassLoader when using tomcat maven plugin
121                //java.net.URL[] getURLs
122                Method method = classLoader.getClass().getMethod( "getURLs", new Class[]{ } );
123                if ( method != null )
124                {
125                    return (URL[]) method.invoke( classLoader, null );
126                }
127            }
128            catch ( Exception e )
129            {
130                log.info( "ignore issue trying to find url[] from classloader {}", e.getMessage() );
131            }
132            return new URL[]{ };
133        }
134    
135        public <T> T lookup( Class<T> clazz )
136            throws PlexusSisuBridgeException
137        {
138            ClassLoader ori = Thread.currentThread().getContextClassLoader();
139            try
140            {
141                Thread.currentThread().setContextClassLoader( containerRealm );
142                return plexusContainer.lookup( clazz );
143            }
144            catch ( ComponentLookupException e )
145            {
146                throw new PlexusSisuBridgeException( e.getMessage(), e );
147            }
148            finally
149            {
150                Thread.currentThread().setContextClassLoader( ori );
151            }
152        }
153    
154        public <T> T lookup( Class<T> clazz, String hint )
155            throws PlexusSisuBridgeException
156        {
157            ClassLoader ori = Thread.currentThread().getContextClassLoader();
158    
159            try
160            {
161                Thread.currentThread().setContextClassLoader( containerRealm );
162                return plexusContainer.lookup( clazz, hint );
163            }
164            catch ( ComponentLookupException e )
165            {
166                throw new PlexusSisuBridgeException( e.getMessage(), e );
167            }
168            finally
169            {
170                Thread.currentThread().setContextClassLoader( ori );
171            }
172        }
173    
174        public <T> List<T> lookupList( Class<T> clazz )
175            throws PlexusSisuBridgeException
176        {
177            ClassLoader ori = Thread.currentThread().getContextClassLoader();
178    
179            try
180            {
181                Thread.currentThread().setContextClassLoader( containerRealm );
182                return plexusContainer.lookupList( clazz );
183            }
184            catch ( ComponentLookupException e )
185            {
186                throw new PlexusSisuBridgeException( e.getMessage(), e );
187            }
188            finally
189            {
190                Thread.currentThread().setContextClassLoader( ori );
191            }
192        }
193    
194        public <T> Map<String, T> lookupMap( Class<T> clazz )
195            throws PlexusSisuBridgeException
196        {
197            ClassLoader ori = Thread.currentThread().getContextClassLoader();
198    
199            try
200            {
201                Thread.currentThread().setContextClassLoader( containerRealm );
202                return plexusContainer.lookupMap( clazz );
203            }
204            catch ( ComponentLookupException e )
205            {
206                throw new PlexusSisuBridgeException( e.getMessage(), e );
207            }
208            finally
209            {
210                Thread.currentThread().setContextClassLoader( ori );
211            }
212        }
213    }