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.api;
20  
21  import java.nio.file.Path;
22  import java.time.Instant;
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import org.apache.maven.api.annotations.Experimental;
27  import org.apache.maven.api.annotations.Nonnull;
28  import org.apache.maven.api.annotations.Nullable;
29  import org.apache.maven.api.annotations.ThreadSafe;
30  
31  import static java.util.Objects.requireNonNull;
32  
33  /**
34   * The proto session, material used to create {@link Session}.
35   *
36   * @since 4.0.0
37   */
38  @Experimental
39  @ThreadSafe
40  public interface ProtoSession {
41  
42      /**
43       * Returns immutable user properties to use for interpolation. The user properties have been configured directly
44       * by the user, e.g. via the {@code -Dkey=value} parameter on the command line.
45       *
46       * @return the user properties, never {@code null}
47       */
48      @Nonnull
49      Map<String, String> getUserProperties();
50  
51      /**
52       * Returns immutable system properties to use for interpolation. The system properties are collected from the
53       * runtime environment such as {@link System#getProperties()} and environment variables
54       * (prefixed with {@code env.}).
55       *
56       * @return the system properties, never {@code null}
57       */
58      @Nonnull
59      Map<String, String> getSystemProperties();
60  
61      /**
62       * Returns the properly overlaid map of properties: system + user.
63       */
64      @Nonnull
65      Map<String, String> getEffectiveProperties();
66  
67      /**
68       * Returns the start time of the session.
69       *
70       * @return the start time as an Instant object, never {@code null}
71       */
72      @Nonnull
73      Instant getStartTime();
74  
75      /**
76       * Gets the directory of the topmost project being built, usually the current directory or the
77       * directory pointed at by the {@code -f/--file} command line argument.
78       *
79       * @return the directory of the topmost project, never {@code null}
80       * @see Project#isTopProject()
81       * @see #getRootDirectory()
82       */
83      @Nonnull
84      Path getTopDirectory();
85  
86      /**
87       * Gets the root directory of the session, which is the root directory for the top directory project.
88       *
89       * @return the root directory, never {@code null}
90       * @throws IllegalStateException if the root directory could not be found
91       * @see #getTopDirectory()
92       * @see Project#getRootDirectory()
93       * @see Project#isRootProject()
94       */
95      @Nonnull
96      Path getRootDirectory();
97  
98      /**
99       * Returns a proto session builder of this instance.
100      */
101     @Nonnull
102     default Builder toBuilder() {
103         try {
104             return new Builder(
105                     getUserProperties(), getSystemProperties(), getStartTime(), getTopDirectory(), getRootDirectory());
106         } catch (IllegalStateException e) {
107             return new Builder(getUserProperties(), getSystemProperties(), getStartTime(), getTopDirectory(), null);
108         }
109     }
110 
111     /**
112      * Returns new builder from scratch.
113      */
114     static Builder newBuilder() {
115         return new Builder().withStartTime(MonotonicClock.now());
116     }
117 
118     class Builder {
119         private Map<String, String> userProperties;
120         private Map<String, String> systemProperties;
121         private Instant startTime;
122         private Path topDirectory;
123         private Path rootDirectory;
124 
125         private Builder() {}
126 
127         private Builder(
128                 Map<String, String> userProperties,
129                 Map<String, String> systemProperties,
130                 Instant startTime,
131                 Path topDirectory,
132                 Path rootDirectory) {
133             this.userProperties = userProperties;
134             this.systemProperties = systemProperties;
135             this.startTime = startTime;
136             this.topDirectory = topDirectory;
137             this.rootDirectory = rootDirectory;
138         }
139 
140         public Builder withUserProperties(@Nonnull Map<String, String> userProperties) {
141             this.userProperties = new HashMap<>(userProperties);
142             return this;
143         }
144 
145         public Builder withSystemProperties(@Nonnull Map<String, String> systemProperties) {
146             this.systemProperties = new HashMap<>(systemProperties);
147             return this;
148         }
149 
150         public Builder withStartTime(@Nonnull Instant startTime) {
151             this.startTime = requireNonNull(startTime, "startTime");
152             return this;
153         }
154 
155         public Builder withTopDirectory(@Nonnull Path topDirectory) {
156             this.topDirectory = requireNonNull(topDirectory, "topDirectory");
157             return this;
158         }
159 
160         public Builder withRootDirectory(@Nullable Path rootDirectory) {
161             this.rootDirectory = rootDirectory;
162             return this;
163         }
164 
165         public ProtoSession build() {
166             return new Impl(userProperties, systemProperties, startTime, topDirectory, rootDirectory);
167         }
168 
169         private static class Impl implements ProtoSession {
170             private final Map<String, String> userProperties;
171             private final Map<String, String> systemProperties;
172             private final Map<String, String> effectiveProperties;
173             private final Instant startTime;
174             private final Path topDirectory;
175             private final Path rootDirectory;
176 
177             private Impl(
178                     Map<String, String> userProperties,
179                     Map<String, String> systemProperties,
180                     Instant startTime,
181                     Path topDirectory,
182                     Path rootDirectory) {
183                 this.userProperties = Map.copyOf(userProperties);
184                 this.systemProperties = Map.copyOf(systemProperties);
185                 Map<String, String> cp = new HashMap<>(systemProperties);
186                 cp.putAll(userProperties);
187                 this.effectiveProperties = Map.copyOf(cp);
188                 this.startTime = requireNonNull(startTime);
189                 this.topDirectory = requireNonNull(topDirectory);
190                 this.rootDirectory = rootDirectory;
191             }
192 
193             @Override
194             public Map<String, String> getUserProperties() {
195                 return userProperties;
196             }
197 
198             @Override
199             public Map<String, String> getSystemProperties() {
200                 return systemProperties;
201             }
202 
203             @Override
204             public Map<String, String> getEffectiveProperties() {
205                 return effectiveProperties;
206             }
207 
208             @Override
209             public Instant getStartTime() {
210                 return startTime;
211             }
212 
213             @Override
214             public Path getTopDirectory() {
215                 return topDirectory;
216             }
217 
218             @Override
219             public Path getRootDirectory() {
220                 if (rootDirectory == null) {
221                     throw new IllegalStateException("root directory not set");
222                 }
223                 return rootDirectory;
224             }
225         }
226     }
227 }