/*
* (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* mcedica
*/
package org.nuxeo.ecm.core.management.probes;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.core.management.api.Probe;
import org.nuxeo.ecm.core.management.api.ProbeInfo;
import org.nuxeo.ecm.core.management.api.ProbeManager;
import org.nuxeo.ecm.core.management.api.ProbeStatus;
import org.nuxeo.runtime.management.ManagementRuntimeException;
public class ProbeManagerImpl implements ProbeManager {
protected static final Log log = LogFactory.getLog(ProbeManagerImpl.class);
protected final Map<Class<? extends Probe>, ProbeInfo> infosByTypes = new HashMap<Class<? extends Probe>, ProbeInfo>();
protected final Map<String, ProbeInfo> infosByShortcuts = new HashMap<String, ProbeInfo>();
protected final Map<String, Probe> probesByShortcuts = new HashMap<String, Probe>();
protected final Set<ProbeInfo> failed = new HashSet<ProbeInfo>();
protected final Set<ProbeInfo> succeed = new HashSet<ProbeInfo>();
protected Set<String> doExtractProbesName(Collection<ProbeInfo> runners) {
Set<String> names = new HashSet<String>();
for (ProbeInfo runner : runners) {
names.add(runner.getShortcutName());
}
return names;
}
@Override
public Collection<ProbeInfo> getAllProbeInfos() {
return Collections.unmodifiableCollection(infosByTypes.values());
}
@Override
public Collection<ProbeInfo> getInSuccessProbeInfos() {
return Collections.unmodifiableCollection(succeed);
}
@Override
public Collection<ProbeInfo> getInFailureProbeInfos() {
return Collections.unmodifiableCollection(failed);
}
@Override
public Collection<String> getProbeNames() {
return infosByShortcuts.keySet();
}
@Override
public int getProbesCount() {
return infosByTypes.size();
}
@Override
public Collection<String> getProbesInError() {
return doExtractProbesName(failed);
}
@Override
public int getProbesInErrorCount() {
return failed.size();
}
@Override
public Collection<String> getProbesInSuccess() {
return doExtractProbesName(succeed);
}
@Override
public int getProbesInSuccessCount() {
return succeed.size();
}
@Override
public ProbeInfo getProbeInfo(Class<? extends Probe> probeClass) {
ProbeInfo info = infosByTypes.get(probeClass);
if (info == null) {
throw new IllegalArgumentException("no probe registered for " + probeClass);
}
return info;
}
@Override
public boolean runAllProbes() {
doRun();
return getProbesInErrorCount() <= 0;
}
@Override
public ProbeInfo runProbe(ProbeInfo probe) {
doRunProbe(probe);
return probe;
}
@Override
public ProbeInfo runProbe(String name) {
ProbeInfo probeInfo = getProbeInfo(name);
if (probeInfo == null) {
log.warn("Probe " + name + " can not be found");
return null;
}
return runProbe(probeInfo);
}
@Override
public ProbeInfo getProbeInfo(String name) {
return infosByShortcuts.get(name);
}
public void registerProbe(ProbeDescriptor descriptor) {
Class<? extends Probe> probeClass = descriptor.getProbeClass();
Probe probe;
try {
probe = probeClass.newInstance();
} catch (ReflectiveOperationException e) {
throw new ManagementRuntimeException("Cannot create management probe for " + descriptor);
}
ProbeInfoImpl info = new ProbeInfoImpl(descriptor);
infosByTypes.put(probeClass, info);
infosByShortcuts.put(descriptor.getShortcut(), info);
probesByShortcuts.put(descriptor.getShortcut(), probe);
}
public void unregisterProbe(ProbeDescriptor descriptor) {
Class<? extends Probe> probeClass = descriptor.getProbeClass();
infosByTypes.remove(probeClass);
infosByShortcuts.remove(descriptor.getShortcut());
}
protected void doRun() {
for (ProbeInfo probe : infosByTypes.values()) {
doRunProbe(probe);
}
}
protected static Long doGetDuration(Date fromDate, Date toDate) {
return toDate.getTime() - fromDate.getTime();
}
protected void doRunProbe(ProbeInfo probe) {
if (!probe.isEnabled()) {
return;
}
boolean ok = false;
try {
ProbeInfoImpl probeInfoImpl = (ProbeInfoImpl) probe;
Thread currentThread = Thread.currentThread();
ClassLoader lastLoader = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(ProbeInfoImpl.class.getClassLoader());
probeInfoImpl.lastRunnedDate = new Date();
probeInfoImpl.runnedCount += 1;
try {
Probe runnableProbe = probesByShortcuts.get(probe.getShortcutName());
probeInfoImpl.lastStatus = runnableProbe.run();
if (probeInfoImpl.lastStatus.isSuccess()) {
probeInfoImpl.lastSucceedDate = probeInfoImpl.lastRunnedDate;
probeInfoImpl.lastSuccessStatus = probeInfoImpl.lastStatus;
probeInfoImpl.successCount += 1;
} else {
probeInfoImpl.lastFailureStatus = probeInfoImpl.lastStatus;
probeInfoImpl.failureCount += 1;
probeInfoImpl.lastFailureDate = probeInfoImpl.lastRunnedDate;
}
} catch (RuntimeException e) {
probeInfoImpl.failureCount += 1;
probeInfoImpl.lastFailureDate = new Date();
probeInfoImpl.lastFailureStatus = ProbeStatus.newError(e);
// then swallow exception
} finally {
probeInfoImpl.lastDuration = doGetDuration(probeInfoImpl.lastRunnedDate, new Date());
currentThread.setContextClassLoader(lastLoader);
}
if (probe.isInError()) {
succeed.remove(probe);
failed.add(probe);
} else {
failed.remove(probe);
succeed.add(probe);
}
ok = true;
} finally {
if (!ok) {
succeed.remove(probe);
failed.add(probe);
}
}
}
}