// Copyright 2018 The Bazel Authors. All rights reserved. // // 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.devtools.build.android.resources; import static java.util.stream.Collectors.joining; import com.google.common.collect.ImmutableSet; import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Stream; /** Validates resource identifiers and packages for java identifier validity. */ public class JavaIdentifierValidator { private JavaIdentifierValidator() {} /** Thrown when a resource filed is not a valida java identifier. */ public static class InvalidJavaIdentifier extends RuntimeException { /** Creates a new exception. */ public InvalidJavaIdentifier(String message) { super(message); } } /** * Validates a resource identifier for java correctness. * * @param identifier an identifier derived from an android resource. * @param additionalInformation optional information about the identifier. * @return The identifier if valid. * @throws InvalidJavaIdentifier if the identifier is invalid. */ public static String validate(String identifier, Object... additionalInformation) { if (VALID_JAVA_IDENTIFIER.test(identifier)) { return identifier; } throw new InvalidJavaIdentifier( String.format( "%s is an invalid java identifier %s.", identifier, Stream.of(additionalInformation).map(Object::toString).collect(joining(" ")))); } private static final ImmutableSet JAVA_RESERVED = ImmutableSet.of( "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "double", "do", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while"); private static final Predicate VALID_JAVA_IDENTIFIER = ((Predicate) JAVA_RESERVED::contains) .negate() .and(Pattern.compile("^([a-zA-Z_$][a-zA-Z\\d_$]*)$").asPredicate()); }