001package org.apache.maven.scm;
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 java.io.File;
023import java.io.InputStream;
024import java.util.Map;
025
026import com.google.inject.Module;
027import org.codehaus.plexus.ContainerConfiguration;
028import org.codehaus.plexus.DefaultContainerConfiguration;
029import org.codehaus.plexus.DefaultPlexusContainer;
030import org.codehaus.plexus.PlexusConstants;
031import org.codehaus.plexus.PlexusContainer;
032import org.codehaus.plexus.PlexusContainerException;
033import org.codehaus.plexus.configuration.PlexusConfiguration;
034import org.codehaus.plexus.context.Context;
035import org.codehaus.plexus.context.DefaultContext;
036import org.junit.After;
037import org.junit.Before;
038import org.junit.Rule;
039import org.junit.rules.TestName;
040
041import static org.junit.Assert.fail;
042
043/**
044 * Based on PlexusTestCase from org.sonatype.sisu:sisu-inject-plexus.
045 * Note: this class is copied from maven-release.
046 *
047 * @author Robert Scholte
048 */
049public abstract class PlexusJUnit4TestSupport
050{
051    private PlexusContainer container;
052
053    private static String basedir;
054
055    @Rule
056    public TestName testName = new TestName();
057
058    @Before
059    public void setUp()
060            throws Exception
061    {
062        basedir = getBasedir();
063    }
064
065    protected String getName()
066    {
067        return testName.getMethodName();
068    }
069
070    protected void setupContainer()
071    {
072        // ----------------------------------------------------------------------------
073        // Context Setup
074        // ----------------------------------------------------------------------------
075
076        final DefaultContext context = new DefaultContext();
077
078        context.put( "basedir", getBasedir() );
079
080        customizeContext( context );
081
082        final boolean hasPlexusHome = context.contains( "plexus.home" );
083
084        if ( !hasPlexusHome )
085        {
086            final File f = getTestFile( "target/plexus-home" );
087
088            if ( !f.isDirectory() )
089            {
090                f.mkdir();
091            }
092
093            context.put( "plexus.home", f.getAbsolutePath() );
094        }
095
096        // ----------------------------------------------------------------------------
097        // Configuration
098        // ----------------------------------------------------------------------------
099
100        final String config = getCustomConfigurationName();
101
102        final ContainerConfiguration containerConfiguration =
103                new DefaultContainerConfiguration()
104                        .setName( "test" )
105                        .setContext( context.getContextData() )
106                        .setAutoWiring( true )
107                        .setClassPathScanning( PlexusConstants.SCANNING_CACHE );
108
109        if ( config != null )
110        {
111            containerConfiguration.setContainerConfiguration( config );
112        }
113        else
114        {
115            final String resource = getConfigurationName( null );
116
117            containerConfiguration.setContainerConfiguration( resource );
118        }
119
120        customizeContainerConfiguration( containerConfiguration );
121
122        try
123        {
124            container = new DefaultPlexusContainer( containerConfiguration, getCustomModules() );
125        }
126        catch ( final PlexusContainerException e )
127        {
128            e.printStackTrace();
129            fail( "Failed to create plexus container." );
130        }
131    }
132
133    /**
134     * Allows test to define custom modules.
135     */
136    protected Module[] getCustomModules()
137    {
138        return new Module[0];
139    }
140
141    /**
142     * Allow custom test case implementations do augment the default container configuration before executing tests.
143     *
144     * @param containerConfiguration
145     */
146    protected void customizeContainerConfiguration( final ContainerConfiguration containerConfiguration )
147    {
148    }
149
150    protected void customizeContext( final Context context )
151    {
152    }
153
154    protected PlexusConfiguration customizeComponentConfiguration()
155    {
156        return null;
157    }
158
159    @After
160    public void tearDown()
161            throws Exception
162    {
163        if ( container != null )
164        {
165            container.dispose();
166
167            container = null;
168        }
169    }
170
171    protected PlexusContainer getContainer()
172    {
173        if ( container == null )
174        {
175            setupContainer();
176        }
177
178        return container;
179    }
180
181    protected InputStream getConfiguration()
182            throws Exception
183    {
184        return getConfiguration( null );
185    }
186
187    @SuppressWarnings( "unused" )
188    protected InputStream getConfiguration( final String subname )
189            throws Exception
190    {
191        return getResourceAsStream( getConfigurationName( subname ) );
192    }
193
194    protected String getCustomConfigurationName()
195    {
196        return null;
197    }
198
199    /**
200     * Allow the retrieval of a container configuration that is based on the name of the test class being run. So if you
201     * have a test class called org.foo.FunTest, then this will produce a resource name of org/foo/FunTest.xml which
202     * would be used to configure the Plexus container before running your test.
203     *
204     * @param subname
205     * @return
206     */
207    protected String getConfigurationName( final String subname )
208    {
209        return getClass().getName().replace( '.', '/' ) + ".xml";
210    }
211
212    protected InputStream getResourceAsStream( final String resource )
213    {
214        return getClass().getResourceAsStream( resource );
215    }
216
217    protected ClassLoader getClassLoader()
218    {
219        return getClass().getClassLoader();
220    }
221
222    // ----------------------------------------------------------------------
223    // Container access
224    // ----------------------------------------------------------------------
225
226    protected Object lookup( final String componentKey )
227            throws Exception
228    {
229        return getContainer().lookup( componentKey );
230    }
231
232    protected Object lookup( final String role, final String roleHint )
233            throws Exception
234    {
235        return getContainer().lookup( role, roleHint );
236    }
237
238    protected <T> T lookup( final Class<T> componentClass )
239            throws Exception
240    {
241        return getContainer().lookup( componentClass );
242    }
243
244    protected <T> T lookup( final Class<T> componentClass, final String roleHint )
245            throws Exception
246    {
247        return getContainer().lookup( componentClass, roleHint );
248    }
249
250    protected <T> Map<String, T> lookupMap( final Class<T> componentClass )
251            throws Exception
252    {
253        return getContainer().lookupMap( componentClass );
254    }
255
256    protected void release( final Object component )
257            throws Exception
258    {
259        getContainer().release( component );
260    }
261
262    // ----------------------------------------------------------------------
263    // Helper methods for sub classes
264    // ----------------------------------------------------------------------
265
266    public static File getTestFile( final String path )
267    {
268        return new File( getBasedir(), path );
269    }
270
271    @SuppressWarnings( "hiding" )
272    public static File getTestFile( final String basedir, final String path )
273    {
274        File basedirFile = new File( basedir );
275
276        if ( !basedirFile.isAbsolute() )
277        {
278            basedirFile = getTestFile( basedir );
279        }
280
281        return new File( basedirFile, path );
282    }
283
284    public static String getTestPath( final String path )
285    {
286        return getTestFile( path ).getAbsolutePath();
287    }
288
289    @SuppressWarnings( "hiding" )
290    public static String getTestPath( final String basedir, final String path )
291    {
292        return getTestFile( basedir, path ).getAbsolutePath();
293    }
294
295    public static String getBasedir()
296    {
297        if ( basedir != null )
298        {
299            return basedir;
300        }
301
302        basedir = System.getProperty( "basedir" );
303
304        if ( basedir == null )
305        {
306            basedir = new File( "" ).getAbsolutePath();
307        }
308
309        return basedir;
310    }
311
312    public String getTestConfiguration()
313    {
314        return getTestConfiguration( getClass() );
315    }
316
317    public static String getTestConfiguration( final Class<?> clazz )
318    {
319        final String s = clazz.getName().replace( '.', '/' );
320
321        return s.substring( 0, s.indexOf( "$" ) ) + ".xml";
322    }
323}