package com.google.code.joto.ui; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Map; import javax.swing.event.SwingPropertyChangeSupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.code.joto.JotoConfig; import com.google.code.joto.eventrecorder.RecordEventStore; import com.google.code.joto.eventrecorder.impl.DefaultMemoryRecordEventStore; import com.google.code.joto.eventrecorder.spy.calls.MethodCallEventUtils; import com.google.code.joto.eventrecorder.spy.calls.MethodEventWriterAopInterceptor; import com.google.code.joto.eventrecorder.spy.calls.MethodEventWriterProxyTransformer; import com.google.code.joto.eventrecorder.spy.calls.ObjectReplacementMap; import com.google.code.joto.eventrecorder.writer.FilteringRecordEventWriter; import com.google.code.joto.eventrecorder.writer.RecordEventWriter; import com.google.code.joto.ui.filter.RecordEventFilterCategoryModel; import com.google.code.joto.ui.filter.RecordEventFilterFile; import com.google.code.joto.ui.spy.calls.MethodCallCaptureCategoryPanel; /** * */ public class JotoContext { public static final String PROP_RECORDING_STATUS = "recordingStatus"; public static enum RecordingStatus { RECORDING, IDDLE } private static Logger log = LoggerFactory.getLogger(JotoContext.class); // ------------------------------------------------------------------------ private JotoConfig config; private RecordEventStore eventStore; private SwingPropertyChangeSupport changeSupport = new SwingPropertyChangeSupport(this); private RecordingStatus recordingStatus = RecordingStatus.IDDLE; private RecordEventFilterCategoryModel captureFilterCategoryModel; protected Map<String,RecordEventFilterCategoryModel> filterCategoryModels = new HashMap<String,RecordEventFilterCategoryModel>(); protected ObjectReplacementMap objReplMap = new ObjectReplacementMap(); protected MethodEventWriterAopInterceptor defaultMethodEventWriterAopInterceptor; protected MethodEventWriterProxyTransformer defaultMethodEventWriterProxyTransformer; // ------------------------------------------------------------------------ public JotoContext(JotoConfig optConfig, RecordEventStore optEventStore) { this.config = (optConfig != null)? optConfig : new JotoConfig(); this.eventStore = (optEventStore != null)? optEventStore : this.config.getEventStoreFactory().create(); RecordEventWriter asyncEventWriter = eventStore.getAsyncEventWriter(); this.captureFilterCategoryModel = new RecordEventFilterCategoryModel(asyncEventWriter); captureFilterCategoryModel.setName("jotoContext.captureFiltersWriterModel"); captureFilterCategoryModel.setOwner(this); captureFilterCategoryModel.getResultFilteringEventWriter().setOwner(captureFilterCategoryModel); // getOrCreateFilteringEventWriterModelCategory(MethodCallCaptureCategoryPanel.METHODCALL_CAPTURE_CATEGORY); // getOrCreateFilteringEventWriterModelCategory(LogCallCaptureCategoryPanel.LOGS_CAPTURE_CATEGORY); // getOrCreateFilteringEventWriterModelCategory(AWTEventCaptureCategoryPanel.AWTSPY_CAPTURE_CATEGORY); eventStore.open("rw"); } /** helper constructor, for test */ public JotoContext(JotoConfig optConfig) { this(optConfig, null); } /** helper constructor, for test */ public JotoContext() { this(new JotoConfig(), new DefaultMemoryRecordEventStore()); } // ------------------------------------------------------------------------ public void addPropertyChangeListener(PropertyChangeListener p) { changeSupport.addPropertyChangeListener(p); } public void removePropertyChangeListener(PropertyChangeListener p) { changeSupport.removePropertyChangeListener(p); } public RecordEventStore getEventStore() { return eventStore; } public JotoConfig getConfig() { return config; } public void setConfig(JotoConfig p) { JotoConfig old = config; this.config = p; changeSupport.firePropertyChange("config", old, p); } public void startRecord() { if (isEnableStartRecord()) { // do start record.. // TODO setRecordingStatus(RecordingStatus.RECORDING); } } public boolean isEnableStartRecord() { return recordingStatus == RecordingStatus.IDDLE; } public void stopRecord() { if (isEnableStopRecord()) { // do stop record // TODO setRecordingStatus(RecordingStatus.IDDLE); } } public boolean isEnableStopRecord() { return recordingStatus == RecordingStatus.RECORDING; } private void setRecordingStatus(RecordingStatus p) { if (p != recordingStatus) { RecordingStatus old = recordingStatus; this.recordingStatus = p; log.info("setRecordingStatus " + p); changeSupport.firePropertyChange(PROP_RECORDING_STATUS, old, p); } } public RecordEventWriter getEventWriter() { return eventStore.getEventWriter(); } public RecordEventWriter getUnfilteredAsyncEventWriter() { return eventStore.getAsyncEventWriter(); } public RecordEventWriter getAsyncEventWriter() { return captureFilterCategoryModel.getResultFilteringEventWriter(); } public RecordEventFilterCategoryModel getCaptureFilterCategoryModel() { return captureFilterCategoryModel; } public RecordEventFilterCategoryModel getOrCreateFilterCategoryModel(String name) { RecordEventFilterCategoryModel res = filterCategoryModels.get(name); if (res == null) { FilteringRecordEventWriter mainAsyncEventWriter = captureFilterCategoryModel.getResultFilteringEventWriter(); res = new RecordEventFilterCategoryModel(mainAsyncEventWriter); res.setName(name); boolean debugOwner = true; if (debugOwner) { res.setOwner(this); FilteringRecordEventWriter resFilter = res.getResultFilteringEventWriter(); resFilter.setOwner(res); resFilter.setName(name); } filterCategoryModels.put(name, res); } return res; } public FilteringRecordEventWriter getOrCreateFilterCategoryEventWriter(String name) { RecordEventFilterCategoryModel tmpres = getOrCreateFilterCategoryModel(name); return tmpres.getResultFilteringEventWriter(); } /** helper method for getOrCreateFilteringEventWriterCategory(METHODCALL_CAPTURE_CATEGORY) */ public RecordEventFilterCategoryModel getMethodCallFilterCategoryModel() { return getOrCreateFilterCategoryModel(MethodCallCaptureCategoryPanel.METHODCALL_CAPTURE_CATEGORY); } /** helper method for getOrCreateFilteringEventWriterCategory(DEFAULT_METHODCALL_CAPTURE_CATEGORY) */ public FilteringRecordEventWriter getMethodCallFilterCategoryEventWriter() { return getMethodCallFilterCategoryModel().getResultFilteringEventWriter(); } /** helper method for getOrCreateFilteringEventWriterCategory(DEFAULT_METHODCALL_CAPTURE_CATEGORY).addFilter(filter) */ public void addMethodCallFilter(RecordEventFilterFile filter) { getMethodCallFilterCategoryModel().addFilterRow(filter); } /** * helper method to create a default MethodEventWriterAopInterceptor, * with writer filtering on category MethodCallEventUtils.METHODCALL_EVENT_TYPE * * typical example in Spring configuration file: * <code><PRE> * <bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> * <property name="targetObject" ref="jotoContext"/> * <property name="targetMethod" value="getDefaultMethodEventWriterAopInterceptor"/> * </bean> * </PRE> * </code> */ public MethodEventWriterAopInterceptor getDefaultMethodEventWriterAopInterceptor() { if (defaultMethodEventWriterAopInterceptor == null) { String writerCategory = MethodCallEventUtils.METHODCALL_EVENT_TYPE; String eventType = MethodCallEventUtils.METHODCALL_EVENT_TYPE; defaultMethodEventWriterAopInterceptor = createMethodEventWriterAopInterceptor(writerCategory, eventType); } return defaultMethodEventWriterAopInterceptor; } /** * helper method to create a MethodEventWriterAopInterceptor, with writer filtering on <code>writerCategory</code> * @param writerCategory * @param eventType * @return */ public MethodEventWriterAopInterceptor createMethodEventWriterAopInterceptor(String writerCategory, String eventType) { FilteringRecordEventWriter eventWriter = getOrCreateFilterCategoryEventWriter(writerCategory); MethodEventWriterAopInterceptor res = new MethodEventWriterAopInterceptor(eventWriter, eventType); return res; } public MethodEventWriterProxyTransformer getDefaultMethodEventWriterProxyTransformer() { if (defaultMethodEventWriterProxyTransformer == null) { RecordEventWriter methodCallWriter = getOrCreateFilterCategoryEventWriter(MethodCallEventUtils.METHODCALL_EVENT_TYPE); defaultMethodEventWriterProxyTransformer = new MethodEventWriterProxyTransformer(methodCallWriter, this.getObjReplMap()); } return defaultMethodEventWriterProxyTransformer; } public <T> T createDefaultMethodEventWriterProxy(T targetObjCallToRecord) { Class<?> objClass = targetObjCallToRecord.getClass(); Class<?>[] objInterfaces = objClass.getInterfaces(); @SuppressWarnings("unchecked") T resProxy = (T) createDefaultMethodEventWriterProxy(objInterfaces, targetObjCallToRecord); return resProxy; } public Object createDefaultMethodEventWriterProxy(Class<?>[] proxyInterfaces, Object targetObjCallToRecord) { MethodEventWriterProxyTransformer tf = getDefaultMethodEventWriterProxyTransformer(); Object resProxy = tf.createProxy(proxyInterfaces, targetObjCallToRecord); return resProxy; } public ObjectReplacementMap getObjReplMap() { return objReplMap; } public void setObjReplMap(ObjectReplacementMap p) { this.objReplMap = p; } }