Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Davis2016-07-20 03:53:53 +0000
committerSam Davis2016-07-20 21:21:59 +0000
commitb7621a8cb6f0306a65499b3802640a23f01c9ac0 (patch)
tree6ee20d5b65e830ac19b7eb457ef75bbeddbb1b12 /connector-bugzilla-rest
parent7305015c049e295171c6ebb3930f001eea16c9e0 (diff)
downloadorg.eclipse.mylyn.tasks-b7621a8cb6f0306a65499b3802640a23f01c9ac0.tar.gz
org.eclipse.mylyn.tasks-b7621a8cb6f0306a65499b3802640a23f01c9ac0.tar.xz
org.eclipse.mylyn.tasks-b7621a8cb6f0306a65499b3802640a23f01c9ac0.zip
495085: Bugzilla REST connector should use proxy information from
TaskRepository Change-Id: I1b8734a3080c4c777e427017e6d53dca960fb043 Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=495085
Diffstat (limited to 'connector-bugzilla-rest')
-rw-r--r--connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestConnector.java943
1 files changed, 482 insertions, 461 deletions
diff --git a/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestConnector.java b/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestConnector.java
index bc6092738..4c1375b5e 100644
--- a/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestConnector.java
+++ b/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestConnector.java
@@ -1,461 +1,482 @@
-/*******************************************************************************
- * Copyright (c) 2013 Frank Becker and others.
- * 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:
- * Frank Becker - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.mylyn.internal.bugzilla.rest.core;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.mylyn.commons.core.StatusHandler;
-import org.eclipse.mylyn.commons.core.operations.IOperationMonitor;
-import org.eclipse.mylyn.commons.core.operations.OperationUtil;
-import org.eclipse.mylyn.commons.net.AuthenticationCredentials;
-import org.eclipse.mylyn.commons.net.Policy;
-import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation;
-import org.eclipse.mylyn.commons.repositories.core.auth.AuthenticationType;
-import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials;
-import org.eclipse.mylyn.internal.bugzilla.rest.core.response.data.Field;
-import org.eclipse.mylyn.internal.bugzilla.rest.core.response.data.FieldValues;
-import org.eclipse.mylyn.internal.commons.core.operations.NullOperationMonitor;
-import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants;
-import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
-import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
-import org.eclipse.mylyn.tasks.core.ITask;
-import org.eclipse.mylyn.tasks.core.RepositoryInfo;
-import org.eclipse.mylyn.tasks.core.RepositoryVersion;
-import org.eclipse.mylyn.tasks.core.TaskRepository;
-import org.eclipse.mylyn.tasks.core.data.AbstractTaskAttachmentHandler;
-import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
-import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
-import org.eclipse.mylyn.tasks.core.data.TaskData;
-import org.eclipse.mylyn.tasks.core.data.TaskDataCollector;
-import org.eclipse.mylyn.tasks.core.data.TaskMapper;
-import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;
-
-import com.google.common.base.Optional;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.UncheckedExecutionException;
-
-public class BugzillaRestConnector extends AbstractRepositoryConnector {
-
- public static final Duration CLIENT_CACHE_DURATION = new Duration(24, TimeUnit.HOURS);
-
- public static final Duration CONFIGURATION_CACHE_EXPIRE_DURATION = new Duration(7, TimeUnit.DAYS);
-
- public static final Duration CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION = new Duration(1, TimeUnit.DAYS);
-
- private static final ThreadLocal<IOperationMonitor> context = new ThreadLocal<IOperationMonitor>();
-
- private BugzillaRestTaskAttachmentHandler attachmentHandler;
-
- private boolean ignoredProperty(String propertyName) {
- if (propertyName.equals(RepositoryLocation.PROPERTY_LABEL) || propertyName.equals(TaskRepository.OFFLINE)
- || propertyName.equals(IRepositoryConstants.PROPERTY_ENCODING)
- || propertyName.equals(TaskRepository.PROXY_HOSTNAME) || propertyName.equals(TaskRepository.PROXY_PORT)
- || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.savePassword") //$NON-NLS-1$
- || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.usedefault") //$NON-NLS-1$
- || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.savePassword") //$NON-NLS-1$
- || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.username") //$NON-NLS-1$
- || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.password") //$NON-NLS-1$
- || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.enabled")) { //$NON-NLS-1$
- return true;
- }
- return false;
- }
-
- private final PropertyChangeListener repositoryChangeListener4ClientCache = new PropertyChangeListener() {
-
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (ignoredProperty(evt.getPropertyName())) {
- return;
- }
- TaskRepository taskRepository = (TaskRepository) evt.getSource();
- clientCache.invalidate(new RepositoryKey(taskRepository));
- }
- };
-
- private final PropertyChangeListener repositoryChangeListener4ConfigurationCache = new PropertyChangeListener() {
-
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (ignoredProperty(evt.getPropertyName())
- || evt.getPropertyName().equals("org.eclipse.mylyn.tasklist.repositories.password")) { //$NON-NLS-1$
- return;
- }
- TaskRepository taskRepository = (TaskRepository) evt.getSource();
- configurationCache.invalidate(new RepositoryKey(taskRepository));
- }
- };
-
- private final LoadingCache<RepositoryKey, BugzillaRestClient> clientCache = CacheBuilder.newBuilder()
- .expireAfterAccess(CLIENT_CACHE_DURATION.getValue(), CLIENT_CACHE_DURATION.getUnit())
- .build(new CacheLoader<RepositoryKey, BugzillaRestClient>() {
-
- @Override
- public BugzillaRestClient load(RepositoryKey key) throws Exception {
- TaskRepository repository = key.getRepository();
- repository.addChangeListener(repositoryChangeListener4ClientCache);
- return createClient(repository);
- }
- });
-
- private final LoadingCache<RepositoryKey, Optional<BugzillaRestConfiguration>> configurationCache;
-
- public BugzillaRestConnector() {
- this(CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION);
- }
-
- public BugzillaRestConnector(Duration refreshAfterWriteDuration) {
- super();
- this.attachmentHandler = new BugzillaRestTaskAttachmentHandler(this);
- configurationCache = createCacheBuilder(CONFIGURATION_CACHE_EXPIRE_DURATION, refreshAfterWriteDuration)
- .build(new CacheLoader<RepositoryKey, Optional<BugzillaRestConfiguration>>() {
-
- @Override
- public Optional<BugzillaRestConfiguration> load(RepositoryKey key) throws Exception {
- BugzillaRestClient client = clientCache.get(key);
- TaskRepository repository = key.getRepository();
- repository.addChangeListener(repositoryChangeListener4ConfigurationCache);
- return Optional.fromNullable(client.getConfiguration(key.getRepository(), context.get()));
- }
-
- @Override
- public ListenableFuture<Optional<BugzillaRestConfiguration>> reload(final RepositoryKey key,
- Optional<BugzillaRestConfiguration> oldValue) throws Exception {
- // asynchronous!
- ListenableFutureJob<Optional<BugzillaRestConfiguration>> job = new ListenableFutureJob<Optional<BugzillaRestConfiguration>>(
- "") {
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- BugzillaRestClient client;
- try {
- client = clientCache.get(key);
- set(Optional
- .fromNullable(client.getConfiguration(key.getRepository(), context.get())));
- } catch (ExecutionException e) {
- e.printStackTrace();
- return new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN,
- "BugzillaRestConnector reload Configuration", e);
- }
- return Status.OK_STATUS;
- }
- };
- job.schedule();
- return job;
- }
- });
- }
-
- protected CacheBuilder<Object, Object> createCacheBuilder(Duration expireAfterWriteDuration,
- Duration refreshAfterWriteDuration) {
- return CacheBuilder.newBuilder()
- .expireAfterWrite(expireAfterWriteDuration.getValue(), expireAfterWriteDuration.getUnit())
- .refreshAfterWrite(refreshAfterWriteDuration.getValue(), refreshAfterWriteDuration.getUnit());
- }
-
- @Override
- public boolean canCreateNewTask(TaskRepository repository) {
- return true;
- }
-
- @Override
- public boolean canCreateTaskFromKey(TaskRepository repository) {
- // ignore
- return false;
- }
-
- @Override
- public String getConnectorKind() {
- return BugzillaRestCore.CONNECTOR_KIND;
- }
-
- @Override
- public String getLabel() {
- return "Bugzilla 5.0 or later with REST";
- }
-
- @Override
- public String getRepositoryUrlFromTaskUrl(String taskUrl) {
- if (taskUrl == null) {
- return null;
- }
- int index = taskUrl.indexOf("/rest.cgi/"); //$NON-NLS-1$
- return index == -1 ? null : taskUrl.substring(0, index);
- }
-
- @Override
- public TaskData getTaskData(TaskRepository repository, String taskIdOrKey, IProgressMonitor monitor)
- throws CoreException {
- return ((BugzillaRestTaskDataHandler) getTaskDataHandler()).getTaskData(repository, taskIdOrKey, monitor);
- }
-
- @Override
- public String getTaskIdFromTaskUrl(String taskUrl) {
- // ignore
- return null;
- }
-
- @Override
- public String getTaskUrl(String repositoryUrl, String taskIdOrKey) {
- return repositoryUrl + "/rest.cgi/bug/" + taskIdOrKey; //$NON-NLS-1$
- }
-
- @Override
- public boolean hasTaskChanged(TaskRepository taskRepository, ITask task, TaskData taskData) {
- // ignore
- return false;
- }
-
- @Override
- public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector collector,
- ISynchronizationSession session, IProgressMonitor monitor) {
- monitor = Policy.monitorFor(monitor);
- try {
- monitor.beginTask("performQuery", IProgressMonitor.UNKNOWN);
- BugzillaRestClient client = getClient(repository);
- IOperationMonitor progress = OperationUtil.convert(monitor, "performQuery", 3); //$NON-NLS-1$
- return client.performQuery(repository, query, collector, progress);
- } catch (CoreException e) {
- return new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, IStatus.INFO,
- "CoreException from performQuery", e);
- } catch (BugzillaRestException e) {
- return new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, IStatus.INFO,
- "BugzillaRestException from performQuery", e);
- } finally {
- monitor.done();
- }
- }
-
- @Override
- public void updateRepositoryConfiguration(TaskRepository taskRepository, IProgressMonitor monitor)
- throws CoreException {
- context.set(monitor != null ? OperationUtil.convert(monitor) : new NullOperationMonitor());
- configurationCache.refresh(new RepositoryKey(taskRepository));
- context.remove();
- }
-
- @Override
- public void updateTaskFromTaskData(TaskRepository taskRepository, ITask task, TaskData taskData) {
- TaskMapper scheme = getTaskMapping(taskData);
- scheme.applyTo(task);
- task.setUrl(taskData.getRepositoryUrl() + "/rest.cgi/bug/" + taskData.getTaskId()); //$NON-NLS-1$
-
- boolean isComplete = false;
- TaskAttribute attributeStatus = taskData.getRoot().getMappedAttribute(TaskAttribute.STATUS);
- if (attributeStatus != null) {
- try {
- BugzillaRestConfiguration configuration;
- configuration = getRepositoryConfiguration(taskRepository);
- if (configuration != null) {
- Field stat = configuration.getFieldWithName(IBugzillaRestConstants.BUG_STATUS);
- for (FieldValues fieldValue : stat.getValues()) {
- if (attributeStatus.getValue().equals(fieldValue.getName())) {
- isComplete = !fieldValue.isOpen();
- }
- }
- }
- } catch (CoreException e) {
- StatusHandler.log(new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN,
- "Error during get BugzillaRestConfiguration", e));
- }
- }
- if (taskData.isPartial()) {
- if (isComplete) {
- if (task.getCompletionDate() == null) {
- task.setCompletionDate(new Date(0));
- }
- } else {
- task.setCompletionDate(null);
- }
- } else {
- inferCompletionDate(task, taskData, scheme, isComplete);
- }
-
- }
-
- private void inferCompletionDate(ITask task, TaskData taskData, TaskMapper scheme, boolean isComplete) {
- if (isComplete) {
- Date completionDate = null;
- List<TaskAttribute> taskComments = taskData.getAttributeMapper().getAttributesByType(taskData,
- TaskAttribute.TYPE_COMMENT);
- if (taskComments != null && taskComments.size() > 0) {
- TaskAttribute lastComment = taskComments.get(taskComments.size() - 1);
- if (lastComment != null) {
- TaskAttribute attributeCommentDate = lastComment.getMappedAttribute(TaskAttribute.COMMENT_DATE);
- if (attributeCommentDate != null) {
- completionDate = new Date(Long.parseLong(attributeCommentDate.getValue()));
- }
- }
- }
- if (completionDate == null) {
- // Use last modified date
- TaskAttribute attributeLastModified = taskData.getRoot()
- .getMappedAttribute(TaskAttribute.DATE_MODIFICATION);
- if (attributeLastModified != null && attributeLastModified.getValue().length() > 0) {
- completionDate = taskData.getAttributeMapper().getDateValue(attributeLastModified);
- }
- }
- task.setCompletionDate(completionDate);
- } else {
- task.setCompletionDate(null);
- }
- // Bugzilla Specific Attributes
-
- // Product
- if (scheme.getProduct() != null) {
- task.setAttribute(BugzillaRestTaskSchema.getDefault().PRODUCT.getKey(), scheme.getProduct());
- }
-
- // Severity
- TaskAttribute attrSeverity = taskData.getRoot()
- .getMappedAttribute(BugzillaRestTaskSchema.getDefault().SEVERITY.getKey());
- if (attrSeverity != null && !attrSeverity.getValue().equals("")) { //$NON-NLS-1$
- task.setAttribute(BugzillaRestTaskSchema.getDefault().SEVERITY.getKey(), attrSeverity.getValue());
- }
-
- // Severity
- TaskAttribute attrDelta = taskData.getRoot()
- .getAttribute(BugzillaRestTaskSchema.getDefault().DATE_MODIFICATION.getKey());
- if (attrDelta != null && !attrDelta.getValue().equals("")) { //$NON-NLS-1$
- task.setAttribute(BugzillaRestTaskSchema.getDefault().DATE_MODIFICATION.getKey(), attrDelta.getValue());
- }
- }
-
- @Override
- public AbstractTaskDataHandler getTaskDataHandler() {
- return new BugzillaRestTaskDataHandler(this);
- }
-
- private BugzillaRestClient createClient(TaskRepository repository) {
- RepositoryLocation location = new RepositoryLocation(repository.getProperties());
- AuthenticationCredentials credentials1 = repository
- .getCredentials(org.eclipse.mylyn.commons.net.AuthenticationType.REPOSITORY);
- UserCredentials credentials = new UserCredentials(credentials1.getUserName(), credentials1.getPassword(), null,
- true);
- location.setCredentials(AuthenticationType.REPOSITORY, credentials);
- BugzillaRestClient client = new BugzillaRestClient(location, this);
-
- return client;
- }
-
- /**
- * Returns the Client for the {@link TaskRepository}.
- *
- * @param repository
- * the {@link TaskRepository} object
- * @return the client Object
- * @throws CoreException
- */
- public BugzillaRestClient getClient(TaskRepository repository) throws CoreException {
- try {
- return clientCache.get(new RepositoryKey(repository));
- } catch (ExecutionException e) {
- throw new CoreException(
- new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, "TaskRepositoryManager is null"));
- }
- }
-
- @Override
- public RepositoryInfo validateRepository(TaskRepository repository, IProgressMonitor monitor) throws CoreException {
- try {
- BugzillaRestClient client = createClient(repository);
- if (!client.validate(OperationUtil.convert(monitor))) {
- throw new CoreException(
- new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, "repository is invalide"));
- }
- BugzillaRestVersion version = client.getVersion(OperationUtil.convert(monitor));
- return new RepositoryInfo(new RepositoryVersion(version.toString()));
- } catch (Exception e) {
- throw new CoreException(new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, e.getMessage(), e));
- }
- }
-
- public BugzillaRestConfiguration getRepositoryConfiguration(TaskRepository repository) throws CoreException {
- if (clientCache.getIfPresent(new RepositoryKey(repository)) == null) {
- getClient(repository);
- }
- try {
- Optional<BugzillaRestConfiguration> configurationOptional = configurationCache
- .get(new RepositoryKey(repository));
- return configurationOptional.isPresent() ? configurationOptional.get() : null;
- } catch (UncheckedExecutionException e) {
- throw new CoreException(new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, e.getMessage(), e));
- } catch (ExecutionException e) {
- throw new CoreException(new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, e.getMessage(), e));
- }
- }
-
- public void clearClientCache() {
- clientCache.invalidateAll();
- }
-
- public void clearConfigurationCache() {
- configurationCache.invalidateAll();
- }
-
- public void clearAllCaches() {
- clearClientCache();
- clearConfigurationCache();
- }
-
- @Override
- public boolean isRepositoryConfigurationStale(TaskRepository repository, IProgressMonitor monitor)
- throws CoreException {
- return false;
- }
-
- @Override
- public TaskMapper getTaskMapping(final TaskData taskData) {
-
- return new TaskMapper(taskData) {
- @Override
- public String getTaskKey() {
- TaskAttribute attribute = getTaskData().getRoot()
- .getAttribute(BugzillaRestTaskSchema.getDefault().BUG_ID.getKey());
- if (attribute != null) {
- return attribute.getValue();
- }
- return super.getTaskKey();
- }
-
- @Override
- public String getTaskKind() {
- return taskData.getConnectorKind();
- }
-
- @Override
- public String getTaskUrl() {
- return taskData.getRepositoryUrl();
- }
- };
- }
-
- @Override
- @Nullable
- public AbstractTaskAttachmentHandler getTaskAttachmentHandler() {
- return attachmentHandler;
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2013 Frank Becker and others.
+ * 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:
+ * Frank Becker - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.bugzilla.rest.core;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.mylyn.commons.core.StatusHandler;
+import org.eclipse.mylyn.commons.core.operations.IOperationMonitor;
+import org.eclipse.mylyn.commons.core.operations.OperationUtil;
+import org.eclipse.mylyn.commons.net.AuthenticationCredentials;
+import org.eclipse.mylyn.commons.net.Policy;
+import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation;
+import org.eclipse.mylyn.commons.repositories.core.auth.AuthenticationType;
+import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials;
+import org.eclipse.mylyn.internal.bugzilla.rest.core.response.data.Field;
+import org.eclipse.mylyn.internal.bugzilla.rest.core.response.data.FieldValues;
+import org.eclipse.mylyn.internal.commons.core.operations.NullOperationMonitor;
+import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants;
+import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
+import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
+import org.eclipse.mylyn.tasks.core.ITask;
+import org.eclipse.mylyn.tasks.core.RepositoryInfo;
+import org.eclipse.mylyn.tasks.core.RepositoryVersion;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.core.data.AbstractTaskAttachmentHandler;
+import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
+import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
+import org.eclipse.mylyn.tasks.core.data.TaskData;
+import org.eclipse.mylyn.tasks.core.data.TaskDataCollector;
+import org.eclipse.mylyn.tasks.core.data.TaskMapper;
+import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;
+
+import com.google.common.base.Optional;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+
+public class BugzillaRestConnector extends AbstractRepositoryConnector {
+
+ public static final Duration CLIENT_CACHE_DURATION = new Duration(24, TimeUnit.HOURS);
+
+ public static final Duration CONFIGURATION_CACHE_EXPIRE_DURATION = new Duration(7, TimeUnit.DAYS);
+
+ public static final Duration CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION = new Duration(1, TimeUnit.DAYS);
+
+ private static final ThreadLocal<IOperationMonitor> context = new ThreadLocal<IOperationMonitor>();
+
+ private BugzillaRestTaskAttachmentHandler attachmentHandler;
+
+ private boolean ignoredProperty(String propertyName) {
+ if (propertyName.equals(RepositoryLocation.PROPERTY_LABEL) || propertyName.equals(TaskRepository.OFFLINE)
+ || propertyName.equals(IRepositoryConstants.PROPERTY_ENCODING)
+ || propertyName.equals(TaskRepository.PROXY_HOSTNAME) || propertyName.equals(TaskRepository.PROXY_PORT)
+ || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.savePassword") //$NON-NLS-1$
+ || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.usedefault") //$NON-NLS-1$
+ || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.savePassword") //$NON-NLS-1$
+ || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.username") //$NON-NLS-1$
+ || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.password") //$NON-NLS-1$
+ || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.enabled")) { //$NON-NLS-1$
+ return true;
+ }
+ return false;
+ }
+
+ private final PropertyChangeListener repositoryChangeListener4ClientCache = new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (ignoredProperty(evt.getPropertyName())) {
+ return;
+ }
+ TaskRepository taskRepository = (TaskRepository) evt.getSource();
+ clientCache.invalidate(new RepositoryKey(taskRepository));
+ }
+ };
+
+ private final PropertyChangeListener repositoryChangeListener4ConfigurationCache = new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (ignoredProperty(evt.getPropertyName())
+ || evt.getPropertyName().equals("org.eclipse.mylyn.tasklist.repositories.password")) { //$NON-NLS-1$
+ return;
+ }
+ TaskRepository taskRepository = (TaskRepository) evt.getSource();
+ configurationCache.invalidate(new RepositoryKey(taskRepository));
+ }
+ };
+
+ private final LoadingCache<RepositoryKey, BugzillaRestClient> clientCache = CacheBuilder.newBuilder()
+ .expireAfterAccess(CLIENT_CACHE_DURATION.getValue(), CLIENT_CACHE_DURATION.getUnit())
+ .build(new CacheLoader<RepositoryKey, BugzillaRestClient>() {
+
+ @Override
+ public BugzillaRestClient load(RepositoryKey key) throws Exception {
+ TaskRepository repository = key.getRepository();
+ repository.addChangeListener(repositoryChangeListener4ClientCache);
+ return createClient(repository);
+ }
+ });
+
+ private final LoadingCache<RepositoryKey, Optional<BugzillaRestConfiguration>> configurationCache;
+
+ public BugzillaRestConnector() {
+ this(CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION);
+ }
+
+ public BugzillaRestConnector(Duration refreshAfterWriteDuration) {
+ super();
+ this.attachmentHandler = new BugzillaRestTaskAttachmentHandler(this);
+ configurationCache = createCacheBuilder(CONFIGURATION_CACHE_EXPIRE_DURATION, refreshAfterWriteDuration)
+ .build(new CacheLoader<RepositoryKey, Optional<BugzillaRestConfiguration>>() {
+
+ @Override
+ public Optional<BugzillaRestConfiguration> load(RepositoryKey key) throws Exception {
+ BugzillaRestClient client = clientCache.get(key);
+ TaskRepository repository = key.getRepository();
+ repository.addChangeListener(repositoryChangeListener4ConfigurationCache);
+ return Optional.fromNullable(client.getConfiguration(key.getRepository(), context.get()));
+ }
+
+ @Override
+ public ListenableFuture<Optional<BugzillaRestConfiguration>> reload(final RepositoryKey key,
+ Optional<BugzillaRestConfiguration> oldValue) throws Exception {
+ // asynchronous!
+ ListenableFutureJob<Optional<BugzillaRestConfiguration>> job = new ListenableFutureJob<Optional<BugzillaRestConfiguration>>(
+ "") {
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ BugzillaRestClient client;
+ try {
+ client = clientCache.get(key);
+ set(Optional
+ .fromNullable(client.getConfiguration(key.getRepository(), context.get())));
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ return new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN,
+ "BugzillaRestConnector reload Configuration", e);
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.schedule();
+ return job;
+ }
+ });
+ }
+
+ protected CacheBuilder<Object, Object> createCacheBuilder(Duration expireAfterWriteDuration,
+ Duration refreshAfterWriteDuration) {
+ return CacheBuilder.newBuilder()
+ .expireAfterWrite(expireAfterWriteDuration.getValue(), expireAfterWriteDuration.getUnit())
+ .refreshAfterWrite(refreshAfterWriteDuration.getValue(), refreshAfterWriteDuration.getUnit());
+ }
+
+ @Override
+ public boolean canCreateNewTask(TaskRepository repository) {
+ return true;
+ }
+
+ @Override
+ public boolean canCreateTaskFromKey(TaskRepository repository) {
+ // ignore
+ return false;
+ }
+
+ @Override
+ public String getConnectorKind() {
+ return BugzillaRestCore.CONNECTOR_KIND;
+ }
+
+ @Override
+ public String getLabel() {
+ return "Bugzilla 5.0 or later with REST";
+ }
+
+ @Override
+ public String getRepositoryUrlFromTaskUrl(String taskUrl) {
+ if (taskUrl == null) {
+ return null;
+ }
+ int index = taskUrl.indexOf("/rest.cgi/"); //$NON-NLS-1$
+ return index == -1 ? null : taskUrl.substring(0, index);
+ }
+
+ @Override
+ public TaskData getTaskData(TaskRepository repository, String taskIdOrKey, IProgressMonitor monitor)
+ throws CoreException {
+ return ((BugzillaRestTaskDataHandler) getTaskDataHandler()).getTaskData(repository, taskIdOrKey, monitor);
+ }
+
+ @Override
+ public String getTaskIdFromTaskUrl(String taskUrl) {
+ // ignore
+ return null;
+ }
+
+ @Override
+ public String getTaskUrl(String repositoryUrl, String taskIdOrKey) {
+ return repositoryUrl + "/rest.cgi/bug/" + taskIdOrKey; //$NON-NLS-1$
+ }
+
+ @Override
+ public boolean hasTaskChanged(TaskRepository taskRepository, ITask task, TaskData taskData) {
+ // ignore
+ return false;
+ }
+
+ @Override
+ public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector collector,
+ ISynchronizationSession session, IProgressMonitor monitor) {
+ monitor = Policy.monitorFor(monitor);
+ try {
+ monitor.beginTask("performQuery", IProgressMonitor.UNKNOWN);
+ BugzillaRestClient client = getClient(repository);
+ IOperationMonitor progress = OperationUtil.convert(monitor, "performQuery", 3); //$NON-NLS-1$
+ return client.performQuery(repository, query, collector, progress);
+ } catch (CoreException e) {
+ return new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, IStatus.INFO,
+ "CoreException from performQuery", e);
+ } catch (BugzillaRestException e) {
+ return new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, IStatus.INFO,
+ "BugzillaRestException from performQuery", e);
+ } finally {
+ monitor.done();
+ }
+ }
+
+ @Override
+ public void updateRepositoryConfiguration(TaskRepository taskRepository, IProgressMonitor monitor)
+ throws CoreException {
+ context.set(monitor != null ? OperationUtil.convert(monitor) : new NullOperationMonitor());
+ configurationCache.refresh(new RepositoryKey(taskRepository));
+ context.remove();
+ }
+
+ @Override
+ public void updateTaskFromTaskData(TaskRepository taskRepository, ITask task, TaskData taskData) {
+ TaskMapper scheme = getTaskMapping(taskData);
+ scheme.applyTo(task);
+ task.setUrl(taskData.getRepositoryUrl() + "/rest.cgi/bug/" + taskData.getTaskId()); //$NON-NLS-1$
+
+ boolean isComplete = false;
+ TaskAttribute attributeStatus = taskData.getRoot().getMappedAttribute(TaskAttribute.STATUS);
+ if (attributeStatus != null) {
+ try {
+ BugzillaRestConfiguration configuration;
+ configuration = getRepositoryConfiguration(taskRepository);
+ if (configuration != null) {
+ Field stat = configuration.getFieldWithName(IBugzillaRestConstants.BUG_STATUS);
+ for (FieldValues fieldValue : stat.getValues()) {
+ if (attributeStatus.getValue().equals(fieldValue.getName())) {
+ isComplete = !fieldValue.isOpen();
+ }
+ }
+ }
+ } catch (CoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN,
+ "Error during get BugzillaRestConfiguration", e));
+ }
+ }
+ if (taskData.isPartial()) {
+ if (isComplete) {
+ if (task.getCompletionDate() == null) {
+ task.setCompletionDate(new Date(0));
+ }
+ } else {
+ task.setCompletionDate(null);
+ }
+ } else {
+ inferCompletionDate(task, taskData, scheme, isComplete);
+ }
+
+ }
+
+ private void inferCompletionDate(ITask task, TaskData taskData, TaskMapper scheme, boolean isComplete) {
+ if (isComplete) {
+ Date completionDate = null;
+ List<TaskAttribute> taskComments = taskData.getAttributeMapper().getAttributesByType(taskData,
+ TaskAttribute.TYPE_COMMENT);
+ if (taskComments != null && taskComments.size() > 0) {
+ TaskAttribute lastComment = taskComments.get(taskComments.size() - 1);
+ if (lastComment != null) {
+ TaskAttribute attributeCommentDate = lastComment.getMappedAttribute(TaskAttribute.COMMENT_DATE);
+ if (attributeCommentDate != null) {
+ completionDate = new Date(Long.parseLong(attributeCommentDate.getValue()));
+ }
+ }
+ }
+ if (completionDate == null) {
+ // Use last modified date
+ TaskAttribute attributeLastModified = taskData.getRoot()
+ .getMappedAttribute(TaskAttribute.DATE_MODIFICATION);
+ if (attributeLastModified != null && attributeLastModified.getValue().length() > 0) {
+ completionDate = taskData.getAttributeMapper().getDateValue(attributeLastModified);
+ }
+ }
+ task.setCompletionDate(completionDate);
+ } else {
+ task.setCompletionDate(null);
+ }
+ // Bugzilla Specific Attributes
+
+ // Product
+ if (scheme.getProduct() != null) {
+ task.setAttribute(BugzillaRestTaskSchema.getDefault().PRODUCT.getKey(), scheme.getProduct());
+ }
+
+ // Severity
+ TaskAttribute attrSeverity = taskData.getRoot()
+ .getMappedAttribute(BugzillaRestTaskSchema.getDefault().SEVERITY.getKey());
+ if (attrSeverity != null && !attrSeverity.getValue().equals("")) { //$NON-NLS-1$
+ task.setAttribute(BugzillaRestTaskSchema.getDefault().SEVERITY.getKey(), attrSeverity.getValue());
+ }
+
+ // Severity
+ TaskAttribute attrDelta = taskData.getRoot()
+ .getAttribute(BugzillaRestTaskSchema.getDefault().DATE_MODIFICATION.getKey());
+ if (attrDelta != null && !attrDelta.getValue().equals("")) { //$NON-NLS-1$
+ task.setAttribute(BugzillaRestTaskSchema.getDefault().DATE_MODIFICATION.getKey(), attrDelta.getValue());
+ }
+ }
+
+ @Override
+ public AbstractTaskDataHandler getTaskDataHandler() {
+ return new BugzillaRestTaskDataHandler(this);
+ }
+
+ private BugzillaRestClient createClient(TaskRepository repository) {
+ RepositoryLocation location = new RepositoryLocation(convertProperties(repository));
+ AuthenticationCredentials credentials1 = repository
+ .getCredentials(org.eclipse.mylyn.commons.net.AuthenticationType.REPOSITORY);
+ UserCredentials credentials = new UserCredentials(credentials1.getUserName(), credentials1.getPassword(), null,
+ true);
+ location.setCredentials(AuthenticationType.REPOSITORY, credentials);
+ BugzillaRestClient client = new BugzillaRestClient(location, this);
+
+ return client;
+ }
+
+ private Map<String, String> convertProperties(TaskRepository repository) {
+ return repository.getProperties()
+ .entrySet()
+ .stream()
+ .collect(Collectors.toMap(e -> convertProperty(e.getKey()), Map.Entry::getValue));
+ }
+
+ @SuppressWarnings("restriction")
+ private String convertProperty(String key) {
+ if (TaskRepository.PROXY_USEDEFAULT.equals(key)) {
+ return RepositoryLocation.PROPERTY_PROXY_USEDEFAULT;
+ } else if (TaskRepository.PROXY_HOSTNAME.equals(key)) {
+ return RepositoryLocation.PROPERTY_PROXY_HOST;
+ } else if (TaskRepository.PROXY_PORT.equals(key)) {
+ return RepositoryLocation.PROPERTY_PROXY_PORT;
+ }
+ return key;
+ }
+
+ /**
+ * Returns the Client for the {@link TaskRepository}.
+ *
+ * @param repository
+ * the {@link TaskRepository} object
+ * @return the client Object
+ * @throws CoreException
+ */
+ public BugzillaRestClient getClient(TaskRepository repository) throws CoreException {
+ try {
+ return clientCache.get(new RepositoryKey(repository));
+ } catch (ExecutionException e) {
+ throw new CoreException(
+ new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, "TaskRepositoryManager is null"));
+ }
+ }
+
+ @Override
+ public RepositoryInfo validateRepository(TaskRepository repository, IProgressMonitor monitor) throws CoreException {
+ try {
+ BugzillaRestClient client = createClient(repository);
+ if (!client.validate(OperationUtil.convert(monitor))) {
+ throw new CoreException(
+ new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, "repository is invalide"));
+ }
+ BugzillaRestVersion version = client.getVersion(OperationUtil.convert(monitor));
+ return new RepositoryInfo(new RepositoryVersion(version.toString()));
+ } catch (Exception e) {
+ throw new CoreException(new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, e.getMessage(), e));
+ }
+ }
+
+ public BugzillaRestConfiguration getRepositoryConfiguration(TaskRepository repository) throws CoreException {
+ if (clientCache.getIfPresent(new RepositoryKey(repository)) == null) {
+ getClient(repository);
+ }
+ try {
+ Optional<BugzillaRestConfiguration> configurationOptional = configurationCache
+ .get(new RepositoryKey(repository));
+ return configurationOptional.isPresent() ? configurationOptional.get() : null;
+ } catch (UncheckedExecutionException e) {
+ throw new CoreException(new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, e.getMessage(), e));
+ } catch (ExecutionException e) {
+ throw new CoreException(new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, e.getMessage(), e));
+ }
+ }
+
+ public void clearClientCache() {
+ clientCache.invalidateAll();
+ }
+
+ public void clearConfigurationCache() {
+ configurationCache.invalidateAll();
+ }
+
+ public void clearAllCaches() {
+ clearClientCache();
+ clearConfigurationCache();
+ }
+
+ @Override
+ public boolean isRepositoryConfigurationStale(TaskRepository repository, IProgressMonitor monitor)
+ throws CoreException {
+ return false;
+ }
+
+ @Override
+ public TaskMapper getTaskMapping(final TaskData taskData) {
+
+ return new TaskMapper(taskData) {
+ @Override
+ public String getTaskKey() {
+ TaskAttribute attribute = getTaskData().getRoot()
+ .getAttribute(BugzillaRestTaskSchema.getDefault().BUG_ID.getKey());
+ if (attribute != null) {
+ return attribute.getValue();
+ }
+ return super.getTaskKey();
+ }
+
+ @Override
+ public String getTaskKind() {
+ return taskData.getConnectorKind();
+ }
+
+ @Override
+ public String getTaskUrl() {
+ return taskData.getRepositoryUrl();
+ }
+ };
+ }
+
+ @Override
+ @Nullable
+ public AbstractTaskAttachmentHandler getTaskAttachmentHandler() {
+ return attachmentHandler;
+ }
+
+}

Back to the top