/******************************************************************************* * * Copyright (c) 2004-2010 Oracle Corporation. * * 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: * * Kohsuke Kawaguchi * * *******************************************************************************/ package hudson.model; import hudson.Util; import hudson.diagnosis.OldDataMonitor; import hudson.util.KeyedDataStorage; import java.io.File; import java.io.IOException; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; /** * Cache of {@link Fingerprint}s. * * <p> This implementation makes sure that no two {@link Fingerprint} objects * lie around for the same hash code, and that unused {@link Fingerprint} will * be adequately GC-ed to prevent memory leak. * * @author Kohsuke Kawaguchi * @see Hudson#getFingerprintMap() */ public final class FingerprintMap extends KeyedDataStorage<Fingerprint, FingerprintParams> { /** * @deprecated since 2007-03-26. Some old version of Hudson incorrectly * serialized this information to the disk. So we need this field to be here * for such configuration to be read correctly. This field is otherwise no * longer in use. */ private transient ConcurrentHashMap<String, Object> core = new ConcurrentHashMap<String, Object>(); /** * Returns true if there's some data in the fingerprint database. */ public boolean isReady() { return new File(Hudson.getInstance().getRootDir(), "fingerprints").exists(); } /** * @param build set to non-null if {@link Fingerprint} to be created (if so) * will have this build as the owner. Otherwise null, to indicate an * owner-less build. */ public Fingerprint getOrCreate(AbstractBuild build, String fileName, byte[] md5sum) throws IOException { return getOrCreate(build, fileName, Util.toHexString(md5sum)); } public Fingerprint getOrCreate(AbstractBuild build, String fileName, String md5sum) throws IOException { return super.getOrCreate(md5sum, new FingerprintParams(build, fileName)); } public Fingerprint getOrCreate(Run build, String fileName, String md5sum) throws IOException { return super.getOrCreate(md5sum, new FingerprintParams(build, fileName)); } @Override protected Fingerprint get(String md5sum, boolean createIfNotExist, FingerprintParams createParams) throws IOException { // sanity check if (md5sum.length() != 32) { return null; // illegal input } md5sum = md5sum.toLowerCase(Locale.ENGLISH); return super.get(md5sum, createIfNotExist, createParams); } private byte[] toByteArray(String md5sum) { byte[] data = new byte[16]; for (int i = 0; i < md5sum.length(); i += 2) { data[i / 2] = (byte) Integer.parseInt(md5sum.substring(i, i + 2), 16); } return data; } protected Fingerprint create(String md5sum, FingerprintParams createParams) throws IOException { return new Fingerprint(createParams.build, createParams.fileName, toByteArray(md5sum)); } protected Fingerprint load(String key) throws IOException { return Fingerprint.load(toByteArray(key)); } private Object readResolve() { if (core != null) { OldDataMonitor.report(Hudson.getInstance(), "1.91"); } return this; } } class FingerprintParams { /** * Null if the build isn't claiming to be the owner. */ final Run build; final String fileName; public FingerprintParams(Run build, String fileName) { this.build = build; this.fileName = fileName; assert fileName != null; } }