001 package net.sf.logdistiller.gui; 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.awt.BorderLayout; 018 import java.awt.Component; 019 import java.awt.Container; 020 import java.awt.Frame; 021 import java.awt.LayoutManager; 022 import java.awt.event.ActionEvent; 023 import java.io.*; 024 import java.util.HashMap; 025 import java.util.List; 026 import java.util.Map; 027 import javax.swing.*; 028 029 import com.jgoodies.forms.factories.ButtonBarFactory; 030 import com.jgoodies.forms.factories.DefaultComponentFactory; 031 import org.apache.commons.io.IOUtils; 032 import org.apache.commons.lang.StringUtils; 033 034 import net.sf.logdistiller.LogType; 035 import net.sf.logdistiller.LogTypes; 036 import net.sf.logdistiller.util.FormatUtil; 037 import net.sf.logdistiller.util.PropertiesReplacer; 038 039 /** 040 * Dialog to create a new rules configuration file: you select the log type and give some basic information (an id, STMP 041 * server, url), and it generates a new rules configuration. Then you just need to refine the rules. 042 */ 043 public class NewDialog 044 { 045 private File currentDir; 046 047 public NewDialog( File directory ) 048 { 049 currentDir = directory; 050 } 051 052 protected JPanel panel = new JPanel(); 053 054 private JTextField tfId = new JTextField( "rules-id", 15 ); 055 056 private JTextField tfDescription = new JTextField( "rules description" ); 057 058 private JComboBox cbLogtype; 059 060 private JTextField tfSmtp = new JTextField( "smtp.provider.com" ); 061 062 private JTextField tfMailTo = new JTextField( "admin@localhost" ); 063 064 private JTextField tfHttp = new JTextField( "http://mysite.com/logdistiller/logs" ); 065 066 private JButton btSaveAs = new JButton( "save as..." ); 067 068 private JButton btCancel = new JButton( "cancel" ); 069 070 public static JComboBox createCbLogtype( boolean withUndefined ) 071 { 072 List logtypes = LogTypes.getAllLogTypes(); 073 int len = logtypes.size(); 074 String[] logtypeIds = new String[len]; 075 for ( int i = 0; i < len; i++ ) 076 { 077 logtypeIds[i] = ( (LogType) logtypes.get( i ) ).getId(); 078 } 079 JComboBox cb = new JComboBox( logtypeIds ); 080 if ( withUndefined ) 081 { 082 cb.insertItemAt( "undefined", 0 ); 083 cb.setSelectedIndex( 0 ); 084 } 085 return cb; 086 } 087 088 private void initComponents() 089 { 090 cbLogtype = createCbLogtype( false ); 091 092 btSaveAs.addActionListener( SwingAdapter.getActionListener( this, "btSaveAsActionPerformed" ) ); 093 btCancel.addActionListener( SwingAdapter.getActionListener( this, "btCancelActionPerformed" ) ); 094 } 095 096 private void addLabel( String label, String id ) 097 { 098 panel.add( new JLabel( label ), id ); 099 } 100 101 private void addSeparator( String label, String id ) 102 { 103 panel.add( DefaultComponentFactory.getInstance().createSeparator( label ), id ); 104 } 105 106 public LayoutManager createLayout( String layoutId ) 107 { 108 return MainPanel.SIMPLE_LAYOUT_CONSTRAINTS_MANAGER.getLayout( layoutId ); 109 } 110 111 public JComponent buildPanel() 112 { 113 initComponents(); 114 115 panel.setBorder( com.jgoodies.forms.factories.Borders.DIALOG_BORDER ); 116 panel.setLayout( createLayout( "newDialog" ) ); 117 118 addSeparator( "main parameters", "sepMain" ); 119 addLabel( "configuration id:", "lblId" ); 120 panel.add( tfId, "tfId" ); 121 addLabel( "configuration description:", "lblDescription" ); 122 panel.add( tfDescription, "tfDescription" ); 123 addLabel( "logtype:", "lblLogtype" ); 124 panel.add( cbLogtype, "cbLogtype" ); 125 126 addSeparator( "advanced parameters", "sepOptions" ); 127 addLabel( "SMTP host:", "lblSmtp" ); 128 panel.add( tfSmtp, "tfSmtp" ); 129 addLabel( "mail reports to:", "lblMailTo" ); 130 panel.add( tfMailTo, "tfMailTo" ); 131 addLabel( "reports publication URL:", "lblHttp" ); 132 panel.add( tfHttp, "tfHttp" ); 133 134 Component bbar = ButtonBarFactory.buildRightAlignedBar( new JButton[] { btSaveAs, btCancel } ); 135 panel.add( bbar, "bbar" ); 136 137 return panel; 138 } 139 140 private JDialog createDialog( Component parent ) 141 { 142 Frame frame = 143 parent instanceof Frame ? (Frame) parent : (Frame) SwingUtilities.getAncestorOfClass( Frame.class, parent ); 144 JDialog dialog = new JDialog( frame, "new classification rules configuration", true ); 145 146 Container contentPane = dialog.getContentPane(); 147 contentPane.setLayout( new BorderLayout() ); 148 contentPane.add( buildPanel(), BorderLayout.CENTER ); 149 150 dialog.pack(); 151 dialog.setLocationRelativeTo( parent ); 152 return dialog; 153 } 154 155 private JDialog dialog; 156 157 public File showNewConfigurationDialog( Component parent ) 158 { 159 dialog = createDialog( parent ); 160 dialog.show(); 161 dialog.dispose(); 162 dialog = null; 163 return configurationFile; 164 } 165 166 private File configurationFile; 167 168 public void btSaveAsActionPerformed( ActionEvent ae ) 169 { 170 JFileChooser fc = new JFileChooser( currentDir ); 171 fc.setFileFilter( new XmlFileFilter() ); 172 fc.setSelectedFile( new File( currentDir, tfId.getText() + ".xml" ) ); 173 int ret = fc.showSaveDialog( dialog ); 174 if ( ret == JFileChooser.APPROVE_OPTION ) 175 { 176 saveConfigurationFile( fc.getSelectedFile() ); 177 configurationFile = fc.getSelectedFile(); 178 if ( dialog != null ) 179 { 180 dialog.setVisible( false ); 181 } 182 } 183 } 184 185 /** 186 * Saves a new rules configuration to a file. 187 * 188 * @param fileTo the file to save to 189 */ 190 private void saveConfigurationFile( File fileTo ) 191 { 192 try 193 { 194 PrintWriter out = new PrintWriter( new OutputStreamWriter( new FileOutputStream( fileTo ), "utf-8" ) ); 195 generateConfiguration( out ); 196 out.close(); 197 } 198 catch ( FileNotFoundException fnfe ) 199 { 200 fnfe.printStackTrace(); 201 } 202 catch ( UnsupportedEncodingException uee ) 203 { 204 uee.printStackTrace(); 205 } 206 } 207 208 /** 209 * Generate a new configuration stream by filling <code>reference-rules.xml</code> with values taken from the GUI. 210 * 211 * @param out the stream to write to (in UTF-8 encoding) 212 */ 213 private void generateConfiguration( PrintWriter out ) 214 { 215 LogType logtype = LogTypes.getLogType( (String) cbLogtype.getSelectedItem() ); 216 LogType.Description description = logtype.newDescription( new HashMap() ); 217 218 String logeventAttributes = FormatUtil.join( ",", description.getAttributeNames() ); 219 int dateAttributeIndex = description.getTimestampAttribute(); 220 221 try 222 { 223 String reference = IOUtils.toString( MainPanel.class.getResourceAsStream( "reference-rules.xml" ), "UTF-8" ); 224 225 Map properties = new HashMap(); 226 properties.put( "id", tfId.getText() ); 227 properties.put( "description", tfDescription.getText() ); 228 properties.put( "logtype", cbLogtype.getSelectedItem() ); 229 properties.put( "logtype.attributes", logeventAttributes ); 230 properties.put( "mail.to", tfMailTo.getText() ); 231 properties.put( "mail.smtp.host", tfSmtp.getText() ); 232 properties.put( "logs.url", tfHttp.getText() ); 233 properties.put( "logtype.groups", description.getDefaultSpecificGroups() ); 234 235 String skipCondition = // default matching condition for skip group, if no timestamp available 236 " <!-- this logtype does not have a timestamp: we can't really skip events with bad date -->\n" 237 + " <match attribute=\"logSource\" type=\"equals\"></match>\n" 238 + " <!-- if this logtype had a timestamp, the condition would look like the following: -->\n" 239 + " <!--match attribute=\"(timestamp attribute?)\" type=\"!contains\">${date}</match!-->"; 240 if ( dateAttributeIndex >= 0 ) 241 { 242 skipCondition = 243 " <match attribute=\"" + description.getAttributeName( dateAttributeIndex ) 244 + "\" type=\"!contains\">${date}</match>"; 245 } 246 properties.put( "skip.condition", skipCondition ); 247 248 // let's compute the sampling.rule property for this LogType 249 String samplingAttributes = description.getDefaultSamplingAttributes(); 250 String samplingRule = // default comment when no sampling attributes defined 251 "\n <!--plugin type=\"sampling\">\n" 252 + " <param name=\"attributes\">most discriminating attribute</param>\n" 253 + " </plugin-->"; 254 if ( samplingAttributes.length() > 0 ) 255 { 256 // ok, there are sampling attributes 257 samplingRule = 258 "\n <plugin type=\"sampling\">\n" 259 + " <param name=\"attributes\">" + samplingAttributes + "</param>\n" 260 + " </plugin>"; 261 } 262 properties.put( "sampling.rule", samplingRule ); 263 264 PropertiesReplacer repl = new PropertiesReplacer( properties, "#(", ")" ); 265 266 out.print( repl.replaceProperties( reference ) ); 267 } 268 catch ( IOException ioe ) 269 { 270 ioe.printStackTrace(); 271 } 272 } 273 274 public void btCancelActionPerformed( ActionEvent ae ) 275 { 276 configurationFile = null; 277 if ( dialog != null ) 278 { 279 dialog.setVisible( false ); 280 } 281 } 282 }