/**********************************************************************
* Copyright (c) 2005-2009 ant4eclipse project team.
*
* 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:
* Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich
**********************************************************************/
package org.ant4eclipse.lib.jdt.ecj.internal.tools.loader;
import java.io.File;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.ant4eclipse.lib.core.Assure;
import org.ant4eclipse.lib.core.ClassName;
import org.ant4eclipse.lib.jdt.ecj.ClassFile;
import org.ant4eclipse.lib.jdt.ecj.ClassFileLoader;
import org.ant4eclipse.lib.jdt.ecj.ReferableSourceFile;
import org.ant4eclipse.lib.jdt.ecj.ReferableType;
import org.ant4eclipse.lib.jdt.ecj.internal.tools.DefaultReferableType;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.AccessRule;
/**
* <p>
* </p>
*
* @author Gerd Wuetherich (gerd@gerd-wuetherich.de)
*/
public class FilteringClassFileLoader implements ClassFileLoader {
/** the class file loader that should be filtered */
private ClassFileLoader _classFileLoader;
/** the filter string */
private String _filter;
/** the include patterns */
private List<String> _includes;
/** the exclude patterns */
private List<String> _excludes;
/** - */
private Set<String> _containedPackages;
/**
* <p>
* </p>
*
* @param classFileLoader
* @param filter
*/
public FilteringClassFileLoader(ClassFileLoader classFileLoader, String filter) {
Assure.notNull("classFileLoader", classFileLoader);
Assure.nonEmpty("filter", filter);
this._classFileLoader = classFileLoader;
this._filter = filter;
this._includes = new LinkedList<String>();
this._excludes = new LinkedList<String>();
init();
}
/**
* {@inheritDoc}
*/
public File[] getClasspath() {
return this._classFileLoader.getClasspath();
}
/**
* {@inheritDoc}
*/
public String[] getAllPackages() {
return this._classFileLoader.getAllPackages();
}
/**
* {@inheritDoc}
*/
public boolean hasPackage(String packageName) {
return this._classFileLoader.hasPackage(packageName);
}
/**
* {@inheritDoc}
*/
public ClassFile loadClass(ClassName className) {
ClassFile result = this._classFileLoader.loadClass(className);
setAccessRestrictions(result, className);
return result;
}
/**
* {@inheritDoc}
*/
public ReferableSourceFile loadSource(ClassName className) {
ReferableSourceFile result = this._classFileLoader.loadSource(className);
setAccessRestrictions(result, className);
return result;
}
/**
* <p>
* </p>
*
* @param referableType
* @return
*/
private ReferableType setAccessRestrictions(ReferableType referableType, ClassName className) {
//
if (referableType == null) {
return referableType;
}
// try 'shortcut'
if (this._containedPackages != null && this._containedPackages.contains(className.getPackageName())) {
return referableType;
}
//
String classFileName = className.asClassFileName();
//
for (String includePattern : this._includes) {
if (classFileName.matches(includePattern)) {
return referableType;
}
}
//
for (String exludePattern : this._excludes) {
if (classFileName.matches(exludePattern)) {
if (referableType instanceof DefaultReferableType) {
AccessRestriction accessRestriction = new AccessRestriction(new AccessRule("**".toCharArray(),
IProblem.ForbiddenReference), referableType.getLibraryType(), referableType.getLibraryLocation());
((DefaultReferableType) referableType).setAccessRestriction(accessRestriction);
}
return referableType;
}
}
return referableType;
}
/**
* <p>
* </p>
*/
private void init() {
//
this._containedPackages = new HashSet<String>();
//
for (String part : this._filter.split(";")) {
// step 0:
if (part.matches("\\+.*/\\*")) {
this._containedPackages.add(part.substring(1, part.length() - 2).replace('/', '.'));
} else if (part.matches("\\-\\*\\*/\\*")) {
//
} else {
this._containedPackages = null;
}
// step 1: replace all occurrences of '**/*' with '###' (temporary step)
String transformedPart = part.substring(1).replaceAll("\\*\\*/\\*", "###");
// step 2: replace all occurrences of '*' with '[^\.]*'
transformedPart = transformedPart.replaceAll("\\*", "[^\\\\.]*");
// step 3: replace all occurrences of '###' (formally '**/*') with '.*'
transformedPart = transformedPart.replaceAll("###", ".*");
// step 4: append '\.class'
transformedPart = transformedPart.concat("\\.class");
if (part.startsWith("+")) {
this._includes.add(transformedPart);
}
if (part.startsWith("-")) {
this._excludes.add(transformedPart);
}
}
}
}