package com.perforce.polarion.element.cron; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import com.perforce.p4java.core.IJob; import com.perforce.p4java.exception.P4JavaException; import com.perforce.p4java.option.server.CounterOptions; import com.perforce.p4java.option.server.GetJobsOptions; import com.perforce.p4java.server.IOptionsServer; import com.perforce.p4java.server.IServerInfo; import com.perforce.polarion.element.event.WorkItemEvent; import com.perforce.polarion.repository.provider.ConnectionFactory; import com.perforce.polarion.repository.provider.P4RepositoryConfiguration; import com.polarion.alm.projects.IProjectService; import com.polarion.alm.projects.model.IProject; import com.polarion.platform.context.IContext; import com.polarion.platform.core.IPlatform; import com.polarion.platform.core.PlatformContext; import com.polarion.platform.jobs.GenericJobException; import com.polarion.platform.jobs.IJobDescriptor; import com.polarion.platform.jobs.IJobStatus; import com.polarion.platform.jobs.IJobUnit; import com.polarion.platform.jobs.IJobUnitFactory; import com.polarion.platform.jobs.IProgressMonitor; import com.polarion.platform.jobs.spi.AbstractJobUnit; import com.polarion.platform.jobs.spi.BasicJobDescriptor; import com.polarion.platform.jobs.spi.JobParameterPrimitiveType; import com.polarion.platform.jobs.spi.SimpleJobParameter; public class JobScannerFactory implements IJobUnitFactory { /** * <job name="Perforce Job Scanner" id="jobscanner.job" * cronExpression="0 0 1 ? * *" scope="project:paul"> <path></path> * <window>500</window> <create>false</create> </job> */ @Override public IJobUnit createJobUnit(String name) throws GenericJobException { return new JobScanner(name, this); } @Override public IJobDescriptor getJobDescriptor(IJobUnit jobUnit) { BasicJobDescriptor desc = new BasicJobDescriptor("P4Job Scanner", jobUnit); JobParameterPrimitiveType stringType = new JobParameterPrimitiveType("String", String.class); JobParameterPrimitiveType integerType = new JobParameterPrimitiveType("Integer", Integer.class); JobParameterPrimitiveType boolType = new JobParameterPrimitiveType("Boolean", Boolean.class); desc.addParameter(new SimpleJobParameter(desc.getRootParameterGroup(), "path", "Perforce depot path to filter jobs.", stringType)); desc.addParameter(new SimpleJobParameter(desc.getRootParameterGroup(), "window", "Window size for recent change (seconds).", integerType)); desc.addParameter(new SimpleJobParameter(desc.getRootParameterGroup(), "create", "Enable Polarion to import new Perforce Jobs.", boolType)); return desc; } @Override public String getName() { return IJobScanner.JOB_NAME; } private final class JobScanner extends AbstractJobUnit implements IJobScanner { private final Logger log = Logger.getLogger(JobScanner.class); private static final String POLARION_COUNTER = "Polarion.Job.Time"; private String path; private int window; private boolean create; public JobScanner(String name, IJobUnitFactory creator) { super(name, creator); } public void setPath(String path) { this.path = path; } public void setWindow(int window) { this.window = window; } public void setCreate(boolean create) { this.create = create; } /** * The main job method * * @param progress */ @Override protected IJobStatus runInternal(IProgressMonitor progress) { IPlatform platform = PlatformContext.getPlatform(); IProjectService projectService = (IProjectService) platform.lookupService(IProjectService.class); IContext scope = getScope(); progress.beginTask(getName(), 0); WorkItemEvent event = new WorkItemEvent(); try { IProject project = projectService.getProjectForContextId(scope.getId()); if (project == null) { return getStatusFailed("Scope '" + scope.getId() + "' is not project.", null); } // Given the context find all the Perforce connections List<P4RepositoryConfiguration> configs = ConnectionFactory.getConnections(scope.getId()); for (P4RepositoryConfiguration config : configs) { List<IJob> jobs = queryJobs(config); for (IJob job : jobs) { log.info("CRON: found: " + job.getId()); event.update(job); } } return getStatusOK(null); } finally { progress.done(); } } private List<IJob> queryJobs(P4RepositoryConfiguration config) { log.info("CRON: Scanning " + config.getP4Port()); IOptionsServer p4 = ConnectionFactory.getConnection(config); try { long scan = getLastScan(p4); long serverTime = getServerTime(p4); // Get jobs modified since last scan and not by Polarion String user = config.getP4User(); String jobView = " " + "ModifiedDate>" + scan + " ^ModifiedBy=" + user; GetJobsOptions opts = new GetJobsOptions(); opts.setJobView(jobView); List<IJob> jobs = p4.getJobs(null, opts); // Update the last scan time setLastScan(serverTime, p4); return jobs; } catch (P4JavaException e) { log.warn("Perforce Error.", e); } catch (ParseException e) { log.warn("Unable to parse date.", e); } finally { try { p4.disconnect(); } catch (P4JavaException e) { log.error("Unable to disconnect!", e); } } // return empty list return new ArrayList<>(); } private long getServerTime(IOptionsServer p4) throws P4JavaException, ParseException { IServerInfo info = p4.getServerInfo(); String dateStr = info.getServerDate(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z"); Date date = formatter.parse(dateStr); long time = date.getTime() / 1000; log.info("CRON: Server time: " + time); return time; } private void setLastScan(long scan, IOptionsServer p4) throws P4JavaException { CounterOptions opts = new CounterOptions(); p4.setCounter(POLARION_COUNTER, String.valueOf(scan), opts); } private long getLastScan(IOptionsServer p4) throws P4JavaException { String value = p4.getCounter(POLARION_COUNTER); long scan = 0; try { scan = Long.parseLong(value); } catch (NumberFormatException e) { log.warn("Unable to read counter " + POLARION_COUNTER + ": " + value); } log.debug("CRON: Last scan: " + scan); return scan; } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 17342 | Paul Allen | Delete old Perforce job after Import and Status lookup in Jobspec (or use 'unknown'). | ||
#4 | 17341 | Paul Allen |
Job Import - Import new Jobs to Polarion. Cron definition specifies Polarion WorkItem type for all jobs and a JobView to filter. Perforce counter 'Polarion.Import.Time' used to store last Import and looks at ReportedDate. |
||
#3 | 17338 | Paul Allen | Job scanner - looks for changes to Perforce Jobs and updates the linked WorkItems. | ||
#2 | 16861 | Paul Allen |
Added job query code for scanner. Use Perforce counter to track last scan. JobSpec MUST include fields 'ModifiedBy' and 'ModifiedDate'. - updated p4java 15.2 |
||
#1 | 16847 | Paul Allen |
Added framework for a Perforce Job scanner, using the Polarion cron system. Implemented last scan tracking using the Perforce server time. |