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          StringBuilder sb = new StringBuilder();
100         for (String element : unmodifiableElements) {
101             sb.append(element).append(pathSeparatorChar);
102         }
103         System.setProperty(propertyName, sb.toString());
104     }
105 
106     @Override
107     public boolean equals(Object o) {
108         if (this == o) {
109             return true;
110         }
111         if (o == null || getClass() != o.getClass()) {
112             return false;
113         }
114 
115         Classpath classpath = (Classpath) o;
116 
117         return unmodifiableElements.equals(classpath.unmodifiableElements);
118     }
119 
120     public ClassLoader createClassLoader(boolean childDelegation, boolean enableAssertions, @Nonnull String roleName)
121             throws SurefireExecutionException {
122         try {
123             ClassLoader parent = SystemUtils.platformClassLoader();
124             IsolatedClassLoader classLoader = new IsolatedClassLoader(parent, childDelegation, roleName);
125             for (String classPathElement : unmodifiableElements) {
126                 classLoader.addURL(new File(classPathElement).toURI().toURL());
127             }
128             if (parent != null) {
129                 parent.setDefaultAssertionStatus(enableAssertions);
130             }
131             classLoader.setDefaultAssertionStatus(enableAssertions);
132             return classLoader;
133         } catch (MalformedURLException e) {
134             throw new SurefireExecutionException("When creating classloader", e);
135         }
136     }
137 
138     @Override
139     public int hashCode() {
140         return unmodifiableElements.hashCode();
141     }
142 
143     public String getLogMessage(@Nonnull String descriptor) {
144         StringBuilder result = new StringBuilder(descriptor);
145         for (String element : unmodifiableElements) {
146             result.append("  ").append(element);
147         }
148         return result.toString();
149     }
150 
151     public String getCompactLogMessage(@Nonnull String descriptor) {
152         StringBuilder result = new StringBuilder(descriptor);
153         for (String element : unmodifiableElements) {
154             result.append("  ");
155             int pos = element.lastIndexOf(File.separatorChar);
156             result.append(pos == -1 ? element : element.substring(pos + 1));
157         }
158         return result.toString();
159     }
160 
161     @Override
162     public Iterator<String> iterator() {
163         return unmodifiableElements.iterator();
164     }
165 
166     @Override
167     public Classpath clone() {
168         return new Classpath(unmodifiableElements);
169     }
170 }