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.net.URL;
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.Collections;
29  import java.util.Iterator;
30  import java.util.LinkedHashSet;
31  import java.util.List;
32  
33  import static java.io.File.pathSeparatorChar;
34  import static org.apache.maven.surefire.util.internal.UrlUtils.toURL;
35  
36  /**
37   * An ordered list of classpath elements with set behaviour
38   *
39   * A Classpath is immutable and thread safe.
40   *
41   * Immutable and thread safe
42   *
43   * @author Kristian Rosenvold
44   */
45  public final class Classpath implements Iterable<String>, Cloneable
46  {
47      private final List<String> unmodifiableElements;
48  
49      public static Classpath join( Classpath firstClasspath, Classpath secondClasspath )
50      {
51          LinkedHashSet<String> accumulated =  new LinkedHashSet<String>();
52          if ( firstClasspath != null )
53          {
54              firstClasspath.addTo( accumulated );
55          }
56          if ( secondClasspath != null )
57          {
58              secondClasspath.addTo( accumulated );
59          }
60          return new Classpath( accumulated );
61      }
62  
63      private void addTo( @Nonnull Collection<String> c )
64      {
65          c.addAll( unmodifiableElements );
66      }
67  
68      private Classpath()
69      {
70          unmodifiableElements = Collections.emptyList();
71      }
72  
73      public Classpath( @Nonnull Classpath other, @Nonnull String additionalElement )
74      {
75          ArrayList<String> elems = new ArrayList<String>( other.unmodifiableElements );
76          elems.add( additionalElement );
77          unmodifiableElements = Collections.unmodifiableList( elems );
78      }
79  
80      public Classpath( @Nonnull Collection<String> elements )
81      {
82          List<String> newCp = new ArrayList<String>( elements.size() );
83          for ( String element : elements )
84          {
85              element = element.trim();
86              if ( !element.isEmpty() )
87              {
88                  newCp.add( element );
89              }
90          }
91          unmodifiableElements = Collections.unmodifiableList( newCp );
92      }
93  
94      public static Classpath emptyClasspath()
95      {
96          return new Classpath();
97      }
98  
99      public Classpath addClassPathElementUrl( String path )
100     {
101         if ( path == null )
102         {
103             throw new IllegalArgumentException( "Null is not a valid class path element url." );
104         }
105         return !unmodifiableElements.contains( path ) ? new Classpath( this, path ) : this;
106     }
107 
108     @Nonnull
109     public List<String> getClassPath()
110     {
111         return unmodifiableElements;
112     }
113 
114     /**
115      * @deprecated this should be package private method which returns List of Files. It will be
116      * removed in the next major version.
117      *
118      * @return list of {@link URL jar files paths} with {@code file} protocol in URL.
119      * @throws MalformedURLException if {@link URL} could not be created upon given class-path element(s)
120      */
121     @Deprecated
122     public List<URL> getAsUrlList()
123         throws MalformedURLException
124     {
125         List<URL> urls = new ArrayList<URL>();
126         for ( String url : unmodifiableElements )
127         {
128             File f = new File( url );
129             urls.add( toURL( f ) );
130         }
131         return urls;
132     }
133 
134     public void writeToSystemProperty( @Nonnull String propertyName )
135     {
136         StringBuilder sb = new StringBuilder();
137         for ( String element : unmodifiableElements )
138         {
139             sb.append( element )
140               .append( pathSeparatorChar );
141         }
142         System.setProperty( propertyName, sb.toString() );
143     }
144 
145     @Override
146     public boolean equals( Object o )
147     {
148         if ( this == o )
149         {
150             return true;
151         }
152         if ( o == null || getClass() != o.getClass() )
153         {
154             return false;
155         }
156 
157         Classpath classpath = (Classpath) o;
158 
159         return unmodifiableElements.equals( classpath.unmodifiableElements );
160     }
161 
162     public ClassLoader createClassLoader( boolean childDelegation, boolean enableAssertions, @Nonnull String roleName )
163         throws SurefireExecutionException
164     {
165         try
166         {
167             ClassLoader parent = SystemUtils.platformClassLoader();
168             IsolatedClassLoader classLoader = new IsolatedClassLoader( parent, childDelegation, roleName );
169             for ( String classPathElement : unmodifiableElements )
170             {
171                 classLoader.addURL( new File( classPathElement ).toURL() );
172             }
173             if ( parent != null )
174             {
175                 parent.setDefaultAssertionStatus( enableAssertions );
176             }
177             classLoader.setDefaultAssertionStatus( enableAssertions );
178             return classLoader;
179         }
180         catch ( MalformedURLException e )
181         {
182             throw new SurefireExecutionException( "When creating classloader", e );
183         }
184     }
185 
186     @Override
187     public int hashCode()
188     {
189         return unmodifiableElements.hashCode();
190     }
191 
192     public String getLogMessage( @Nonnull String descriptor )
193     {
194         StringBuilder result = new StringBuilder( descriptor );
195         for ( String element : unmodifiableElements )
196         {
197             result.append( "  " )
198                     .append( element );
199         }
200         return result.toString();
201     }
202 
203     public String getCompactLogMessage( @Nonnull String descriptor )
204     {
205         StringBuilder result = new StringBuilder( descriptor );
206         for ( String element : unmodifiableElements )
207         {
208             result.append( "  " );
209             if ( element != null )
210             {
211                 int pos = element.lastIndexOf( File.separatorChar );
212                 result.append( pos == -1 ? element : element.substring( pos + 1 ) );
213             }
214             else
215             {
216                 result.append( (String) null );
217             }
218         }
219         return result.toString();
220     }
221 
222     @Override
223     public Iterator<String> iterator()
224     {
225         return unmodifiableElements.iterator();
226     }
227 
228     @Override
229     public Classpath clone()
230     {
231         return new Classpath( unmodifiableElements );
232     }
233 }