/*******************************************************************************
* 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.wink.common.internal.application;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;
import org.apache.wink.common.DynamicResource;
import org.apache.wink.common.internal.i18n.Messages;
import org.apache.wink.common.internal.registry.metadata.ProviderMetadataCollector;
import org.apache.wink.common.internal.registry.metadata.ResourceMetadataCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Used to validate classes and objects returned by the Application.
*/
public class ApplicationValidator {
/**
* This maps should keep all classes that were already added to any of
* registries.
*/
private final Set<Class<?>> singletonClasses = new LinkedHashSet<Class<?>>();
private static final Logger logger =
LoggerFactory
.getLogger(ApplicationValidator.class);
/**
* Returns true if the resource is valid resource and false otherwise.
* Notice that a class with Path annotation can be validated only once,
* since it must be unique. Therefore, calling this method for the same
* class can return true only for the first time.
*
* @param cls
* @return true if the resource is valid resource and false otherwise.
*/
public boolean isValidResource(Class<?> cls) {
return isValidClass(cls) && ((ResourceMetadataCollector.isStaticResource(cls) && classUnique(cls)) || ResourceMetadataCollector
.isDynamicResource(cls));
}
/**
* Returns true if the resource is valid provider and false otherwise.
* Notice that a class with Provider annotation can be validated only once,
* since it must be unique. Therefore, calling this method for the same
* class can return true only for the first time.
*
* @param cls
* @return true if the resource is valid provider and false otherwise.
*/
public boolean isValidProvider(Class<?> cls) {
return isValidClass(cls) && ProviderMetadataCollector.isProvider(cls) && classUnique(cls);
}
/**
* returns true if called first time for the given class. The second call
* with the same class to this method will return false.
*/
private boolean classUnique(Class<? extends Object> cls) {
if (!singletonClasses.add(cls)) {
// the singleton of this class already exists
if (logger.isWarnEnabled()) {
logger.warn(Messages.getMessage("classAlreadyAdded", cls.getName())); //$NON-NLS-1$
}
return false;
}
return true;
}
/**
* Validates that class has only one of the following: Path, Provider,
* DynamicResource
*
* @param cls
* @return
*/
private static boolean isValidClass(Class<?> cls) {
int counter = 0;
if (ResourceMetadataCollector.isStaticResource(cls)) {
++counter;
}
if (ProviderMetadataCollector.isProvider(cls)) {
++counter;
}
if (ResourceMetadataCollector.isDynamicResource(cls)) {
++counter;
}
boolean valid = counter <= 1;
if (!valid) {
if (logger.isWarnEnabled()) {
logger.warn(Messages.getMessage("classNotValid", //$NON-NLS-1$
cls.getName(),
Path.class.getName(),
DynamicResource.class.getName(),
Provider.class.getName()));
}
}
return valid;
}
}