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.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      @Inject
70      private ModelLocator locator;
71  
72      @Inject
73      private ModelReader reader;
74  
75      public DefaultModelProcessor setModelLocator( ModelLocator locator )
76      {
77          this.locator = locator;
78          return this;
79      }
80  
81      public DefaultModelProcessor setModelReader( ModelReader reader )
82      {
83          this.reader = reader;
84          return this;
85      }
86  
87      @Override
88      public File locatePom( File projectDirectory )
89      {
90          return locator.locatePom( projectDirectory );
91      }
92  
93      @Override
94      public Model read( File input, Map<String, ?> options )
95          throws IOException
96      {
97          return reader.read( input, options );
98      }
99  
100     @Override
101     public Model read( Reader input, Map<String, ?> options )
102         throws IOException
103     {
104         return reader.read( input, options );
105     }
106 
107     @Override
108     public Model read( InputStream input, Map<String, ?> options )
109         throws IOException
110     {
111         return reader.read( input, options );
112     }
113 
114 }