001package org.apache.maven.doxia.parser; 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 java.io.File; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.Reader; 026import java.io.StringReader; 027 028import java.util.Properties; 029 030import org.apache.maven.doxia.logging.Log; 031import org.apache.maven.doxia.logging.SystemStreamLog; 032import org.apache.maven.doxia.macro.Macro; 033import org.apache.maven.doxia.macro.MacroExecutionException; 034import org.apache.maven.doxia.macro.MacroRequest; 035import org.apache.maven.doxia.macro.manager.MacroManager; 036import org.apache.maven.doxia.macro.manager.MacroNotFoundException; 037import org.apache.maven.doxia.sink.Sink; 038import org.codehaus.plexus.component.annotations.Requirement; 039 040/** 041 * An abstract base class that defines some convenience methods for parsers. 042 * Provides a macro mechanism to give dynamic functionalities for the parsing. 043 * 044 * @author Jason van Zyl 045 * @since 1.0 046 */ 047public abstract class AbstractParser 048 implements Parser 049{ 050 /** Indicates that a second parsing is required. */ 051 private boolean secondParsing = false; 052 053 @Requirement 054 private MacroManager macroManager; 055 056 /** Log instance. */ 057 private Log logger; 058 059 /** 060 * Emit Doxia comment events when parsing comments? 061 */ 062 private boolean emitComments = true; 063 064 private static final String DOXIA_VERSION; 065 066 static 067 { 068 final Properties props = new Properties(); 069 final InputStream is = AbstractParser.class.getResourceAsStream( "/build-info.properties" ); 070 071 if ( is == null ) 072 { 073 props.setProperty( "version", "unknown" ); // should not happen 074 } 075 else 076 { 077 try 078 { 079 props.load( is ); 080 } 081 catch ( IOException ex ) 082 { 083 props.setProperty( "version", "unknown" ); // should not happen 084 } 085 finally 086 { 087 try 088 { 089 is.close(); 090 } 091 catch ( IOException ex ) 092 { 093 // oh well... 094 } 095 } 096 } 097 098 DOXIA_VERSION = props.getProperty( "version" ); 099 } 100 101 /** 102 * {@inheritDoc} 103 * 104 * @return a int 105 */ 106 public int getType() 107 { 108 return UNKNOWN_TYPE; 109 } 110 111 /** {@inheritDoc} */ 112 public void setEmitComments( boolean emitComments ) 113 { 114 this.emitComments = emitComments; 115 } 116 117 /** 118 * <p>isEmitComments.</p> 119 * 120 * @return a boolean 121 */ 122 public boolean isEmitComments() 123 { 124 return emitComments; 125 } 126 127 /** 128 * Execute a macro on the given sink. 129 * 130 * @param macroId an id to lookup the macro 131 * @param request the corresponding MacroRequest 132 * @param sink the sink to receive the events 133 * @throws org.apache.maven.doxia.macro.MacroExecutionException if an error occurred during execution 134 * @throws org.apache.maven.doxia.macro.manager.MacroNotFoundException if the macro could not be found 135 */ 136 // Made public right now because of the structure of the APT parser and 137 // all its inner classes. 138 public void executeMacro( String macroId, MacroRequest request, Sink sink ) 139 throws MacroExecutionException, MacroNotFoundException 140 { 141 Macro macro = getMacroManager().getMacro( macroId ); 142 143 macro.enableLogging( getLog() ); 144 145 macro.execute( sink, request ); 146 } 147 148 /** 149 * Returns the current base directory. 150 * 151 * @return the base directory 152 * @deprecated this does not work in multi-module builds, see DOXIA-373 153 */ 154 protected File getBasedir() 155 { 156 // TODO: This is baaad, it should come in with the request. 157 // (this is only used for macro requests, see AptParser) 158 159 String basedir = System.getProperty( "basedir" ); 160 161 if ( basedir != null ) 162 { 163 return new File( basedir ); 164 } 165 166 return new File( new File( "" ).getAbsolutePath() ); 167 } 168 169 /** 170 * {@inheritDoc} 171 * 172 * Convenience method to parse an arbitrary string and emit events into the given sink. 173 * 174 * @param string a string that provides the source input 175 * @param sink a sink that consumes the Doxia events 176 * @throws org.apache.maven.doxia.parser.ParseException if the string could not be parsed 177 * @since 1.1 178 */ 179 public void parse( String string, Sink sink ) 180 throws ParseException 181 { 182 this.parse( string, sink, null ); 183 } 184 185 /** 186 * {@inheritDoc} 187 * 188 * Convenience method to parse an arbitrary string and emit events into the given sink. 189 * 190 * @param string a string that provides the source input 191 * @param sink a sink that consumes the Doxia events 192 * @param reference a string containing the reference to the source of the input string (e.g. filename) 193 * @throws org.apache.maven.doxia.parser.ParseException if the string could not be parsed 194 * @since 1.10 195 */ 196 public void parse( String string, Sink sink, String reference ) 197 throws ParseException 198 { 199 parse( new StringReader( string ), sink, reference ); 200 } 201 202 /** {@inheritDoc} */ 203 @Override 204 public void parse( Reader source, Sink sink ) 205 throws ParseException 206 { 207 parse( source, sink, null ); 208 } 209 210 /** 211 * Set <code>secondParsing</code> to true, if we need a second parsing. 212 * 213 * @param second true for second parsing 214 */ 215 public void setSecondParsing( boolean second ) 216 { 217 this.secondParsing = second; 218 } 219 220 /** 221 * Indicates if we are currently parsing a second time. 222 * 223 * @return true if we are currently parsing a second time 224 * @since 1.1 225 */ 226 protected boolean isSecondParsing() 227 { 228 return secondParsing; 229 } 230 231 /** {@inheritDoc} */ 232 public void enableLogging( Log log ) 233 { 234 this.logger = log; 235 } 236 237 /** 238 * Returns the current logger for this parser. 239 * If no logger has been configured yet, a new SystemStreamLog is returned. 240 * 241 * @return Log 242 * @since 1.1 243 */ 244 protected Log getLog() 245 { 246 if ( logger == null ) 247 { 248 logger = new SystemStreamLog(); 249 } 250 251 return logger; 252 } 253 254 /** 255 * Gets the current {@link MacroManager}. 256 * 257 * @return the current {@link MacroManager} 258 * @since 1.1 259 */ 260 protected MacroManager getMacroManager() 261 { 262 return macroManager; 263 } 264 265 /** 266 * Initialize the parser. This is called first by 267 * {@link #parse(java.io.Reader, org.apache.maven.doxia.sink.Sink)} and can be used 268 * to set the parser into a clear state so it can be re-used. 269 * 270 * @since 1.1.2 271 */ 272 protected void init() 273 { 274 // nop 275 } 276 277 /** 278 * The current Doxia version. 279 * 280 * @return the current Doxia version as a String 281 * @since 1.2 282 */ 283 protected static String doxiaVersion() 284 { 285 return DOXIA_VERSION; 286 } 287}