View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.cms.ui.workbench.useradmin;
17  
18  import java.text.DateFormat;
19  import java.text.SimpleDateFormat;
20  import java.util.Arrays;
21  import java.util.Date;
22  import java.util.LinkedList;
23  import java.util.List;
24  
25  import org.argeo.node.ArgeoLogListener;
26  import org.eclipse.jface.viewers.ILazyContentProvider;
27  import org.eclipse.jface.viewers.TableViewer;
28  import org.eclipse.jface.viewers.Viewer;
29  import org.eclipse.swt.widgets.Table;
30  import org.eclipse.swt.widgets.TableItem;
31  
32  /** A content provider maintaining an array of lines */
33  class LogContentProvider implements ILazyContentProvider, ArgeoLogListener {
34  	private static final long serialVersionUID = -2084872367738339721L;
35  
36  	private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
37  
38  	private final Long start;
39  	/** current - start = line number. first line is number '1' */
40  	private Long current;
41  
42  	// TODO make it configurable
43  	private final Integer maxLineBufferSize = 10 * 1000;
44  
45  	private final TableViewer viewer;
46  	private LinkedList<LogLine> lines;
47  
48  	public LogContentProvider(TableViewer viewer) {
49  		this.viewer = viewer;
50  		start = System.currentTimeMillis();
51  		lines = new LinkedList<LogLine>();
52  		current = start;
53  	}
54  
55  	public synchronized void dispose() {
56  		lines.clear();
57  		lines = null;
58  	}
59  
60  	@SuppressWarnings("unchecked")
61  	public synchronized void inputChanged(Viewer viewer, Object oldInput,
62  			Object newInput) {
63  		List<String> lin = (List<String>) newInput;
64  		if (lin == null)
65  			return;
66  		for (String line : lin) {
67  			addLine(line);
68  		}
69  		this.viewer.setItemCount(lines.size());
70  	}
71  
72  	public void updateElement(int index) {
73  		viewer.replace(lines.get(index), index);
74  	}
75  
76  	public synchronized void appendLog(String username, Long timestamp,
77  			String level, String category, String thread, Object msg,
78  			String[] exception) {
79  		// check if valid
80  		if (lines == null)
81  			return;
82  
83  		String message = msg.toString();
84  		int count = 0;
85  		String prefix = prefix(username, timestamp, level, category, thread)
86  				.toString();
87  		// String suffix = suffix(username, timestamp, level, category, thread);
88  		for (String line : message.split("\n")) {
89  			addLine(count == 0 ? prefix + line : line);
90  			count++;
91  		}
92  
93  		if (exception != null) {
94  			for (String ste : exception) {
95  				addLine(ste);
96  			}
97  		}
98  
99  		viewer.getTable().getDisplay().asyncExec(new Runnable() {
100 			public void run() {
101 				if (lines == null)
102 					return;
103 				viewer.setItemCount(lines.size());
104 				// doesn't work with syncExec
105 				scrollToLastLine();
106 			}
107 		});
108 	}
109 
110 	protected StringBuffer prefix(String username, Long timestamp,
111 			String level, String category, String thread) {
112 		StringBuffer buf = new StringBuffer("");
113 		buf.append(dateFormat.format(new Date(timestamp))).append(" ");
114 		// buf.append(level).append(" ");
115 		return buf;
116 	}
117 
118 	/** Normalize string to the given size */
119 	protected String norm(String str, Integer size) {
120 		int length = str.length();
121 		if (length == size)
122 			return str;
123 		else if (length > size)
124 			return str.substring(0, size);
125 		else {
126 			char[] arr = new char[size - length];
127 			Arrays.fill(arr, ' ');
128 			return str + new String(arr);
129 		}
130 	}
131 
132 	// protected String suffix(String username, Long timestamp, String level,
133 	// String category, String thread) {
134 	// return "";
135 	// }
136 
137 	/** Scroll to the last line */
138 	protected synchronized void scrollToLastLine() {
139 		// we try to show last line with two methods
140 		// viewer.reveal(lines.peekLast());
141 
142 		Table table = viewer.getTable();
143 		TableItem ti = table.getItem(table.getItemCount() - 1);
144 		table.showItem(ti);
145 	}
146 
147 	protected synchronized LogLine addLine(String line) {
148 		// check for maximal size and purge if necessary
149 		while (lines.size() >= maxLineBufferSize) {
150 			for (int i = 0; i < maxLineBufferSize / 10; i++) {
151 				lines.poll();
152 			}
153 		}
154 
155 		current++;
156 		LogLine logLine = new LogLine(current, line);
157 		lines.add(logLine);
158 		return logLine;
159 	}
160 
161 	private class LogLine {
162 		private Long linenumber;
163 		private String message;
164 
165 		public LogLine(Long linenumber, String message) {
166 			this.linenumber = linenumber;
167 			this.message = message;
168 		}
169 
170 		@Override
171 		public int hashCode() {
172 			return linenumber.intValue();
173 		}
174 
175 		@Override
176 		public boolean equals(Object obj) {
177 			if (obj instanceof LogLine)
178 				return ((LogLine) obj).linenumber.equals(linenumber);
179 			else
180 				return false;
181 		}
182 
183 		@Override
184 		public String toString() {
185 			return message;
186 		}
187 	}
188 }