001: /*
002: * MessageBuffer.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.util;
013:
014: import java.util.Collections;
015: import java.util.LinkedList;
016: import java.util.List;
017: import workbench.resource.Settings;
018:
019: /**
020: * A class to store messages efficiently.
021: * The messages are internally stored in a LinkedList, but only up to
022: * a specified maximum number of entries (not total size in bytes)
023: *
024: * If the maximum is reached {@link #getBuffer()} will add "(...)" at the beginning
025: * of the generated result to indicate that messages have been cut off.
026: *
027: * This ensures that collecting warnings or errors during long running
028: * jobs, does not cause an OutOfMemory error.
029: *
030: * @author support@sql-workbench.net
031: */
032: public class MessageBuffer {
033: private LinkedList<CharSequence> messages = new LinkedList<CharSequence>();
034: private int length = 0;
035: private final String newLine = "\n";
036: private final int maxSize;
037: private boolean trimmed = false;
038:
039: /**
040: * Create a new MessageBuffer, retrieving the max. number of entries
041: * from the Settings object. If nothing has been specified in the .settings
042: * file, a maximum number of 1000 entries is used.
043: */
044: public MessageBuffer() {
045: this (Settings.getInstance().getIntProperty(
046: "workbench.messagebuffer.maxentries", 1000));
047: }
048:
049: /**
050: * Create a new MessageBuffer holding a maximum number of <tt>maxEntries</tt>
051: * Entries in its internal list
052: * @param maxEntries the max. number of entries to hold in the internal list
053: */
054: public MessageBuffer(int maxEntries) {
055: maxSize = maxEntries;
056: }
057:
058: /**
059: * Returns an unmodifiable reference to the stored messages.
060: */
061: public List<CharSequence> getMessages() {
062: return Collections.unmodifiableList(messages);
063: }
064:
065: public synchronized void clear() {
066: this .messages.clear();
067: this .length = 0;
068: }
069:
070: /**
071: * Create a StringBuilder that contains the collected messages.
072: * Once the result is returned, the internal list is emptied.
073: * This means the second call to this method returns an empty
074: * buffer if no messages have been added between the calls.
075: */
076: public synchronized CharSequence getBuffer() {
077: StringBuilder result = new StringBuilder(this .length + 50);
078: if (trimmed)
079: result.append("(...)\n");
080:
081: while (messages.size() > 0) {
082: CharSequence s = messages.removeFirst();
083: result.append(s);
084: }
085: length = 0;
086: return result;
087: }
088:
089: private synchronized void trimSize() {
090: if (maxSize > 0 && messages.size() >= maxSize) {
091: trimmed = true;
092: while (messages.size() >= maxSize) {
093: CharSequence s = messages.removeFirst();
094: if (s != null)
095: this .length -= s.length();
096: }
097: }
098: }
099:
100: /**
101: * Returns the total length in characters of all messages
102: * that are currently kept in this MessageBuffer
103: */
104: public synchronized int getLength() {
105: return length;
106: }
107:
108: public synchronized void append(MessageBuffer buff) {
109: if (buff == null)
110: return;
111: int count = buff.messages.size();
112: if (count == 0)
113: return;
114: this .length += buff.length;
115: while (this .messages.size() + count > maxSize) {
116: CharSequence s = messages.removeFirst();
117: if (s != null)
118: this .length -= s.length();
119: }
120: for (CharSequence s : buff.messages) {
121: this .messages.add(s);
122: }
123: }
124:
125: public synchronized void append(CharSequence s) {
126: if (StringUtil.isEmptyString(s))
127: return;
128: trimSize();
129: this .messages.add(s);
130: length += s.length();
131: }
132:
133: public synchronized void appendNewLine() {
134: append(newLine);
135: }
136:
137: public String toString() {
138: return getBuffer().toString();
139: }
140:
141: }
|