blob: 83b1be32740fdc4ef54142e7bb83a6a75f6834a9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.myfaces.scripting.core.dependencyScan;
import org.objectweb.asm.Type;
import java.util.Collection;
import java.util.Set;
/**
* @author Werner Punz (latest modification by $Author$)
* @version $Revision$ $Date$
* <p/>
* Utils which store the shared code
*/
class ClassScanUtils {
public static final String BINARY_PACKAGE = "\\/";
private static final String DOMAIN_JAVA = "java.";
private static final String DOMAIN_JAVAX = "javax.";
private static final String DOMAIN_COM_SUN = "com.sun";
private static final String DOMAIN_APACHE = "org.apache.";
private static final String DOMAIN_MYFACES = "org.apache.myfaces";
private static final String DOMAIN_JBOSS = "org.jboss";
private static final String DOMAIN_SPRING = "org.springframework";
private static final String DOMAIN_JUNIT = "org.junit";
private static final String DOMAIN_ECLIPSE = "org.eclipse";
private static final String DOMAIN_NETBEANS = "org.netbeans";
private static final String DOMAIN_GROOVY = "groovy.";
private static final String DOMAIN_SCALA = "scala.";
private static final String DOMAIN_JYTHON = "jython.";
private static final String DOMAIN_JRUBY = "jruby.";
/**
* checks if a given package or class
* belongs to a standard namespaces which is
* untouchable by an implementer
*
* @param in the page or fully qualified classname
* @return true if it belongs to one of the standard namespaces, false if not
*/
public static boolean isStandardNamespace(String in) {
//We don't use a regexp here, because an test has shown that direct startsWith is 5 times as fast as applying
//a precompiled regexp with match
//shortcuts for a faster killing of the add before going into the heavier
//whitelist check, this one kills off classes which belong to standard
//and semi standard namespaces before whitelisting the rest
return in.startsWith(DOMAIN_JAVA) ||
in.startsWith(DOMAIN_JAVAX) ||
in.startsWith(DOMAIN_COM_SUN) ||
in.startsWith(DOMAIN_GROOVY) ||
in.startsWith(DOMAIN_JYTHON) ||
in.startsWith(DOMAIN_JRUBY) ||
in.startsWith(DOMAIN_SCALA) ||
in.startsWith(DOMAIN_JBOSS) ||
in.startsWith(DOMAIN_SPRING) ||
in.startsWith(DOMAIN_JUNIT) ||
in.startsWith(DOMAIN_ECLIPSE) ||
in.startsWith(DOMAIN_NETBEANS) ||
//apache domain has to be treated specially myfaces can be referenced due to our tests and demos, otherwise this one
//is also treated as taboo zone
((in.startsWith(DOMAIN_APACHE) &&
!in.startsWith(DOMAIN_MYFACES)));
}
/**
* checks for an allowed namespaces from a given namespace list
* if the class or package is in the list of allowed namespaces
* a true is returned otherwise a false
*
* @param classOrPackage the class or package name to be checked for allowance
* @param nameSpaces the list of allowed namespaces
* @return true if the namespace is within the boundaries of the whitelist false otherwise
*/
@SuppressWarnings("unused")
public static boolean allowedNamespaces(String classOrPackage, String[] nameSpaces) {
//ok this is probably the fastest way to iterate hence we use this old construct
//a direct or would be faster but we cannot do it here since we are not dynamic here
int len = nameSpaces.length;
for (int cnt = 0; cnt < len; cnt++) {
if (classOrPackage.startsWith(nameSpaces[cnt])) {
return true;
}
}
return false;
}
/**
* renames the internal member class descriptors of L<qualified classnamewith />; to its source name
*
* @param internalClassName the internal class name
* @return the changed classname in its sourceform
*/
public static String internalClassDescriptorToSource(String internalClassName) {
//we strip the meta information which is not needed
//aka start with ( strip all to )
//()means usually beginning of a native type
if (internalClassName.startsWith("(")) {
internalClassName = internalClassName.substring(internalClassName.lastIndexOf(')') + 1);
}
//()I for single data types
if (internalClassName.equals("") || internalClassName.length() == 1) {
return null;
}
//fully qualified name with meta information
if (internalClassName.endsWith(";")) {
//we can skip all the other meta information, a class identifier on sub class level
//has to start with L the format is <META ATTRIBUTES>L<CLASS QUALIFIED NAME>;
//The meta attributes can be for instance [ for array
internalClassName = internalClassName.substring(internalClassName.indexOf('L') + 1, internalClassName.length() - 1);
}
//normal fully qualified name with no meta info attached
internalClassName = internalClassName.replaceAll(BINARY_PACKAGE, ".");
return internalClassName;
}
/**
* logs a dependency if it does not belong to the standard namespaces
* and also it only is added if it belongs to our whitelist of
* non standard namespaces (the standard check is just a short circuiting
* for performance reasons, before going into the heavier whitelist
* namespace check)
*
* @param dependencies the target which has to receive the dependency in source format
* @param whiteList the whitelist of allowed dependencies
* @param parameters the list of dependencies which have to be added
*/
public static void logParmList(Collection<String> dependencies, final Set<String> whiteList, final String... parameters) {
for (String singleParameter : parameters) {
if (singleParameter == null) continue;
if (singleParameter.equals("")) continue;
singleParameter = internalClassDescriptorToSource(singleParameter);
if (singleParameter == null || isStandardNamespace(singleParameter)) continue;
String[] packages = singleParameter.split("\\.");
StringBuilder fullPackage = null;
for (String currPackage : packages) {
if (fullPackage != null) {
fullPackage.append(".");
fullPackage.append(currPackage);
} else {
fullPackage = new StringBuilder(singleParameter.length());
fullPackage.append(currPackage);
}
String tempPackage = fullPackage.toString();
if (whiteList.contains(tempPackage)) {
dependencies.add(singleParameter);
break;
}
}
}
}
}