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