View Javadoc
1   package org.apache.maven.usability.plugin;
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 org.apache.maven.usability.plugin.io.xpp3.ParamdocXpp3Reader;
23  import org.codehaus.plexus.util.ReaderFactory;
24  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
25  
26  import java.io.BufferedReader;
27  import java.io.File;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.Reader;
31  import java.net.MalformedURLException;
32  import java.net.URL;
33  import java.net.URLClassLoader;
34  import java.util.HashMap;
35  import java.util.List;
36  import java.util.Map;
37  
38  public class ExpressionDocumenter
39  {
40  
41      private static final String[] EXPRESSION_ROOTS =
42      {
43          "project", "settings", "session", "plugin", "rootless"
44      };
45  
46      private static final String EXPRESSION_DOCO_ROOTPATH = "META-INF/maven/plugin-expressions/";
47  
48      private static Map<String, Expression> expressionDocumentation;
49  
50      public static Map<String, Expression> load()
51          throws ExpressionDocumentationException
52      {
53          if ( expressionDocumentation == null )
54          {
55              expressionDocumentation = new HashMap<>();
56  
57              ClassLoader docLoader = initializeDocLoader();
58  
59              for ( String root : EXPRESSION_ROOTS )
60              {
61                  try ( InputStream docStream = docLoader.getResourceAsStream(
62                      EXPRESSION_DOCO_ROOTPATH + root + ".paramdoc.xml" ) )
63                  {
64                      if ( docStream != null )
65                      {
66                          Map<String, Expression> doco = parseExpressionDocumentation( docStream );
67  
68                          expressionDocumentation.putAll( doco );
69                      }
70                  }
71                  catch ( IOException e )
72                  {
73                      throw new ExpressionDocumentationException(
74                          "Failed to read documentation for expression root: " + root, e );
75                  }
76                  catch ( XmlPullParserException e )
77                  {
78                      throw new ExpressionDocumentationException(
79                          "Failed to parse documentation for expression root: " + root, e );
80                  }
81  
82              }
83          }
84  
85          return expressionDocumentation;
86      }
87  
88      /**
89       * <expressions>
90       * <expression>
91       * <syntax>project.distributionManagementArtifactRepository</syntax>
92       * <origin><![CDATA[
93       * <distributionManagement>
94       * <repository>
95       * <id>some-repo</id>
96       * <url>scp://host/path</url>
97       * </repository>
98       * <snapshotRepository>
99       * <id>some-snap-repo</id>
100      * <url>scp://host/snapshot-path</url>
101      * </snapshotRepository>
102      * </distributionManagement>
103      * ]]></origin>
104      * <usage><![CDATA[
105      * The repositories onto which artifacts should be deployed.
106      * One is for releases, the other for snapshots.
107      * ]]></usage>
108      * </expression>
109      * <expressions>
110      *
111      * @throws IOException
112      * @throws XmlPullParserException
113      */
114     private static Map<String, Expression> parseExpressionDocumentation( InputStream docStream )
115         throws IOException, XmlPullParserException
116     {
117         Reader reader = new BufferedReader( ReaderFactory.newXmlReader( docStream ) );
118 
119         ParamdocXpp3Reader paramdocReader = new ParamdocXpp3Reader();
120 
121         ExpressionDocumentation documentation = paramdocReader.read( reader, true );
122 
123         List<Expression> expressions = documentation.getExpressions();
124 
125         Map<String, Expression> bySyntax = new HashMap<>();
126 
127         if ( expressions != null && !expressions.isEmpty() )
128         {
129             for ( Expression expression : expressions )
130             {
131                 bySyntax.put( expression.getSyntax(), expression );
132             }
133         }
134 
135         return bySyntax;
136     }
137 
138     private static ClassLoader initializeDocLoader()
139         throws ExpressionDocumentationException
140     {
141         String myResourcePath = ExpressionDocumenter.class.getName().replace( '.', '/' ) + ".class";
142 
143         URL myResource = ExpressionDocumenter.class.getClassLoader().getResource( myResourcePath );
144 
145         assert myResource != null : "The resource is this class itself loaded by its own classloader and must exist";
146 
147         String myClasspathEntry = myResource.getPath();
148 
149         myClasspathEntry = myClasspathEntry.substring( 0, myClasspathEntry.length() - ( myResourcePath.length() + 2 ) );
150 
151         if ( myClasspathEntry.startsWith( "file:" ) )
152         {
153             myClasspathEntry = myClasspathEntry.substring( "file:".length() );
154         }
155 
156         URL docResource;
157         try
158         {
159             docResource = new File( myClasspathEntry ).toURL();
160         }
161         catch ( MalformedURLException e )
162         {
163             throw new ExpressionDocumentationException(
164                 "Cannot construct expression documentation classpath" + " resource base.", e );
165         }
166 
167         return new URLClassLoader( new URL[]
168         {
169             docResource
170         } );
171     }
172 
173 }