View Javadoc
1   package org.apache.maven.model.building;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.Reader;
26  import java.util.Map;
27  
28  import javax.inject.Inject;
29  import javax.inject.Named;
30  import javax.inject.Singleton;
31  
32  import org.apache.maven.api.model.Model;
33  import org.apache.maven.model.io.ModelReader;
34  import org.apache.maven.model.locator.ModelLocator;
35  import org.eclipse.sisu.Typed;
36  
37  /**
38   *
39   * Note: uses @Typed to limit the types it is available for injection to just ModelProcessor.
40   *
41   * This is because the ModelProcessor interface extends ModelLocator and ModelReader. If we
42   * made this component available under all its interfaces then it could end up being injected
43   * into itself leading to a stack overflow.
44   *
45   * A side effect of using @Typed is that it translates to explicit bindings in the container.
46   * So instead of binding the component under a 'wildcard' key it is now bound with an explicit
47   * key. Since this is a default component this will be a plain binding of ModelProcessor to
48   * this implementation type, ie. no hint/name.
49   *
50   * This leads to a second side effect in that any @Inject request for just ModelProcessor in
51   * the same injector is immediately matched to this explicit binding, which means extensions
52   * cannot override this binding. This is because the lookup is always short-circuited in this
53   * specific situation (plain @Inject request, and plain explicit binding for the same type.)
54   *
55   * The simplest solution is to use a custom @Named here so it isn't bound under the plain key.
56   * This is only necessary for default components using @Typed that want to support overriding.
57   *
58   * As a non-default component this now gets a negative priority relative to other implementations
59   * of the same interface. Since we want to allow overriding this doesn't matter in this case.
60   * (if it did we could add @Priority of 0 to match the priority given to default components.)
61   */
62  @Named( "core-default" )
63  @Singleton
64  @Typed( ModelProcessor.class )
65  public class DefaultModelProcessor
66      implements ModelProcessor
67  {
68  
69      private final ModelLocator locator;
70      private final ModelReader reader;
71  
72      @Inject
73      public DefaultModelProcessor( ModelLocator locator, ModelReader reader )
74      {
75          this.locator = locator;
76          this.reader = reader;
77      }
78  
79      @Override
80      public File locatePom( File projectDirectory )
81      {
82          return locator.locatePom( projectDirectory );
83      }
84  
85      @Override
86      public Model read( File input, Map<String, ?> options )
87          throws IOException
88      {
89          return reader.read( input, options );
90      }
91  
92      @Override
93      public Model read( Reader input, Map<String, ?> options )
94          throws IOException
95      {
96          return reader.read( input, options );
97      }
98  
99      @Override
100     public Model read( InputStream input, Map<String, ?> options )
101         throws IOException
102     {
103         return reader.read( input, options );
104     }
105 
106 }