blob: 971a1d8d90acbb7eb118e555cb52242bd96bb02a [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* 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.
*/
package com.google.gwt.dev.javac;
import com.google.gwt.core.ext.TreeLogger;
import org.apache.commons.collections.map.AbstractReferenceMap;
import org.apache.commons.collections.map.ReferenceMap;
import java.util.Collections;
import java.util.Map;
/**
* This cache stores {@link CompilationUnit} instances in a Map.
*
* Only one unit is cached per resource path. If the contentId of the unit
* changes, the old unit is discarded and replaced with the new unit.
*/
class MemoryUnitCache implements UnitCache {
/**
* Storage for a compilation unit in the map.
*/
protected static class UnitCacheEntry {
private final UnitOrigin origin;
private final CompilationUnit unit;
protected UnitCacheEntry(CompilationUnit unit, UnitOrigin source) {
this.unit = unit;
this.origin = source;
}
public UnitOrigin getOrigin() {
return origin;
}
public CompilationUnit getUnit() {
return unit;
}
}
/**
* Track how the unit was loaded. Useful in {@link PersistentUnitCache} for
* consolidating old cache files.
*
*/
protected static enum UnitOrigin {
/**
* Unit was loaded from an archive.
*/
ARCHIVE,
/**
* Unit was loaded from persistent store.
*/
PERSISTENT,
/**
* Unit was introduced by an add due to a run-time compile.
*/
RUN_TIME;
}
/**
* References to all {@link CompilationUnit} objects loaded from the
* persistent store, and any new ones added to the store as well.
*
* The key is resource path.
*/
@SuppressWarnings("unchecked")
protected final Map<String, UnitCacheEntry> unitMap = Collections
.synchronizedMap(new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT));
/**
* References {@link CompilationUnit} objects by {@link ContentId}, which is
* composed of the type name and a hash on the source code contents.
*/
@SuppressWarnings("unchecked")
protected final Map<ContentId, UnitCacheEntry> unitMapByContentId = Collections
.synchronizedMap(new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT));
/**
* Adds a new entry into the cache.
*/
@Override
public void add(CompilationUnit newUnit) {
add(newUnit, UnitOrigin.RUN_TIME);
}
/**
* Adds a new entry into the cache, but marks it as already coming from a
* persistent archive. This means it doesn't need to be saved out to disk.
*/
@Override
public void addArchivedUnit(CompilationUnit newUnit) {
add(newUnit, UnitOrigin.ARCHIVE);
}
/**
* This method is a no-op for an in-memory cache.
*/
@Override
public synchronized void cleanup(final TreeLogger logger) {
// do nothing.
}
@Override
public CompilationUnit find(ContentId contentId) {
UnitCacheEntry entry = unitMapByContentId.get(contentId);
if (entry != null) {
return entry.getUnit();
}
return null;
}
@Override
public CompilationUnit find(String resourcePath) {
UnitCacheEntry entry = unitMap.get(resourcePath);
if (entry != null) {
return entry.getUnit();
}
return null;
}
@Override
public void remove(CompilationUnit unit) {
unitMap.remove(unit.getResourcePath());
unitMapByContentId.remove(unit.getContentId());
}
private void add(CompilationUnit newUnit, UnitOrigin origin) {
UnitCacheEntry newEntry = new UnitCacheEntry(newUnit, origin);
String resourcePath = newUnit.getResourcePath();
UnitCacheEntry oldEntry = unitMap.get(resourcePath);
if (oldEntry != null) {
remove(oldEntry.getUnit());
}
unitMap.put(resourcePath, newEntry);
unitMapByContentId.put(newUnit.getContentId(), newEntry);
}
}