/*******************************************************************************
 * Copyright (c) 2015 IBH SYSTEMS GmbH.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBH SYSTEMS GmbH - initial API and implementation
 *******************************************************************************/
package org.eclipse.packagedrone.job.web.internal;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.packagedrone.job.JobFactoryDescriptor;
import org.eclipse.packagedrone.job.JobHandle;
import org.eclipse.packagedrone.job.JobManager;
import org.eclipse.packagedrone.sec.web.controller.HttpContraintControllerInterceptor;
import org.eclipse.packagedrone.sec.web.controller.Secured;
import org.eclipse.packagedrone.sec.web.controller.SecuredControllerInterceptor;
import org.eclipse.packagedrone.web.Controller;
import org.eclipse.packagedrone.web.LinkTarget;
import org.eclipse.packagedrone.web.ModelAndView;
import org.eclipse.packagedrone.web.RequestMapping;
import org.eclipse.packagedrone.web.RequestMethod;
import org.eclipse.packagedrone.web.ViewResolver;
import org.eclipse.packagedrone.web.controller.ControllerInterceptor;
import org.eclipse.packagedrone.web.controller.binding.PathVariable;
import org.eclipse.packagedrone.web.controller.binding.RequestParameter;
import org.eclipse.packagedrone.web.util.Requests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Controller
@ViewResolver ( "/WEB-INF/views/%s.jsp" )
@Secured
@RequestMapping ( "/job" )
@ControllerInterceptor ( SecuredControllerInterceptor.class )
@HttpConstraint ( rolesAllowed = "MANAGER" )
@ControllerInterceptor ( HttpContraintControllerInterceptor.class )
public class JobController
{
    private final static Logger logger = LoggerFactory.getLogger ( JobController.class );

    private JobManager manager;

    public void setManager ( final JobManager manager )
    {
        this.manager = manager;
    }

    @RequestMapping ( value = "/{factoryId}/create", method = RequestMethod.POST )
    @HttpConstraint ( rolesAllowed = { "MANAGER", "ADMIN" } )
    public ModelAndView create ( @PathVariable ( "factoryId" ) final String factoryId, @RequestParameter (
            required = false, value = "data" ) final String data)
    {
        final JobHandle job = this.manager.startJob ( factoryId, data );

        // forward to get loose of the POST request, so that we can reload the status page
        return new ModelAndView ( String.format ( "redirect:/job/%s/view", job.getId () ) );
    }

    @RequestMapping ( "/{id}/view" )
    public ModelAndView view ( @PathVariable ( "id" ) final String id)
    {
        final JobHandle job = this.manager.getJob ( id );

        final Map<String, Object> model = new HashMap<> ( 1 );
        model.put ( "job", job );
        return new ModelAndView ( "view", model );
    }

    /**
     * Monitor the job, only produces an HTML fragment of the current job state
     *
     * @param id
     *            the job id
     * @return the view
     */
    @RequestMapping ( "/{id}/monitor" )
    public ModelAndView monitor ( @PathVariable ( "id" ) final String id)
    {
        final JobHandle job = this.manager.getJob ( id );

        if ( job != null )
        {
            logger.debug ( "Job: {} - {}", job.getId (), job.getState () );
        }
        else
        {
            logger.debug ( "No job: {}", id );
        }

        final Map<String, Object> model = new HashMap<> ( 1 );
        model.put ( "job", job );
        return new ModelAndView ( "monitor", model );
    }

    @RequestMapping ( "/{id}/result" )
    public ModelAndView result ( @PathVariable ( "id" ) final String id, final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
    {
        final JobHandle job = this.manager.getJob ( id );

        if ( job != null && job.isComplete () && job.getError () != null )
        {
            // show default error page
            return defaultResult ( job );
        }

        final String factoryId = job.getRequest ().getFactoryId ();
        final JobFactoryDescriptor desc = this.manager.getFactory ( factoryId );

        if ( desc == null )
        {
            return defaultResult ( job );
        }

        final LinkTarget target = desc.getResultTarget ();
        if ( target == null )
        {
            return defaultResult ( job );
        }

        final LinkTarget url = target.expand ( Collections.singletonMap ( "id", id ) );

        logger.debug ( "Forwarding to job result view: {}", url );

        if ( url.getUrl ().equals ( Requests.getOriginalPath ( request ) ) )
        {
            throw new IllegalStateException ( String.format ( "Illegal redirect to same URL: %s", url.getUrl () ) );
        }

        final RequestDispatcher rd = request.getRequestDispatcher ( url.getUrl () );
        rd.forward ( request, response );

        return null;
    }

    protected ModelAndView defaultResult ( final JobHandle job )
    {
        final Map<String, Object> model = new HashMap<> ( 1 );
        model.put ( "job", job );
        return new ModelAndView ( "defaultResult", model );
    }
}

@@ -1575,24 +1575,85 @@
 ewResolver;%0A
+import org.eclipse.packagedrone.web.common.CommonController;%0A
 import org.e
@@ -4387,32 +4387,146 @@
 getJob ( id );%0A%0A
+        if ( job == null )%0A        %7B%0A            return CommonController.createNotFound ( %22job%22, id );%0A        %7D%0A%0A
         if ( job

fix a possible NPE