001package net.sf.logdistiller; 002 003/* 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017import java.io.IOException; 018import java.io.Reader; 019import java.util.*; 020 021import net.sf.logdistiller.Attributes.Extension; 022import net.sf.logdistiller.util.FormatUtil; 023 024/** 025 * Base class for log type implementation. A log type identifies the log format, which can be customized depending on 026 * parameter's values. When defining a new log type, {@link #newDescription newDescription(Map params)} method has to be 027 * implemented to define and handle log type's parameters. 028 * 029 * @see LogType.Basic 030 * @see LogType.Description 031 * @see LogTypes 032 */ 033public abstract class LogType 034{ 035 private final String id; 036 037 protected LogType( String id ) 038 { 039 this.id = id; 040 } 041 042 /** 043 * Create a new log description customized with parameters. 044 * 045 * @param params the parameters to customize the log type definition 046 */ 047 public abstract Description newDescription( Map<String, String> params ); 048 049 public String getId() 050 { 051 return id; 052 } 053 054 /** 055 * Basic logtype definition that does not provide any parameters for customization. It always returns the same 056 * Description instance, which must have been set by calling {@link #setDescription}. 057 */ 058 public static class Basic 059 extends LogType 060 { 061 private Description description; 062 063 public Basic( String id ) 064 { 065 super( id ); 066 } 067 068 public void setDescription( Description description ) 069 { 070 this.description = description; 071 } 072 073 public Description newDescription( Map<String, String> params ) 074 { 075 if ( description == null ) 076 { 077 throw new IllegalStateException( "description must be set before basic logtype use" ); 078 } 079 return description; 080 } 081 } 082 083 /** 084 * Description of a log format corresponding to a log type. It must be subclassed for every log type to implement 085 * specialized {@link #newFactory(Reader, String)} method. 086 */ 087 public static abstract class Description 088 { 089 private final LogType logtype; 090 091 private final List<String> attributeNames; 092 093 /** 094 * Extensions of the log type attributes. Each extension can define multiple extension attributes. 095 * @since 1.1 096 */ 097 private Attributes.Extension[] extensions = Attributes.NO_EXTENSIONS; 098 099 /** 100 * Attributes defined by extensions, with corresponding extension index position. 101 * @since 1.1 102 */ 103 private Map<String, Integer> extendedAttributes = new HashMap<String, Integer>(); 104 105 /** 106 * Create a new LogType description. By convention, the first attribute should be <code>logSource</code> and the 107 * second should be the timestamp (if this notion is relevant for the log type). 108 * 109 * @param logtype 110 * @param attributeNames 111 * @see #getTimestampAttribute() 112 * @see LogEvent#getTimestamp() 113 */ 114 public Description( LogType logtype, String[] attributeNames ) 115 { 116 this.logtype = logtype; 117 this.attributeNames = Collections.unmodifiableList( Arrays.asList( attributeNames ) ); 118 } 119 120 public LogType getLogType() 121 { 122 return logtype; 123 } 124 125 public List<String> getAttributeNames() 126 { 127 return attributeNames; 128 } 129 130 public int getAttributesCount() 131 { 132 return attributeNames.size(); 133 } 134 135 public String getAttributeName( int pos ) 136 { 137 return attributeNames.get( pos ); 138 } 139 140 /** @since 1.1 */ 141 public void setExtensions( Attributes.Extension[] extensions ) 142 { 143 this.extensions = extensions; 144 for ( int i = extensions.length - 1; i >= 0; i-- ) 145 { 146 Attributes.Extension extension = extensions[i]; 147 for ( String attribute : extension.getProvides() ) 148 { 149 extendedAttributes.put( attribute, new Integer( i ) ); 150 } 151 } 152 } 153 154 /** @since 1.1 */ 155 public Attributes.Extension[] getExtensions() 156 { 157 return extensions; 158 } 159 160 /** 161 * Gets the extension index position which defines corresponding attribute. 162 * 163 * @return the extension index, or -1 if not found 164 * @since 1.1 165 */ 166 public int getExtensionIndex( String attribute ) 167 { 168 Integer index = extendedAttributes.get( attribute ); 169 return ( index == null ) ? -1 : index.intValue(); 170 } 171 172 /** 173 * Get the attribute that represents the timestamp. 174 * 175 * @return the attribute count, or <code>-1</code> if this logtype does not have a timestamp 176 */ 177 public int getTimestampAttribute() 178 { 179 return 1; 180 } 181 182 /** 183 * Get the group definitions specific to this log type that will be added to the generated rules configuration 184 * generated by the GUI. 185 * 186 * @return an XML fragment containing group definitions 187 */ 188 public String getDefaultSpecificGroups() 189 { 190 return ""; 191 } 192 193 /** 194 * Get the attributes that can be used as a sorting key to get useful event sampling in the last "unknown" group 195 * (separated with a quote when multiple attributes). They will be used as a default sampling rule 196 * configuration. 197 * 198 * @return "attr1[,attr2[,...]]" 199 */ 200 public String getDefaultSamplingAttributes() 201 { 202 return ""; 203 } 204 205 /** 206 * Find the attribute index corresponding to an attribute name (provided attributes only). 207 * 208 * @param name String the attribute name to search for 209 * @return int the index of the attribute, or -1 if not found 210 * @see #getExtensionIndex(String) to find an extension attribute index 211 */ 212 public int getAttributeIndex( String name ) 213 { 214 return attributeNames.indexOf( name ); 215 } 216 217 public AttributeInfo getAttributeInfo( String name ) 218 { 219 int index = getAttributeIndex( name ); 220 if ( index > -1 ) 221 { 222 return new AttributeInfo( index ); 223 } 224 index = getExtensionIndex( name ); 225 if ( index < 0 ) 226 { 227 throw new IllegalArgumentException( "unknown attribute '" + name + "'. " 228 + "Provided attributes are: " + FormatUtil.join( ", ", getAttributeNames() ) 229 + ", extended attributes are: " + FormatUtil.join( ", ", extendedAttributes.keySet() ) + "." ); 230 } 231 Extension extension = extensions[index]; 232 return new AttributeInfo( index, extension.getProvides().indexOf( name ) ); 233 } 234 235 /** 236 * Create a new LogEvent factory for a log stream corresponding to this log description. 237 * 238 * @param reader the stream containing to parse 239 * @param logSource a textual description of the stream's source (useful when LogDistiller works on multiple 240 * simultaneous log sources) 241 */ 242 public abstract LogEvent.Factory newFactory( Reader reader, String logSource ) 243 throws IOException; 244 } 245 246 public static class AttributeInfo 247 { 248 public final boolean extended; 249 250 public final int index; 251 252 public final int regexpGroup; 253 254 AttributeInfo( int index ) 255 { 256 extended = false; 257 this.index = index; 258 regexpGroup = -1; 259 } 260 261 AttributeInfo( int index, int regexpGroup ) 262 { 263 extended = true; 264 this.index = index; 265 this.regexpGroup = regexpGroup; 266 } 267 } 268}