001 package 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 017 import java.io.IOException; 018 import java.io.Reader; 019 import java.util.*; 020 021 import net.sf.logdistiller.Attributes.Extension; 022 import 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 */ 033 public 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 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 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 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(); 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 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 (String) 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 ( Iterator iter = extension.getProvides().iterator(); iter.hasNext(); ) 148 { 149 String attribute = (String)iter.next(); 150 extendedAttributes.put( attribute, new Integer( i ) ); 151 } 152 } 153 } 154 155 /** @since 1.1 */ 156 public Attributes.Extension[] getExtensions() 157 { 158 return extensions; 159 } 160 161 /** 162 * Gets the extension index position which defines corresponding attribute. 163 * 164 * @return the extension index, or -1 if not found 165 * @since 1.1 166 */ 167 public int getExtensionIndex( String attribute ) 168 { 169 Integer index = (Integer) extendedAttributes.get( attribute ); 170 return ( index == null ) ? -1 : index.intValue(); 171 } 172 173 /** 174 * Get the attribute that represents the timestamp. 175 * 176 * @return the attribute count, or <code>-1</code> if this logtype does not have a timestamp 177 */ 178 public int getTimestampAttribute() 179 { 180 return 1; 181 } 182 183 /** 184 * Get the group definitions specific to this log type that will be added to the generated rules configuration 185 * generated by the GUI. 186 * 187 * @return an XML fragment containing group definitions 188 */ 189 public String getDefaultSpecificGroups() 190 { 191 return ""; 192 } 193 194 /** 195 * Get the attributes that can be used as a sorting key to get useful event sampling in the last "unknown" group 196 * (separated with a quote when multiple attributes). They will be used as a default sampling rule 197 * configuration. 198 * 199 * @return "attr1[,attr2[,...]]" 200 */ 201 public String getDefaultSamplingAttributes() 202 { 203 return ""; 204 } 205 206 /** 207 * Find the attribute index corresponding to an attribute name (provided attributes only). 208 * 209 * @param name String the attribute name to search for 210 * @return int the index of the attribute, or -1 if not found 211 * @see #getExtensionIndex(String) to find an extension attribute index 212 */ 213 public int getAttributeIndex( String name ) 214 { 215 return attributeNames.indexOf( name ); 216 } 217 218 public AttributeInfo getAttributeInfo( String name ) 219 { 220 int index = getAttributeIndex( name ); 221 if ( index > -1 ) 222 { 223 return new AttributeInfo( index ); 224 } 225 index = getExtensionIndex( name ); 226 if ( index < 0 ) 227 { 228 throw new IllegalArgumentException( "unknown attribute '" + name + "'. " 229 + "Provided attributes are: " + FormatUtil.join( ", ", getAttributeNames() ) 230 + ", extended attributes are: " + FormatUtil.join( ", ", extendedAttributes.keySet() ) + "." ); 231 } 232 Extension extension = extensions[index]; 233 return new AttributeInfo( index, extension.getProvides().indexOf( name ) ); 234 } 235 236 /** 237 * Create a new LogEvent factory for a log stream corresponding to this log description. 238 * 239 * @param reader the stream containing to parse 240 * @param logSource a textual description of the stream's source (useful when LogDistiller works on multiple 241 * simultaneous log sources) 242 */ 243 public abstract LogEvent.Factory newFactory( Reader reader, String logSource ) 244 throws IOException; 245 } 246 247 public static class AttributeInfo 248 { 249 public final boolean extended; 250 251 public final int index; 252 253 public final int regexpGroup; 254 255 AttributeInfo( int index ) 256 { 257 extended = false; 258 this.index = index; 259 regexpGroup = -1; 260 } 261 262 AttributeInfo( int index, int regexpGroup ) 263 { 264 extended = true; 265 this.index = index; 266 this.regexpGroup = regexpGroup; 267 } 268 } 269 }