/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Yahoo! Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.model;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import hudson.Util;
import hudson.XmlFile;
import hudson.BulkChange;
import hudson.Extension;
import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SaveableListener;
import hudson.util.HexBinaryConverter;
import hudson.util.Iterators;
import hudson.util.PersistedList;
import hudson.util.RunList;
import hudson.util.XStream2;
import jenkins.model.FingerprintFacet;
import jenkins.model.Jenkins;
import jenkins.model.TransientFingerprintFacetFactory;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import java.io.File;
import java.io.IOException;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A file being tracked by Jenkins.
*
*
* Lifecycle is managed by {@link FingerprintMap}.
*
* @author Kohsuke Kawaguchi
* @see FingerprintMap
*/
@ExportedBean
public class Fingerprint implements ModelObject, Saveable {
/**
* Pointer to a {@link Build}.
*/
@ExportedBean(defaultVisibility=2)
public static class BuildPtr {
String name;
final int number;
public BuildPtr(String name, int number) {
this.name = name;
this.number = number;
}
public BuildPtr(Run run) {
this( run.getParent().getFullName(), run.getNumber() );
}
/**
* Gets {@link Job#getFullName() the full name of the job}.
*
* Such job could be since then removed,
* so there might not be a corresponding
* {@link Job}.
*/
@Exported
public String getName() {
return name;
}
void setName(String newName) {
name = newName;
}
/**
* Gets the {@link Job} that this pointer points to,
* or null if such a job no longer exists.
*/
public AbstractProject getJob() {
return Jenkins.getInstance().getItemByFullName(name,AbstractProject.class);
}
/**
* Gets the project build number.
*
* Such {@link Run} could be since then
* discarded.
*/
@Exported
public int getNumber() {
return number;
}
/**
* Gets the {@link Job} that this pointer points to,
* or null if such a job no longer exists.
*/
public Run getRun() {
Job j = getJob();
if(j==null) return null;
return j.getBuildByNumber(number);
}
private boolean isAlive() {
return getRun()!=null;
}
/**
* Returns true if {@link BuildPtr} points to the given run.
*/
public boolean is(Run r) {
return r.getNumber()==number && r.getParent().getFullName().equals(name);
}
/**
* Returns true if {@link BuildPtr} points to the given job.
*/
public boolean is(Job job) {
return job.getFullName().equals(name);
}
/**
* Returns true if {@link BuildPtr} points to the given job
* or one of its subordinates.
*
*
* This is useful to check if an artifact in MavenModule
* belongs to MavenModuleSet.
*/
public boolean belongsTo(Job job) {
Item p = Jenkins.getInstance().getItemByFullName(name);
while(p!=null) {
if(p==job)
return true;
// go up the chain while we
ItemGroup extends Item> parent = p.getParent();
if (!(parent instanceof Item)) {
return false;
}
p = (Item) parent;
}
return false;
}
}
/**
* Range of build numbers [start,end). Immutable.
*/
@ExportedBean(defaultVisibility=4)
public static final class Range {
final int start;
final int end;
public Range(int start, int end) {
assert start ranges;
public RangeSet() {
this(new ArrayList());
}
private RangeSet(List data) {
this.ranges = data;
}
/**
* List all numbers in this range set, in the ascending order.
*/
public Iterable listNumbers() {
final List ranges = getRanges();
return new Iterable() {
public Iterator iterator() {
return new Iterators.FlattenIterator(ranges) {
protected Iterator expand(Range range) {
return Iterators.sequence(range.start,range.end).iterator();
}
};
}
};
}
// /**
// * List up builds.
// */
// public ,R extends Run> Iterable listBuilds(final J job) {
// return new Iterable() {
// public Iterator iterator() {
// return new Iterators.FilterIterator(new AdaptedIterator(listNumbers().iterator()) {
// protected R adapt(Integer n) {
// return job.getBuildByNumber(n);
// }
// }) {
// protected boolean filter(R r) {
// return r!=null;
// }
// };
// }
// };
// }
/**
* List all numbers in this range set in the descending order.
*/
public Iterable listNumbersReverse() {
final List ranges = getRanges();
return new Iterable() {
public Iterator iterator() {
return new Iterators.FlattenIterator(Iterators.reverse(ranges)) {
protected Iterator expand(Range range) {
return Iterators.reverseSequence(range.start,range.end).iterator();
}
};
}
};
}
/**
* Gets all the ranges.
*/
@Exported
public synchronized List getRanges() {
return new ArrayList(ranges);
}
/**
* Expands the range set to include the given value.
* If the set already includes this number, this will be a no-op.
*/
public synchronized void add(int n) {
for( int i=0; i0) buf.append(',');
buf.append(r);
}
return buf.toString();
}
public synchronized boolean isEmpty() {
return ranges.isEmpty();
}
/**
* Returns the smallest value in this range.
*
* If this range is empty, this method throws an exception.
*/
public synchronized int min() {
return ranges.get(0).start;
}
/**
* Returns the largest value in this range.
*
* If this range is empty, this method throws an exception.
*/
public synchronized int max() {
return ranges.get(ranges.size()-1).end;
}
/**
* Returns true if all the integers logically in this {@link RangeSet}
* is smaller than the given integer. For example, {[1,3)} is smaller than 3,
* but {[1,3),[100,105)} is not smaller than anything less than 105.
*
* Note that {} is smaller than any n.
*/
public synchronized boolean isSmallerThan(int n) {
if(ranges.isEmpty()) return true;
return ranges.get(ranges.size() - 1).isSmallerThan(n);
}
/**
* Parses a {@link RangeSet} from a string like "1-3,5,7-9"
*/
public static RangeSet fromString(String list, boolean skipError) {
RangeSet rs = new RangeSet();
for (String s : Util.tokenize(list,",")) {
s = s.trim();
// s is either single number or range "x-y".
// note that the end range is inclusive in this notation, but not in the Range class
try {
if(s.contains("-")) {
String[] tokens = Util.tokenize(s,"-");
rs.ranges.add(new Range(Integer.parseInt(tokens[0]),Integer.parseInt(tokens[1])+1));
} else {
int n = Integer.parseInt(s);
rs.ranges.add(new Range(n,n+1));
}
} catch (NumberFormatException e) {
if (!skipError)
throw new IllegalArgumentException("Unable to parse "+list);
// ignore malformed text
}
}
return rs;
}
static final class ConverterImpl implements Converter {
private final Converter collectionConv; // used to convert ArrayList in it
public ConverterImpl(Converter collectionConv) {
this.collectionConv = collectionConv;
}
public boolean canConvert(Class type) {
return type==RangeSet.class;
}
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
RangeSet src = (RangeSet) source;
StringBuilder buf = new StringBuilder(src.ranges.size()*10);
for (Range r : src.ranges) {
if(buf.length()>0) buf.append(',');
if(r.isSingle())
buf.append(r.start);
else
buf.append(r.start).append('-').append(r.end-1);
}
writer.setValue(buf.toString());
}
public Object unmarshal(HierarchicalStreamReader reader, final UnmarshallingContext context) {
if(reader.hasMoreChildren()) {
/* old format where elements are nested like
1337
1479
*/
return new RangeSet((List)(collectionConv.unmarshal(reader,context)));
} else {
return RangeSet.fromString(reader.getValue(),true);
}
}
}
}
@Extension
public static final class ProjectRenameListener extends ItemListener {
@Override
public void onRenamed(Item item, String oldName, String newName) {
if (item instanceof AbstractProject) {
AbstractProject p = Hudson.getInstance().getItemByFullName(newName, AbstractProject.class);
if (p != null) {
RunList builds = p.getBuilds();
for (Object build : builds) {
if (build instanceof AbstractBuild) {
Collection fingerprints = ((AbstractBuild)build).getBuildFingerprints();
for (Fingerprint f : fingerprints) {
try {
f.rename(oldName, newName);
} catch (IOException e) {
logger.log(Level.WARNING, "Failed to update fingerprint record " + f.getFileName() + " when " + oldName + " was renamed to " + newName, e);
}
}
}
}
}
}
}
}
private final Date timestamp;
/**
* Null if this fingerprint is for a file that's
* apparently produced outside.
*/
private final BuildPtr original;
private final byte[] md5sum;
private final String fileName;
/**
* Range of builds that use this file keyed by a job full name.
*/
private final Hashtable usages = new Hashtable();
private PersistedList facets = new PersistedList(this);
/**
* Lazily computed immutable {@link FingerprintFacet}s created from {@link TransientFingerprintFacetFactory}.
*/
private transient volatile List transientFacets = null;
public Fingerprint(Run build, String fileName, byte[] md5sum) throws IOException {
this.original = build==null ? null : new BuildPtr(build);
this.md5sum = md5sum;
this.fileName = fileName;
this.timestamp = new Date();
save();
}
/**
* The first build in which this file showed up,
* if the file looked like it's created there.
*
* This is considered as the "source" of this file,
* or the owner, in the sense that this project "owns"
* this file.
*
* @return null
* if the file is apparently created outside Hudson.
*/
@Exported
public BuildPtr getOriginal() {
return original;
}
public String getDisplayName() {
return fileName;
}
/**
* The file name (like "foo.jar" without path).
*/
@Exported
public String getFileName() {
return fileName;
}
/**
* Gets the MD5 hash string.
*/
@Exported(name="hash")
public String getHashString() {
return Util.toHexString(md5sum);
}
/**
* Gets the timestamp when this record is created.
*/
@Exported
public Date getTimestamp() {
return timestamp;
}
/**
* Gets the string that says how long since this build has scheduled.
*
* @return
* string like "3 minutes" "1 day" etc.
*/
public String getTimestampString() {
long duration = System.currentTimeMillis()-timestamp.getTime();
return Util.getPastTimeString(duration);
}
/**
* Gets the build range set for the given job name.
*
*
* These builds of this job has used this file.
*/
public RangeSet getRangeSet(String jobFullName) {
RangeSet r = usages.get(jobFullName);
if(r==null) r = new RangeSet();
return r;
}
public RangeSet getRangeSet(Job job) {
return getRangeSet(job.getFullName());
}
/**
* Gets the sorted list of job names where this jar is used.
*/
public List getJobs() {
List r = new ArrayList();
r.addAll(usages.keySet());
Collections.sort(r);
return r;
}
public Hashtable getUsages() {
return usages;
}
@ExportedBean(defaultVisibility=2)
public static final class RangeItem {
@Exported
public final String name;
@Exported
public final RangeSet ranges;
public RangeItem(String name, RangeSet ranges) {
this.name = name;
this.ranges = ranges;
}
}
// this is for remote API
@Exported(name="usage")
public List _getUsages() {
List r = new ArrayList();
for (Entry e : usages.entrySet())
r.add(new RangeItem(e.getKey(),e.getValue()));
return r;
}
public synchronized void add(AbstractBuild b) throws IOException {
add(b.getParent().getFullName(),b.getNumber());
}
/**
* Records that a build of a job has used this file.
*/
public synchronized void add(String jobFullName, int n) throws IOException {
synchronized(usages) {
RangeSet r = usages.get(jobFullName);
if(r==null) {
r = new RangeSet();
usages.put(jobFullName,r);
}
r.add(n);
}
save();
}
/**
* Returns true if any of the builds recorded in this fingerprint
* is still retained.
*
*
* This is used to find out old fingerprint records that can be removed
* without losing too much information.
*/
public synchronized boolean isAlive() {
if(original!=null && original.isAlive())
return true;
for (Entry e : usages.entrySet()) {
Job j = Jenkins.getInstance().getItemByFullName(e.getKey(),Job.class);
if(j==null)
continue;
Run firstBuild = j.getFirstBuild();
if(firstBuild==null)
continue;
int oldest = firstBuild.getNumber();
if(!e.getValue().isSmallerThan(oldest))
return true;
}
return false;
}
/**
* Gets the associated {@link FingerprintFacet}s.
*
*
* This method always return a non-empty collection, which is a synthetic collection.
* It contains persisted {@link FingerprintFacet}s (those that are added explicitly, like
* {@code fingerprint.getFacets().add(x)}), as well those {@linkplain TransientFingerprintFacetFactory that are transient}.
*
*
* Mutation to this collection will manipulate persisted set of {@link FingerprintFacet}s, and therefore regardless
* of what you do, this collection will always contain a set of {@link FingerprintFacet}s that are added
* by {@link TransientFingerprintFacetFactory}s.
*
* @since 1.421
*/
public Collection getFacets() {
if (transientFacets==null) {
List transientFacets = new ArrayList();
for (TransientFingerprintFacetFactory fff : TransientFingerprintFacetFactory.all()) {
fff.createFor(this,transientFacets);
}
this.transientFacets = ImmutableList.copyOf(transientFacets);
}
return new AbstractCollection() {
@Override
public Iterator iterator() {
return Iterators.sequence(facets.iterator(), transientFacets.iterator());
}
@Override
public boolean add(FingerprintFacet e) {
try {
facets.add(e);
return true;
} catch (IOException x) {
throw new Error(x);
}
}
@Override
public boolean remove(Object o) {
try {
return facets.remove((FingerprintFacet)o);
} catch (IOException x) {
throw new Error(x);
}
}
@Override
public boolean contains(Object o) {
return facets.contains(o) || transientFacets.contains(o);
}
@Override
public int size() {
return facets.size()+transientFacets.size();
}
};
}
public Collection getSortedFacets() {
List r = new ArrayList(getFacets());
Collections.sort(r,new Comparator() {
public int compare(FingerprintFacet o1, FingerprintFacet o2) {
long a = o1.getTimestamp();
long b = o2.getTimestamp();
if (a getActions() {
List r = new ArrayList();
for (FingerprintFacet ff : getFacets())
ff.createActions(r);
return Collections.unmodifiableList(r);
}
/**
* Save the settings to a file.
*/
public synchronized void save() throws IOException {
if(BulkChange.contains(this)) return;
long start=0;
if(logger.isLoggable(Level.FINE))
start = System.currentTimeMillis();
File file = getFingerprintFile(md5sum);
getConfigFile(file).write(this);
SaveableListener.fireOnChange(this, getConfigFile(file));
if(logger.isLoggable(Level.FINE))
logger.fine("Saving fingerprint "+file+" took "+(System.currentTimeMillis()-start)+"ms");
}
/**
* Update references to a renamed job in the fingerprint
*/
public synchronized void rename(String oldName, String newName) throws IOException {
boolean touched = false;
if (original != null) {
if (original.getName().equals(oldName)) {
original.setName(newName);
touched = true;
}
}
if (usages != null) {
RangeSet r = usages.get(oldName);
if (r != null) {
usages.put(newName, r);
usages.remove(oldName);
touched = true;
}
}
if (touched) {
save();
}
}
public Api getApi() {
return new Api(this);
}
/**
* The file we save our configuration.
*/
private static XmlFile getConfigFile(File file) {
return new XmlFile(XSTREAM,file);
}
/**
* Determines the file name from md5sum.
*/
private static File getFingerprintFile(byte[] md5sum) {
assert md5sum.length==16;
return new File( Jenkins.getInstance().getRootDir(),
"fingerprints/"+ Util.toHexString(md5sum,0,1)+'/'+Util.toHexString(md5sum,1,1)+'/'+Util.toHexString(md5sum,2,md5sum.length-2)+".xml");
}
/**
* Loads a {@link Fingerprint} from a file in the image.
*/
/*package*/ static Fingerprint load(byte[] md5sum) throws IOException {
return load(getFingerprintFile(md5sum));
}
/*package*/ static Fingerprint load(File file) throws IOException {
XmlFile configFile = getConfigFile(file);
if(!configFile.exists())
return null;
long start=0;
if(logger.isLoggable(Level.FINE))
start = System.currentTimeMillis();
try {
Fingerprint f = (Fingerprint) configFile.read();
if(logger.isLoggable(Level.FINE))
logger.fine("Loading fingerprint "+file+" took "+(System.currentTimeMillis()-start)+"ms");
if (f.facets==null)
f.facets = new PersistedList(f);
for (FingerprintFacet facet : f.facets)
facet._setOwner(f);
return f;
} catch (IOException e) {
if(file.exists() && file.length()==0) {
// Despite the use of AtomicFile, there are reports indicating that people often see
// empty XML file, presumably either due to file system corruption (perhaps by sudden
// power loss, etc.) or abnormal program termination.
// generally we don't want to wipe out user data just because we can't load it,
// but if the file size is 0, which is what's reported in HUDSON-2012, then it seems
// like recovering it silently by deleting the file is not a bad idea.
logger.log(Level.WARNING, "Size zero fingerprint. Disk corruption? "+configFile,e);
file.delete();
return null;
}
logger.log(Level.WARNING, "Failed to load "+configFile,e);
throw e;
}
}
private static final XStream XSTREAM = new XStream2();
static {
XSTREAM.alias("fingerprint",Fingerprint.class);
XSTREAM.alias("range",Range.class);
XSTREAM.alias("ranges",RangeSet.class);
XSTREAM.registerConverter(new HexBinaryConverter(),10);
XSTREAM.registerConverter(new RangeSet.ConverterImpl(
new CollectionConverter(XSTREAM.getMapper()) {
@Override
protected Object createCollection(Class type) {
return new ArrayList();
}
}
),10);
}
private static final Logger logger = Logger.getLogger(Fingerprint.class.getName());
}
----- Classpath: ---------------------------------------------
bootPath: /space/jdk1.7.0_15/jre/lib/resources.jar:/space/jdk1.7.0_15/jre/lib/rt.jar:/space/jdk1.7.0_15/jre/lib/sunrsasign.jar:/space/jdk1.7.0_15/jre/lib/jsse.jar:/space/jdk1.7.0_15/jre/lib/jce.jar:/space/jdk1.7.0_15/jre/lib/charsets.jar:/space/jdk1.7.0_15/jre/lib/jfr.jar:/space/jdk1.7.0_15/jre/classes:/space/jdk1.7.0_15/jre/lib/ext/localedata.jar:/space/jdk1.7.0_15/jre/lib/ext/dnsns.jar:/space/jdk1.7.0_15/jre/lib/ext/sunjce_provider.jar:/space/jdk1.7.0_15/jre/lib/ext/sunpkcs11.jar:/space/jdk1.7.0_15/jre/lib/ext/zipfs.jar:/space/jdk1.7.0_15/jre/lib/ext/sunec.jar
classPath: /space/tmp/m2repo/org/jenkins-ci/main/remoting/2.22/remoting-2.22.jar:/space/tmp/m2repo/org/jenkins-ci/main/cli/1.504-SNAPSHOT/cli-1.504-SNAPSHOT.jar:/space/tmp/m2repo/org/jenkins-ci/version-number/1.1/version-number-1.1.jar:/space/tmp/m2repo/org/jenkins-ci/crypto-util/1.1/crypto-util-1.1.jar:/space/tmp/m2repo/org/jvnet/hudson/jtidy/4aug2000r7-dev-hudson-1/jtidy-4aug2000r7-dev-hudson-1.jar:/space/tmp/m2repo/org/jenkins-ci/core-annotation-processors/1.0/core-annotation-processors-1.0.jar:/space/tmp/m2repo/org/sonatype/sisu/sisu-guice/3.1.0/sisu-guice-3.1.0.jar:/space/tmp/m2repo/javax/inject/javax.inject/1/javax.inject-1.jar:/space/tmp/m2repo/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/space/tmp/m2repo/org/jruby/ext/posix/jna-posix/1.0.3/jna-posix-1.0.3.jar:/space/tmp/m2repo/org/kohsuke/trilead-putty-extension/1.2/trilead-putty-extension-1.2.jar:/space/tmp/m2repo/org/jenkins-ci/trilead-ssh2/build214-jenkins-1/trilead-ssh2-build214-jenkins-1.jar:/space/tmp/m2repo/org/kohsuke/stapler/stapler-groovy/1.199/stapler-groovy-1.199.jar:/space/tmp/m2repo/org/kohsuke/stapler/stapler-jelly/1.199/stapler-jelly-1.199.jar:/space/tmp/m2repo/org/jenkins-ci/commons-jelly/1.1-jenkins-20120928/commons-jelly-1.1-jenkins-20120928.jar:/space/tmp/m2repo/org/jvnet/hudson/dom4j/dom4j/1.6.1-hudson-3/dom4j-1.6.1-hudson-3.jar:/space/tmp/m2repo/org/kohsuke/stapler/stapler-jrebel/1.199/stapler-jrebel-1.199.jar:/space/tmp/m2repo/org/kohsuke/stapler/stapler/1.199/stapler-1.199.jar:/space/tmp/m2repo/commons-discovery/commons-discovery/0.4/commons-discovery-0.4.jar:/space/tmp/m2repo/org/jvnet/tiger-types/1.3/tiger-types-1.3.jar:/space/tmp/m2repo/org/kohsuke/asm3/3.3.0/asm3-3.3.0.jar:/space/tmp/m2repo/commons-fileupload/commons-fileupload/1.2.1/commons-fileupload-1.2.1.jar:/space/tmp/m2repo/org/kohsuke/windows-package-checker/1.0/windows-package-checker-1.0.jar:/space/tmp/m2repo/org/kohsuke/stapler/stapler-adjunct-zeroclipboard/1.0.7-1/stapler-adjunct-zeroclipboard-1.0.7-1.jar:/space/tmp/m2repo/org/kohsuke/stapler/stapler-adjunct-timeline/1.3/stapler-adjunct-timeline-1.3.jar:/space/tmp/m2repo/org/kohsuke/stapler/stapler-adjunct-codemirror/1.1/stapler-adjunct-codemirror-1.1.jar:/space/tmp/m2repo/com/infradna/tool/bridge-method-annotation/1.4/bridge-method-annotation-1.4.jar:/space/tmp/m2repo/org/kohsuke/stapler/json-lib/2.1-rev7/json-lib-2.1-rev7.jar:/space/tmp/m2repo/net/sf/ezmorph/ezmorph/1.0.3/ezmorph-1.0.3.jar:/space/tmp/m2repo/commons-httpclient/commons-httpclient/3.1/commons-httpclient-3.1.jar:/space/tmp/m2repo/args4j/args4j/2.0.21/args4j-2.0.21.jar:/space/tmp/m2repo/org/jenkins-ci/annotation-indexer/1.4/annotation-indexer-1.4.jar:/space/tmp/m2repo/org/jvnet/hudson/task-reactor/1.2/task-reactor-1.2.jar:/space/tmp/m2repo/org/jvnet/localizer/localizer/1.10/localizer-1.10.jar:/space/tmp/m2repo/antlr/antlr/2.7.6/antlr-2.7.6.jar:/space/tmp/m2repo/org/jvnet/hudson/xstream/1.3.1-jenkins-11/xstream-1.3.1-jenkins-11.jar:/space/tmp/m2repo/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar:/space/tmp/m2repo/jfree/jfreechart/1.0.9/jfreechart-1.0.9.jar:/space/tmp/m2repo/jfree/jcommon/1.0.12/jcommon-1.0.12.jar:/space/tmp/m2repo/org/apache/ant/ant/1.8.3/ant-1.8.3.jar:/space/tmp/m2repo/org/apache/ant/ant-launcher/1.8.3/ant-launcher-1.8.3.jar:/space/tmp/m2repo/javax/servlet/servlet-api/2.4/servlet-api-2.4.jar:/space/tmp/m2repo/commons-io/commons-io/1.4/commons-io-1.4.jar:/space/tmp/m2repo/commons-lang/commons-lang/2.6/commons-lang-2.6.jar:/space/tmp/m2repo/commons-digester/commons-digester/2.1/commons-digester-2.1.jar:/space/tmp/m2repo/commons-beanutils/commons-beanutils/1.8.3/commons-beanutils-1.8.3.jar:/space/tmp/m2repo/javax/mail/mail/1.4.4/mail-1.4.4.jar:/space/tmp/m2repo/org/jvnet/hudson/activation/1.1.1-hudson-1/activation-1.1.1-hudson-1.jar:/space/tmp/m2repo/jaxen/jaxen/1.1-beta-11/jaxen-1.1-beta-11.jar:/space/tmp/m2repo/commons-jelly/commons-jelly-tags-fmt/1.0/commons-jelly-tags-fmt-1.0.jar:/space/tmp/m2repo/commons-jelly/commons-jelly-tags-xml/1.1/commons-jelly-tags-xml-1.1.jar:/space/tmp/m2repo/org/jvnet/hudson/commons-jelly-tags-define/1.0.1-hudson-20071021/commons-jelly-tags-define-1.0.1-hudson-20071021.jar:/space/tmp/m2repo/org/jenkins-ci/commons-jexl/1.1-jenkins-20111212/commons-jexl-1.1-jenkins-20111212.jar:/space/tmp/m2repo/org/acegisecurity/acegi-security/1.0.7/acegi-security-1.0.7.jar:/space/tmp/m2repo/org/springframework/spring-jdbc/1.2.9/spring-jdbc-1.2.9.jar:/space/tmp/m2repo/org/springframework/spring-dao/1.2.9/spring-dao-1.2.9.jar:/space/tmp/m2repo/oro/oro/2.0.8/oro-2.0.8.jar:/space/tmp/m2repo/org/codehaus/groovy/groovy-all/1.8.5/groovy-all-1.8.5.jar:/space/tmp/m2repo/jline/jline/0.9.94/jline-0.9.94.jar:/space/tmp/m2repo/org/fusesource/jansi/jansi/1.9/jansi-1.9.jar:/space/tmp/m2repo/org/springframework/spring-webmvc/2.5.6.SEC03/spring-webmvc-2.5.6.SEC03.jar:/space/tmp/m2repo/org/springframework/spring-beans/2.5.6.SEC03/spring-beans-2.5.6.SEC03.jar:/space/tmp/m2repo/org/springframework/spring-context/2.5.6.SEC03/spring-context-2.5.6.SEC03.jar:/space/tmp/m2repo/org/springframework/spring-context-support/2.5.6.SEC03/spring-context-support-2.5.6.SEC03.jar:/space/tmp/m2repo/org/springframework/spring-web/2.5.6.SEC03/spring-web-2.5.6.SEC03.jar:/space/tmp/m2repo/org/springframework/spring-core/2.5.6.SEC03/spring-core-2.5.6.SEC03.jar:/space/tmp/m2repo/org/springframework/spring-aop/2.5.6.SEC03/spring-aop-2.5.6.SEC03.jar:/space/tmp/m2repo/xpp3/xpp3/1.1.4c/xpp3-1.1.4c.jar:/space/tmp/m2repo/javax/servlet/jstl/1.1.0/jstl-1.1.0.jar:/space/tmp/m2repo/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/space/tmp/m2repo/com/sun/xml/txw2/txw2/20110809/txw2-20110809.jar:/space/tmp/m2repo/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar:/space/tmp/m2repo/relaxngDatatype/relaxngDatatype/20020414/relaxngDatatype-20020414.jar:/space/tmp/m2repo/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar:/space/tmp/m2repo/org/jvnet/winp/winp/1.16/winp-1.16.jar:/space/tmp/m2repo/org/jenkins-ci/memory-monitor/1.7/memory-monitor-1.7.jar:/space/tmp/m2repo/org/codehaus/woodstox/wstx-asl/3.2.9/wstx-asl-3.2.9.jar:/space/tmp/m2repo/stax/stax-api/1.0.1/stax-api-1.0.1.jar:/space/tmp/m2repo/org/jenkins-ci/jmdns/3.4.0-jenkins-3/jmdns-3.4.0-jenkins-3.jar:/space/tmp/m2repo/net/java/dev/jna/jna/3.3.0-jenkins-3/jna-3.3.0-jenkins-3.jar:/space/tmp/m2repo/org/kohsuke/akuma/1.9/akuma-1.9.jar:/space/tmp/m2repo/org/kohsuke/libpam4j/1.6/libpam4j-1.6.jar:/space/tmp/m2repo/org/jvnet/libzfs/libzfs/0.5/libzfs-0.5.jar:/space/tmp/m2repo/com/sun/solaris/embedded_su4j/1.1/embedded_su4j-1.1.jar:/space/tmp/m2repo/net/java/sezpoz/sezpoz/1.9/sezpoz-1.9.jar:/space/tmp/m2repo/org/jenkins-ci/jinterop-wmi/1.1/jinterop-wmi-1.1.jar:/space/tmp/m2repo/org/kohsuke/jinterop/jinterop-proxy/1.1/jinterop-proxy-1.1.jar:/space/tmp/m2repo/org/kohsuke/jinterop/j-interop/2.0.6-kohsuke-1/j-interop-2.0.6-kohsuke-1.jar:/space/tmp/m2repo/org/kohsuke/jinterop/j-interopdeps/2.0.6-kohsuke-1/j-interopdeps-2.0.6-kohsuke-1.jar:/space/tmp/m2repo/org/jenkins-ci/windows-remote-command/1.3/windows-remote-command-1.3.jar:/space/tmp/m2repo/org/samba/jcifs/jcifs/1.3.14-kohsuke-1/jcifs-1.3.14-kohsuke-1.jar:/space/tmp/m2repo/org/kohsuke/metainf-services/metainf-services/1.4/metainf-services-1.4.jar:/space/tmp/m2repo/org/jvnet/robust-http-client/robust-http-client/1.2/robust-http-client-1.2.jar:/space/tmp/m2repo/commons-codec/commons-codec/1.6/commons-codec-1.6.jar:/space/tmp/m2repo/org/kohsuke/access-modifier-annotation/1.4/access-modifier-annotation-1.4.jar:/space/tmp/m2repo/findbugs/annotations/1.0.0/annotations-1.0.0.jar:/space/tmp/m2repo/org/kohsuke/owasp-html-sanitizer/r88/owasp-html-sanitizer-r88.jar:/space/tmp/m2repo/org/mindrot/jbcrypt/0.3m/jbcrypt-0.3m.jar:/space/tmp/m2repo/com/google/guava/guava/11.0.1/guava-11.0.1.jar:/space/tmp/m2repo/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.jar:/space/tmp/m2repo/org/codehaus/mojo/animal-sniffer-annotations/1.9/animal-sniffer-annotations-1.9.jar
sourcePath: /space/src/hudson/jenkins/core/src/main/java:/space/src/hudson/jenkins/core/target/generated-sources/taglib-interface:/space/src/hudson/jenkins/core/target/generated-sources/antlr:/space/src/hudson/jenkins/core/target/generated-sources/localizer:/space/src/hudson/jenkins/core/target/generated-sources/groovy-stubs:/space/src/hudson/jenkins/core/src/main/resources:/space/src/hudson/jenkins/core/src/filter/resources
----- Original exception ---------------------------------------------
java.lang.AssertionError
at com.sun.tools.javac.util.Assert.error(Assert.java:126)
at com.sun.tools.javac.util.Assert.check(Assert.java:45)
at com.sun.tools.javac.comp.MemberEnter$5.enterAnnotation(MemberEnter.java:1001)
at com.sun.tools.javac.comp.Annotate.flush(Annotate.java:131)
at com.sun.tools.javac.comp.Annotate.enterDone(Annotate.java:123)
at com.sun.tools.javac.comp.Enter.complete(Enter.java:740)
at com.sun.tools.javac.main.JavaCompiler.complete(JavaCompiler.java:1065)
at com.sun.tools.javac.main.JavaCompiler.enterTrees(JavaCompiler.java:1027)
at com.sun.tools.javac.api.JavacTaskImpl.enter(JavacTaskImpl.java:365)
at com.sun.tools.javac.api.JavacTaskImpl.enter(JavacTaskImpl.java:305)
at org.netbeans.modules.java.source.parsing.JavacParser.moveToPhase(JavacParser.java:650)
at org.netbeans.modules.java.source.parsing.CompilationInfoImpl.toPhase(CompilationInfoImpl.java:385)
at org.netbeans.api.java.source.CompilationController.toPhase(CompilationController.java:109)
at org.netbeans.modules.refactoring.java.plugins.JavaWhereUsedQueryPlugin$FindTask.run(JavaWhereUsedQueryPlugin.java:490)
at org.netbeans.modules.refactoring.java.plugins.JavaWhereUsedQueryPlugin$FindTask.run(JavaWhereUsedQueryPlugin.java:469)
at org.netbeans.api.java.source.JavaSource$MultiTask.run(JavaSource.java:488)
at org.netbeans.modules.parsing.impl.TaskProcessor.callUserTask(TaskProcessor.java:586)
at org.netbeans.modules.parsing.api.ParserManager$MultiUserTaskAction.run(ParserManager.java:191)
at org.netbeans.modules.parsing.api.ParserManager$MultiUserTaskAction.run(ParserManager.java:163)
at org.netbeans.modules.parsing.impl.TaskProcessor$2.call(TaskProcessor.java:201)
at org.netbeans.modules.parsing.impl.TaskProcessor$2.call(TaskProcessor.java:198)
at org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager.priorityIO(FileChangedManager.java:176)
at org.netbeans.modules.masterfs.providers.ProvidedExtensions.priorityIO(ProvidedExtensions.java:360)
at org.netbeans.modules.parsing.impl.Utilities.runPriorityIO(Utilities.java:74)
at org.netbeans.modules.parsing.impl.TaskProcessor.runUserTask(TaskProcessor.java:198)
at org.netbeans.modules.parsing.api.ParserManager.parse(ParserManager.java:108)
at org.netbeans.api.java.source.JavaSource.runUserActionTaskImpl(JavaSource.java:438)
at org.netbeans.api.java.source.JavaSource.runUserActionTask(JavaSource.java:409)
at org.netbeans.modules.refactoring.java.spi.JavaRefactoringPlugin.processFiles(JavaRefactoringPlugin.java:275)
at org.netbeans.modules.refactoring.java.spi.JavaRefactoringPlugin.queryFiles(JavaRefactoringPlugin.java:259)
at org.netbeans.modules.refactoring.java.plugins.JavaWhereUsedQueryPlugin.prepare(JavaWhereUsedQueryPlugin.java:374)
at org.netbeans.modules.refactoring.api.AbstractRefactoring.pluginsPrepare2(AbstractRefactoring.java:437)
at org.netbeans.modules.refactoring.api.AbstractRefactoring.pluginsPrepare(AbstractRefactoring.java:421)
at org.netbeans.modules.refactoring.api.AbstractRefactoring.prepare(AbstractRefactoring.java:232)
at org.netbeans.modules.refactoring.spi.impl.ParametersPanel$Prepare$2.run(ParametersPanel.java:1016)
at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1432)
at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2044)