001    package org.apache.maven.usability.plugin;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.maven.usability.plugin.io.xpp3.ParamdocXpp3Reader;
023    import org.codehaus.plexus.util.IOUtil;
024    import org.codehaus.plexus.util.ReaderFactory;
025    import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
026    
027    import java.io.BufferedReader;
028    import java.io.File;
029    import java.io.IOException;
030    import java.io.InputStream;
031    import java.io.Reader;
032    import java.net.MalformedURLException;
033    import java.net.URL;
034    import java.net.URLClassLoader;
035    import java.util.HashMap;
036    import java.util.Iterator;
037    import java.util.List;
038    import java.util.Map;
039    
040    public class ExpressionDocumenter
041    {
042    
043        private static final String[] EXPRESSION_ROOTS = { "project", "settings", "session", "plugin", "rootless" };
044    
045        private static final String EXPRESSION_DOCO_ROOTPATH = "META-INF/maven/plugin-expressions/";
046    
047        private static Map expressionDocumentation;
048    
049        public static Map load()
050            throws ExpressionDocumentationException
051        {
052            if ( expressionDocumentation == null )
053            {
054                expressionDocumentation = new HashMap();
055    
056                ClassLoader docLoader = initializeDocLoader();
057    
058                for ( String EXPRESSION_ROOT : EXPRESSION_ROOTS )
059                {
060                    InputStream docStream = null;
061                    try
062                    {
063                        docStream =
064                            docLoader.getResourceAsStream( EXPRESSION_DOCO_ROOTPATH + EXPRESSION_ROOT + ".paramdoc.xml" );
065    
066                        if ( docStream != null )
067                        {
068                            Map doco = parseExpressionDocumentation( docStream );
069    
070                            expressionDocumentation.putAll( doco );
071                        }
072                    }
073                    catch ( IOException e )
074                    {
075                        throw new ExpressionDocumentationException(
076                            "Failed to read documentation for expression root: " + EXPRESSION_ROOT, e );
077                    }
078                    catch ( XmlPullParserException e )
079                    {
080                        throw new ExpressionDocumentationException(
081                            "Failed to parse documentation for expression root: " + EXPRESSION_ROOT, e );
082                    }
083                    finally
084                    {
085                        IOUtil.close( docStream );
086                    }
087                }
088            }
089    
090            return expressionDocumentation;
091        }
092    
093        /**
094         * <expressions>
095         *   <expression>
096         *     <syntax>project.distributionManagementArtifactRepository</syntax>
097         *     <origin><![CDATA[
098         *   <distributionManagement>
099         *     <repository>
100         *       <id>some-repo</id>
101         *       <url>scp://host/path</url>
102         *     </repository>
103         *     <snapshotRepository>
104         *       <id>some-snap-repo</id>
105         *       <url>scp://host/snapshot-path</url>
106         *     </snapshotRepository>
107         *   </distributionManagement>
108         *   ]]></origin>
109         *     <usage><![CDATA[
110         *   The repositories onto which artifacts should be deployed.
111         *   One is for releases, the other for snapshots.
112         *   ]]></usage>
113         *   </expression>
114         * <expressions>
115         * @throws IOException
116         * @throws XmlPullParserException
117         */
118        private static Map parseExpressionDocumentation( InputStream docStream )
119            throws IOException, XmlPullParserException
120        {
121            Reader reader = new BufferedReader( ReaderFactory.newXmlReader( docStream ) );
122    
123            ParamdocXpp3Reader paramdocReader = new ParamdocXpp3Reader();
124    
125            ExpressionDocumentation documentation = paramdocReader.read( reader, true );
126    
127            List expressions = documentation.getExpressions();
128    
129            Map bySyntax = new HashMap();
130    
131            if ( expressions != null && !expressions.isEmpty() )
132            {
133                for ( Object expression : expressions )
134                {
135                    Expression expr = (Expression) expression;
136    
137                    bySyntax.put( expr.getSyntax(), expr );
138                }
139            }
140    
141            return bySyntax;
142        }
143    
144        private static ClassLoader initializeDocLoader()
145            throws ExpressionDocumentationException
146        {
147            String myResourcePath = ExpressionDocumenter.class.getName().replace( '.', '/' ) + ".class";
148    
149            URL myResource = ExpressionDocumenter.class.getClassLoader().getResource( myResourcePath );
150    
151            String myClasspathEntry = myResource.getPath();
152    
153            myClasspathEntry = myClasspathEntry.substring( 0, myClasspathEntry.length() - ( myResourcePath.length() + 2 ) );
154    
155            if ( myClasspathEntry.startsWith( "file:" ) )
156            {
157                myClasspathEntry = myClasspathEntry.substring( "file:".length() );
158            }
159    
160            URL docResource;
161            try
162            {
163                docResource = new File( myClasspathEntry ).toURL();
164            }
165            catch ( MalformedURLException e )
166            {
167                throw new ExpressionDocumentationException(
168                                                            "Cannot construct expression documentation classpath resource base.",
169                                                            e );
170            }
171    
172            return new URLClassLoader( new URL[] { docResource } );
173        }
174    
175    }