001package 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 022import org.apache.maven.usability.plugin.io.xpp3.ParamdocXpp3Reader; 023import org.codehaus.plexus.util.IOUtil; 024import org.codehaus.plexus.util.ReaderFactory; 025import org.codehaus.plexus.util.xml.pull.XmlPullParserException; 026 027import java.io.BufferedReader; 028import java.io.File; 029import java.io.IOException; 030import java.io.InputStream; 031import java.io.Reader; 032import java.net.MalformedURLException; 033import java.net.URL; 034import java.net.URLClassLoader; 035import java.util.HashMap; 036import java.util.List; 037import java.util.Map; 038 039public class ExpressionDocumenter 040{ 041 042 private static final String[] EXPRESSION_ROOTS = { "project", "settings", "session", "plugin", "rootless" }; 043 044 private static final String EXPRESSION_DOCO_ROOTPATH = "META-INF/maven/plugin-expressions/"; 045 046 private static Map expressionDocumentation; 047 048 public static Map load() 049 throws ExpressionDocumentationException 050 { 051 if ( expressionDocumentation == null ) 052 { 053 expressionDocumentation = new HashMap(); 054 055 ClassLoader docLoader = initializeDocLoader(); 056 057 for ( String EXPRESSION_ROOT : EXPRESSION_ROOTS ) 058 { 059 InputStream docStream = null; 060 try 061 { 062 docStream = 063 docLoader.getResourceAsStream( EXPRESSION_DOCO_ROOTPATH + EXPRESSION_ROOT + ".paramdoc.xml" ); 064 065 if ( docStream != null ) 066 { 067 Map doco = parseExpressionDocumentation( docStream ); 068 069 expressionDocumentation.putAll( doco ); 070 } 071 } 072 catch ( IOException e ) 073 { 074 throw new ExpressionDocumentationException( 075 "Failed to read documentation for expression root: " + EXPRESSION_ROOT, e ); 076 } 077 catch ( XmlPullParserException e ) 078 { 079 throw new ExpressionDocumentationException( 080 "Failed to parse documentation for expression root: " + EXPRESSION_ROOT, e ); 081 } 082 finally 083 { 084 IOUtil.close( docStream ); 085 } 086 } 087 } 088 089 return expressionDocumentation; 090 } 091 092 /** 093 * <expressions> 094 * <expression> 095 * <syntax>project.distributionManagementArtifactRepository</syntax> 096 * <origin><![CDATA[ 097 * <distributionManagement> 098 * <repository> 099 * <id>some-repo</id> 100 * <url>scp://host/path</url> 101 * </repository> 102 * <snapshotRepository> 103 * <id>some-snap-repo</id> 104 * <url>scp://host/snapshot-path</url> 105 * </snapshotRepository> 106 * </distributionManagement> 107 * ]]></origin> 108 * <usage><![CDATA[ 109 * The repositories onto which artifacts should be deployed. 110 * One is for releases, the other for snapshots. 111 * ]]></usage> 112 * </expression> 113 * <expressions> 114 * @throws IOException 115 * @throws XmlPullParserException 116 */ 117 private static Map 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 expressions = documentation.getExpressions(); 127 128 Map bySyntax = new HashMap(); 129 130 if ( expressions != null && !expressions.isEmpty() ) 131 { 132 for ( Object expression : expressions ) 133 { 134 Expression expr = (Expression) expression; 135 136 bySyntax.put( expr.getSyntax(), expr ); 137 } 138 } 139 140 return bySyntax; 141 } 142 143 private static ClassLoader initializeDocLoader() 144 throws ExpressionDocumentationException 145 { 146 String myResourcePath = ExpressionDocumenter.class.getName().replace( '.', '/' ) + ".class"; 147 148 URL myResource = ExpressionDocumenter.class.getClassLoader().getResource( myResourcePath ); 149 150 assert myResource != null : "The resource is this class itself loaded by its own classloader and must exist"; 151 152 String myClasspathEntry = myResource.getPath(); 153 154 myClasspathEntry = myClasspathEntry.substring( 0, myClasspathEntry.length() - ( myResourcePath.length() + 2 ) ); 155 156 if ( myClasspathEntry.startsWith( "file:" ) ) 157 { 158 myClasspathEntry = myClasspathEntry.substring( "file:".length() ); 159 } 160 161 URL docResource; 162 try 163 { 164 docResource = new File( myClasspathEntry ).toURL(); 165 } 166 catch ( MalformedURLException e ) 167 { 168 throw new ExpressionDocumentationException( "Cannot construct expression documentation classpath" 169 + " resource base.", e ); 170 } 171 172 return new URLClassLoader( new URL[] { docResource } ); 173 } 174 175}