/******************************************************************************* * Copyright (c) 2007,2008 Itsolut, Inc 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: * Chris Shane - Initial API and implementation. * David Carver - STAR - Mylyn 3.0 implementation. *******************************************************************************/ package com.itsolut.mantis.core; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.mylyn.commons.net.Policy; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.AbstractTaskAttachmentHandler; import org.eclipse.mylyn.tasks.core.data.AbstractTaskAttachmentSource; import org.eclipse.mylyn.tasks.core.data.TaskAttachmentMapper; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import com.google.inject.Inject; import com.itsolut.mantis.core.exception.MantisException; import com.itsolut.mantis.core.model.MantisTicketComment; import com.itsolut.mantis.core.util.MantisUtils; /** * * <p>Works around the fact that Mantis does not have a description column for attachments ( which * is required for storing contexts ) by setting a special filename, which contains the expected * description + a timestamp.</p> * * @see MantisAttributeMapper#updateTaskAttachment(org.eclipse.mylyn.tasks.core.ITaskAttachment, TaskAttribute) * * @author Steffen Pingel * @author Chris Hane */ public class MantisAttachmentHandler extends AbstractTaskAttachmentHandler { static final String CONTEXT_DESCRIPTION = "mylyn/context/zip";; private final DateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss"); private final IMantisClientManager clientManager; private final StatusFactory statusFactory; @Inject public MantisAttachmentHandler(IMantisClientManager clientManager, StatusFactory statusFactory) { this.clientManager = clientManager; this.statusFactory = statusFactory; } private byte[] getAttachmentData(TaskRepository repository, TaskAttachmentMapper attachment, IProgressMonitor monitor) throws CoreException { String id = attachment.getAttachmentId(); if (id == null || id.length() == 0) { throw new CoreException(statusFactory.toStatus("Attachment download from " + repository.getRepositoryUrl() + " failed, missing attachment filename.", null, repository)); } try { IMantisClient client = clientManager.getRepository(repository); return client.getAttachmentData(Integer.parseInt(id), monitor); } catch (MantisException e) { throw new CoreException(statusFactory.toStatus("Attachment download from " +repository.getRepositoryUrl() + " failed : " + e.getMessage(), e , repository)); } } private InputStream getAttachmentAsStream(TaskRepository repository, TaskAttachmentMapper attachment, IProgressMonitor monitor) throws CoreException { return new ByteArrayInputStream( getAttachmentData(repository, attachment, monitor) ); } @Override public boolean canGetContent(TaskRepository repository, ITask task) { return repository != null; } @Override public boolean canPostContent(TaskRepository repository, ITask task) { return repository != null; } @Override public InputStream getContent(TaskRepository repository, ITask task, TaskAttribute attachmentAttribute, IProgressMonitor monitor) throws CoreException { try { monitor.beginTask("Getting attachment", IProgressMonitor.UNKNOWN); TaskAttachmentMapper attachment = TaskAttachmentMapper.createFrom(attachmentAttribute); return getAttachmentAsStream(repository, attachment, monitor); } finally { monitor.done(); } } @Override public void postContent(TaskRepository repository, ITask task, AbstractTaskAttachmentSource source, String comment, TaskAttribute attachmentAttribute, IProgressMonitor monitor) throws CoreException { monitor.beginTask("Uploading attachment", 2); try { IMantisClient client = clientManager.getRepository(repository); int id = Integer.parseInt(task.getTaskId()); byte[] data = readData(source, monitor); //hack since context methods are final in superclasses & Mantis does not have a description column String filename = source.getName(); if (CONTEXT_DESCRIPTION.equals(source.getDescription())) filename = CONTEXT_DESCRIPTION + "-" + dateFormat.format(new Date()) + ".zip"; // add zip extension else if ( attachmentAttribute != null){ TaskAttachmentMapper mapper = TaskAttachmentMapper.createFrom(attachmentAttribute); if ( mapper.getFileName() != null) filename = mapper.getFileName(); } client.putAttachmentData(id, filename, data, monitor); Policy.advance(monitor, 1); if ( !MantisUtils.isEmpty(comment) ) client.addIssueComment(id, new MantisTicketComment(comment, 0), monitor); Policy.advance(monitor, 1); } catch (MantisException e) { throw new CoreException(statusFactory.toStatus("Attachment upload to " + task.getRepositoryUrl() + " failed, please see details.", e , repository)); } catch (IOException e) { throw new CoreException(statusFactory.toStatus("Attachment upload to " + task.getRepositoryUrl() + " failed, please see details.", e , repository)); } finally { monitor.done(); } } private byte[] readData(AbstractTaskAttachmentSource attachment, IProgressMonitor monitor) throws IOException, CoreException { InputStream in = attachment.createInputStream(monitor); try { byte[] data = new byte[(int) attachment.getLength()]; in.read(data, 0, (int) attachment.getLength()); return data; } finally { in.close(); } } }