001 /** 002 * 003 * Copyright 2005 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.derby; 018 019 import org.apache.geronimo.gbean.GBeanInfo; 020 import org.apache.geronimo.gbean.GBeanInfoBuilder; 021 022 import java.io.File; 023 import java.io.RandomAccessFile; 024 import java.nio.CharBuffer; 025 import java.nio.MappedByteBuffer; 026 import java.nio.channels.FileChannel; 027 import java.nio.charset.Charset; 028 import java.util.LinkedList; 029 import java.util.List; 030 import java.util.regex.Matcher; 031 import java.util.regex.Pattern; 032 import java.util.regex.PatternSyntaxException; 033 034 /** 035 * ReplaceMe 036 * 037 * @version $Rev: 355877 $ $Date: 2005-12-10 18:48:27 -0800 (Sat, 10 Dec 2005) $ 038 */ 039 public class DerbyLogGBean implements DerbyLog { 040 // Pattern that matches a single line (used to calculate line numbers and text search in a line) 041 private final static Pattern FULL_LINE_PATTERN = Pattern.compile("^.*", Pattern.MULTILINE); 042 private final DerbySystem derby; 043 private File logFile = null; 044 045 public DerbyLogGBean(DerbySystem derby) { 046 this.derby = derby; 047 } 048 049 public SearchResults searchLog(Integer startLine, Integer endLine, Integer max, String text) { 050 // Get log file 051 if(logFile == null) { 052 logFile = new File(derby.getDerbyHome(), "derby.log"); 053 if(!logFile.canRead()) { 054 throw new IllegalStateException("Cannot read Derby log file at '"+logFile.getAbsolutePath()+"'"); 055 } 056 } 057 // Check that the text pattern is valid 058 Pattern textPattern; 059 try { 060 textPattern = text == null || text.equals("") ? null : Pattern.compile(text); 061 } catch (PatternSyntaxException e) { 062 throw new IllegalArgumentException("Bad regular expression '"+text+"'"); 063 } 064 return searchFile(logFile, textPattern, startLine, endLine, 065 max == null ? MAX_SEARCH_RESULTS : Math.min(MAX_SEARCH_RESULTS, max.intValue())); 066 } 067 068 private static SearchResults searchFile(File file, Pattern textSearch, Integer start, Integer stop, int max) { 069 List list = new LinkedList(); 070 boolean capped = false; 071 int lineCount = 0; 072 try { 073 RandomAccessFile raf = new RandomAccessFile(file, "r"); 074 FileChannel fc = raf.getChannel(); 075 MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); 076 CharBuffer cb = Charset.forName("US-ASCII").decode(bb); //todo: does Derby use a different charset on a foreign PC? 077 Matcher lines = FULL_LINE_PATTERN.matcher(cb); 078 Matcher text = textSearch == null ? null : textSearch.matcher(""); 079 max = Math.min(max, MAX_SEARCH_RESULTS); 080 while(lines.find()) { 081 ++lineCount; 082 if(start != null && start.intValue() > lineCount) { 083 continue; 084 } 085 if(stop != null && stop.intValue() < lineCount) { 086 continue; 087 } 088 CharSequence line = cb.subSequence(lines.start(), lines.end()); 089 if(text != null) { 090 text.reset(line); 091 if(!text.find()) { 092 continue; 093 } 094 } 095 list.add(new LogMessage(lineCount,line.toString())); 096 if(list.size() > max) { 097 list.remove(0); 098 capped = true; 099 } 100 } 101 fc.close(); 102 raf.close(); 103 } catch (Exception e) {} 104 return new SearchResults(lineCount, (LogMessage[]) list.toArray(new LogMessage[list.size()]), capped); 105 } 106 public static final GBeanInfo GBEAN_INFO; 107 108 static { 109 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Derby Log", DerbyLogGBean.class); 110 111 infoFactory.addReference("DerbySystem", DerbySystem.class, "GBean"); 112 infoFactory.addInterface(DerbyLog.class); 113 infoFactory.setConstructor(new String[]{"DerbySystem"}); 114 115 GBEAN_INFO = infoFactory.getBeanInfo(); 116 } 117 118 public static GBeanInfo getGBeanInfo() { 119 return GBEAN_INFO; 120 } 121 }