Skip to content
Permalink
Browse files
BATCHEE-107 improve getJobNames handling
  • Loading branch information
struberg committed Aug 17, 2016
1 parent a40e368 commit 8f61b727030a85e069bbb5082ab3c2346b2db12f
Showing 11 changed files with 97 additions and 10 deletions.
@@ -25,6 +25,7 @@
public class ShiroSecurityService extends DefaultSecurityService {
private String instancePrefix;
private String permissionPrefix;
private String jobNamePrefix;

private boolean isAuthenticatedAndAuthorized(final String permission) {
return getSubject().isAuthenticated() && getSubject().isPermitted(permission);
@@ -40,6 +41,11 @@ public boolean isAuthorized(final String perm) {
return isAuthenticatedAndAuthorized(permissionPrefix + perm);
}

@Override
public boolean isAuthorizedJobName(String jobName) {
return isAuthenticatedAndAuthorized(jobNamePrefix + jobName);
}

@Override
public String getLoggedUser() {
if (getSubject().isAuthenticated()) {
@@ -53,5 +59,6 @@ public void init(final Properties batchConfig) {
super.init(batchConfig);
permissionPrefix = batchConfig.getProperty("security.job.permission-prefix", "jbatch:");
instancePrefix = permissionPrefix + batchConfig.getProperty("security.job.permission-prefix", "instance:");
jobNamePrefix = permissionPrefix + batchConfig.getProperty("security.job.permission-prefix", "jobName:");
}
}
@@ -54,7 +54,6 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
@@ -173,8 +172,8 @@ public void abandon(final long executionId) throws NoSuchJobExecutionException,
final InternalJobExecution jobEx = persistenceManagerService.jobOperatorGetJobExecution(executionId);

// if it is not in STARTED or STARTING state, mark it as ABANDONED
BatchStatus status = jobEx.getBatchStatus();
if (status == BatchStatus.STARTING || status == BatchStatus.STARTED) {
BatchStatus status = jobEx.getBatchStatus();
if (status == BatchStatus.STARTING || status == BatchStatus.STARTED) {
throw new JobExecutionIsRunningException("Job Execution: " + executionId + " is still running");
}

@@ -284,11 +283,10 @@ public List<JobInstance> getJobInstances(String jobName, int start,
@Override
public Set<String> getJobNames() throws JobSecurityException {
final Set<String> jobNames = new HashSet<String>();
final Map<Long, String> data = persistenceManagerService.jobOperatorGetExternalJobInstanceData();
for (final Map.Entry<Long, String> entry : data.entrySet()) {
long instanceId = entry.getKey();
if (securityService.isAuthorized(instanceId)) {
jobNames.add(entry.getValue());
final Set<String> jobNamesFromDb = persistenceManagerService.getJobNames();
for (String jobName : jobNamesFromDb) {
if (securityService.isAuthorizedJobName(jobName)) {
jobNames.add(jobName);
}
}
return jobNames;
@@ -570,6 +570,30 @@ public Map<Long, String> jobOperatorGetExternalJobInstanceData() {
return data;
}

@Override
public Set<String> getJobNames() {
Connection conn = null;
PreparedStatement statement = null;
ResultSet rs = null;

Set<String> jobNames = new HashSet<String>();
try {
conn = getConnection();

statement = conn.prepareStatement(dictionary.getFindJobNames());
rs = statement.executeQuery();
while (rs.next()) {
jobNames.add(rs.getString(1));
}

} catch (final SQLException e) {
throw new PersistenceException(e);
} finally {
cleanupConnection(conn, rs, statement);
}
return jobNames;
}

@Override
public Timestamp jobOperatorQueryJobExecutionTimestamp(final long key, final TimestampType timestampType) {
Connection conn = null;
@@ -63,6 +63,7 @@
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

@@ -165,6 +166,22 @@ public Map<Long, String> jobOperatorGetExternalJobInstanceData() {
return data;
}

@Override
public Set<String> getJobNames() {
Set<String> jobNames = new TreeSet<String>();
final EntityManager em = emProvider.newEntityManager();

try {
final List<String> list = em.createNamedQuery(JobInstanceEntity.Queries.FIND_JOBNAMES, String.class)
.setParameter("pattern", PartitionedStepBuilder.JOB_ID_SEPARATOR + "%")
.getResultList();
jobNames.addAll(list);
} finally {
emProvider.release(em);
}
return jobNames;
}

@Override
public JobStatus getJobStatusFromExecution(final long executionId) {
final EntityManager em = emProvider.newEntityManager();
@@ -143,6 +143,17 @@ public Map<Long, String> jobOperatorGetExternalJobInstanceData() {
return out;
}

@Override
public Set<String> getJobNames() {
Set<String> jobNames = new HashSet<String>();
for (final Structures.JobInstanceData jobInstanceData : data.jobInstanceData.values()) {
if (jobInstanceData.instance.getJobName() != null && !jobInstanceData.instance.getJobName().startsWith(PartitionedStepBuilder.JOB_ID_SEPARATOR)) {
jobNames.add(jobInstanceData.instance.getJobName());
}
}
return jobNames;
}

@Override
public List<Long> jobOperatorGetJobInstanceIds(final String jobName, final int start, final int count) {
return jobOperatorGetJobInstanceIds(jobName, null, start, count);
@@ -20,7 +20,7 @@
import org.apache.batchee.container.services.persistence.jdbc.database.Database;

public class Dictionary {
public static interface SQL { // needs to be kept aligned with JPA mapping, we can't use reflection to find fields since order can change between executions with java 7
public interface SQL { // needs to be kept aligned with JPA mapping, we can't use reflection to find fields since order can change between executions with java 7
String CREATE_TABLE = "create table ";
String INSERT_INTO = "insert into ";
String SELECT = "select ";
@@ -45,6 +45,7 @@ public static interface SQL { // needs to be kept aligned with JPA mapping, we c
String JOB_INSTANCE_COUNT = JOB_INSTANCE_COUNT_FROM_NAME + " and %s = ?";
String JOB_INSTANCE_IDS = SELECT + "%s" + FROM + "%s" + WHERE + "%s = ? and %s = ? order by %s desc";
String JOB_INSTANCE_IDS_FROM_NAME = SELECT + "%s" + FROM + "%s" + WHERE + " %s = ? order by %s desc";
String JOB_NAMES = SELECT + "distinct %s" + FROM + "%s" + WHERE + "%s not like '%s'";
String EXTERNAL_JOB_INSTANCE = SELECT + "distinct %s, %s" + FROM + "%s" + WHERE + "%s not like '%s'";
String JOB_INSTANCE_CREATE = INSERT_INTO + "%s" + "(%s, %s) VALUES(?, ?)";
String JOB_INSTANCE_CREATE_WITH_JOB_XML = INSERT_INTO + "%s" + "(%s, %s, %s) VALUES(?, ?, ?)";
@@ -112,6 +113,7 @@ public static interface SQL { // needs to be kept aligned with JPA mapping, we c
private final String countJobInstanceByNameAndTag;
private final String findJoBInstanceIds;
private final String findJobInstanceIdsByName;
private final String findJobNames;
private final String findExternalJobInstances;
private final String createJobInstance;
private final String createJobInstanceWithJobXml;
@@ -199,6 +201,7 @@ public Dictionary(final String checkpointTable, final String jobInstanceTable, f
this.findJoBInstanceIds = String.format(SQL.JOB_INSTANCE_IDS, jobInstanceColumns[0], jobInstanceTable, jobInstanceColumns[3],
jobInstanceColumns[8], jobInstanceColumns[0]);
this.findJobInstanceIdsByName = String.format(SQL.JOB_INSTANCE_IDS_FROM_NAME, jobInstanceColumns[0], jobInstanceTable, jobInstanceColumns[3], jobInstanceColumns[0]);
this.findJobNames = String.format(SQL.JOB_NAMES, jobInstanceColumns[3], jobInstanceTable, jobInstanceColumns[3], PartitionedStepBuilder.JOB_ID_SEPARATOR + "%");
this.findExternalJobInstances = String.format(SQL.EXTERNAL_JOB_INSTANCE, jobInstanceColumns[0], jobInstanceColumns[3], jobInstanceTable,
jobInstanceColumns[3], PartitionedStepBuilder.JOB_ID_SEPARATOR + "%");
this.createJobInstance = String.format(SQL.JOB_INSTANCE_CREATE, jobInstanceTable, jobInstanceColumns[3], jobInstanceColumns[8]);
@@ -365,6 +368,10 @@ public String getFindExternalJobInstances() {
return findExternalJobInstances;
}

public String getFindJobNames() {
return findJobNames;
}

public String getCreateJobInstance() {
return createJobInstance;
}
@@ -39,6 +39,7 @@
@NamedQuery(name = JobInstanceEntity.Queries.COUNT_BY_NAME, query = "select count(j) from JobInstanceEntity j where j.name = :name"),
@NamedQuery(name = JobInstanceEntity.Queries.FIND_FROM_EXECUTION, query = "select j from JobInstanceEntity j inner join j.executions e where e.executionId = :executionId"),
@NamedQuery(name = JobInstanceEntity.Queries.FIND_EXTERNALS, query = "select j from JobInstanceEntity j where j.name not like :pattern"),
@NamedQuery(name = JobInstanceEntity.Queries.FIND_JOBNAMES, query = "select distinct(j.name) from JobInstanceEntity j where j.name not like :pattern"),
@NamedQuery(name = JobInstanceEntity.Queries.FIND_BY_NAME_AND_TAG, query = "select j from JobInstanceEntity j where j.name = :name and j.tag = :tag"),
@NamedQuery(name = JobInstanceEntity.Queries.FIND_BY_NAME, query = "select j from JobInstanceEntity j where j.name = :name"),
@NamedQuery(name = JobInstanceEntity.Queries.DELETE_BY_INSTANCE_ID, query = "delete from JobInstanceEntity e where e.jobInstanceId = :instanceId"),
@@ -48,12 +49,13 @@
})
@Table(name=JobInstanceEntity.TABLE_NAME)
public class JobInstanceEntity {
public static interface Queries {
public interface Queries {
String COUNT_BY_NAME_AND_TAG = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.countByNameAndTag";
String COUNT_BY_NAME = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.countByName";
String FIND_BY_NAME = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.findByName";
String FIND_BY_NAME_AND_TAG = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.findByNameAndTag";
String FIND_EXTERNALS = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.findExternals";
String FIND_JOBNAMES = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.findJobNames";
String FIND_FROM_EXECUTION = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.findByExecution";
String DELETE_BY_INSTANCE_ID = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.deleteFromInstanceId";
String DELETE_BY_DATE = "org.apache.batchee.container.services.persistence.jpa.domain.JobInstanceEntity.deleteByDate";
@@ -34,6 +34,11 @@ public boolean isAuthorized(final String perm) {
return isDefaultUserAuthorized();
}

@Override
public boolean isAuthorizedJobName(String jobName) {
return isDefaultUserAuthorized();
}

@Override
public String getLoggedUser() {
return defaultUser;
@@ -50,6 +50,11 @@ public boolean isAuthorized(final String perm) {
return isAuthenticatedAndAuthorized(perm);
}

@Override
public boolean isAuthorizedJobName(String jobName) {
return isAuthenticatedAndAuthorized("read");
}

@Override
public String getLoggedUser() {
final Subject subject = getSubject();
@@ -49,6 +49,11 @@ public enum TimestampType { CREATE, END, LAST_UPDATED, STARTED }

int jobOperatorGetJobInstanceCount(String jobName, String appTag);

Set<String> getJobNames();

/**
* @deprecated replaced by {@link #getJobNames()}
*/
Map<Long, String> jobOperatorGetExternalJobInstanceData();

List<Long> jobOperatorGetJobInstanceIds(String jobName, int start, int count);
@@ -20,6 +20,12 @@ public interface SecurityService extends BatchService {
boolean isAuthorized(long instanceId);
boolean isAuthorized(String perm);

/**
* @return whether the current user is allowed to see the given jobName
* @see javax.batch.operations.JobOperator#getJobNames()
*/
boolean isAuthorizedJobName(String jobName);

/**
* @return logged user if exists or a default name for anonymous launches
*/

0 comments on commit 8f61b72

Please sign in to comment.