View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.booter;
20  
21  import javax.annotation.Nonnull;
22  
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      private final List<String> unmodifiableElements;
45  
46      public static Classpath join(Classpath firstClasspath, Classpath secondClasspath) {
47          LinkedHashSet<String> accumulated = new LinkedHashSet<>();
48          if (firstClasspath != null) {
49              firstClasspath.addTo(accumulated);
50          }
51          if (secondClasspath != null) {
52              secondClasspath.addTo(accumulated);
53          }
54          return new Classpath(accumulated);
55      }
56  
57      private void addTo(@Nonnull Collection<String> c) {
58          c.addAll(unmodifiableElements);
59      }
60  
61      private Classpath() {
62          unmodifiableElements = Collections.emptyList();
63      }
64  
65      public Classpath(@Nonnull Classpath other, @Nonnull String additionalElement) {
66          ArrayList<String> elems = new ArrayList<>(other.unmodifiableElements);
67          elems.add(additionalElement);
68          unmodifiableElements = Collections.unmodifiableList(elems);
69      }
70  
71      public Classpath(@Nonnull Collection<String> elements) {
72          List<String> newCp = new ArrayList<>(elements.size());
73          for (String element : elements) {
74              element = element.trim();
75              if (!element.isEmpty()) {
76                  newCp.add(element);
77              }
78          }
79          unmodifiableElements = Collections.unmodifiableList(newCp);
80      }
81  
82      public static Classpath emptyClasspath() {
83          return new Classpath();
84      }
85  
86      public Classpath addClassPathElementUrl(String path) {
87          if (path == null) {
88              throw new IllegalArgumentException("Null is not a valid class path element url.");
89          }
90          return unmodifiableElements.contains(path) ? this : new Classpath(this, path);
91      }
92  
93      @Nonnull
94      public List<String> getClassPath() {
95          return unmodifiableElements;
96      }
97  
98      public void writeToSystemProperty(@Nonnull String propertyName) {
99          System.setProperty(propertyName, String.join(String.valueOf(pathSeparatorChar), unmodifiableElements));
100     }
101 
102     @Override
103     public boolean equals(Object o) {
104         if (this == o) {
105             return true;
106         }
107         if (o == null || getClass() != o.getClass()) {
108             return false;
109         }
110 
111         Classpath classpath = (Classpath) o;
112 
113         return unmodifiableElements.equals(classpath.unmodifiableElements);
114     }
115 
116     public ClassLoader createClassLoader(boolean childDelegation, boolean enableAssertions, @Nonnull String roleName)
117             throws SurefireExecutionException {
118         try {
119             ClassLoader parent = SystemUtils.platformClassLoader();
120             IsolatedClassLoader classLoader = new IsolatedClassLoader(parent, childDelegation, roleName);
121             for (String classPathElement : unmodifiableElements) {
122                 classLoader.addURL(new File(classPathElement).toURI().toURL());
123             }
124             if (parent != null) {
125                 parent.setDefaultAssertionStatus(enableAssertions);
126             }
127             classLoader.setDefaultAssertionStatus(enableAssertions);
128             return classLoader;
129         } catch (MalformedURLException e) {
130             throw new SurefireExecutionException("When creating classloader", e);
131         }
132     }
133 
134     @Override
135     public int hashCode() {
136         return unmodifiableElements.hashCode();
137     }
138 
139     public String getLogMessage(@Nonnull String descriptor) {
140         StringBuilder result = new StringBuilder(descriptor);
141         for (String element : unmodifiableElements) {
142             result.append("  ").append(element);
143         }
144         return result.toString();
145     }
146 
147     public String getCompactLogMessage(@Nonnull String descriptor) {
148         StringBuilder result = new StringBuilder(descriptor);
149         for (String element : unmodifiableElements) {
150             result.append("  ");
151             int pos = element.lastIndexOf(File.separatorChar);
152             result.append(pos == -1 ? element : element.substring(pos + 1));
153         }
154         return result.toString();
155     }
156 
157     @Override
158     public Iterator<String> iterator() {
159         return unmodifiableElements.iterator();
160     }
161 
162     @Override
163     public Classpath clone() {
164         return new Classpath(unmodifiableElements);
165     }
166 }