View Javadoc
1   package org.codehaus.mojo.exec;
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.beans.IntrospectionException;
23  import java.beans.PropertyDescriptor;
24  import java.io.File;
25  import java.lang.reflect.InvocationTargetException;
26  import java.lang.reflect.Method;
27  import java.util.ArrayList;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Properties;
31  
32  import org.apache.maven.toolchain.MisconfiguredToolchainException;
33  import org.apache.maven.toolchain.RequirementMatcherFactory;
34  import org.apache.maven.toolchain.ToolchainFactory;
35  import org.apache.maven.toolchain.ToolchainPrivate;
36  import org.apache.maven.toolchain.model.ToolchainModel;
37  import org.codehaus.plexus.component.annotations.Component;
38  import org.codehaus.plexus.component.annotations.Requirement;
39  import org.codehaus.plexus.logging.Logger;
40  import org.codehaus.plexus.util.FileUtils;
41  import org.codehaus.plexus.util.xml.Xpp3Dom;
42  
43  /**
44   * Factory for {@link PathsToolchain}.
45   *
46   * @author Markus KARG (markus@headcrashing.eu)
47   */
48  @Component( role = ToolchainFactory.class, hint = "paths" )
49  class PathsToolchainFactory
50      implements ToolchainFactory
51  {
52  
53      @Requirement
54      private Logger logger;
55  
56      public ToolchainPrivate createToolchain( final ToolchainModel model )
57          throws MisconfiguredToolchainException
58      {
59          if ( model == null )
60              return null;
61  
62          final PathsToolchain pathsToolchain = new PathsToolchain( model, this.logger );
63          final Properties provides = this.getProvidesProperties( model );
64          for ( final Map.Entry<Object, Object> provide : provides.entrySet() )
65          {
66              final String key = (String) provide.getKey();
67              final String value = (String) provide.getValue();
68              if ( value == null )
69                  throw new MisconfiguredToolchainException( "Provides token '" + key
70                      + "' doesn't have any value configured." );
71  
72              pathsToolchain.addProvideToken( key, RequirementMatcherFactory.createExactMatcher( value ) );
73          }
74  
75          final Xpp3Dom config = (Xpp3Dom) model.getConfiguration();
76          if ( config == null )
77              return pathsToolchain;
78  
79          final Xpp3Dom pathDom = config.getChild( "paths" );
80          if ( pathDom == null )
81              return pathsToolchain;
82  
83          final Xpp3Dom[] pathDoms = pathDom.getChildren( "path" );
84          if ( pathDoms == null || pathDoms.length == 0 )
85              return pathsToolchain;
86  
87          final List<String> paths = new ArrayList<String>( pathDoms.length );
88          for ( final Xpp3Dom pathdom : pathDoms )
89          {
90              final String pathString = pathdom.getValue();
91  
92              if ( pathString == null )
93                  throw new MisconfiguredToolchainException( "path element is empty" );
94  
95              final String normalizedPath = FileUtils.normalize( pathString );
96              final File file = new File( normalizedPath );
97              if ( !file.exists() )
98                  throw new MisconfiguredToolchainException( "Non-existing path '" + file.getAbsolutePath() + "'" );
99  
100             paths.add( normalizedPath );
101         }
102 
103         pathsToolchain.setPaths( paths );
104 
105         return pathsToolchain;
106     }
107 
108     public ToolchainPrivate createDefaultToolchain()
109     {
110         return null;
111     }
112 
113     protected Properties getProvidesProperties( final ToolchainModel model )
114     {
115         final Object value = this.getBeanProperty( model, "provides" );
116 
117         return value instanceof Properties ? (Properties) value : toProperties( (Xpp3Dom) value );
118     }
119 
120     protected static Properties toProperties( final Xpp3Dom dom )
121     {
122         final Properties props = new Properties();
123 
124         final Xpp3Dom[] children = dom.getChildren();
125         for ( final Xpp3Dom child : children )
126             props.put( child.getName(), child.getValue() );
127 
128         return props;
129     }
130 
131     protected Object getBeanProperty( final Object obj, final String property )
132     {
133         try
134         {
135             final Method method = new PropertyDescriptor( property, obj.getClass() ).getReadMethod();
136 
137             return method.invoke( obj );
138         }
139         catch ( final IntrospectionException e )
140         {
141             throw new RuntimeException( "Incompatible toolchain API", e );
142         }
143         catch ( final IllegalAccessException e )
144         {
145             throw new RuntimeException( "Incompatible toolchain API", e );
146         }
147         catch ( final InvocationTargetException e )
148         {
149             final Throwable cause = e.getCause();
150 
151             if ( cause instanceof RuntimeException )
152                 throw (RuntimeException) cause;
153 
154             throw new RuntimeException( "Incompatible toolchain API", e );
155         }
156     }
157 }