Auto backup of process configuration XML source
We're working with process inheritance model, where the process configuration is maintained in a "Master Project Area" and the actual projects work on consuming project areas, which use the process from the Master PA.
To have a "recovery plan" from any unintentional changes to the process configuration on the consuming project areas (one must remember that any minor changes in the consuming PA results in broken inheritance), we need a method to backup the XML process configuration source of the consuming projects automatically (best preferred solution).
To develop this, we need a method to retrive this XML process configuration source fo a patricular Project Area.
regards
Madhan
Accepted answer
static String keyname = "com.ibm.team.internal.process.compiled.xml";
// get the project area
IProjectArea ip = projectList.get(i);
System.out.println("\nproject name = " + ip.getName());
// get the process data
@SuppressWarnings("unchecked")
Map<Object, Object> pd = ip.getProcessData();
// get the content Manager
IContentManager icm = repo.contentManager();
// get the process config content object
IContent processSource = (IContent) pd.get(keyname);
if (processSource != null)
{
System.out.println("have xml source");
saveXMLSource(ip, processSource, icm, sPm);
}
.
.
// save the process source for the project
private static void saveXMLSource(IProjectArea ip, IContent ic,
IContentManager icm, SysoutProgressMonitor sPm)
{
// make an output stream for the content manager
OutputStream os = new ByteArrayOutputStream();
// get the content of the content object.
try
{
icm.retrieveContent(ic, os, sPm);
// write xml content to file
// project name + data name
FileOutputStream fo = new FileOutputStream(ip.getName() + "."
+ keyname);
// write
fo.write(os.toString().getBytes(), 0, os.toString().length());
// close
fo.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
Comments
Perfect!
It works..
Thanks a lot... :)
Is it also possible to fetch via code (plain Java API) the History entries of a Project Area? Reason: I want to run a scheduled executable which checks into the History of the Project Area and notify (via Email) when there is an entry for "Process Configuration" change.
I have not looked into how to do this..
Hi Madhan/Sam,
3 other answers
Comments
The hint regarding the history view Eclipse client was helpfull..
Regarding the History view in web client, well because of the strange/unique display of the change content, its not readable/useable when we have ~3 to 5K lines of xml..
I'd expect the history is shown in two column layout with separate display for Old and New values, to be able to use it...
I am happy with the availability of all versions of the process configuration in the Eclipse client..
but some doubts in this regard..
1. Would it be possible to open the project area and recover this content from the Eclipse client in case the project area is messed up due to any mis-configurations?
2. Is there some possibility to add comments about the changes done to the process configuration? Would you recommend adding a comment in the header section of the xm itself? Or any other method possible?
here is the whole thing
package com.sd.tools;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import com.ibm.team.repository.client.IContentManager;
import com.ibm.team.repository.client.IItemManager;
import com.ibm.team.repository.client.ITeamRepository;
import com.ibm.team.repository.client.TeamPlatform;
import com.ibm.team.repository.common.IContent;
import com.ibm.team.repository.common.IItem;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.ibm.team.process.client.*;
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.IIterationType;
import com.ibm.team.process.common.IIterationTypeHandle;
import com.ibm.team.process.common.IProjectArea;
import com.ibm.team.process.common.IProjectAreaHandle;
import com.ibm.team.process.internal.common.IterationType;
import com.ibm.team.process.internal.common.ProjectArea;
//import com.ibm.team.process.internal.common.impl.ProjectAreaImpl;
public class GetProjectSource
{
/**
* key used to store project process configuration source
*/
static String keyname = "com.ibm.team.internal.process.compiled.xml";
@SuppressWarnings("restriction")
public static void main(String[] args)
{
String url = null; // repository address
String userid = null; // userid
String password = null; // password
String ProjectType = null; // * or name of project
String newProjectParent = null; // name of new process parent project,
// optional
if (args.length < 4)
{
System.out.println("Parameters are" +
"URL of repository\n" +
"Userid of Admin user\n" +
"Password of Admin user\n"+
"project scope\n" +
" * for all projects (save all project source)\n" +
" specific Name of project to locate\n" +
"\n" +
"optional:\n" +
" new parent project name"
);
return;
}
url = args[0];
userid = args[1];
password = args[2];
// under eclipse * parm sends in junk
ProjectType = args[3].equalsIgnoreCase("foo") ? "*" : args[3];
newProjectParent = args[4];
// startup the teamplatform runtime, if not already
if (!TeamPlatform.isStarted())
TeamPlatform.startup();
try
{
// create required Monitor
SysoutProgressMonitor sPm = new SysoutProgressMonitor();
// login
if (login(url, userid, password, sPm) != null)
{
// get the repository object where we are connecting
ITeamRepository repo = getRepository(url);
// get the list of projects
// * means all
// specific name means only that one.. case sensitive I think
List<IProjectArea> projectList = getProjectArea(repo, sPm,
ProjectType);
System.out.println(" there are " + projectList.size()
+ " projects");
// loop thru the list of projects, if any
for (int i = 0; i < projectList.size(); i++)
{
// get the project area
IProjectArea ip = projectList.get(i);
System.out.println("\nproject name = " + ip.getName());
// get the process data
@SuppressWarnings("unchecked")
Map<Object, Object> pd = ip.getProcessData();
// get the content Manager
IContentManager icm = repo.contentManager();
// get the process config content object
IContent processSource = (IContent) pd.get(keyname);
if (processSource != null)
{
System.out.println("have xml source");
saveXMLSource(ip, processSource, icm, sPm);
}
IProjectArea ipi = (IProjectArea) ip.getWorkingCopy();
// call the internal only method to get the parent process
// provider.. if any
IProjectAreaHandle iparenthandle = ((ProjectArea) ipi)
.getProcessProvider();
// if there was a parent
if (iparenthandle != null)
{
// get it
IProjectArea parentProject = (IProjectArea) (repo
.itemManager().fetchCompleteItem(iparenthandle,
IItemManager.DEFAULT, sPm));
System.out.println("have parent project name = "
+ parentProject.getName());
// if we are changing the parent
if (newProjectParent != null)
{
// find the new one
List<IProjectArea> plist = getProjectArea(repo,
sPm, newProjectParent);
// if we found it
if (plist.size() > 0)
{
// get its handle
IProjectAreaHandle newParentHandle = (IProjectAreaHandle) plist
.get(0);
// always checking
if (newParentHandle != null)
{
// set the provider field
((ProjectArea) ipi)
.setProcessProvider(newParentHandle);
// save the project area
getProcessItemService(repo).save(
(IProjectArea) ipi, sPm);
}
}
}
}
}
}
else
{
System.out.println("unable to logon to " + url + " as "
+ userid);
}
}
catch (Exception ex)
{
System.out.println("exception=" + ex.toString());
}
}
// save the process source for the project
private static void saveXMLSource(IProjectArea ip, IContent ic,
IContentManager icm, SysoutProgressMonitor sPm)
{
// make an output stream for the content manager
OutputStream os = new ByteArrayOutputStream();
// get the content of the content object.
try
{
icm.retrieveContent(ic, os, sPm);
// write xml content to file
// project name + data name
FileOutputStream fo = new FileOutputStream(ip.getName() + "."
+ keyname);
// write
fo.write(os.toString().getBytes(), 0, os.toString().length());
// close
fo.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
// login to the repository
public static ITeamRepository login(String url, final String userid,
final String password, IProgressMonitor monitor)
throws TeamRepositoryException
{
getRepository(url).registerLoginHandler(
new ITeamRepository.ILoginHandler()
{
public ILoginInfo challenge(ITeamRepository repository)
{
return new ILoginInfo()
{
public String getUserId()
{
return userid;
}
public String getPassword()
{
return password;
}
};
}
});
monitor.subTask("Contacting " + url);
getRepository(url).login(monitor);
monitor.subTask("Connected");
return getRepository(url);
}
// worker function repository
private static ITeamRepository repo1 = null;
private static ITeamRepository getRepository(String url)
{
if (repo1 == null)
{
repo1 = TeamPlatform.getTeamRepositoryService().getTeamRepository(
url);
}
return repo1;
}
// worker function process item service
private static IProcessItemService processitemservice = null;
private static IProcessItemService getProcessItemService(
ITeamRepository repo)
{
if (processitemservice == null)
{
processitemservice = (IProcessItemService) repo
.getClientLibrary(IProcessItemService.class);
}
return processitemservice;
}
public static List<IProjectArea> getProjectArea(ITeamRepository repo,
IProgressMonitor monitor, String projectAreaName)
throws TeamRepositoryException
{
List<IProjectArea> projectareaonly = new ArrayList<IProjectArea>();
@SuppressWarnings("unchecked")
// get all the projects in this repository
List<IProjectArea> projectAreas = getProcessItemService(repo)
.findAllProjectAreas(null, monitor);
// if Not ALL projects
if (!projectAreaName.equalsIgnoreCase("*"))
{
for (int i = 0; i < projectAreas.size(); i++)
{
// get next preoject from arraypackage com.sd.tools;
import java.io.ByteArrayOutputStream;
//import com.ibm.team.process.internal.common.impl.ProjectAreaImpl;
public class GetProjectSource
{
/**
* key used to store project process configuration source
*/
static String keyname = "com.ibm.team.internal.process.compiled.xml";
@SuppressWarnings("restriction")
public static void main(String[] args)
{
String url = null; // repository address
String userid = null; // userid
String password = null; // password
String ProjectType = null; // * or name of project
String newProjectParent = null; // name of new process parent project,
// optional
if (args.length < 4)
{
System.out.println("Parameters are" +
"URL of repository\n" +
"Userid of Admin user\n" +
"Password of Admin user\n"+
"project scope\n" +
" * for all projects (save all project source)\n" +
" specific Name of project to locate\n" +
"\n" +
"optional:\n" +
" new parent project name"
);
return;
}
url = args[0];
userid = args[1];
password = args[2];
// under eclipse * parm sends in junk
ProjectType = args[3].equalsIgnoreCase("foo") ? "*" : args[3];
newProjectParent = args[4];
// startup the teamplatform runtime, if not already
if (!TeamPlatform.isStarted())
TeamPlatform.startup();
try
{
// create required Monitor
SysoutProgressMonitor sPm = new SysoutProgressMonitor();
// login
if (login(url, userid, password, sPm) != null)
{
// get the repository object where we are connecting
ITeamRepository repo = getRepository(url);
// get the list of projects
// * means all
// specific name means only that one.. case sensitive I think
List<IProjectArea> projectList = getProjectArea(repo, sPm,
ProjectType);
System.out.println(" there are " + projectList.size()
+ " projects");
// loop thru the list of projects, if any
for (int i = 0; i < projectList.size(); i++)
{
// get the project area
IProjectArea ip = projectList.get(i);
//IDevelopmentLineHandle[] idl =ip.getDevelopmentLines();
//IIterationTypeHandle[] iii = ip.getIterationTypes();
System.out.println("\nproject name = " + ip.getName());
//IDevelopmentLine ixl =(IDevelopmentLine) idl[0].getFullState();
//IIterationHandle iih = ixl.getCurrentIteration();
//IIteration iif = (IIteration) iih.getFullState();
//IIterationHandle[] iip = ixl.getIterations();
// get the process data
@SuppressWarnings("unchecked")
Map<Object, Object> pd = ip.getProcessData();
// get the content Manager
IContentManager icm = repo.contentManager();
// get the process config content object
IContent processSource = (IContent) pd.get(keyname);
if (processSource != null)
{
System.out.println("have xml source");
saveXMLSource(ip, processSource, icm, sPm);
}
IProjectArea ipi = (IProjectArea) ip.getWorkingCopy();
// call the internal only method to get the parent process
// provider.. if any
IProjectAreaHandle iparenthandle = ((ProjectArea) ipi)
.getProcessProvider();
// if there was a parent
if (iparenthandle != null)
{
// get it
IProjectArea parentProject = (IProjectArea) (repo
.itemManager().fetchCompleteItem(iparenthandle,
IItemManager.DEFAULT, sPm));
System.out.println("have parent project name = "
+ parentProject.getName());
// if we are changing the parent
if (newProjectParent != null)
{
// find the new one
List<IProjectArea> plist = getProjectArea(repo,
sPm, newProjectParent);
// if we found it
if (plist.size() > 0)
{
// get its handle
IProjectAreaHandle newParentHandle = (IProjectAreaHandle) plist
.get(0);
// always checking
if (newParentHandle != null)
{
// set the provider field
((ProjectArea) ipi)
.setProcessProvider(newParentHandle);
// save the project area
getProcessItemService(repo).save(
(IProjectArea) ipi, sPm);
}
}
}
}
}
}
else
{
System.out.println("unable to logon to " + url + " as "
+ userid);
}
}
catch (Exception ex)
{
System.out.println("exception=" + ex.toString());
}
}
// save the process source for the project
private static void saveXMLSource(IProjectArea ip, IContent ic,
IContentManager icm, SysoutProgressMonitor sPm)
{
// make an output stream for the content manager
OutputStream os = new ByteArrayOutputStream();
// get the content of the content object.
try
{
icm.retrieveContent(ic, os, sPm);
// write xml content to file
// project name + data name
FileOutputStream fo = new FileOutputStream(ip.getName() + "."
+ keyname);
// write
fo.write(os.toString().getBytes(), 0, os.toString().length());
// close
fo.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
// login to the repository
public static ITeamRepository login(String url, final String userid,
final String password, IProgressMonitor monitor)
throws TeamRepositoryException
{
getRepository(url).registerLoginHandler(
new ITeamRepository.ILoginHandler()
{
public ILoginInfo challenge(ITeamRepository repository)
{
return new ILoginInfo()
{
public String getUserId()
{
return userid;
}
public String getPassword()
{
return password;
}
};
}
});
monitor.subTask("Contacting " + url);
getRepository(url).login(monitor);
monitor.subTask("Connected");
return getRepository(url);
}
// worker function repository
private static ITeamRepository repo1 = null;
private static ITeamRepository getRepository(String url)
{
if (repo1 == null)
{
repo1 = TeamPlatform.getTeamRepositoryService().getTeamRepository(
url);
}
return repo1;
}
// worker function process item service
private static IProcessItemService processitemservice = null;
private static IProcessItemService getProcessItemService(
ITeamRepository repo)
{
if (processitemservice == null)
{
processitemservice = (IProcessItemService) repo
.getClientLibrary(IProcessItemService.class);
}
return processitemservice;
}
public static List<IProjectArea> getProjectArea(ITeamRepository repo,
IProgressMonitor monitor, String projectAreaName)
throws TeamRepositoryException
{
List<IProjectArea> projectareaonly = new ArrayList<IProjectArea>();
@SuppressWarnings("unchecked")
// get all the projects in this repository
List<IProjectArea> projectAreas = getProcessItemService(repo)
.findAllProjectAreas(null, monitor);
// if Not ALL projects
if (!projectAreaName.equalsIgnoreCase("*"))
{
for (int i = 0; i < projectAreas.size(); i++)
{
// get next preoject from array
IProjectArea projectArea = projectAreas.get(i);
// if the names are equal, case sensitive
if (projectArea.getName().equals(projectAreaName))
{
// return this one project to the caller
System.out.println("Found " + projectAreaName);
projectareaonly.add(projectArea);
break;
}
else if (i + 1 == projectAreas.size())
{
System.out.println("Failed to find requested project '"
+ projectAreaName + "'");
}
}
return projectareaonly;
}
else
projectareaonly = projectAreas;
return projectareaonly;
}
}
IProjectArea projectArea = projectAreas.get(i);
// if the names are equal, case sensitive
if (projectArea.getName().equals(projectAreaName))
{
// return this one project to the caller
System.out.println("Found " + projectAreaName);
projectareaonly.add(projectArea);
break;
}
else if (i + 1 == projectAreas.size())
{
System.out.println("Failed to find requested project '"
+ projectAreaName + "'");
}
}
return projectareaonly;
}
else
projectareaonly = projectAreas;
return projectareaonly;
}
}
Comments
Sam,
Thanks a lot for your help!! What is the difference between "ProjectType" and "NewParentProject" variables? Paren project var gets the name of the project, right?
this set of code can change ONE project, or ALL projects..
great, thanks!
public static List<iprojectarea> getProjectArea(ITeamRepository repo,
IProgressMonitor monitor, String projectAreaName)
throws TeamRepositoryException -- should 'iprojectarea' be changed to 'IProjectArea'? When I am using 'iprojectarea', I am getting an error saying "iprojectarea cannot be resolved to a type"
I am also getting an error for: 'Map<object, Object=""> pd = ip.getProcessData();' shows me an error at the comma after object and the '=' sign. not sure why...
yes, the forum software messes up the formatting and case..
Thanks a bunch! I misread your post, which is why I typed the one below. I was able to fix all the errors. Sorry for all the questions, but where do I type in the information about the repo, project name, userid, and pass?
Comments
Thanks! I have it working, now it got to : if (processSource != null) { System.out.println("have xml source"); ....}
in a file called
+ keyname);
Thanks a bunch for all your help so far!
the keyname is the string IBM uses to store the value in the process area data map table
from above
<pre>
Map<Object, Object> pd = ip.getProcessData();
IContent processSource = (IContent) pd.get(keyname);
</pre>