/*******************************************************************************
* 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.server.internal.application;
import java.lang.reflect.Modifier;
import java.util.Set;
import javax.ws.rs.core.Application;
import org.apache.wink.common.WinkApplication;
import org.apache.wink.common.internal.i18n.Messages;
import org.apache.wink.common.internal.registry.ProvidersRegistry;
import org.apache.wink.common.internal.registry.metadata.ProviderMetadataCollector;
import org.apache.wink.common.internal.registry.metadata.ResourceMetadataCollector;
import org.apache.wink.server.internal.registry.ResourceRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Processes the Application object. First singletons are processed and later
* classes. If the provided Application extends WinkApplication, instances are
* also processed AFTER the singletons and the classes.
* <p>
* Pay Attention that classes returned by getSingletons are ignored by both
* getClasses and getInstances. And classes returned by getClasses are ignored
* by getInstances.
*
* @see Application
* @see WinkApplication
*/
public class ApplicationProcessor {
private static final Logger logger = LoggerFactory.getLogger(ApplicationProcessor.class);
private final Application application;
private final ResourceRegistry resourceRegistry;
private final ProvidersRegistry providersRegistry;
private final boolean isSystemApplication;
public ApplicationProcessor(Application application,
ResourceRegistry resourceRegistry,
ProvidersRegistry providersRegistry,
boolean isSystemApplication) {
super();
this.application = application;
this.resourceRegistry = resourceRegistry;
this.providersRegistry = providersRegistry;
this.isSystemApplication = isSystemApplication;
}
public void process() {
logger.trace("Processing Application: {}", application); //$NON-NLS-1$
double priority = WinkApplication.DEFAULT_PRIORITY;
if (application instanceof WinkApplication) {
priority = ((WinkApplication)application).getPriority();
logger.trace("WinkApplication priority is set to: {}", priority); //$NON-NLS-1$
}
// process singletons
Set<Object> singletons = application.getSingletons();
if (singletons != null && singletons.size() > 0) {
processSingletons(singletons, priority);
}
// process classes
Set<Class<?>> classes = application.getClasses();
if (classes != null && classes.size() > 0) {
processClasses(classes, priority);
}
if (application instanceof WinkApplication) {
processWinkApplication((WinkApplication)application);
}
// always produce INFO output after completing application processing:
if (!isSystemApplication && logger.isInfoEnabled()) {
logger.info(Messages
.getMessage("applicationProcessed", application.getClass().getName())); //$NON-NLS-1$
}
logger.trace("Processing of Application completed."); //$NON-NLS-1$
}
private void processWinkApplication(WinkApplication sApplication) {
Set<Object> instances = sApplication.getInstances();
double priority = sApplication.getPriority();
if (instances == null) {
logger.trace("WinkApplication.getInstances() returned null"); //$NON-NLS-1$
return;
}
for (Object obj : instances) {
try {
logger.trace("Processing instance: {}", obj); //$NON-NLS-1$
Class<?> cls = obj.getClass();
// the validations were moved to registry
if (ResourceMetadataCollector.isDynamicResource(cls)) {
resourceRegistry.addResource(obj, priority);
} else if (ResourceMetadataCollector.isStaticResource(cls)) {
resourceRegistry.addResource(obj, priority);
} else if (ProviderMetadataCollector.isProvider(cls)) {
providersRegistry.addProvider(obj, priority, isSystemApplication);
} else {
if (logger.isWarnEnabled()) {
logger.warn(Messages
.getMessage("classNotADynamicResourceNorResourceNorProvider", obj //$NON-NLS-1$
.getClass().getName()));
}
}
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error(Messages
.getMessage("exceptionOccurredDuringInstanceProcessing", obj //$NON-NLS-1$
.getClass().getCanonicalName()), e);
}
if (logger.isDebugEnabled()) {
logger.debug(Messages
.getMessage("exceptionOccurredDuringInstanceProcessing", obj //$NON-NLS-1$
.getClass().getCanonicalName()), e);
}
} catch (NoClassDefFoundError e) {
if (logger.isErrorEnabled()) {
logger.error(Messages.getMessage("exceptionOccurredDuringInstanceProcessing", //$NON-NLS-1$
obj.getClass().getCanonicalName()), e);
}
if (logger.isDebugEnabled()) {
logger.debug(Messages
.getMessage("exceptionOccurredDuringInstanceProcessing", obj //$NON-NLS-1$
.getClass().getCanonicalName()), e);
}
}
}
}
private void processClasses(Set<Class<?>> classes, double priority) {
for (Class<?> cls : classes) {
try {
logger.trace("Processing class: {}", cls); //$NON-NLS-1$
int modifiers = cls.getModifiers();
if (Modifier.isInterface(modifiers) || Modifier.isAbstract(modifiers)) {
logger
.trace("Class {} is an interface or abstract class and will not be added as a resource or provider.", //$NON-NLS-1$
cls);
continue;
}
// the validations were moved to registry
if (ResourceMetadataCollector.isStaticResource(cls)) {
resourceRegistry.addResource(cls, priority);
} else if (ProviderMetadataCollector.isProvider(cls)) {
providersRegistry.addProvider(cls, priority, isSystemApplication);
} else {
if (logger.isWarnEnabled()) {
logger.warn(Messages.getMessage("classNotAResourceNorProvider", cls //$NON-NLS-1$
.getName()));
}
}
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error(Messages.getMessage("exceptionOccurredDuringClassProcessing", cls //$NON-NLS-1$
.getName()), e);
}
if (logger.isDebugEnabled()) {
logger.debug(Messages.getMessage("exceptionOccurredDuringClassProcessing", cls //$NON-NLS-1$
.getCanonicalName()), e);
}
} catch (NoClassDefFoundError e) {
if (logger.isErrorEnabled()) {
logger.error(Messages.getMessage("exceptionOccurredDuringClassProcessing", cls //$NON-NLS-1$
.getCanonicalName()), e);
}
if (logger.isDebugEnabled()) {
logger.debug(Messages.getMessage("exceptionOccurredDuringClassProcessing", cls //$NON-NLS-1$
.getCanonicalName()), e);
}
}
}
}
private void processSingletons(Set<Object> singletons, double priority) {
// add singletons
for (Object obj : singletons) {
try {
logger.trace("Processing singleton: {}", obj); //$NON-NLS-1$
Class<?> cls = obj.getClass();
if (ResourceMetadataCollector.isStaticResource(cls)) {
resourceRegistry.addResource(obj, priority);
} else if (ProviderMetadataCollector.isProvider(cls)) {
providersRegistry.addProvider(obj, priority, isSystemApplication);
} else {
if (logger.isWarnEnabled()) {
logger.warn(Messages
.getMessage("classNotAResourceNorProvider", obj.getClass())); //$NON-NLS-1$
}
}
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.warn(Messages
.getMessage("exceptionOccurredDuringSingletonProcessing", obj //$NON-NLS-1$
.getClass().getCanonicalName()), e);
}
if (logger.isDebugEnabled()) {
logger.debug(Messages
.getMessage("exceptionOccurredDuringSingletonProcessing", obj //$NON-NLS-1$
.getClass().getCanonicalName()), e);
}
} catch (NoClassDefFoundError e) {
if (logger.isErrorEnabled()) {
logger.error(Messages.getMessage("exceptionOccurredDuringSingletonProcessing", //$NON-NLS-1$
obj.getClass().getCanonicalName()), e);
}
if (logger.isDebugEnabled()) {
logger.debug(Messages
.getMessage("exceptionOccurredDuringSingletonProcessing", obj //$NON-NLS-1$
.getClass().getCanonicalName()), e);
}
}
}
}
}