Can RTC create a work item via an email?
Does RTC have the equivalent of this feature?
https://confluence.atlassian.com/display/SERVICEDESK/Setting+up+the+email+channel
Your customers can open requests and communicate with your service team by working from their familiar email box when the email channel is enabled for your service desk. Here's how it works:
•A customer sends an email to the email account designated for your service desk.
•A new request is created based on the email. The customer receives an email notification that contains the details of the request.
•Your agent sees the issue in one of the queues and works on the issue. When customer-visible comments are added to the issue or the status of the issue is changed, the customer receives email notifications.
•When the customer replies to email notifications, the reply is added as a comment to the issue.
|
Accepted answer
Hi Michael,
There are several RFE records on jazz.net. All seem to link to Email importer (95864) Create work item from email (149682) The ability to create work items by email (64824) Email created work items (183408) Create and comment on workitems through email (89470) ...etc. Michael Aldor selected this answer as the correct answer
Comments
Michael Aldor
commented Nov 05 '14, 2:58 p.m.
Thanks for the information, that is too bad that this has been an RFE since 2009
I guess an approach to get this functionality could be to develop an application that reads a mail servers inbox and uses the REST API to create or update a workitem
sam detweiler
commented Nov 05 '14, 4:00 p.m.
There are IBM partners that provide this functionality, so unlikely IBM would implement it. |
6 other answers
OK Suresh, sorry about the delay, but here's the code in two parts. Firstly, please note that I am certainly no star Java programmer and there will be scope for improvement. It's stuff I have built over time and is subject to steady improvement as my knowledge improves and time allows. Secondly there may be a few things directly related to the setup in my organisation, so some things may not be generalised as well as they might be or may refer to internal processes such as Governance.
There is a Common class which is a library of utility methods and the class you're interested in which does, of course, use the Common methods. Thirdly you'll see that I use log4j2.
Finally, with grateful thanks to Ralph Schoon and other contributors to this site without whose generous sharing of their knowledge I could not have got this far, here it is:
package com.nbs.nsl.utility;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import com.ibm.team.apt.common.IIterationPlanRecord;
import com.ibm.team.apt.common.IIterationPlanRecordHandle;
import com.ibm.team.apt.internal.client.IIterationPlanClient;
import com.ibm.team.apt.internal.client.IterationPlanClient;
import com.ibm.team.apt.internal.common.rcp.IIterationPlanService;
import com.ibm.team.apt.internal.common.rcp.dto.DTO_IterationPlanSaveResult;
import com.ibm.team.apt.internal.common.wiki.IWikiPage;
import com.ibm.team.filesystem.client.FileSystemCore;
import com.ibm.team.filesystem.client.IFileContentManager;
import com.ibm.team.filesystem.client.workitems.IFileSystemWorkItemManager;
import com.ibm.team.filesystem.common.FileLineDelimiter;
import com.ibm.team.filesystem.common.IFileContent;
import com.ibm.team.filesystem.common.IFileItem;
import com.ibm.team.foundation.common.text.XMLString;
import com.ibm.team.links.common.IItemReference;
import com.ibm.team.links.common.factory.IReferenceFactory;
import com.ibm.team.process.client.IProcessItemService;
import com.ibm.team.process.common.IDevelopmentLine;
import com.ibm.team.process.common.IDevelopmentLineHandle;
import com.ibm.team.process.common.IIteration;
import com.ibm.team.process.common.IIterationHandle;
import com.ibm.team.process.common.IProcessArea;
import com.ibm.team.process.common.IProcessAreaHandle;
import com.ibm.team.process.common.IProcessItem;
import com.ibm.team.process.common.IProjectArea;
import com.ibm.team.process.common.IProjectAreaHandle;
import com.ibm.team.repository.client.IExternalUserRegistryManager;
import com.ibm.team.repository.client.IItemManager;
import com.ibm.team.repository.client.ITeamRepository;
import com.ibm.team.repository.client.internal.TeamRepository;
import com.ibm.team.repository.client.util.IClientLibraryContext;
import com.ibm.team.repository.common.IAuditable;
import com.ibm.team.repository.common.IContent;
import com.ibm.team.repository.common.IContributorHandle;
import com.ibm.team.repository.common.IExternalUser;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.ibm.team.repository.common.IContributor;
import com.ibm.team.repository.common.UnknownUserException;
import com.ibm.team.repository.common.model.query.BaseContributorQueryModel.ContributorQueryModel;
import com.ibm.team.repository.common.query.IItemQuery;
import com.ibm.team.repository.common.query.IItemQueryPage;
import com.ibm.team.repository.common.query.ast.IPredicate;
import com.ibm.team.repository.common.service.IQueryService;
import com.ibm.team.scm.client.IWorkspaceConnection;
import com.ibm.team.scm.client.content.util.VersionedContentManagerByteArrayInputStreamPovider;
import com.ibm.team.scm.common.IChangeSetHandle;
import com.ibm.team.scm.common.IComponentHandle;
import com.ibm.team.scm.common.IFolder;
import com.ibm.team.workitem.api.common.WorkItemAttributes;
import com.ibm.team.workitem.client.IAuditableClient;
import com.ibm.team.workitem.client.IDetailedStatus;
import com.ibm.team.workitem.client.IQueryClient;
import com.ibm.team.workitem.client.IWorkItemClient;
import com.ibm.team.workitem.client.IWorkItemWorkingCopyManager;
import com.ibm.team.workitem.client.WorkItemWorkingCopy;
import com.ibm.team.workitem.common.IAuditableCommon;
import com.ibm.team.workitem.common.expression.AttributeExpression;
import com.ibm.team.workitem.common.expression.Expression;
import com.ibm.team.workitem.common.expression.IQueryableAttribute;
import com.ibm.team.workitem.common.expression.IQueryableAttributeFactory;
import com.ibm.team.workitem.common.expression.QueryableAttributes;
import com.ibm.team.workitem.common.expression.Term;
import com.ibm.team.workitem.common.expression.Term.Operator;
import com.ibm.team.workitem.common.model.AttributeOperation;
import com.ibm.team.workitem.common.model.IApproval;
import com.ibm.team.workitem.common.model.IApprovalDescriptor;
import com.ibm.team.workitem.common.model.IApprovals;
import com.ibm.team.workitem.common.model.IAttachment;
import com.ibm.team.workitem.common.model.IAttribute;
import com.ibm.team.workitem.common.model.IAttributeHandle;
import com.ibm.team.workitem.common.model.ICategory;
import com.ibm.team.workitem.common.model.ICategoryHandle;
import com.ibm.team.workitem.common.model.IEnumeration;
import com.ibm.team.workitem.common.model.ILiteral;
import com.ibm.team.workitem.common.model.IWorkItem;
import com.ibm.team.workitem.common.model.IWorkItemHandle;
import com.ibm.team.workitem.common.model.IWorkItemType;
import com.ibm.team.workitem.common.model.Identifier;
import com.ibm.team.workitem.common.model.ItemProfile;
import com.ibm.team.workitem.common.model.WorkItemEndPoints;
import com.ibm.team.workitem.common.model.WorkItemLinkTypes;
import com.ibm.team.workitem.common.query.IQueryResult;
import com.ibm.team.workitem.common.query.IResolvedResult;
import com.ibm.team.workitem.common.IWorkItemCommon;
import org.apache.logging.log4j.Logger;
public class Common {
public static void addFolderStructureToComponent(ITeamRepository repo, String path, IWorkspaceConnection repoWorkspace,
IComponentHandle componentHdl, IChangeSetHandle csHdl, IFolder parent,
IProgressMonitor monitor, Logger log) throws TeamRepositoryException, IOException {
log.info("addFolderStructureToComponent Entry");
if (parent == null) {
parent = (IFolder) repoWorkspace.configuration(componentHdl).rootFolderHandle(monitor);
}
File folder = new File( path );
// Create this folder in the repo workspace
log.info("Creating this folder");
IFolder newParent = createFolder(folder.getName(), parent, repoWorkspace, csHdl, monitor, log);
log.info("Path is "+path+" Folder Name is "+folder.getName());
// Look for children of this folder
File[] list = folder.listFiles();
if (list == null) return;
for ( File f : list ) {
if ( f.isDirectory() ) {
addFolderStructureToComponent(repo, f.getAbsolutePath(), repoWorkspace, componentHdl, csHdl, newParent, monitor, log);
}
else {
log.info("Creating file "+f.getName());
IFileItem addedFile = createFileItem(f.getName(), newParent);
ByteArrayOutputStream contents = getFileData(f);
IFileContentManager contentManager = FileSystemCore.getContentManager(repo);
IFileContent storedContent = null;
log.info("Storing (uploading) its content");
String binFile = "(.\.(zip|gzip|7z|bar|jar|war|doc|docx|xls|xlsx|class|exe|jpeg|jpg|png)$)";
Pattern pattern = Pattern.compile(binFile);
Matcher matcher = pattern.matcher(f.getName());
if (matcher.matches()) {
storedContent = contentManager.storeContent(
null,
FileLineDelimiter.LINE_DELIMITER_NONE,
new VersionedContentManagerByteArrayInputStreamPovider(contents.toByteArray()),
null, monitor);
}
else {
storedContent = contentManager.storeContent(
IFileContent.ENCODING_UTF_8,
FileLineDelimiter.LINE_DELIMITER_PLATFORM,
new VersionedContentManagerByteArrayInputStreamPovider(contents.toByteArray()),
null, monitor);
}
log.info("Committing the upload");
IFileItem addedFileWC = (IFileItem) addedFile.getWorkingCopy();
addedFileWC.setContent(storedContent);
repoWorkspace.commit(csHdl, Collections
.singletonList(repoWorkspace.configurationOpFactory().save(addedFileWC)), monitor);
contents.close();
}
}
log.info("addFolderStructureToComponent Exit");
}
public static void addSubscriberToWorkitem(IWorkItem workItem, IContributor contributor, IProgressMonitor monitor, Logger log) throws TeamRepositoryException {
log.info("addSubscriberToWorkitem entry.");
IContributorHandle subscriber = (IContributorHandle) contributor.getItemHandle();
WorkItemWorkingCopy workingCopy = getWorkItemWorkingCopy(workItem);
workItem = workingCopy.getWorkItem();
workItem.getSubscriptions().add(subscriber);
log.info("Saving the Work Item");
IDetailedStatus s = workingCopy.save(monitor);
if(! s.isOK()) {
throw new TeamRepositoryException("Error saving work item", s.getException());
}
log.info("addSubscriberToWorkitem exit.");
}
public static void attachFile(ITeamRepository repo, IWorkItem workItem, String filename, String contentType, String encoding, IProgressMonitor monitor, Logger log)
throws TeamRepositoryException, IOException {
log.info("attachFile entry.");
File attachmentFile = new File(filename);
FileInputStream fis = new FileInputStream(attachmentFile);
IWorkItemClient workItemClient = (IWorkItemClient) ((ITeamRepository)workItem.getOrigin()).getClientLibrary(IWorkItemClient.class);
WorkItemWorkingCopy workingCopy = getWorkItemWorkingCopy(workItem);
workItem = workingCopy.getWorkItem();
log.info("Filename is "+filename);
log.info("Content Type is "+contentType);
log.info("Encoding is "+encoding);
try {
IAttachment newAttachment = workItemClient.createAttachment(workItem.getProjectArea(), attachmentFile.getName(), "", contentType, encoding, fis, monitor);
newAttachment = (IAttachment) newAttachment.getWorkingCopy();
newAttachment = workItemClient.saveAttachment(newAttachment, monitor);
IItemReference reference = WorkItemLinkTypes.createAttachmentReference(newAttachment);
workingCopy.getReferences().add(WorkItemEndPoints.ATTACHMENT, reference);
log.info("Saving the Work Item");
IDetailedStatus s = workingCopy.save(monitor);
if(! s.isOK()) {
throw new TeamRepositoryException("Error saving work item", s.getException());
}
} finally {
if (fis != null) {
fis.close();
}
}
log.info("attachFile exit.");
}
public static void createApprovals(ITeamRepository repo, String approvalType, String description, Timestamp dueDate,
List<IContributor> approvers, IWorkItem workItem, IWorkItemClient workitemClient, Logger log)
throws TeamRepositoryException, IOException {
log.info("createApprovals Entry");
IWorkItemWorkingCopyManager mgr = workitemClient.getWorkItemWorkingCopyManager();
mgr.connect(workItem, IWorkItem.FULL_PROFILE, null);
WorkItemWorkingCopy copy = mgr.getWorkingCopy(workItem);
IApprovals approvals = copy.getWorkItem().getApprovals();
// Create the Descriptor
IApprovalDescriptor approvalDescriptor = approvals.createDescriptor(approvalType, description);
if (dueDate != null ) {
log.info("Due Date is "+dueDate.toString());
approvalDescriptor.setDueDate(dueDate);
}
// Then add the approvals
IApproval approval = null;
for (int i = 0; i < approvers.size(); i++) {
log.info("Adding approver "+(approvers.get(i)).getUserId());
approval = approvals.createApproval(approvalDescriptor, approvers.get(i));
approvals.add(approval);
}
copy.save(null);
mgr.disconnect(workItem);
log.info("createApprovals Exit");
}
public static ICategory createCategory(ITeamRepository repo, IProjectArea projectArea, String categoryName,
IProgressMonitor monitor, Logger log)
throws TeamRepositoryException {
IWorkItemClient workItemClient = (IWorkItemClient) repo.getClientLibrary(IWorkItemClient.class);
ICategory category = workItemClient.createCategory(projectArea, categoryName, monitor);
return workItemClient.saveCategory(category, monitor);
}
public static IDevelopmentLine createDevelopmentLine (IProjectArea projectArea, String tlName, String tlId,
IProcessItemService processItem, IProgressMonitor monitor, Logger log)
throws TeamRepositoryException, IOException {
log.info("createDevelopmentLine Entry");
projectArea = (IProjectArea) processItem.getMutableCopy(projectArea);
IDevelopmentLine newTimeline = (IDevelopmentLine) IDevelopmentLine.ITEM_TYPE.createItem();
newTimeline.setName(tlName);
newTimeline.setId(tlId);
newTimeline.setProjectArea(projectArea);
projectArea.addDevelopmentLine(newTimeline);
log.info("Saving development line with Id " + tlId + " ...");
processItem.save(new IProcessItem[] {(IProcessItem) projectArea, newTimeline }, monitor);
log.info("createDevelopmentLine Exit");
return (newTimeline);
}
public static ICategory createSubCategory(ITeamRepository repo, ICategoryHandle parentCategory, String categoryName,
IProgressMonitor monitor, Logger log)
throws TeamRepositoryException {
IWorkItemClient workItemClient = (IWorkItemClient) repo.getClientLibrary(IWorkItemClient.class);
ICategory category = workItemClient.createSubcategory(parentCategory, categoryName, monitor);
return workItemClient.saveCategory(category, monitor);
}
public static IFileItem createFileItem(String name, IFolder parentFolder)
throws TeamRepositoryException {
IFileItem aFile = (IFileItem) IFileItem.ITEM_TYPE.createItem();
aFile.setParent(parentFolder);
aFile.setName(name);
String binFile = "(.\.(zip|gzip|7z|bar|jar|war|doc|docx|xls|xlsx|class|exe|jpeg|jpg|png)$)";
Pattern pattern = Pattern.compile(binFile);
Matcher matcher = pattern.matcher(name);
if (matcher.matches()) {
aFile.setContentType(IFileItem.CONTENT_TYPE_UNKNOWN);
}
else {
aFile.setContentType(IFileItem.CONTENT_TYPE_TEXT);
}
aFile.setFileTimestamp(new Date());
return aFile;
}
public static IFolder createFolder(String folderName, IFolder parent, IWorkspaceConnection repoWorkspace, IChangeSetHandle csHdl,
IProgressMonitor monitor, Logger log)
throws TeamRepositoryException {
IFolder newFolder = (IFolder) IFolder.ITEM_TYPE.createItem();
newFolder.setParent(parent);
newFolder.setName(folderName);
repoWorkspace.commit(csHdl, Collections.singletonList(repoWorkspace
.configurationOpFactory().save(newFolder)), monitor);
return newFolder;
}
public static IIteration createIteration (ITeamRepository repo, IDevelopmentLine timeline, IIteration parent, String itName, String itId,
Date startDate, Date endDate, IProcessItemService processItem, IProgressMonitor monitor, Logger log)
throws TeamRepositoryException, IOException {
log.info("createIteration Entry");
IIteration newIteration = (IIteration) IIteration.ITEM_TYPE.createItem();
newIteration.setName(itName);
newIteration.setId(itId);
newIteration.setHasDeliverable(true);
if (startDate != null) {
newIteration.setStartDate(startDate);
}
if (endDate != null) {
newIteration.setEndDate(endDate);
}
IDevelopmentLine line = (IDevelopmentLine) timeline.getWorkingCopy();
newIteration.setDevelopmentLine(line);
if (parent == null) {
log.info("Saving iteration with Id " + itId + " ...");
line.addIteration((IIterationHandle) newIteration.getItemHandle());
processItem.save(new IProcessItem[] { line, newIteration }, monitor);
}
else {
log.info("Saving child iteration with Id " + itId + " and parent iteration Id "+parent.getId());
parent = (IIteration) parent.getWorkingCopy();
parent.addChild((IIterationHandle) newIteration.getItemHandle());
newIteration.setParent((IIterationHandle) parent.getItemHandle());
processItem.save(new IProcessItem[] { line, parent, newIteration }, monitor);
}
log.info("createIteration Exit");
return(getIteration(repo, timeline, itId, monitor, log));
}
public static IIterationPlanRecord createIterationPlan (ITeamRepository repo, IProjectArea projectArea, String planName, IIteration planIteration, String planType,
IProcessArea planTeam, IContributor creator, Logger log)
throws TeamRepositoryException, UnsupportedEncodingException, IOException {
log.info("createPlan Entry");
// get classes for plan creation
IAuditableCommon audit = (IAuditableCommon) repo.getClientLibrary(IAuditableCommon.class);
IIterationPlanService planService = (IIterationPlanService)((IClientLibraryContext) repo).getServiceInterface(IIterationPlanService.class);
// create necessary plan items
IIterationPlanRecord plan = (IIterationPlanRecord) IIterationPlanRecord.ITEM_TYPE.createItem();
IWikiPage wiki = (IWikiPage) IWikiPage.ITEM_TYPE.createItem();
// setup plan values
plan.setName(planName);
plan.setIteration(planIteration);
plan.setPlanType(planType);
plan.setOwner(planTeam);
// setup wiki page
wiki.setName("");
wiki.setWikiID(IIterationPlanRecord.OVERVIEW_PAGE_ID);
wiki.setCreator(creator);
wiki.setOwner(plan);
String encoding = "UTF8";
String xmlText = "";
byte[] bytes = xmlText.getBytes(encoding);
InputStream inputStream = new ByteArrayInputStream(bytes);
wiki.setContent(audit.storeContent(IContent.CONTENT_TYPE_TEXT, encoding, inputStream, bytes.length, null));
IProcessAreaHandle paHandle = (IProcessAreaHandle) projectArea.getItemHandle();
// save plan
DTO_IterationPlanSaveResult saveResult = planService.save(paHandle, plan, wiki);
if (saveResult.isSetIterationPlanRecord() == false) {
throw new TeamRepositoryException("Saving Plan failed!");
}
log.info("createPlan Exit");
return(plan);
}
public static IWorkItem createWorkItem(ITeamRepository repo, IProjectAreaHandle paHdl,
String wiType, String wiSummary, String categoryName,
String timelineId, String iterationId, ArrayList<String> attribIds, ArrayList<Object> attribObjs, IWorkItem parent,
IProgressMonitor monitor, Logger log) throws TeamRepositoryException, IOException {
// The minimum we need to create a work item is:
// Type
// Summary
// Timeline + Iteration (Planned For)
// Category (Filed Against)
//
log.info("createWorkItem Entry");
IWorkItemClient wiClientSvc = (IWorkItemClient) repo.getClientLibrary(IWorkItemClient.class);
IWorkItemCommon wiCommonSvc = (IWorkItemCommon) repo.getClientLibrary(IWorkItemCommon.class);
IWorkItemType workItemType = wiClientSvc.findWorkItemType(paHdl, wiType, monitor);
if (workItemType == null) {
throw new TeamRepositoryException("ERROR - work item type \'" + wiType + "\' unknown");
}
// Create the work item
IWorkItemHandle handle = wiClientSvc.getWorkItemWorkingCopyManager().connectNew(workItemType, monitor);
WorkItemWorkingCopy wc = wiClientSvc.getWorkItemWorkingCopyManager().getWorkingCopy(handle);
IWorkItem workItem = wc.getWorkItem();
ICategoryHandle categoryHdl = null;
IProjectArea projectArea = (IProjectArea) repo.itemManager().fetchCompleteItem(paHdl, IItemManager.REFRESH, null);
try {
// Creator
workItem.setCreator(repo.loggedInContributor());
log.info("Getting handle for workitem category " + categoryName);
// Get our category handle
List <String> catList = new ArrayList<String>();
catList.add(0, categoryName);
categoryHdl = wiClientSvc.findCategoryByNamePath(paHdl, catList, monitor);
if (categoryHdl == null) {
log.info("Category " + categoryName + " was NOT found");
throw new TeamRepositoryException("Category " + categoryName + " was NOT found");
}
// Filed Against
workItem.setCategory(categoryHdl);
IDevelopmentLine timeline = Common.getDevelopmentLine (repo, projectArea, timelineId, monitor, log);
if (timeline == null) {
throw new TeamRepositoryException("Could not find timeline with Id " + timelineId);
}
IIteration iter = Common.getIteration (repo, timeline, iterationId, monitor, log);
if (iter == null) {
throw new TeamRepositoryException("Could not find iteration with Id " + iterationId);
}
// Planned For
IAttribute attrib = wiCommonSvc.findAttribute(paHdl, WorkItemAttributes.PLANNED_FOR, monitor);
if (attrib == null) {
throw new TeamRepositoryException("Could not find attribute PLANNED_FOR");
}
workItem.setValue(attrib, iter);
// Summary
workItem.setHTMLSummary(XMLString.createFromPlainText(wiSummary));
// Set remaining attributes
IAttributeHandle attrHdl = null;
Identifier literalID = null;
for (int i = 0; i < attribIds.size(); i++) {
log.info("Setting remaining attrib with Id " + attribIds.get(i));
switch (attribIds.get(i)) {
case "owner":
if (attribObjs.get(i) == null) {
log.info("WARNING - Unknown user so unable to set Owner.");
}
else {
workItem.setOwner((IContributorHandle) attribObjs.get(i));
}
break;
case "description":
workItem.setHTMLDescription(XMLString.createFromPlainText(attribObjs.get(i).toString()));
break;
case "com.nbs.workitem.attribute.domain":
// Enumeration so we need to find the literalId for this value
attrib = wiCommonSvc.findAttribute(paHdl, "com.nbs.workitem.attribute.domain", monitor);
if (attrib == null) {
throw new TeamRepositoryException("Could not find attribute with Id \'com.nbs.workitem.attribute.domain\'");
}
attrHdl = (IAttributeHandle) attrib.getItemHandle();
literalID = getLiteralEqualsString((String) attribObjs.get(i),
attrHdl, repo, log);
if (literalID == null) {
throw new TeamRepositoryException("Could not find literal ID for " + (String) attribObjs.get(i));
}
log.info("Literal ID for this attribute is " + literalID.toString());
workItem.setValue(attrib, literalID);
break;
case "com.nbs.workitem.attribute.design_document":
// Enumeration so we need to find the literalId for this value
attrib = wiCommonSvc.findAttribute(paHdl, "com.nbs.workitem.attribute.design_document", monitor);
if (attrib == null) {
throw new TeamRepositoryException("Could not find attribute with Id \'com.nbs.workitem.attribute.design_document\'");
}
attrHdl = (IAttributeHandle) attrib.getItemHandle();
literalID = getLiteralEqualsString((String) attribObjs.get(i),
attrHdl, repo, log);
if (literalID == null) {
throw new TeamRepositoryException("Could not find literal ID for " + (String) attribObjs.get(i));
}
log.info("Literal ID for this attribute is " + literalID.toString());
workItem.setValue(attrib, literalID);
break;
case "com.nbs.workitem.attribute.project_code":
attrib = wiCommonSvc.findAttribute(paHdl, attribIds.get(i), monitor);
workItem.setValue(attrib, (String) attribObjs.get(i));
break;
default:
throw new TeamRepositoryException("Attribute type of \'" + attribIds.get(i) + "\' is not yet catered for");
}
}
if (parent != null) {
// Create a link between the parent work item and the new, child, work item
log.info("Creating link to parent work item");
IWorkItemHandle parentHdl = (IWorkItemHandle) parent.getItemHandle();
IItemReference reference = IReferenceFactory.INSTANCE.createReferenceToItem(parentHdl);
wc.getReferences().add(WorkItemEndPoints.PARENT_WORK_ITEM, reference);
}
IDetailedStatus s = wc.save(null);
if(! s.isOK()) {
throw new TeamRepositoryException("Error saving work item", s.getException());
}
} finally {
wiClientSvc.getWorkItemWorkingCopyManager().disconnect(workItem);
}
workItem = (IWorkItem) repo.itemManager().fetchCompleteItem(workItem, IItemManager.DEFAULT, monitor);
monitor.subTask("Created work item with Id: " + workItem.getId());
log.info("Created work item with Id: " + workItem.getId());
log.info("createWorkItem Exit");
return workItem;
}
public static void createWorkItemChangeSetLink(ITeamRepository teamRepository, IWorkItemHandle[] workItemHandles,
IChangeSetHandle changeSetHandle, Logger log)
throws TeamRepositoryException {
IFileSystemWorkItemManager workItemManager = (IFileSystemWorkItemManager) teamRepository.getClientLibrary(
IFileSystemWorkItemManager.class);
workItemManager.createLink(null, changeSetHandle, workItemHandles,
null);
}
public static boolean deleteDirectory(File dir, Logger log)
throws IOException {
if (dir.isDirectory()) {
File[] children = dir.listFiles();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDirectory(children[i], log);
if (!success) {
return false;
}
}
}
// either file or an empty directory
log.info("removing file or directory : " + dir.getName());
return dir.delete();
}
public static Object getCellValue(Cell cell) {
switch (cell.getCellTypeEnum()) {
case STRING :
return cell.getStringCellValue();
case BOOLEAN:
return cell.getBooleanCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)){
return cell.getDateCellValue();
}
else {
return cell.getNumericCellValue();
}
}
return null;
}
public static IIteration getChildIteration (ITeamRepository repo, IIterationHandle iterHdl, String itId,
IProgressMonitor monitor, Logger log)
throws TeamRepositoryException, IOException {
log.info("getChildIteration Entry - looking for Iteration with ID "+itId);
IIteration iter = (IIteration) repo.itemManager().fetchCompleteItem(iterHdl, 0, monitor);
// log.info("\t\tIterationId: " + iter.getId());
if (iter.getId().trim().equals(itId)) {
log.info("getChildIteration Exit - returning iteration");
return iter;
}
else {
// log.info("getChildIteration - checking for children");
IIterationHandle[] childIterHdls = iter.getChildren();
if (childIterHdls.length > 0) {
for (int i = 0; i < childIterHdls.length; i++) {
IIteration childIter = getChildIteration(repo, childIterHdls[i], itId, monitor, log);
if ((childIter != null) && (childIter.getId().trim().equals(itId))) {
log.info("getIteration Exit - returning child iteration");
return childIter;
}
}
}
}
log.info("getChildIteration Exit");
return null;
}
public static String getContentTypeByFileName(String fileName) {
String extension = FilenameUtils.getExtension(fileName);
switch (extension) {
// MS Office stuff
case "doc": return("application/msword");
case "dot": return("application/msword");
case "docx": return("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
case "dotx": return("application/vnd.openxmlformats-officedocument.wordprocessingml.template");
case "docm": return("application/vnd.ms-word.document.macroEnabled.12");
case "dotm": return("application/vnd.ms-word.template.macroEnabled.12");
case "xls": return("application/vnd.ms-excel");
case "xlt": return("application/vnd.ms-excel");
case "xla": return("application/vnd.ms-excel");
case "xlsx": return("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
case "xltx": return("application/vnd.openxmlformats-officedocument.spreadsheetml.template");
case "xlsm": return("application/vnd.ms-excel.sheet.macroEnabled.12");
case "xltm": return("application/vnd.ms-excel.template.macroEnabled.12");
case "xlam": return("application/vnd.ms-excel.addin.macroEnabled.12");
case "xlsb": return("application/vnd.ms-excel.sheet.binary.macroEnabled.12");
case "ppt": return("application/vnd.ms-powerpoint");
case "pot": return("application/vnd.ms-powerpoint");
case "pps": return("application/vnd.ms-powerpoint");
case "ppa": return("application/vnd.ms-powerpoint");
case "pptx": return("application/vnd.openxmlformats-officedocument.presentationml.presentation");
case "potx": return("application/vnd.openxmlformats-officedocument.presentationml.template");
case "ppsx": return("application/vnd.openxmlformats-officedocument.presentationml.slideshow");
case "ppam": return("application/vnd.ms-powerpoint.addin.macroEnabled.12");
case "pptm": return("application/vnd.ms-powerpoint.presentation.macroEnabled.12");
case "potm": return("application/vnd.ms-powerpoint.template.macroEnabled.12");
case "ppsm": return("application/vnd.ms-powerpoint.slideshow.macroEnabled.12");
}
FileNameMap mimeTypes = URLConnection.getFileNameMap();
String contentType = "";
contentType = mimeTypes.getContentTypeFor(fileName);
if (contentType == null || contentType.isEmpty()) {
contentType = "content type unknown";
}
return contentType;
}
public static IContributor getContributorById (ITeamRepository repo, String userId, Boolean externalRegistry,
IProgressMonitor monitor, Logger log)
throws TeamRepositoryException, IOException {
log.info("getContributorById Entry");
userId = userId.toUpperCase(); // Most userIds are uc so try that first
if ((userId == null) || (userId.trim().equalsIgnoreCase(""))) {
log.info("WARNING - No userId supplied. getContributorById Exit");
return null;
}
// Check the user is in the repository and report if not
try {
IContributor user = repo.contributorManager().fetchContributorByUserId(userId, monitor);
log.info("getContributorById Exit");
return user;
}
catch (com.ibm.team.repository.common.ItemNotFoundException e) {
log.info("WARNING - User with ID \'" + userId + "\' does NOT exist in the repository.");
}
// A small number of users have lower case IDs. Check this just in case ....
try {
log.info("Try again with userId in lower case");
IContributor user = repo.contributorManager().fetchContributorByUserId(userId.toLowerCase(), monitor);
log.info("getContributorById Exit");
return user;
}
catch (com.ibm.team.repository.common.ItemNotFoundException e) {
}
if (!externalRegistry) {
log.info("getContributorById Exit");
return null;
}
//Get the ExternalUser Registry and retrieve the required user
log.info("looking in the external registry");
IExternalUserRegistryManager externalUserRegMgr = repo.externalUserRegistryManager();
try {
IExternalUser exUser = null;
exUser = externalUserRegMgr.fetchUser(userId.toUpperCase(), monitor);
//Once User is found in ExternalUser Registry import it
if (exUser == null) {
log.info("WARNING - User doesn't exist in ExternalUser Registry so cannot be imported");
log.info("getContributorById Exit");
return null;
}
// Create user, set its attributes from the external user then save it
IContributor user = (IContributor) IContributor.ITEM_TYPE.createItem();
user.setEmailAddress(exUser.getEmailAddresses().get(0));
user.setName(exUser.getFullNames().get(0));
user.setUserId(exUser.getUserId());
user.setArchived(false);
user = repo.contributorManager().saveContributor(user, null);
log.info("getContributorById Exit");
return user;
}
catch (UnknownUserException e) {
log.info("WARNING - User doesn't exist in ExternalUser Registry so cannot be imported");
log.info("getContributorById Exit");
return null;
}
}
public static List<IContributor> getContributorByName(ITeamRepository repo, String userName,
IProgressMonitor monitor, Logger log)
throws TeamRepositoryException, IOException {
log.info("getContributorByName Entry");
// Create a query for the ContributorQueryModel
final IItemQuery query = IItemQuery.FACTORY.newInstance(ContributorQueryModel.ROOT);
// Create a predicate with a parameter to search for name property
final IPredicate predicate = ContributorQueryModel.ROOT.name()._eq(query.newStringArg());
// Use the predicate as query filter
final IItemQuery filtered = (IItemQuery) query.filter(predicate);
// Get the query service. This is a cast to an internal class. Note TeamRepository and not ITeamRepository is casted.
final IQueryService qs = ((TeamRepository) repo).getQueryService();
// Run this ItemQuery. Note, there are also other types of queries qs.queryData(dataQuery, parameters, pageSize)
final IItemQueryPage page = qs.queryItems(filtered, new Object[] { userName }, IQueryService.DATA_QUERY_MAX_PAGE_SIZE);
// Finding users by name can return multiple users. We return all of them and let the
// caller decide what to do.
// Get the item handles if any
final List<?> handles = page.getItemHandles();
List<IContributor> contributors = new ArrayList <IContributor>();
log.info("Hits: " + handles.size());
if (!handles.isEmpty()) {
log.info("Found user.");
// Resolve and print the information to the contributor object.
final IContributorHandle handle = (IContributorHandle) handles.get(0);
IContributor foundContributor = (IContributor) repo.itemManager().fetchCompleteItem(handle, IItemManager.DEFAULT, monitor);
contributors.add(foundContributor);
}
log.info("getContributorByName Exit");
return contributors;
}
public static Timestamp getDateFromGovernanceIteration (String iterName, Logger log)
throws TeamRepositoryException, IOException {
// Iteration name has fixed format of 'AAA dd <month> yyyy'.
// We need it expressed as 'yyyy-mm-dd hh:mm:ss' for the Timestamp method
String delimiter = " ";
String[] parts;
parts = iterName.split(delimiter);
String month;
switch (parts[2]) {
case "January":
month = "01";
break;
case "February":
month = "02";
break;
case "March":
month = "03";
break;
case "April":
month = "04";
break;
case "May":
month = "05";
break;
case "June":
month = "06";
break;
case "July":
month = "07";
break;
case "August":
month = "08";
break;
case "September":
month = "09";
break;
case "October":
month = "10";
break;
case "November":
month = "11";
break;
case "December":
month = "12";
break;
default:
log.info("Unknown or wrongly formatted \'month\' text: "+parts[2]);
throw new TeamRepositoryException ("Unknown or wrongly formatted \'month\' text: "+parts[2]+"\n");
}
String iterDate = parts[3] + "-" + month + "-" + parts[1] + " 12:00:00";
log.info("Date from iteration name: "+iterDate);
return (Timestamp.valueOf(iterDate));
}
public static IDevelopmentLine getDevelopmentLine (ITeamRepository repo, IProjectArea projectArea, String tlId,
IProgressMonitor monitor, Logger log)
throws TeamRepositoryException, IOException {
log.info("getDevelopmentLine Entry");
IDevelopmentLineHandle[] developmentLineHandles = projectArea.getDevelopmentLines();
if (developmentLineHandles == null) {
throw new TeamRepositoryException("Cannot find a development line\n");
}
List developmentLines = repo.itemManager().fetchCompleteItems(Arrays.asList(developmentLineHandles),
IItemManager.DEFAULT, new SubProgressMonitor(monitor, 500));
// For each timeline
for (Iterator e = developmentLines.iterator(); e.hasNext();) {
IDevelopmentLine line = (IDevelopmentLine) e.next();
// if the timeline exists
if (line.getId().trim().equals(tlId)) {
log.info("getDevelopmentLine Exit - returning timeline");
return line;
}
}
log.info("getDevelopmentLine Exit");
return null;
}
public static ByteArrayOutputStream getFileData(File f)
throws IOException {
ByteArrayOutputStream contents = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(f);
byte[] buf = new byte[2048];
int read;
while ((read = fis.read(buf)) != -1) {
contents.write(buf, 0, read);
}
contents.flush();
return contents;
}
public static File getFileFromSharepoint(String user, String pwd, String source, String target, Logger log)
throws IOException, Exception {
log.info("getFileFromSharepoint Entry");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new NTCredentials(user, pwd, "", ""));
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider)
.build();
String getFile = source.replaceAll(" ", "%20");
HttpGet request = new HttpGet(getFile);
CloseableHttpResponse response = null;
log.info("Executing the GET");
response = httpclient.execute(request);
int rc = response.getStatusLine().getStatusCode();
log.info("GET response: " + response.getStatusLine().toString());
File f;
File ff;
if (rc == HttpStatus.SC_OK) {
log.info("Writing "+ source + " to " + target);
f = new File(source);
ff = new File(target, f.getName().replaceAll("%20", " ")); // target
log.info("Getting the response entity");
HttpEntity entity = response.getEntity();
if (entity == null) {
log.info("No response entity returned");
throw new Exception("No response entity returned");
}
// writing the byte array into a file using Apache Commons IO
FileUtils.writeByteArrayToFile(ff, EntityUtils.toByteArray(entity));
}
else {
String reason = response.getStatusLine().getReasonPhrase();
log.info("Problem while receiving " + source + " reason: "
+ reason + " httpcode: " + rc);
throw new Exception("Problem while receiving " + source + " reason: "
+ reason + " httpcode: " + rc);
}
response.close();
log.info("getFileFromSharepoint Exit");
return (ff);
}
public static IIteration getIteration (ITeamRepository repo, IDevelopmentLine line, String itId,
IProgressMonitor monitor, Logger log)
throws TeamRepositoryException, IOException {
// Recurse through the Iteration tree to find the Iteration - we assume iteration IDs are unique
log.info("getIteration Entry - looking for Iteration with ID "+itId);
// for each iteration
for (IIterationHandle iteration : line.getIterations()) {
IIteration iter = (IIteration) repo.itemManager().fetchCompleteItem(iteration, 0, monitor);
// log.info("\t\tIterationId: " + iter.getId() + ");
// If the iteration exists
if (iter.getId().trim().equals(itId)) {
log.info("Found iteration. getIteration Exit - returning iteration");
return iter;
}
else { // If there are child iterations process them and any of their children
// log.info("getIteration - checking for children);
IIterationHandle[] childIterHdls = iter.getChildren();
if (childIterHdls.length > 0) {
for (int i = 0; i < childIterHdls.length; i++) {
IIteration childIter = getChildIteration(repo, childIterHdls[i], itId, monitor, log);
if ((childIter != null) && (childIter.getId().trim().equals(itId))) {
log.info("Found child iteration. getIteration Exit - returning child iteration");
return childIter;
}
}
}
}
}
log.info("Did not find iteration. getIteration Exit");
return null;
}
public static IIterationPlanRecord getIterationPlanRecord (ITeamRepository repo, String planName, Logger log)
throws TeamRepositoryException, IOException {
log.info("getIterationPlanRecord Entry. Looking for Plan \'"+planName+"\'");
IIterationPlanClient planClient = (IIterationPlanClient) repo.getClientLibrary(IIterationPlanClient.class);
IAuditableClient auditableClient = (IAuditableClient) repo.getClientLibrary(IAuditableClient.class);
List<IIterationPlanRecordHandle> phandles = ((IterationPlanClient) planClient)
.fetchAllIterationPlans(ItemProfile.ITERATION_DEFAULT, null);
List<IAuditable> itall = auditableClient.fetchCurrentAuditables(
phandles,
ItemProfile.createFullProfile(IIterationPlanRecord.ITEM_TYPE),
null);
int i; for (i = itall.size() - 1; i >= 0; i--) { // Loop from last to first
IIterationPlanRecord ipr = (IIterationPlanRecord) itall.get(i);
String thisPlan = ipr.getName();
if (thisPlan.equalsIgnoreCase(planName)) {
log.info("Found the plan. getIterationPlanRecord Exit");
return (ipr);
}
}
log.info("Did not find the plan. getIterationPlanRecord Exit");
return (null);
}
public static Identifier getLiteralEqualsString(String name, IAttributeHandle ia, ITeamRepository repo, Logger log)
throws TeamRepositoryException, IOException {
log.info("getLiteralEqualsString Entry. Looking for " + name);
IWorkItemClient workItemClient = (IWorkItemClient) repo.getClientLibrary(IWorkItemClient.class);
Identifier literalID = null;
IEnumeration enumeration = workItemClient.resolveEnumeration(ia, null); // or IWorkitemCommon
List literals = enumeration.getEnumerationLiterals();
log.info("This enumeration returned " + literals.size() + " literals");
for (Iterator iterator = literals.iterator(); iterator.hasNext();) {
ILiteral iLiteral = (ILiteral) iterator.next();
log.info("\tLiteral Name: " + iLiteral.getName());
if (iLiteral.getName().equals(name)) {
literalID = iLiteral.getIdentifier2();
break;
}
}
log.info("getLiteralEqualsString Exit");
return literalID;
}
public static IIteration getPlanIteration (ITeamRepository repo, String planName, Logger log)
throws TeamRepositoryException, IOException {
log.info("getPlanIteration Entry. Looking for Plan \'"+planName+"\'");
IIteration iter = null;
IIterationPlanClient planClient = (IIterationPlanClient) repo.getClientLibrary(IIterationPlanClient.class);
IAuditableClient auditableClient = (IAuditableClient) repo.getClientLibrary(IAuditableClient.class);
IProgressMonitor monitor = new NullProgressMonitor();
List<IIterationPlanRecordHandle> phandles = ((IterationPlanClient) planClient)
.fetchAllIterationPlans(ItemProfile.ITERATION_DEFAULT, null);
List<IAuditable> itall = auditableClient.fetchCurrentAuditables(
phandles,
ItemProfile.createFullProfile(IIterationPlanRecord.ITEM_TYPE),
null);
int i; for (i = itall.size() - 1; i >= 0; i--) { // Loop from last to first
IIterationPlanRecord ipr = (IIterationPlanRecord) itall.get(i);
String thisPlan = ipr.getName();
log.info("Plan Name: "+thisPlan);
if (thisPlan.equalsIgnoreCase(planName)) {
iter = (IIteration) repo.itemManager().fetchCompleteItem(ipr.getIteration(), 0, monitor);
i = -1;
}
}
log.info("getPlanIteration Exit");
return (iter);
}
public static IQueryResult<IResolvedResult<IWorkItem>> getResultsResolvedByExpression(
ITeamRepository teamRepository, IProjectAreaHandle projectArea,
Expression expression, ItemProfile<IWorkItem> profile)
throws TeamRepositoryException {
IWorkItemClient workItemClient = (IWorkItemClient) teamRepository
.getClientLibrary(IWorkItemClient.class);
IQueryClient queryClient = workItemClient.getQueryClient();
IQueryResult<IResolvedResult<IWorkItem>> results = queryClient.
getResolvedExpressionResults(projectArea, expression, profile);
return results;
}
public static IQueryResult getResultsUnresolvedByExpression(
ITeamRepository teamRepository, IProjectAreaHandle projectArea,
Expression expression) throws TeamRepositoryException {
IWorkItemClient workItemClient = (IWorkItemClient) teamRepository
.getClientLibrary(IWorkItemClient.class);
IQueryClient queryClient = workItemClient.getQueryClient();
IQueryResult results = queryClient.getExpressionResults(
projectArea, expression);
return results;
}
public static Workbook getWorkbook(FileInputStream inputStream, String excelFilePath)
throws IOException {
Workbook workbook = null;
if (excelFilePath.endsWith("xlsx")) {
workbook = new XSSFWorkbook(inputStream);
} else if (excelFilePath.endsWith("xls")) {
workbook = new HSSFWorkbook(inputStream);
} else {
throw new IllegalArgumentException("The specified file is not an Excel file");
}
return workbook;
}
public static IWorkItem getWorkItemById(ITeamRepository repo, IProjectArea projArea, String workItemId, Logger log)
throws TeamRepositoryException, IOException {
// HAVEN'T TESTED THIS YET ****
log.info("getWorkItemById Entry");
IAuditableClient auditableClient = (IAuditableClient)repo.getClientLibrary(IAuditableClient.class);
IQueryClient queryClient = (IQueryClient) repo.getClientLibrary(IQueryClient.class);
final IQueryableAttributeFactory factory = QueryableAttributes.getFactory(IWorkItem.ITEM_TYPE);
final IQueryableAttribute attributeID = factory.findAttribute(projArea,"id", auditableClient, null);
final Expression attributeExpression = new AttributeExpression(attributeID, AttributeOperation.EQUALS, workItemId);
final IQueryableAttribute att = factory.findAttribute(projArea,IWorkItem.PROJECT_AREA_PROPERTY, auditableClient, null);
final Expression expression = new AttributeExpression(att,AttributeOperation.EQUALS, projArea);
final Term term = new Term(Operator.AND);
term.add(expression);
final Term term2 = new Term(Operator.AND);
term2.add(attributeExpression);
term.add(term2);
final IQueryResult<IResolvedResult<IWorkItem>> result = queryClient.getResolvedExpressionResults(projArea, term, IWorkItem.DEFAULT_PROFILE);
if (result.hasNext(null)) {
final IResolvedResult<IWorkItem> resolved = result.next(null);
log.info("getWorkItemById Exiting after success");
return resolved.getItem();
}
log.info("getWorkItemById Exit");
return null;
}
public static WorkItemWorkingCopy getWorkItemWorkingCopy(IWorkItem workItem) throws TeamRepositoryException {
IWorkItemClient workItemClient = (IWorkItemClient) ((ITeamRepository)workItem.getOrigin()).getClientLibrary(IWorkItemClient.class);
IWorkItemWorkingCopyManager mgr = workItemClient.getWorkItemWorkingCopyManager();
mgr.connect(workItem, IWorkItem.FULL_PROFILE, null);
return(mgr.getWorkingCopy(workItem));
}
public static void sendMail (String to, String cc, String from, String server, String subject,
String body, List<String> fileAttachments, Logger log)
throws MessagingException, IOException {
log.info("sendMail Entry");
// Get system properties
Properties properties = System.getProperties();
// Setup mail server
properties.setProperty("mail.smtp.host", server);
// Get the default Session object.
Session session = Session.getDefaultInstance(properties);
// Create a default MimeMessage object.
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
StringTokenizer st = new StringTokenizer(to,";");
while(st.hasMoreTokens()) {
message.addRecipients(Message.RecipientType.TO, InternetAddress.parse(st.nextToken(), false));
}
if (cc != null) {
StringTokenizer st2 = new StringTokenizer(cc,";");
while(st2.hasMoreTokens()) {
message.addRecipients(Message.RecipientType.CC, InternetAddress.parse(st2.nextToken(),false));
}
}
message.setSubject(subject);
// Create the message body
BodyPart messageBodyPart = new MimeBodyPart();
// Fill the body
messageBodyPart.setText(body);
// Create a multipart message
Multipart multipart = new MimeMultipart();
// Set text message part
multipart.addBodyPart(messageBodyPart);
String delimiter = "/";
String[] parts;
// Add the file attachments
if (fileAttachments != null) {
for (int i = 0; i < fileAttachments.size(); i++) {
log.info("Attaching File "+fileAttachments.get(i));
DataSource source = new FileDataSource(fileAttachments.get(i));
messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler(source));
parts = fileAttachments.get(i).split(delimiter);
messageBodyPart.setFileName(parts[parts.length -1]);
multipart.addBodyPart(messageBodyPart);
}
}
// Send the complete message parts
message.setContent(multipart);
// Send message
log.info("Sending the email");
Transport.send(message);
log.info("sendMail Exit");
}
}
|
What I would suggest is filing an RFE within the RFE Community of which you could reference the information provided by Kot:
The reason that the RFE's on Jazz.net have probably been open since 2009 is that there is no SLA associated to Jazz.net items. If you file the RFE through the RFE community there is a SLA that they would need to provide a answer if it will be included or not by 90 days I believe. RFE Community https://www.ibm.com/developerworks/rfe/?BRAND_ID=1 |
Yes, email reader is a offering from an IBM partner which we have been running in production for 6 years
We now also use email sender which allows to generate emails from the Work Item |
There are still subsets of ClearQuest users that still refuse to adopt team concert without this email reader feature and won't accept the answer to pay for a vendor tool to do this. This is so common in many tool sets, yet IBM continues to ignore it's customer base. |
IBM themselves use a third-party offering but fortunately this isn't terribly difficult to write. I've done this recently and would be happy to share - it's 'work in progress' code and not the finished article, but what's there works.
I agree though that this should be a standard part of the product as it's pretty fundamental functionality.
Comments
Suresh Raman
commented Feb 13 '18, 11:35 a.m.
Cliff, if you don't mind, could you please share the solution.
|
And here's the other part, this time preformatted! package com.nbs.nsl.utility; Comments
Cliff Gardiner
commented Feb 22 '18, 5:09 a.m.
I forgot to mention that this is intended to run as a scheduled task on a server, Windows in our case. Extract as a runnable jar file, etc.
I hope this helps.
|
Your answer
Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.
Comments
Seems like it may have been in the cards originally but this functionality (or the desire to keep it) seems to have been removed.