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