/*******************************************************************************
* 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.repo.importer.aether.web;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.eclipse.packagedrone.job.JobHandle;
import org.eclipse.packagedrone.job.JobManager;
import org.eclipse.packagedrone.job.JobRequest;
import org.eclipse.packagedrone.repo.importer.aether.AetherImporter;
import org.eclipse.packagedrone.repo.importer.aether.ImportConfiguration;
import org.eclipse.packagedrone.repo.importer.aether.MavenCoordinates;
import org.eclipse.packagedrone.repo.importer.aether.SimpleArtifactConfiguration;
import org.eclipse.packagedrone.repo.importer.web.ImportDescriptor;
import org.eclipse.packagedrone.repo.importer.web.ImportRequest;
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.utils.xml.XmlToolsFactory;
import org.eclipse.packagedrone.web.Controller;
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.BindingResult;
import org.eclipse.packagedrone.web.controller.binding.PathVariable;
import org.eclipse.packagedrone.web.controller.binding.RequestParameter;
import org.eclipse.packagedrone.web.controller.form.FormData;
import org.eclipse.packagedrone.web.controller.validator.ControllerValidator;
import org.eclipse.packagedrone.web.controller.validator.ValidationContext;
import org.eclipse.packagedrone.web.util.ParameterOverridingRequestWrapper;
import com.google.gson.GsonBuilder;
@Secured
@Controller
@ViewResolver ( "/WEB-INF/views/%s.jsp" )
@ControllerInterceptor ( SecuredControllerInterceptor.class )
@HttpConstraint ( rolesAllowed = "MANAGER" )
@ControllerInterceptor ( HttpContraintControllerInterceptor.class )
public class ConfigurationController
{
private final GsonBuilder gson = new GsonBuilder ();
private JobManager jobManager;
private XmlToolsFactory xmlToolsFactory;
public void setJobManager ( final JobManager jobManager )
{
this.jobManager = jobManager;
}
public void setXmlToolsFactory ( final XmlToolsFactory xmlToolsFactory )
{
this.xmlToolsFactory = xmlToolsFactory;
}
@RequestMapping ( value = "/import/{token}/aether/start", method = RequestMethod.GET )
public ModelAndView configure ( @RequestParameter ( value = "configuration",
required = false ) final SimpleArtifactConfiguration cfg)
{
final Map<String, Object> model = new HashMap<> ();
if ( cfg != null )
{
model.put ( "command", cfg );
}
else
{
model.put ( "command", new SimpleArtifactConfiguration () );
}
return new ModelAndView ( "configure", model );
}
@RequestMapping ( value = "/import/{token}/aether/edit", method = RequestMethod.POST )
public ModelAndView configurePost ( @RequestParameter ( "configuration" ) final SimpleArtifactConfiguration cfg)
{
final Map<String, Object> model = new HashMap<> ();
model.put ( "command", cfg );
return new ModelAndView ( "configure", model );
}
@RequestMapping ( value = "/import/{token}/aether/start", method = RequestMethod.POST )
public ModelAndView configurePost ( @Valid @FormData ( "command" ) final SimpleArtifactConfiguration data, final BindingResult result)
{
final Map<String, Object> model = new HashMap<> ();
model.put ( "ok", !result.hasErrors () );
return new ModelAndView ( "configure", model );
}
@RequestMapping ( value = "/import/{token}/aether/test", method = RequestMethod.POST )
public ModelAndView testImport ( @Valid @FormData ( "command" ) final SimpleArtifactConfiguration data, @PathVariable ( "token" ) final String token, final BindingResult result, final HttpServletRequest request)
{
if ( result.hasErrors () )
{
return configurePost ( data, result );
}
final Map<String, Object> model = new HashMap<> ();
model.put ( "command", data );
final ImportConfiguration imp = new ImportConfiguration ();
imp.setRepositoryUrl ( data.getUrl () );
imp.setIncludeSources ( data.isIncludeSources () );
imp.setIncludePoms ( data.isIncludePoms () );
imp.setIncludeJavadoc ( data.isIncludeJavadoc () );
imp.setAllOptional ( data.isAllOptional () );
final ImportDescriptor desc = ImportDescriptor.fromBase64 ( token );
if ( desc != null && desc.getChannelId () != null && !desc.getChannelId ().isEmpty () )
{
// set the ID for validating against existing maven artifacts
imp.setValidationChannelId ( desc.getChannelId () );
}
final Map<String, String> properties = new HashMap<> ( 1 );
imp.getCoordinates ().addAll ( Helper.parse ( data.getDependencies (), this.xmlToolsFactory ) );
properties.put ( "simpleConfig", this.gson.create ().toJson ( data ) );
final JobRequest jr = new JobRequest ( data.isResolveDependencies () ? AetherResolver.ID : AetherTester.ID, this.gson.create ().toJson ( imp ), properties );
final JobHandle job = this.jobManager.startJob ( jr );
model.put ( "job", job );
return new ModelAndView ( "test", model );
}
@RequestMapping ( value = "/import/{token}/aether/testComplete", method = RequestMethod.POST )
public ModelAndView completeTest ( @RequestParameter ( "jobId" ) final String jobId, @PathVariable ( "token" ) final String token)
{
final Map<String, Object> model = new HashMap<> ();
final JobHandle job = this.jobManager.getJob ( jobId );
model.put ( "job", job );
final String data = job.getRequest ().getData ();
final ImportConfiguration cfg = this.gson.create ().fromJson ( data, ImportConfiguration.class );
model.put ( "configuration", cfg );
model.put ( "cfgJson", job.getProperties ().get ( "simpleConfig" ) ); // the original config for editing
if ( job != null && job.isFailed () )
{
model.put ( "error", job.getError () );
return new ModelAndView ( "testFailed", model );
}
else
{
final AetherResult result = AetherResult.fromJson ( job.getResult () );
final ImportConfiguration actualCfg = new ImportConfiguration ();
actualCfg.setRepositoryUrl ( cfg.getRepositoryUrl () );
actualCfg.setIncludeSources ( cfg.isIncludeSources () );
for ( final AetherResult.Entry entry : result.getArtifacts () )
{
if ( entry.isResolved () )
{
actualCfg.getCoordinates ().add ( entry.getCoordinates () );
}
}
model.put ( "importConfig", this.gson.create ().toJson ( actualCfg ) );
model.put ( "result", result );
return new ModelAndView ( "testResult", model );
}
}
@RequestMapping ( value = "/import/{token}/aether/perform", method = RequestMethod.POST )
public void performImport ( @PathVariable ( "token" ) final String token, final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
{
final Map<String, String[]> params = new HashMap<> ( request.getParameterMap () );
final ImportConfiguration cfg = this.gson.create ().fromJson ( request.getParameter ( "importConfig" ), ImportConfiguration.class );
final Iterator<MavenCoordinates> i = cfg.getCoordinates ().iterator ();
while ( i.hasNext () )
{
final MavenCoordinates coord = i.next ();
final String checkValue = request.getParameter ( coord.toString () );
if ( checkValue == null )
{
i.remove ();
}
}
params.put ( "request", new String[] { ImportRequest.toJson ( AetherImporter.ID, this.gson.create ().toJson ( cfg ) ) } );
params.put ( "token", new String[] { token } );
request.getRequestDispatcher ( "/import/perform" ).forward ( new ParameterOverridingRequestWrapper ( request, params ), response );
}
@ControllerValidator ( formDataClass = SimpleArtifactConfiguration.class )
public void validateImportConfiguration ( final SimpleArtifactConfiguration cfg, final ValidationContext ctx )
{
final String deps = cfg.getDependencies ();
if ( deps != null && !deps.isEmpty () )
{
final Collection<MavenCoordinates> result = Helper.parse ( deps, this.xmlToolsFactory );
if ( result == null )
{
ctx.error ( "dependencies", "Invalid dependency format" );
}
}
}
}