/*******************************************************************************
* Copyright (c) 2011 Subgraph.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Subgraph - initial API and implementation
******************************************************************************/
package com.subgraph.vega.internal.model.alerts;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;
import com.db4o.ObjectContainer;
import com.db4o.events.Event4;
import com.db4o.events.EventListener4;
import com.db4o.events.EventRegistry;
import com.db4o.events.EventRegistryFactory;
import com.db4o.events.ObjectInfoEventArgs;
import com.db4o.query.Predicate;
import com.subgraph.vega.api.events.EventListenerManager;
import com.subgraph.vega.api.events.IEventHandler;
import com.subgraph.vega.api.model.alerts.ActiveScanInstanceEvent;
import com.subgraph.vega.api.model.alerts.IScanAlertRepository;
import com.subgraph.vega.api.model.alerts.IScanInstance;
import com.subgraph.vega.api.model.alerts.NewScanInstanceEvent;
import com.subgraph.vega.api.xml.IXmlRepository;
public class ScanAlertRepository implements IScanAlertRepository {
private final static Logger logger = Logger.getLogger("alerts");
private final ObjectContainer database;
private final Object scanInstanceLock = new Object();
private final ScanAlertFactory alertFactory;
private final EventListenerManager scanInstanceEventManager;
private IScanInstance activeScanInstance;
public ScanAlertRepository(ObjectContainer db, IXmlRepository xmlRepository) {
this.database = db;
this.alertFactory = new ScanAlertFactory(xmlRepository);
this.scanInstanceEventManager = new EventListenerManager();
final EventRegistry registry = EventRegistryFactory.forObjectContainer(database);
registry.activated().addListener(new EventListener4<ObjectInfoEventArgs>() {
@Override
public void onEvent(Event4<ObjectInfoEventArgs> e, ObjectInfoEventArgs args) {
final Object ob = args.object();
if(ob instanceof ScanInstance) {
final ScanInstance scan = (ScanInstance) ob;
scan.setTransientState(database, alertFactory);
final int status = scan.getScanStatus();
if(status != IScanInstance.SCAN_COMPLETED && status != IScanInstance.SCAN_CANCELLED) {
scan.updateScanStatus(IScanInstance.SCAN_CANCELLED);
}
}
}
});
getProxyScanInstance();
}
@Override
public IScanInstance addActiveScanInstanceListener(IEventHandler listener) {
scanInstanceEventManager.addListener(listener);
return activeScanInstance;
}
@Override
public void removeActiveScanInstanceListener(IEventHandler listener) {
scanInstanceEventManager.removeListener(listener);
}
@Override
public void setActiveScanInstance(IScanInstance scanInstance) {
activeScanInstance = scanInstance;
scanInstanceEventManager.fireEvent(new ActiveScanInstanceEvent(scanInstance));
}
@Override
public IScanInstance getActiveScanInstance() {
return activeScanInstance;
}
@Override
public List<IScanInstance> getAllScanInstances() {
return database.query(IScanInstance.class);
}
@Override
public synchronized IScanInstance createNewScanInstance() {
synchronized(scanInstanceLock) {
final long scanId = allocateNewScanId();
final IScanInstance scan = createScanInstanceForScanId(scanId);
scanInstanceEventManager.fireEvent(new NewScanInstanceEvent(scan));
return scan;
}
}
private IScanInstance createScanInstanceForScanId(long scanId) {
final ScanInstance scan = new ScanInstance(scanId);
scan.setTransientState(database, alertFactory);
database.store(scan);
return scan;
}
@Override
public synchronized IScanInstance getScanInstanceByScanId(final long scanId) {
final List<IScanInstance> results = database.query(new Predicate<IScanInstance>() {
private static final long serialVersionUID = 1L;
@Override
public boolean match(IScanInstance scan) {
return scan.getScanId() == scanId;
}
});
if(results.size() == 0) {
return null;
} else if (results.size() > 1) {
logger.warning("Multiple scan instances for scanId = "+ scanId);
}
return results.get(0);
}
@Override
public synchronized IScanInstance getProxyScanInstance() {
final IScanInstance scan = getScanInstanceByScanId(PROXY_ALERT_ORIGIN_SCAN_ID);
if(scan != null) {
return scan;
}
return createScanInstanceForScanId(PROXY_ALERT_ORIGIN_SCAN_ID);
}
private long allocateNewScanId() {
int count = 0;
final Random r = new Random();
while(true) {
long scanId = r.nextInt(999999) + 1;
if(getScanInstanceByScanId(scanId) == null) {
return scanId;
}
count += 1;
if(count > 10) {
throw new IllegalStateException("Unable to generate unique random scan id");
}
}
}
}