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 }