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.toolchain;
20  
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Optional;
25  
26  import org.apache.maven.api.Session;
27  import org.apache.maven.api.annotations.Nonnull;
28  import org.apache.maven.api.annotations.Nullable;
29  import org.apache.maven.api.di.Inject;
30  import org.apache.maven.api.di.Named;
31  import org.apache.maven.api.di.Priority;
32  import org.apache.maven.api.di.Provides;
33  import org.apache.maven.api.di.Singleton;
34  import org.apache.maven.api.di.Typed;
35  import org.apache.maven.api.services.Lookup;
36  import org.apache.maven.api.services.ToolchainFactoryException;
37  import org.apache.maven.api.services.ToolchainManagerException;
38  import org.apache.maven.execution.MavenSession;
39  import org.apache.maven.impl.MappedList;
40  import org.apache.maven.toolchain.model.ToolchainModel;
41  import org.slf4j.Logger;
42  
43  @Named
44  @Singleton
45  @Deprecated(since = "4.0.0")
46  public class ToolchainManagerFactory {
47  
48      private final Lookup lookup;
49      private final Logger logger;
50  
51      @Inject
52      ToolchainManagerFactory(Lookup lookup) {
53          this(lookup, null);
54      }
55  
56      protected ToolchainManagerFactory(Lookup lookup, Logger logger) {
57          this.lookup = lookup;
58          this.logger = logger;
59      }
60  
61      @Provides
62      @Typed({ToolchainManager.class, ToolchainManagerPrivate.class})
63      @Named // qualifier is required for SiduDIBridge to work
64      DefaultToolchainManagerV3 v3Manager() {
65          return new DefaultToolchainManagerV3();
66      }
67  
68      @Provides
69      @Priority(10)
70      @Typed(org.apache.maven.api.services.ToolchainManager.class)
71      DefaultToolchainManagerV4 v4Manager() {
72          return new DefaultToolchainManagerV4();
73      }
74  
75      @Provides
76      @Typed(ToolchainFactory.class)
77      @Named("jdk")
78      ToolchainFactory jdkFactory() {
79          return createV3FactoryBridge("jdk");
80      }
81  
82      /**
83       * Creates a v3 ToolchainFactory bridge that wraps a v4 ToolchainFactory.
84       */
85      public ToolchainFactory createV3FactoryBridge(String type) {
86          try {
87              org.apache.maven.api.services.ToolchainFactory v4Factory =
88                      lookup.lookup(org.apache.maven.api.services.ToolchainFactory.class, type);
89              if (v4Factory == null) {
90                  return null;
91              }
92              return createV3FactoryBridgeForV4Factory(v4Factory);
93          } catch (Exception e) {
94              // If lookup fails, no v4 factory exists for this type
95              return null;
96          }
97      }
98  
99      /**
100      * Creates a v3 ToolchainFactory bridge that wraps a specific v4 ToolchainFactory instance.
101      */
102     public ToolchainFactory createV3FactoryBridgeForV4Factory(
103             org.apache.maven.api.services.ToolchainFactory v4Factory) {
104         return new ToolchainFactory() {
105             @Override
106             public ToolchainPrivate createToolchain(ToolchainModel model) throws MisconfiguredToolchainException {
107                 try {
108                     org.apache.maven.api.Toolchain v4Toolchain = v4Factory.createToolchain(model.getDelegate());
109                     return getToolchainV3(v4Toolchain);
110                 } catch (ToolchainFactoryException e) {
111                     throw new MisconfiguredToolchainException(e.getMessage(), e);
112                 }
113             }
114 
115             @Override
116             public ToolchainPrivate createDefaultToolchain() {
117                 try {
118                     return v4Factory
119                             .createDefaultToolchain()
120                             .map(ToolchainManagerFactory.this::getToolchainV3)
121                             .orElse(null);
122                 } catch (ToolchainFactoryException e) {
123                     return null;
124                 }
125             }
126         };
127     }
128 
129     private org.apache.maven.impl.DefaultToolchainManager getDelegate() {
130         Map<String, ToolchainFactory> v3Factories = lookup.lookupMap(ToolchainFactory.class);
131         Map<String, org.apache.maven.api.services.ToolchainFactory> v4Factories =
132                 lookup.lookupMap(org.apache.maven.api.services.ToolchainFactory.class);
133         Map<String, org.apache.maven.api.services.ToolchainFactory> allFactories = new HashMap<>();
134         for (Map.Entry<String, ToolchainFactory> entry : v3Factories.entrySet()) {
135             ToolchainFactory v3Factory = entry.getValue();
136             allFactories.put(entry.getKey(), new org.apache.maven.api.services.ToolchainFactory() {
137                 @Nonnull
138                 @Override
139                 public org.apache.maven.api.Toolchain createToolchain(
140                         @Nonnull org.apache.maven.api.toolchain.ToolchainModel model) throws ToolchainFactoryException {
141                     try {
142                         return getToolchainV4(v3Factory.createToolchain(new ToolchainModel(model)));
143                     } catch (MisconfiguredToolchainException e) {
144                         throw new RuntimeException(e);
145                     }
146                 }
147 
148                 @Nonnull
149                 @Override
150                 public Optional<org.apache.maven.api.Toolchain> createDefaultToolchain()
151                         throws ToolchainFactoryException {
152                     return Optional.ofNullable(v3Factory.createDefaultToolchain())
153                             .map(ToolchainManagerFactory.this::getToolchainV4);
154                 }
155             });
156         }
157         allFactories.putAll(v4Factories);
158         return new org.apache.maven.impl.DefaultToolchainManager(allFactories, logger) {};
159     }
160 
161     public class DefaultToolchainManagerV4 implements org.apache.maven.api.services.ToolchainManager {
162         @Nonnull
163         @Override
164         public List<org.apache.maven.api.Toolchain> getToolchains(
165                 @Nonnull Session session, @Nonnull String type, @Nullable Map<String, String> requirements)
166                 throws ToolchainManagerException {
167             return getDelegate().getToolchains(session, type, requirements);
168         }
169 
170         @Nonnull
171         @Override
172         public Optional<org.apache.maven.api.Toolchain> getToolchainFromBuildContext(
173                 @Nonnull Session session, @Nonnull String type) throws ToolchainManagerException {
174             return getDelegate().getToolchainFromBuildContext(session, type);
175         }
176 
177         @Override
178         public void storeToolchainToBuildContext(
179                 @Nonnull Session session, @Nonnull org.apache.maven.api.Toolchain toolchain) {
180             getDelegate().storeToolchainToBuildContext(session, toolchain);
181         }
182 
183         @Nonnull
184         @Override
185         public List<org.apache.maven.api.Toolchain> getToolchains(@Nonnull Session session, @Nonnull String type)
186                 throws ToolchainManagerException {
187             return getDelegate().getToolchains(session, type);
188         }
189     }
190 
191     public class DefaultToolchainManagerV3 implements ToolchainManager, ToolchainManagerPrivate {
192 
193         @Override
194         public Toolchain getToolchainFromBuildContext(String type, MavenSession session) {
195             return getDelegate()
196                     .getToolchainFromBuildContext(session.getSession(), type)
197                     .map(ToolchainManagerFactory.this::getToolchainV3)
198                     .orElse(null);
199         }
200 
201         @Override
202         public List<Toolchain> getToolchains(MavenSession session, String type, Map<String, String> requirements) {
203             return new MappedList<>(
204                     getDelegate().getToolchains(session.getSession(), type, requirements),
205                     ToolchainManagerFactory.this::getToolchainV3);
206         }
207 
208         @Override
209         public ToolchainPrivate[] getToolchainsForType(String type, MavenSession session)
210                 throws MisconfiguredToolchainException {
211             try {
212                 List<org.apache.maven.api.Toolchain> toolchains =
213                         getDelegate().getToolchains(session.getSession(), type);
214                 return toolchains.stream()
215                         .map(ToolchainManagerFactory.this::getToolchainV3)
216                         .toArray(ToolchainPrivate[]::new);
217             } catch (org.apache.maven.api.services.ToolchainManagerException e) {
218                 throw new MisconfiguredToolchainException(e.getMessage(), e);
219             }
220         }
221 
222         @Override
223         public void storeToolchainToBuildContext(ToolchainPrivate toolchain, MavenSession session) {
224             org.apache.maven.api.Toolchain tc = getToolchainV4(toolchain);
225             getDelegate().storeToolchainToBuildContext(session.getSession(), tc);
226         }
227     }
228 
229     private org.apache.maven.api.Toolchain getToolchainV4(ToolchainPrivate toolchain) {
230         return toolchain instanceof ToolchainWrapperV3 v3tc ? v3tc.delegate : new ToolchainWrapperV4(toolchain);
231     }
232 
233     private ToolchainPrivate getToolchainV3(org.apache.maven.api.Toolchain toolchain) {
234         return toolchain instanceof ToolchainWrapperV4 v3tc ? v3tc.delegate : new ToolchainWrapperV3(toolchain);
235     }
236 
237     private record ToolchainWrapperV4(ToolchainPrivate delegate) implements org.apache.maven.api.Toolchain {
238 
239         @Override
240         public String getType() {
241             return delegate.getType();
242         }
243 
244         @Override
245         public String findTool(String toolName) {
246             return delegate.findTool(toolName);
247         }
248 
249         @Override
250         public org.apache.maven.api.toolchain.ToolchainModel getModel() {
251             return delegate.getModel().getDelegate();
252         }
253 
254         @Override
255         public boolean matchesRequirements(Map<String, String> requirements) {
256             return delegate.matchesRequirements(requirements);
257         }
258 
259         @Override
260         public String toString() {
261             return delegate.toString();
262         }
263     }
264 
265     private record ToolchainWrapperV3(org.apache.maven.api.Toolchain delegate) implements Toolchain, ToolchainPrivate {
266 
267         @Override
268         public String getType() {
269             return delegate.getType();
270         }
271 
272         @Override
273         public String findTool(String toolName) {
274             return delegate.findTool(toolName);
275         }
276 
277         @Override
278         public boolean matchesRequirements(Map<String, String> requirements) {
279             return delegate.matchesRequirements(requirements);
280         }
281 
282         @Override
283         public ToolchainModel getModel() {
284             return new ToolchainModel(delegate.getModel());
285         }
286 
287         @Override
288         public String toString() {
289             return delegate.toString();
290         }
291     }
292 }