/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.pinsetter.tasks; import static org.quartz.JobBuilder.newJob; import org.candlepin.common.exceptions.BadRequestException; import org.candlepin.common.exceptions.IseException; import org.candlepin.common.exceptions.NotFoundException; import org.candlepin.common.filter.LoggingFilter; import org.candlepin.controller.ManifestManager; import org.candlepin.model.ImportRecord; import org.candlepin.model.Owner; import org.candlepin.model.OwnerCurator; import org.candlepin.pinsetter.core.model.JobStatus; import org.candlepin.sync.ConflictOverrides; import org.candlepin.sync.ImporterException; import org.candlepin.sync.SyncDataFormatException; import org.candlepin.util.Util; import org.apache.log4j.MDC; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; /** * Runs an asynchronous manifest import. This job expects that the manifest file * was already uploaded. */ public class ImportJob extends UniqueByEntityJob { protected static final String STORED_FILE_ID = "stored_manifest_file_id"; protected static final String CONFLICT_OVERRIDES = "conflict_overrides"; protected static final String UPLOADED_FILE_NAME = "uploaded_file_name"; private static Logger log = LoggerFactory.getLogger(ImportJob.class); private OwnerCurator ownerCurator; private ManifestManager manifestManager; @Inject public ImportJob(OwnerCurator ownerCurator, ManifestManager manifestManager) { this.ownerCurator = ownerCurator; this.manifestManager = manifestManager; } @Override public void toExecute(JobExecutionContext context) throws JobExecutionException { JobDataMap map = context.getMergedJobDataMap(); String ownerKey = (String) map.get(JobStatus.TARGET_ID); ConflictOverrides overrides = new ConflictOverrides((String[]) map.get(CONFLICT_OVERRIDES)); String storedFileId = (String) map.get(STORED_FILE_ID); String uploadedFileName = (String) map.get(UPLOADED_FILE_NAME); Throwable caught = null; Owner targetOwner = null; try { targetOwner = ownerCurator.lookupByKey(ownerKey); if (targetOwner == null) { throw new NotFoundException(String.format("Owner %s was not found.", ownerKey)); } ImportRecord importRecord = manifestManager.importStoredManifest(targetOwner, storedFileId, overrides, uploadedFileName); context.setResult(importRecord); } // Catch and handle SyncDataFormatException and ImporterExceptions // as the OwnerResource.importManifest does which will provide a little more // info about the exception that was thrown (CandlepinException). catch (SyncDataFormatException e) { caught = new BadRequestException(e.getMessage(), e); } catch (ImporterException e) { caught = new IseException(e.getMessage(), e); } catch (Exception e) { caught = e; } if (caught != null) { log.error("ImportJob encountered a problem.", caught); manifestManager.recordImportFailure(targetOwner, caught, uploadedFileName); context.setResult(caught.getMessage()); // If an exception was thrown, the importer's transaction was rolled // back. We want to make sure that the file gets deleted so that it // doesn't take up disk space. It may be possible that the file was // already deleted, but we attempt it anyway. manifestManager.deleteStoredManifest(storedFileId); throw new JobExecutionException(caught.getMessage(), caught, false); } } /** * Schedules the import of the specified stored manifest file targeting the specified {@link Owner}. * * @param owner the target owner. * @param storedFileId the ID of the manifest file to import. * @param uploadedFileName the original uploaded file name. * @param overrides the {@link ConflictOverrides} to apply when importing the manifest. * @return the details of the configured job. */ public static JobDetail scheduleImport(Owner owner, String storedFileId, String uploadedFileName, ConflictOverrides overrides) { JobDataMap map = new JobDataMap(); map.put(JobStatus.OWNER_ID, owner.getKey()); map.put(JobStatus.TARGET_TYPE, JobStatus.TargetType.OWNER); map.put(JobStatus.TARGET_ID, owner.getKey()); map.put(STORED_FILE_ID, storedFileId); map.put(UPLOADED_FILE_NAME, uploadedFileName); map.put(CONFLICT_OVERRIDES, overrides.asStringArray()); map.put(JobStatus.CORRELATION_ID, MDC.get(LoggingFilter.CSID)); JobDetail detail = newJob(ImportJob.class) .withIdentity("import_" + Util.generateUUID()) .usingJobData(map) .build(); return detail; } }