/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License).  You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the license at
* https://glassfish.dev.java.net/public/CDDLv1.0.html or
* glassfish/bootstrap/legal/CDDLv1.0.txt.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at glassfish/bootstrap/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* you own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Copyright (c) Ericsson AB, 2004-2007. All rights reserved.
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*/ 

package org.jvnet.glassfish.comms.deployment.annotations.handlers;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Map;
import java.util.logging.Level;

import javax.servlet.sip.annotation.SipServlet;

import com.ericsson.ssa.dd.ExistsOperand;
import com.ericsson.ssa.dd.Pattern;
import com.ericsson.ssa.dd.Servlet;
import com.ericsson.ssa.dd.ServletMapping;
import com.ericsson.ssa.dd.SipApplication;
import com.sun.enterprise.deployment.annotation.AnnotationInfo;
import com.sun.enterprise.deployment.annotation.AnnotationProcessorException;
import com.sun.enterprise.deployment.annotation.HandlerProcessingResult;
import com.sun.enterprise.deployment.annotation.context.ResourceContainerContext;

/**
 * 
 * @author lmcpepe a.k.a. PellePedro
 * @since 15-Nov-07
 *
 */
public class SipServletHandler extends AbstractSipAnnotationHandler 
{

	@Override
	protected HandlerProcessingResult processAnnotation(
			SipApplication sipApplication, 
			AnnotationInfo ainfo,
			ResourceContainerContext[] rcContexts)
			throws AnnotationProcessorException
	{
        AnnotatedElement annotatedElement = ainfo.getAnnotatedElement();
        
        Annotation [] annotation = annotatedElement.getAnnotations();
        for (int i = 0; i < annotation.length; i++) 
        {
        	Class annotationClass = annotation[i].annotationType();
        	if ( annotationClass == getAnnotationType() )
        	{
        		String servletClassName = ((Class)annotatedElement).getName();
        		String servletName = ((Class)annotatedElement).getSimpleName();


        		Servlet servlet = new Servlet();
        		servlet.setServletClass(servletClassName);
        		
        		// ---- Set load on startup ---
        		SipServlet sipServlet = (SipServlet) ainfo.getAnnotation();
        		
        		int loadOnStartUp = sipServlet.loadOnStartup();
        		servlet.setLoadOnStartup(loadOnStartUp);
        		
        		// --- Set Servlet Name ---
        		// if the annotated Servlet Name is omitted, the the Class Name of the
        		// SipServlet is used as Servlet Name.
        		String annotatedServletName = sipServlet.name();
        		if ( "".equals(annotatedServletName) )
        		{
        			// Servlet Name not annotated
        			annotatedServletName = servletName;
        		}
        		
        		servlet.setServletName(annotatedServletName);
        		
        		// --- Set Application Name ---
        		//TODO Not clear if we need this information
        		String annotatedAppliationName = sipServlet.applicationName();
        		
        		if (theirLog.isLoggable(Level.INFO)) {
        			theirLog.log(Level.INFO, LOGPREFIX + "SipServlet Annotation : Servlet Class[" + servletClassName +
        					 "] ServletName ["+ annotatedServletName +"]");
        		}
        		
        		
        		// Special Case

        		// An "Always True" mapping rule is created under this condition 
        		// 1. Main Servlet specified and we are the main servlet.
        		// 2. No main Servlet specified and we are the first annotated Servlet.
        		//    The "request.method" os true for all requests.

        		//    Otherwise a "Never True condition is created"
        		//    The pattern "NeverMatchMe" is never true for any requests
        		
        		ExistsOperand existsOperand = new ExistsOperand();
        		
        		String annotatedMainServlet = sipApplication.getMainservlet();
        		int processedServlets =  sipApplication.getAnnotatedServlets();
        		
        		if(  annotatedMainServlet != null && annotatedServletName.equals(annotatedMainServlet))
        		{
        			// This is the main Servlet according to SipApplication annotation
        			existsOperand.setVariable("request.method");
        		} else if ( annotatedMainServlet == null && processedServlets == 0 ) {
        			// This is the main Servlet according to : First Match
        			existsOperand.setVariable("request.method");        			
        		} else {
        			existsOperand.setVariable("NeverMatchMe");
        			if (theirLog.isLoggable(Level.INFO)) {
        				theirLog.log(Level.INFO, LOGPREFIX + "Servlet is not MainServlet nor first processed, therefore discarded. "+
        						                             "To enable the servlet, specify a servlet mapping rule in sip.xml");
        			}
        		}
        		
        		sipApplication.incrementAnnotatedServlets();
        		
        		Map<String, Servlet> servlets = sipApplication.getServlets();
        		Map<String, ServletMapping> servletMappings = sipApplication.getServletMappings();
        		
        		// Servlets defined in sip.xml overrides annotations
        		if (servlets.get(annotatedServletName) != null ) {
        			// Servlet specified in sip.xml
        			if (theirLog.isLoggable(Level.INFO)) {
        				theirLog.log(Level.INFO, LOGPREFIX + "SipServlet : Servlet found from sip.xml name = " +  annotatedServletName);
        			}
        			return getDefaultProcessedResult();
        		}

        		sipApplication.addServlet(servlet);	
        		
        		if ( servletMappings.get(annotatedServletName) == null) {

        			// Servlet Mapping is not overridden in sip.xml, so create one

        			Pattern pattern = new Pattern();
        			pattern.addCondition(existsOperand);

        			ServletMapping servletMapping = new ServletMapping();
        			servletMapping.setServletName(annotatedServletName);
        			servletMapping.setPattern(pattern);

        			sipApplication.addServletMapping(servletMapping);
        		} else {
        			if (theirLog.isLoggable(Level.INFO)) {
        				theirLog.log(Level.INFO, LOGPREFIX + "SipServlet : Servlet Mapping reused from sip.xml");
        			}
        		}
        	}
        }
        return getDefaultProcessedResult();
	}

	public Class<? extends Annotation> getAnnotationType() 
	{
		return javax.servlet.sip.annotation.SipServlet.class;
	}

}
