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.cling.invoker;
20  
21  import java.nio.file.Path;
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  import java.util.function.Consumer;
29  
30  import org.apache.maven.api.ProtoSession;
31  import org.apache.maven.api.cli.InvokerException;
32  import org.apache.maven.api.cli.InvokerRequest;
33  import org.apache.maven.api.cli.Logger;
34  import org.apache.maven.api.cli.Options;
35  import org.apache.maven.api.services.Lookup;
36  import org.apache.maven.api.settings.Settings;
37  import org.apache.maven.api.toolchain.PersistedToolchains;
38  import org.apache.maven.cling.logging.Slf4jConfiguration;
39  import org.apache.maven.eventspy.internal.EventSpyDispatcher;
40  import org.apache.maven.logging.BuildEventListener;
41  import org.jline.terminal.Terminal;
42  import org.slf4j.ILoggerFactory;
43  
44  import static java.util.Objects.requireNonNull;
45  
46  @SuppressWarnings("VisibilityModifier")
47  public class LookupContext implements AutoCloseable {
48      public final InvokerRequest invokerRequest;
49      public final CWD cwd;
50      public final Path installationDirectory;
51      public final Path userDirectory;
52      public final boolean containerCapsuleManaged;
53      private final Options options;
54  
55      public LookupContext(InvokerRequest invokerRequest, boolean containerCapsuleManaged, Options options) {
56          this.invokerRequest = requireNonNull(invokerRequest);
57          this.cwd = CWD.create(invokerRequest.cwd());
58          this.installationDirectory = CliUtils.getCanonicalPath(invokerRequest.installationDirectory());
59          this.userDirectory = CliUtils.getCanonicalPath(invokerRequest.userHomeDirectory());
60          this.containerCapsuleManaged = containerCapsuleManaged;
61          this.options = options;
62          this.logger = invokerRequest.parserRequest().logger();
63  
64          Map<String, String> user = new HashMap<>(invokerRequest.userProperties());
65          user.put("session.topDirectory", invokerRequest.topDirectory().toString());
66          if (invokerRequest.rootDirectory().isPresent()) {
67              user.put(
68                      "session.rootDirectory",
69                      invokerRequest.rootDirectory().get().toString());
70          }
71          this.protoSession = ProtoSession.newBuilder()
72                  .withSystemProperties(invokerRequest.systemProperties())
73                  .withUserProperties(user)
74                  .withTopDirectory(invokerRequest.topDirectory())
75                  .withRootDirectory(invokerRequest.rootDirectory().orElse(null))
76                  .build();
77      }
78  
79      public Logger logger;
80  
81      // this one "evolves" as process progresses (instance is immutable but instances are replaced)
82      public ProtoSession protoSession;
83      // here we track which user properties we pushed to Java System Properties (internal only)
84      public Set<String> pushedUserProperties;
85  
86      public ILoggerFactory loggerFactory;
87      public Slf4jConfiguration slf4jConfiguration;
88      public Slf4jConfiguration.Level loggerLevel;
89      public Boolean coloredOutput;
90      public Terminal terminal;
91      public Consumer<String> writer;
92  
93      public ContainerCapsule containerCapsule;
94      public Lookup lookup;
95      public EventSpyDispatcher eventSpyDispatcher;
96  
97      public BuildEventListener buildEventListener;
98  
99      // paths user can override from CLI, and we need to set on MavenExReq
100     public Path installationSettingsPath;
101     public Path projectSettingsPath;
102     public Path userSettingsPath;
103     public boolean interactive;
104     public Path localRepositoryPath;
105     public Settings effectiveSettings;
106     public PersistedToolchains effectiveToolchains;
107 
108     public final List<AutoCloseable> closeables = new ArrayList<>();
109 
110     @Override
111     public void close() throws InvokerException {
112         List<Exception> causes = null;
113         List<AutoCloseable> cs = new ArrayList<>(closeables);
114         Collections.reverse(cs);
115         for (AutoCloseable c : cs) {
116             if (c != null) {
117                 try {
118                     c.close();
119                 } catch (Exception e) {
120                     if (causes == null) {
121                         causes = new ArrayList<>();
122                     }
123                     causes.add(e);
124                 }
125             }
126         }
127         if (causes != null) {
128             InvokerException exception = new InvokerException("Unable to close context");
129             causes.forEach(exception::addSuppressed);
130             throw exception;
131         }
132     }
133 
134     public final void closeContainer() throws Exception {
135         if (containerCapsuleManaged) {
136             doCloseContainer();
137         }
138     }
139 
140     public void doCloseContainer() throws Exception {
141         if (containerCapsule != null) {
142             try {
143                 containerCapsule.close();
144             } finally {
145                 eventSpyDispatcher = null;
146                 lookup = null;
147                 containerCapsule = null;
148             }
149         }
150     }
151 
152     public Options options() {
153         return options;
154     }
155 }