--- /dev/null
+package org.argeo;
+
+/**
+ * Logging framework agnostic identifying a logging service, to which one can
+ * register
+ */
+public interface ArgeoLogger {
+ /**
+ * Register for events by threads with the same authentication (or all
+ * threads if admin)
+ */
+ public void register(ArgeoLogListener listener,
+ Integer numberOfPreviousEvents);
+
+ /**
+ * For admin use only: register for all users
+ *
+ * @param listener
+ * the log listener
+ * @param numberOfPreviousEvents
+ * the number of previous events to notify
+ * @param everything
+ * if true even anonymous is logged
+ */
+ public void registerForAll(ArgeoLogListener listener,
+ Integer numberOfPreviousEvents, boolean everything);
+
+ public void unregister(ArgeoLogListener listener);
+
+ public void unregisterForAll(ArgeoLogListener listener);
+}
</extension>
<extension
point="org.eclipse.ui.activities">
- <activity
- description="Only for admins"
- id="org.argeo.osgi.ui.explorer.adminActivity"
- name="Admin">
- <enabledWhen>
- <with variable="roles">
- <iterate ifEmpty="false" operator="or">
- <equals value="ROLE_ADMIN" />
- </iterate>
- </with>
- </enabledWhen>
- </activity>
<activityPatternBinding
- activityId="org.argeo.osgi.ui.explorer.adminActivity"
+ activityId="org.argeo.security.ui.adminActivity"
isEqualityPattern="true"
pattern="org.argeo.osgi.ui.explorer/org.argeo.osgi.ui.explorer.perspective">
</activityPatternBinding>
</extension>
<extension
point="org.eclipse.ui.activities">
- <activity
- description="Only for admins"
- id="org.argeo.security.ui.admin.adminActivity"
- name="Admin">
- <enabledWhen>
- <with variable="roles">
- <iterate ifEmpty="false" operator="or">
- <equals value="ROLE_ADMIN" />
- </iterate>
- </with>
- </enabledWhen>
- </activity>
<!-- TODO: find a way to exclude evrything -->
<activityPatternBinding
- activityId="org.argeo.security.ui.admin.adminActivity"
+ activityId="org.argeo.security.ui.adminActivity"
isEqualityPattern="true"
pattern="org.argeo.security.ui.admin/org.argeo.security.ui.admin.adminSecurityPerspective">
</activityPatternBinding>
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="openChangePasswordDialog" class="org.argeo.security.ui.commands.OpenChangePasswordDialog"
- scope="prototype">
- <property name="userDetailsManager" ref="userDetailsManager" />
- </bean>
</beans>
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- Log4j appender singleton -->
- <bean id="secureAppender" class="org.argeo.security.log4j.SecureLogger"
+ <bean id="secureLogger" class="org.argeo.security.log4j.SecureLogger"
init-method="init" destroy-method="destroy">
- <property name="listeners" ref="logListeners" />
<property name="configuration">
<value><![CDATA[
log4j.rootLogger=WARN, console
interface="org.springframework.security.userdetails.UserDetailsManager"\r
cardinality="0..1" />\r
\r
- <list id="logListeners" interface="org.argeo.ArgeoLogListener"\r
- cardinality="0..N" />\r
+ <service ref="secureLogger" interface="org.argeo.ArgeoLogger" />\r
</beans:beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <bean id="logView" class="org.argeo.security.ui.views.LogView"
+ scope="prototype">
+ <property name="argeoLogger" ref="secureLogger" />
+ </bean>
+
+ <bean id="adminLogView" class="org.argeo.security.ui.views.AdminLogView"
+ scope="prototype">
+ <property name="argeoLogger" ref="secureLogger" />
+ </bean>
+
+</beans>
<extension
point="org.eclipse.ui.views">
<view
+ id="org.argeo.security.ui.userProfile"
class="org.argeo.security.ui.views.UserProfile"
icon="icons/user.gif"
- id="org.argeo.security.ui.userProfile"
name="Profile"
restorable="true">
</view>
<view
- class="org.argeo.security.ui.views.LogView"
id="org.argeo.security.ui.logView"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
name="Log"
- restorable="true">
+ icon="icons/log.gif"
+ restorable="false">
+ </view>
+ <view
+ id="org.argeo.security.ui.adminLogView"
+ class="org.argeo.eclipse.spring.SpringExtensionFactory"
+ name="Admin Log"
+ icon="icons/adminLog.gif"
+ restorable="false">
</view>
</extension>
<extension
id="org.argeo.security.ui.userHomePerspective"
name="Home">
</perspective>
+ <perspective
+ class="org.argeo.security.ui.MaintenancePerspective"
+ icon="icons/maintenance.gif"
+ id="org.argeo.security.ui.adminMaintenancePerspective"
+ name="Maintenance">
+ </perspective>
</extension>
+ <extension
+ point="org.eclipse.ui.activities">
+ <activity
+ description="Only for admins"
+ id="org.argeo.security.ui.adminActivity"
+ name="Admin">
+ <enabledWhen>
+ <with variable="roles">
+ <iterate ifEmpty="false" operator="or">
+ <equals value="ROLE_ADMIN" />
+ </iterate>
+ </with>
+ </enabledWhen>
+ </activity>
+ <activityPatternBinding
+ activityId="org.argeo.security.ui.adminActivity"
+ isEqualityPattern="true"
+ pattern="org.argeo.security.ui/org.argeo.security.ui.adminMaintenancePerspective">
+ </activityPatternBinding>
+ <activityPatternBinding
+ activityId="org.argeo.security.ui.adminActivity"
+ isEqualityPattern="true"
+ pattern="org.argeo.security.ui/org.argeo.security.ui.adminLogView">
+ </activityPatternBinding>
+ </extension>
</plugin>
--- /dev/null
+package org.argeo.security.ui;
+
+import org.argeo.security.ui.views.AdminLogView;
+import org.argeo.security.ui.views.UserProfile;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** Home perspective for the current user */
+public class MaintenancePerspective implements IPerspectiveFactory {
+ public final static String ID = SecurityUiPlugin.PLUGIN_ID
+ + ".adminMaintenancePerspective";
+
+ public void createInitialLayout(IPageLayout layout) {
+ String editorArea = layout.getEditorArea();
+ layout.setEditorAreaVisible(true);
+ layout.setFixed(false);
+
+ IFolderLayout bottom = layout.createFolder("bottom",
+ IPageLayout.BOTTOM, 0.50f, editorArea);
+ bottom.addView(AdminLogView.ID);
+
+ IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
+ 0.30f, editorArea);
+ left.addView(UserProfile.ID);
+ // left.addView(RolesView.ID);
+
+ }
+
+}
/** Home perspective for the current user */
public class UserHomePerspective implements IPerspectiveFactory {
- public final static String ID = "org.argeo.security.ui.userHomePerspective";
+ public final static String ID = SecurityUiPlugin.PLUGIN_ID
+ + ".userHomePerspective";
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
0.30f, editorArea);
left.addView(UserProfile.ID);
- // left.addView(RolesView.ID);
-
- IFolderLayout bottom = layout.createFolder("bottom",
- IPageLayout.BOTTOM, 0.30f, editorArea);
- bottom.addView(LogView.ID);
+ left.addView(LogView.ID);
}
}
--- /dev/null
+package org.argeo.security.ui.views;
+
+import java.util.ArrayList;
+
+import org.argeo.security.log4j.SecureLogger;
+import org.argeo.security.ui.SecurityUiPlugin;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Display log lines for all users with a virtual table.
+ */
+public class AdminLogView extends ViewPart {
+ public static String ID = SecurityUiPlugin.PLUGIN_ID + ".adminLogView";
+
+ private TableViewer viewer;
+
+ private LogContentProvider logContentProvider;
+ private SecureLogger argeoLogger;
+
+ private Font font;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ // FIXME doesn't return a monospace font in RAP
+ font = JFaceResources.getTextFont();
+// if (font == JFaceResources.getDefaultFont()) {
+// Set<?> keySet = JFaceResources.getFontRegistry().getKeySet();
+// for (Object key : keySet) {
+// System.out.println(key);
+// }
+// }
+
+ viewer = new TableViewer(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL
+ | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
+ viewer.getTable().setFont(font);
+ viewer.setLabelProvider(new LabelProvider());
+ logContentProvider = new LogContentProvider(viewer) {
+
+ @Override
+ protected StringBuffer prefix(String username, Long timestamp,
+ String level, String category, String thread) {
+ return super
+ .prefix(username, timestamp, level, category, thread)
+ .append(norm(level, 5))
+ .append(' ')
+ .append(norm(username != null ? username
+ : "<anonymous>", 16)).append(' ');
+ }
+ };
+ viewer.setContentProvider(logContentProvider);
+ // viewer.setUseHashlookup(true);
+ viewer.setInput(new ArrayList<String>());
+
+ if (argeoLogger != null)
+ argeoLogger.registerForAll(logContentProvider, 1000, true);
+ }
+
+ @Override
+ public void setFocus() {
+ viewer.getTable().setFocus();
+ }
+
+ @Override
+ public void dispose() {
+ if (argeoLogger != null)
+ argeoLogger.unregisterForAll(logContentProvider);
+ }
+
+ public void setArgeoLogger(SecureLogger argeoLogger) {
+ this.argeoLogger = argeoLogger;
+ }
+
+}
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
private final Integer maxLineBufferSize = 10 * 1000;
private final TableViewer viewer;
- private final LinkedList<LogLine> lines;
+ private LinkedList<LogLine> lines;
public LogContentProvider(TableViewer viewer) {
this.viewer = viewer;
public synchronized void dispose() {
lines.clear();
+ lines = null;
}
@SuppressWarnings("unchecked")
return;
String message = msg.toString();
- StringBuffer buf = new StringBuffer("");
- buf.append(dateFormat.format(new Date(timestamp))).append(" ");
- buf.append(level).append(" ");
int count = 0;
+ String prefix = prefix(username, timestamp, level, category, thread)
+ .toString();
+ // String suffix = suffix(username, timestamp, level, category, thread);
for (String line : message.split("\n")) {
- addLine(count == 0 ? buf + line : line);
+ addLine(count == 0 ? prefix + line : line);
count++;
}
addLine(ste);
}
}
- viewer.getTable().getDisplay().syncExec(new Runnable() {
+
+ viewer.getTable().getDisplay().asyncExec(new Runnable() {
public void run() {
+ if (lines == null)
+ return;
viewer.setItemCount(lines.size());
- // viewer.reveal(lines.peekLast());
- Table table = viewer.getTable();
- // table.setTopIndex(lines.size()-1);
- System.out.println("topIndex=" + table.getTopIndex()
- + ", tableSize=" + lines.size());
- // table.select(lines.size() - 1);
- // table.showSelection();
- TableItem ti = table.getItem(lines.size() - 1);
- if (ti == null)
- System.out.println("tableItem is null");
- table.showItem(ti);
+ // doesn't work with syncExec
+ scrollToLastLine();
}
});
}
+ protected StringBuffer prefix(String username, Long timestamp,
+ String level, String category, String thread) {
+ StringBuffer buf = new StringBuffer("");
+ buf.append(dateFormat.format(new Date(timestamp))).append(" ");
+ // buf.append(level).append(" ");
+ return buf;
+ }
+
+ /** Normalize string to the given size */
+ protected String norm(String str, Integer size) {
+ int length = str.length();
+ if (length == size)
+ return str;
+ else if (length > size)
+ return str.substring(0, size);
+ else {
+ char[] arr = new char[size - length];
+ Arrays.fill(arr, ' ');
+ return str + new String(arr);
+ }
+ }
+
+ // protected String suffix(String username, Long timestamp, String level,
+ // String category, String thread) {
+ // return "";
+ // }
+
+ /** Scroll to the last line */
+ protected void scrollToLastLine() {
+ // we try to show last line with two methods
+ // viewer.reveal(lines.peekLast());
+
+ Table table = viewer.getTable();
+ TableItem ti = table.getItem(lines.size() - 1);
+ if (ti == null)
+ System.out.println("tableItem is null");
+ table.showItem(ti);
+ }
+
protected synchronized LogLine addLine(String line) {
// check for maximal size and purge if necessary
while (lines.size() >= maxLineBufferSize) {
import java.util.ArrayList;
import org.argeo.ArgeoLogListener;
+import org.argeo.ArgeoLogger;
import org.argeo.security.ui.SecurityUiPlugin;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
/**
* Display log lines with a virtual table. Register and unregisters a
private TableViewer viewer;
private LogContentProvider logContentProvider;
-
- private ServiceRegistration serviceRegistration;
+ private ArgeoLogger argeoLogger;
@Override
public void createPartControl(Composite parent) {
| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
viewer.setLabelProvider(new LabelProvider());
logContentProvider = new LogContentProvider(viewer);
- serviceRegistration = getBundleContext().registerService(
- ArgeoLogListener.class.getName(), logContentProvider, null);
viewer.setContentProvider(logContentProvider);
- //viewer.setUseHashlookup(true);
+ // viewer.setUseHashlookup(true);
viewer.setInput(new ArrayList<String>());
+
+ if (argeoLogger != null)
+ argeoLogger.register(logContentProvider, 1000);
}
@Override
@Override
public void dispose() {
- if (serviceRegistration != null)
- serviceRegistration.unregister();
+ if (argeoLogger != null)
+ argeoLogger.unregister(logContentProvider);
}
- private BundleContext getBundleContext() {
- return SecurityUiPlugin.getDefault().getBundle().getBundleContext();
+ public void setArgeoLogger(ArgeoLogger argeoLogger) {
+ this.argeoLogger = argeoLogger;
}
+
}
--- /dev/null
+package org.argeo.security;
+
+import org.springframework.security.Authentication;
+import org.springframework.security.GrantedAuthority;
+import org.springframework.security.context.SecurityContext;
+import org.springframework.security.context.SecurityContextHolder;
+import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
+
+/** Static utilities */
+public class SecurityUtils {
+
+ private SecurityUtils() {
+ }
+
+ /** Whether the current thread has the admin role */
+ public static boolean hasCurrentThreadAuthority(String authority) {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ if (securityContext != null) {
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication != null) {
+ for (GrantedAuthority ga : authentication.getAuthorities())
+ if (ga.getAuthority().equals(authority))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return the authenticated username or null if not authenticated /
+ * anonymous
+ */
+ public static String getCurrentThreadUsername() {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+ if (securityContext != null) {
+ Authentication authentication = securityContext.getAuthentication();
+ if (authentication != null) {
+ if (authentication instanceof AnonymousAuthenticationToken) {
+ return null;
+ }
+ return authentication.getName();
+ }
+ }
+ return null;
+ }
+}
package org.argeo.security.log4j;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
import java.util.Properties;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.spi.LoggingEvent;
import org.argeo.ArgeoException;
import org.argeo.ArgeoLogListener;
-import org.springframework.security.Authentication;
-import org.springframework.security.context.SecurityContext;
-import org.springframework.security.context.SecurityContextHolder;
-import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
+import org.argeo.ArgeoLogger;
+import org.argeo.security.SecurityUtils;
/** Not meant to be used directly in standard log4j config */
-public class SecureLogger {
- private List<ArgeoLogListener> listeners;
+public class SecureLogger implements ArgeoLogger {
private Boolean disabled = false;
private AppenderImpl appender;
+ private final List<ArgeoLogListener> everythingListeners = Collections
+ .synchronizedList(new ArrayList<ArgeoLogListener>());
+ private final List<ArgeoLogListener> allUsersListeners = Collections
+ .synchronizedList(new ArrayList<ArgeoLogListener>());
+ private final Map<String, List<ArgeoLogListener>> userListeners = Collections
+ .synchronizedMap(new HashMap<String, List<ArgeoLogListener>>());
+
+ private BlockingQueue<LogEvent> events;
+ private LogDispatcherThread logDispatcherThread = new LogDispatcherThread();
+
+ private Integer maxLastEventsCount = 10 * 1000;
+
/** Marker to prevent stack overflow */
private ThreadLocal<Boolean> dispatching = new ThreadLocal<Boolean>() {
public void init() {
try {
+ events = new LinkedBlockingQueue<LogEvent>();
+
// if (layout != null)
// setLayout(layout);
// else
// setLayout(new PatternLayout(pattern));
appender = new AppenderImpl();
-
- if (configuration != null)
- PropertyConfigurator.configure(configuration);
-
+ reloadConfiguration();
Logger.getRootLogger().addAppender(appender);
+
+ logDispatcherThread = new LogDispatcherThread();
+ logDispatcherThread.start();
} catch (Exception e) {
throw new ArgeoException("Cannot initialize log4j");
}
public void destroy() throws Exception {
Logger.getRootLogger().removeAppender(appender);
+ allUsersListeners.clear();
+ for (List<ArgeoLogListener> lst : userListeners.values())
+ lst.clear();
+ userListeners.clear();
+
+ events.clear();
+ events = null;
+ logDispatcherThread.interrupt();
}
// public void setLayout(Layout layout) {
// this.layout = layout;
// }
+ public synchronized void register(ArgeoLogListener listener,
+ Integer numberOfPreviousEvents) {
+ String username = SecurityUtils.getCurrentThreadUsername();
+ if (username == null)
+ throw new ArgeoException(
+ "Only authenticated users can register a log listener");
+
+ if (!userListeners.containsKey(username)) {
+ List<ArgeoLogListener> lst = Collections
+ .synchronizedList(new ArrayList<ArgeoLogListener>());
+ userListeners.put(username, lst);
+ }
+ userListeners.get(username).add(listener);
+ List<LogEvent> lastEvents = logDispatcherThread.getLastEvents(username,
+ numberOfPreviousEvents);
+ for (LogEvent evt : lastEvents)
+ dispatchEvent(listener, evt);
+ }
+
+ public synchronized void registerForAll(ArgeoLogListener listener,
+ Integer numberOfPreviousEvents, boolean everything) {
+ if (everything)
+ everythingListeners.add(listener);
+ else
+ allUsersListeners.add(listener);
+ List<LogEvent> lastEvents = logDispatcherThread.getLastEvents(null,
+ numberOfPreviousEvents);
+ for (LogEvent evt : lastEvents)
+ if (everything || evt.getUsername() != null)
+ dispatchEvent(listener, evt);
+ }
+
+ public synchronized void unregister(ArgeoLogListener listener) {
+ String username = SecurityUtils.getCurrentThreadUsername();
+ if (!userListeners.containsKey(username))
+ throw new ArgeoException("No user listeners " + listener
+ + " registered for user " + username);
+ if (!userListeners.get(username).contains(listener))
+ throw new ArgeoException("No user listeners " + listener
+ + " registered for user " + username);
+ userListeners.get(username).remove(listener);
+ if (userListeners.get(username).isEmpty())
+ userListeners.remove(username);
+
+ }
+
+ public synchronized void unregisterForAll(ArgeoLogListener listener) {
+ everythingListeners.remove(listener);
+ allUsersListeners.remove(listener);
+ }
+
/** For development purpose, since using regular logging is not easy here */
static void stdOut(Object obj) {
System.out.println(obj);
this.level = level;
}
- public void setListeners(List<ArgeoLogListener> listeners) {
- this.listeners = listeners;
- }
-
public void setConfiguration(Properties configuration) {
this.configuration = configuration;
}
+ public void updateConfiguration(Properties configuration) {
+ setConfiguration(configuration);
+ reloadConfiguration();
+ }
+
+ public Properties getConfiguration() {
+ return configuration;
+ }
+
+ /** Reloads configuration (if the configuration {@link Properties} is set) */
+ protected void reloadConfiguration() {
+ if (configuration != null) {
+ LogManager.resetConfiguration();
+ PropertyConfigurator.configure(configuration);
+ }
+ }
+
+ protected synchronized void processLoggingEvent(LogEvent event) {
+ if (disabled)
+ return;
+
+ if (dispatching.get())
+ return;
+
+ if (level != null && !level.trim().equals("")) {
+ if (log4jLevel == null || !log4jLevel.toString().equals(level))
+ try {
+ log4jLevel = Level.toLevel(level);
+ } catch (Exception e) {
+ System.err
+ .println("Log4j level could not be set for level '"
+ + level + "', resetting it to null.");
+ e.printStackTrace();
+ level = null;
+ }
+
+ if (log4jLevel != null
+ && !event.getLoggingEvent().getLevel()
+ .isGreaterOrEqual(log4jLevel)) {
+ return;
+ }
+ }
+
+ try {
+ // admin listeners
+ Iterator<ArgeoLogListener> everythingIt = everythingListeners
+ .iterator();
+ while (everythingIt.hasNext())
+ dispatchEvent(everythingIt.next(), event);
+
+ if (event.getUsername() != null) {
+ Iterator<ArgeoLogListener> allUsersIt = allUsersListeners
+ .iterator();
+ while (allUsersIt.hasNext())
+ dispatchEvent(allUsersIt.next(), event);
+
+ if (userListeners.containsKey(event.getUsername())) {
+ Iterator<ArgeoLogListener> userIt = userListeners.get(
+ event.getUsername()).iterator();
+ while (userIt.hasNext())
+ dispatchEvent(userIt.next(), event);
+ }
+ }
+ } catch (Exception e) {
+ stdOut("Cannot process logging event");
+ e.printStackTrace();
+ }
+ }
+
+ protected void dispatchEvent(ArgeoLogListener logListener, LogEvent evt) {
+ LoggingEvent event = evt.getLoggingEvent();
+ logListener.appendLog(evt.getUsername(), event.getTimeStamp(), event
+ .getLevel().toString(), event.getLoggerName(), event
+ .getThreadName(), event.getMessage(), event
+ .getThrowableStrRep());
+ }
+
private class AppenderImpl extends AppenderSkeleton {
public boolean requiresLayout() {
return false;
@Override
protected void append(LoggingEvent event) {
- if (disabled)
- return;
+ if (events != null) {
+ try {
+ String username = SecurityUtils.getCurrentThreadUsername();
+ events.put(new LogEvent(username, event));
+ } catch (InterruptedException e) {
+ // silent
+ }
+ }
+ }
- if (dispatching.get())
- return;
+ }
- if (level != null && !level.trim().equals("")) {
- if (log4jLevel == null || !log4jLevel.toString().equals(level))
- try {
- log4jLevel = Level.toLevel(level);
- } catch (Exception e) {
- System.err
- .println("Log4j level could not be set for level '"
- + level + "', resetting it to null.");
- e.printStackTrace();
- level = null;
- }
-
- if (log4jLevel != null
- && !event.getLevel().isGreaterOrEqual(log4jLevel)) {
- return;
+ private class LogDispatcherThread extends Thread {
+ /** encapsulated in order to simplify concurrency management */
+ private LinkedList<LogEvent> lastEvents = new LinkedList<LogEvent>();
+
+ public LogDispatcherThread() {
+ super("Argeo Logging Dispatcher Thread");
+ }
+
+ public void run() {
+ while (events != null) {
+ try {
+ LogEvent loggingEvent = events.take();
+ processLoggingEvent(loggingEvent);
+ addLastEvent(loggingEvent);
+ } catch (InterruptedException e) {
+ if (events == null)
+ return;
}
}
+ }
- try {
- Thread currentThread = Thread.currentThread();
- String username = null;
-
- // find username
- SecurityContext securityContext = SecurityContextHolder
- .getContext();
- if (securityContext != null) {
- Authentication authentication = securityContext
- .getAuthentication();
- if (authentication != null) {
- if (authentication instanceof AnonymousAuthenticationToken) {
- username = null;
- } else {
- username = authentication.getName();
- }
- }
- }
+ protected synchronized void addLastEvent(LogEvent loggingEvent) {
+ if (lastEvents.size() >= maxLastEventsCount)
+ lastEvents.poll();
+ lastEvents.add(loggingEvent);
+ }
- // Spring OSGi safe
- Iterator<ArgeoLogListener> it = listeners.iterator();
- while (it.hasNext()) {
- ArgeoLogListener logListener = it.next();
- logListener.appendLog(username, event.getTimeStamp(), event
- .getLevel().toString(), event.getLoggerName(),
- currentThread.getName(), event.getMessage(), event.getThrowableStrRep());
+ public synchronized List<LogEvent> getLastEvents(String username,
+ Integer maxCount) {
+ LinkedList<LogEvent> evts = new LinkedList<LogEvent>();
+ ListIterator<LogEvent> it = lastEvents.listIterator(lastEvents
+ .size());
+ int count = 0;
+ while (it.hasPrevious() && (count < maxCount)) {
+ LogEvent evt = it.previous();
+ if (username == null || username.equals(evt.getUsername())) {
+ evts.push(evt);
+ count++;
}
- } catch (Exception e) {
- stdOut("Cannot process logging event");
- e.printStackTrace();
}
+ return evts;
+ }
+ }
+
+ private class LogEvent {
+ private final String username;
+ private final LoggingEvent loggingEvent;
+
+ public LogEvent(String username, LoggingEvent loggingEvent) {
+ super();
+ this.username = username;
+ this.loggingEvent = loggingEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ return loggingEvent.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return loggingEvent.equals(obj);
+ }
+
+ @Override
+ public String toString() {
+ return username + "@ " + loggingEvent.toString();
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public LoggingEvent getLoggingEvent() {
+ return loggingEvent;
}
}
<extension
point="org.eclipse.ui.activities">
- <activity
- description="Only for admins"
- id="org.argeo.jcr.ui.explorer.adminActivity"
- name="Admin">
- <enabledWhen>
- <with variable="roles">
- <iterate ifEmpty="false" operator="or">
- <equals value="ROLE_ADMIN" />
- </iterate>
- </with>
- </enabledWhen>
- </activity>
- <!-- TODO: find a way to exclude evrything -->
<activityPatternBinding
- activityId="org.argeo.jcr.ui.explorer.adminActivity"
+ activityId="org.argeo.security.ui.adminActivity"
isEqualityPattern="true"
pattern="org.argeo.jcr.ui.explorer/org.argeo.jcr.ui.explorer.perspective">
</activityPatternBinding>
"Repository Added",
"Remote repository '" + username.getText() + "@"
+ uri.getText() + "' added");
+ super.okPressed();
} catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ ErrorFeedback.show("Cannot add remote repository", e);
}
- super.okPressed();
}
/** Creates label and text. */