View Javadoc
1   package org.apache.maven.surefire.booter;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import javax.annotation.Nonnull;
23  import java.io.File;
24  import java.net.MalformedURLException;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.Iterator;
29  import java.util.LinkedHashSet;
30  import java.util.List;
31  
32  import static java.io.File.pathSeparatorChar;
33  
34  /**
35   * An ordered list of classpath elements with set behaviour
36   *
37   * A Classpath is immutable and thread safe.
38   *
39   * Immutable and thread safe
40   *
41   * @author Kristian Rosenvold
42   */
43  public final class Classpath implements Iterable<String>, Cloneable
44  {
45      private final List<String> unmodifiableElements;
46  
47      public static Classpath join( Classpath firstClasspath, Classpath secondClasspath )
48      {
49          LinkedHashSet<String> accumulated =  new LinkedHashSet<>();
50          if ( firstClasspath != null )
51          {
52              firstClasspath.addTo( accumulated );
53          }
54          if ( secondClasspath != null )
55          {
56              secondClasspath.addTo( accumulated );
57          }
58          return new Classpath( accumulated );
59      }
60  
61      private void addTo( @Nonnull Collection<String> c )
62      {
63          c.addAll( unmodifiableElements );
64      }
65  
66      private Classpath()
67      {
68          unmodifiableElements = Collections.emptyList();
69      }
70  
71      public Classpath( @Nonnull Classpath other, @Nonnull String additionalElement )
72      {
73          ArrayList<String> elems = new ArrayList<>( other.unmodifiableElements );
74          elems.add( additionalElement );
75          unmodifiableElements = Collections.unmodifiableList( elems );
76      }
77  
78      public Classpath( @Nonnull Collection<String> elements )
79      {
80          List<String> newCp = new ArrayList<>( elements.size() );
81          for ( String element : elements )
82          {
83              element = element.trim();
84              if ( !element.isEmpty() )
85              {
86                  newCp.add( element );
87              }
88          }
89          unmodifiableElements = Collections.unmodifiableList( newCp );
90      }
91  
92      public static Classpath emptyClasspath()
93      {
94          return new Classpath();
95      }
96  
97      public Classpath addClassPathElementUrl( String path )
98      {
99          if ( path == null )
100         {
101             throw new IllegalArgumentException( "Null is not a valid class path element url." );
102         }
103         return !unmodifiableElements.contains( path ) ? new Classpath( this, path ) : this;
104     }
105 
106     @Nonnull
107     public List<String> getClassPath()
108     {
109         return unmodifiableElements;
110     }
111 
112     public void writeToSystemProperty( @Nonnull String propertyName )
113     {
114         StringBuilder sb = new StringBuilder();
115         for ( String element : unmodifiableElements )
116         {
117             sb.append( element )
118               .append( pathSeparatorChar );
119         }
120         System.setProperty( propertyName, sb.toString() );
121     }
122 
123     @Override
124     public boolean equals( Object o )
125     {
126         if ( this == o )
127         {
128             return true;
129         }
130         if ( o == null || getClass() != o.getClass() )
131         {
132             return false;
133         }
134 
135         Classpath classpath = (Classpath) o;
136 
137         return unmodifiableElements.equals( classpath.unmodifiableElements );
138     }
139 
140     public ClassLoader createClassLoader( boolean childDelegation, boolean enableAssertions, @Nonnull String roleName )
141         throws SurefireExecutionException
142     {
143         try
144         {
145             ClassLoader parent = SystemUtils.platformClassLoader();
146             IsolatedClassLoader classLoader = new IsolatedClassLoader( parent, childDelegation, roleName );
147             for ( String classPathElement : unmodifiableElements )
148             {
149                 classLoader.addURL( new File( classPathElement ).toURL() );
150             }
151             if ( parent != null )
152             {
153                 parent.setDefaultAssertionStatus( enableAssertions );
154             }
155             classLoader.setDefaultAssertionStatus( enableAssertions );
156             return classLoader;
157         }
158         catch ( MalformedURLException e )
159         {
160             throw new SurefireExecutionException( "When creating classloader", e );
161         }
162     }
163 
164     @Override
165     public int hashCode()
166     {
167         return unmodifiableElements.hashCode();
168     }
169 
170     public String getLogMessage( @Nonnull String descriptor )
171     {
172         StringBuilder result = new StringBuilder( descriptor );
173         for ( String element : unmodifiableElements )
174         {
175             result.append( "  " )
176                     .append( element );
177         }
178         return result.toString();
179     }
180 
181     public String getCompactLogMessage( @Nonnull String descriptor )
182     {
183         StringBuilder result = new StringBuilder( descriptor );
184         for ( String element : unmodifiableElements )
185         {
186             result.append( "  " );
187             if ( element != null )
188             {
189                 int pos = element.lastIndexOf( File.separatorChar );
190                 result.append( pos == -1 ? element : element.substring( pos + 1 ) );
191             }
192             else
193             {
194                 result.append( (String) null );
195             }
196         }
197         return result.toString();
198     }
199 
200     @Override
201     public Iterator<String> iterator()
202     {
203         return unmodifiableElements.iterator();
204     }
205 
206     @Override
207     public Classpath clone()
208     {
209         return new Classpath( unmodifiableElements );
210     }
211 }