1   package org.apache.maven.usability.plugin;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
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  
39  
40  
41  public class ExpressionDocumenter
42  {
43  
44      private static final String[] EXPRESSION_ROOTS =
45      {
46          "project", "settings", "session", "plugin", "rootless"
47      };
48  
49      private static final String EXPRESSION_DOCO_ROOTPATH = "META-INF/maven/plugin-expressions/";
50  
51      private static Map<String, Expression> expressionDocumentation;
52  
53      public static Map<String, Expression> load()
54          throws ExpressionDocumentationException
55      {
56          if ( expressionDocumentation == null )
57          {
58              expressionDocumentation = new HashMap<>();
59  
60              ClassLoader docLoader = initializeDocLoader();
61  
62              for ( String root : EXPRESSION_ROOTS )
63              {
64                  try ( InputStream docStream = docLoader.getResourceAsStream(
65                      EXPRESSION_DOCO_ROOTPATH + root + ".paramdoc.xml" ) )
66                  {
67                      if ( docStream != null )
68                      {
69                          Map<String, Expression> doco = parseExpressionDocumentation( docStream );
70  
71                          expressionDocumentation.putAll( doco );
72                      }
73                  }
74                  catch ( IOException e )
75                  {
76                      throw new ExpressionDocumentationException(
77                          "Failed to read documentation for expression root: " + root, e );
78                  }
79                  catch ( XmlPullParserException e )
80                  {
81                      throw new ExpressionDocumentationException(
82                          "Failed to parse documentation for expression root: " + root, e );
83                  }
84  
85              }
86          }
87  
88          return expressionDocumentation;
89      }
90  
91      
92  
93  
94  
95  
96  
97  
98  
99  
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 
110 
111 
112 
113 
114 
115 
116 
117     private static Map<String, Expression> parseExpressionDocumentation( InputStream docStream )
118         throws IOException, XmlPullParserException
119     {
120         Reader reader = new BufferedReader( ReaderFactory.newXmlReader( docStream ) );
121 
122         ParamdocXpp3Reader paramdocReader = new ParamdocXpp3Reader();
123 
124         ExpressionDocumentation documentation = paramdocReader.read( reader, true );
125 
126         List<Expression> expressions = documentation.getExpressions();
127 
128         Map<String, Expression> bySyntax = new HashMap<>();
129 
130         if ( expressions != null && !expressions.isEmpty() )
131         {
132             for ( Expression expression : expressions )
133             {
134                 bySyntax.put( expression.getSyntax(), expression );
135             }
136         }
137 
138         return bySyntax;
139     }
140 
141     private static ClassLoader initializeDocLoader()
142         throws ExpressionDocumentationException
143     {
144         String myResourcePath = ExpressionDocumenter.class.getName().replace( '.', '/' ) + ".class";
145 
146         URL myResource = ExpressionDocumenter.class.getClassLoader().getResource( myResourcePath );
147 
148         assert myResource != null : "The resource is this class itself loaded by its own classloader and must exist";
149 
150         String myClasspathEntry = myResource.getPath();
151 
152         myClasspathEntry = myClasspathEntry.substring( 0, myClasspathEntry.length() - ( myResourcePath.length() + 2 ) );
153 
154         if ( myClasspathEntry.startsWith( "file:" ) )
155         {
156             myClasspathEntry = myClasspathEntry.substring( "file:".length() );
157         }
158 
159         URL docResource;
160         try
161         {
162             docResource = new File( myClasspathEntry ).toURL();
163         }
164         catch ( MalformedURLException e )
165         {
166             throw new ExpressionDocumentationException(
167                 "Cannot construct expression documentation classpath" + " resource base.", e );
168         }
169 
170         return new URLClassLoader( new URL[]
171         {
172             docResource
173         } );
174     }
175 
176 }