diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/.classpath b/com.ibm.team.tap.tools.attachmentsMigrator/.classpath new file mode 100644 index 0000000..dfd42b8 --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/.classpath @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/.gitignore b/com.ibm.team.tap.tools.attachmentsMigrator/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/.project b/com.ibm.team.tap.tools.attachmentsMigrator/.project new file mode 100644 index 0000000..2c7b5f5 --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/.project @@ -0,0 +1,17 @@ + + + com.ibm.team.tap.tools.attachmentsMigrator + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/.settings/org.eclipse.jdt.core.prefs b/com.ibm.team.tap.tools.attachmentsMigrator/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..3a21537 --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.build.common_3.1.2100.v20211027_1736.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.build.common_3.1.2100.v20211027_1736.jar new file mode 100644 index 0000000..0093bfa Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.build.common_3.1.2100.v20211027_1736.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.calm.foundation.common_3.1.2000.v20220205_0002.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.calm.foundation.common_3.1.2000.v20220205_0002.jar new file mode 100644 index 0000000..2963c84 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.calm.foundation.common_3.1.2000.v20220205_0002.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.foundation.client_1.1.5000.v20201118_1923.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.foundation.client_1.1.5000.v20201118_1923.jar new file mode 100644 index 0000000..fbc592a Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.foundation.client_1.1.5000.v20201118_1923.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.foundation.common_1.3.7000.v20201118_1858.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.foundation.common_1.3.7000.v20201118_1858.jar new file mode 100644 index 0000000..624cd83 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.foundation.common_1.3.7000.v20201118_1858.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.process.client_1.3.7000.v20201118_1923.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.process.client_1.3.7000.v20201118_1923.jar new file mode 100644 index 0000000..297e1a4 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.process.client_1.3.7000.v20201118_1923.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.process.common_1.3.8000.v20201118_1858.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.process.common_1.3.8000.v20201118_1858.jar new file mode 100644 index 0000000..b3c0dd4 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.process.common_1.3.8000.v20201118_1858.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.client_1.3.7000.v20211027_1713.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.client_1.3.7000.v20211027_1713.jar new file mode 100644 index 0000000..1f6507a Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.client_1.3.7000.v20211027_1713.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.json_1.2.5000.v20201118_1858.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.json_1.2.5000.v20201118_1858.jar new file mode 100644 index 0000000..0cabcac Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.json_1.2.5000.v20201118_1858.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.remoteaccess.auth_1.3.5000.v20201118_1858.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.remoteaccess.auth_1.3.5000.v20201118_1858.jar new file mode 100644 index 0000000..2fe68ad Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.remoteaccess.auth_1.3.5000.v20201118_1858.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.remoteaccess_1.2.8000.v20211027_1713.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.remoteaccess_1.2.8000.v20211027_1713.jar new file mode 100644 index 0000000..1a993b7 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.remoteaccess_1.2.8000.v20211027_1713.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.serialize_1.2.7000.v20211027_1713.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.serialize_1.2.7000.v20211027_1713.jar new file mode 100644 index 0000000..1327f0d Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.serialize_1.2.7000.v20211027_1713.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.transport_1.2.4000.v20201118_1858.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.transport_1.2.4000.v20201118_1858.jar new file mode 100644 index 0000000..31c721b Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common.transport_1.2.4000.v20201118_1858.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common_1.5.0.v20220613_1612.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common_1.5.0.v20220613_1612.jar new file mode 100644 index 0000000..3709cc6 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.repository.common_1.5.0.v20220613_1612.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.workitem.client_3.1.2200.v20211027_2325.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.workitem.client_3.1.2200.v20211027_2325.jar new file mode 100644 index 0000000..0a7fc95 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.workitem.client_3.1.2200.v20211027_2325.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.workitem.common_3.3.200.v20220520_2223.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.workitem.common_3.3.200.v20220520_2223.jar new file mode 100644 index 0000000..c462042 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/com.ibm.team.workitem.common_3.3.200.v20220520_2223.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/commons-logging-1.2.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/commons-logging-1.2.jar new file mode 100644 index 0000000..93a3b9f Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/commons-logging-1.2.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-4.5.6.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-4.5.6.jar new file mode 100644 index 0000000..56231de Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-4.5.6.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-cache-4.5.6.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-cache-4.5.6.jar new file mode 100644 index 0000000..df529e3 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-cache-4.5.6.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-win-4.5.6.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-win-4.5.6.jar new file mode 100644 index 0000000..cd8fedf Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpclient-win-4.5.6.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpcore-4.4.10.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpcore-4.4.10.jar new file mode 100644 index 0000000..dc510f8 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/httpcore-4.4.10.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-api-2.17.1.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-api-2.17.1.jar new file mode 100644 index 0000000..1aae243 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-api-2.17.1.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-core-2.17.1.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-core-2.17.1.jar new file mode 100644 index 0000000..4682527 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-core-2.17.1.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-jcl-2.17.1.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-jcl-2.17.1.jar new file mode 100644 index 0000000..ecc8663 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/log4j-jcl-2.17.1.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.codec_1.9.0.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.codec_1.9.0.jar new file mode 100644 index 0000000..ef35f1c Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.codec_1.9.0.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.httpclient_3.1.0.v201012070820.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.httpclient_3.1.0.v201012070820.jar new file mode 100644 index 0000000..2ccaca5 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.httpclient_3.1.0.v201012070820.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.logging_1.2.0.v20220613_1305.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.logging_1.2.0.v20220613_1305.jar new file mode 100644 index 0000000..2d5becd Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.commons.logging_1.2.0.v20220613_1305.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.log4j_2.17.1.v20220613_1305.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.log4j_2.17.1.v20220613_1305.jar new file mode 100644 index 0000000..e4dda84 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.apache.log4j_2.17.1.v20220613_1305.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.jobs_3.6.1.v20141014-1248.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.jobs_3.6.1.v20141014-1248.jar new file mode 100644 index 0000000..d2129b4 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.jobs_3.6.1.v20141014-1248.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.resources_3.9.1.v20140825-1431.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.resources_3.9.1.v20140825-1431.jar new file mode 100644 index 0000000..c4cac5a Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.resources_3.9.1.v20140825-1431.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.runtime_3.10.0.v20140318-2214.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.runtime_3.10.0.v20140318-2214.jar new file mode 100644 index 0000000..8473228 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.core.runtime_3.10.0.v20140318-2214.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.common_2.10.1.v20150123-0348.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.common_2.10.1.v20150123-0348.jar new file mode 100644 index 0000000..f8df07e Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.common_2.10.1.v20150123-0348.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore.change_2.10.0.v20150123-0348.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore.change_2.10.0.v20150123-0348.jar new file mode 100644 index 0000000..8ef4471 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore.change_2.10.0.v20150123-0348.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore.xmi_2.10.2.v20150123-0348.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore.xmi_2.10.2.v20150123-0348.jar new file mode 100644 index 0000000..8532bb8 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore.xmi_2.10.2.v20150123-0348.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore_2.10.2.v20150123-0348.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore_2.10.2.v20150123-0348.jar new file mode 100644 index 0000000..aa9152b Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.emf.ecore_2.10.2.v20150123-0348.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.common_3.6.200.v20130402-1505.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.common_3.6.200.v20130402-1505.jar new file mode 100644 index 0000000..ebd2bf4 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.common_3.6.200.v20130402-1505.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.preferences_3.5.200.v20140224-1527.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.preferences_3.5.200.v20140224-1527.jar new file mode 100644 index 0000000..983f12e Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.preferences_3.5.200.v20140224-1527.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.registry_3.5.400.v20140428-1507.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.registry_3.5.400.v20140428-1507.jar new file mode 100644 index 0000000..287a895 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.equinox.registry_3.5.400.v20140428-1507.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.osgi_3.10.2.v20150203-1939.jar b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.osgi_3.10.2.v20150203-1939.jar new file mode 100644 index 0000000..effc686 Binary files /dev/null and b/com.ibm.team.tap.tools.attachmentsMigrator/lib/org.eclipse.osgi_3.10.2.v20150203-1939.jar differ diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/AttachmentMigrationUtility.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/AttachmentMigrationUtility.java new file mode 100644 index 0000000..0f0c046 --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/AttachmentMigrationUtility.java @@ -0,0 +1,272 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * (c) Copyright IBM Corporation 2019,2024. All Rights Reserved. + * + * Note to U.S. Government Users Restricted Rights: Use, + * duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + *******************************************************************************/ + +package com.ibm.team.tap.tools.attachmentsMigrator; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.Configurator; +import org.apache.logging.log4j.core.config.DefaultConfiguration; +import org.eclipse.core.runtime.IProgressMonitor; + +import com.ibm.team.repository.client.ITeamRepository; +import com.ibm.team.repository.client.TeamPlatform; +import com.ibm.team.repository.common.TeamRepositoryException; + +import com.ibm.team.tap.tools.attachmentsMigrator.util.ProgressMonitor; +import com.ibm.team.tap.tools.attachmentsMigrator.internal.Attachment; +import com.ibm.team.tap.tools.attachmentsMigrator.internal.Repository; +import com.ibm.team.tap.tools.attachmentsMigrator.util.AttachmentUpdateCommand; +import com.ibm.team.tap.tools.attachmentsMigrator.util.Constants; +import com.ibm.team.tap.tools.attachmentsMigrator.util.LogUtils; + +public class AttachmentMigrationUtility { + + private static enum CmdLineArg { + COMMANDS("-c", "-commands"), //$NON-NLS-1$ //$NON-NLS-2$ + LOG("-l", "-log"), //$NON-NLS-1$ //$NON-NLS-2$ + HELP("-h", "-help", false), //$NON-NLS-1$ //$NON-NLS-2$ + USER_NAME("-u", "-username"), //$NON-NLS-1$ //$NON-NLS-2$ + PASSWORD("-pw", "-password"), //$NON-NLS-1$ //$NON-NLS-2$ + SERVER_URI("-uri", "-serverUri"), //$NON-NLS-1$ //$NON-NLS-2$ + UPDATE("-update", "-update", false), //$NON-NLS-1$ //$NON-NLS-2$ + REMOVE_DELETED_WI_LINK("-rmDelWILink", "-rmDelWILink", false), //$NON-NLS-1$ //$NON-NLS-2$ + REMOVE_MULTI_WI_LINK("-rmMultiWILinks", "-rmMultiWILinks", false), //$NON-NLS-1$ //$NON-NLS-2$ + ADD_WI_ID("-addWorkItemId", "-addWorkItemId"), //$NON-NLS-1$ //$NON-NLS-2$ + DELETE_ATTACHMENTS_WITH_NO_WI("-deleteAttachmentsNoWI", "-delAttachmentsNoWI", false), //$NON-NLS-1$ //$NON-NLS-2$ + PROJECT("-p", "-project"); //$NON-NLS-1$ //$NON-NLS-2$ + + private final String fShortName; + private final String fLongName; + private final boolean fIsValueRequired; + private String fValue = null; + + private CmdLineArg(String shortName, String longName) { + this(shortName, longName, true); + } + + private CmdLineArg(String shortName, String longName, boolean isValueRequired) { + fShortName = shortName; + fLongName = longName; + fIsValueRequired = isValueRequired; + }; + + public boolean isEqual(String name) { + return fShortName.equalsIgnoreCase(name) || fLongName.equalsIgnoreCase(name); + } + + public boolean isValueRequired() { + return fIsValueRequired; + } + + public String getValue() { + return fValue; + } + + public void setValue(String value) { + if (value != null) { + fValue = value.trim(); + } + } + + public String getName() { + return fLongName; + } + } + + public static void main(String[] args) { + + TeamPlatform.startup(); + int systemExitCode = 0; + try { + String userName = null; + String password = null; + String serverUri = null; + boolean update = false; + boolean remDeletedWILink = false; + boolean remMultiWILinks = false; + String addWorkItemId = null; + boolean delete = false; + String projectItemId= null; + Level level = Level.INFO; + + setUpLoggingLevels(level); + List cmdArgs = processArgs(args); + if ((cmdArgs.contains(CmdLineArg.HELP)) || (cmdArgs.size() == 0)) { + InputStream inputStream = AttachmentMigrationUtility.class.getResourceAsStream("readme.txt"); //$NON-NLS-1$ + BufferedReader readmeReader = new BufferedReader(new InputStreamReader(inputStream)); + String line = null; + while ((line = readmeReader.readLine()) != null) { + System.out.println(line); + } + System.exit(systemExitCode); + } + + if (cmdArgs.contains(CmdLineArg.LOG)) { + LogUtils.setLogFile(CmdLineArg.LOG.getValue()); + } + + if (cmdArgs.contains(CmdLineArg.USER_NAME)) { + userName = CmdLineArg.USER_NAME.getValue(); + } + + if (cmdArgs.contains(CmdLineArg.PASSWORD)) { + password = CmdLineArg.PASSWORD.getValue(); + } + + if (cmdArgs.contains(CmdLineArg.SERVER_URI)) { + serverUri = CmdLineArg.SERVER_URI.getValue(); + } + + if (cmdArgs.contains(CmdLineArg.UPDATE)) { + update = cmdArgs.contains(CmdLineArg.UPDATE); + } + + if (cmdArgs.contains(CmdLineArg.REMOVE_DELETED_WI_LINK)) { + remDeletedWILink = cmdArgs.contains(CmdLineArg.REMOVE_DELETED_WI_LINK); + } + + if (cmdArgs.contains(CmdLineArg.REMOVE_MULTI_WI_LINK)) { + remMultiWILinks = cmdArgs.contains(CmdLineArg.REMOVE_MULTI_WI_LINK); + } + + if (cmdArgs.contains(CmdLineArg.ADD_WI_ID)) { + addWorkItemId = CmdLineArg.ADD_WI_ID.getValue(); + } + + if (cmdArgs.contains(CmdLineArg.PROJECT)) { + projectItemId = CmdLineArg.PROJECT.getValue(); + } + + if (cmdArgs.contains(CmdLineArg.DELETE_ATTACHMENTS_WITH_NO_WI)) { + delete = cmdArgs.contains(CmdLineArg.DELETE_ATTACHMENTS_WITH_NO_WI); + if (delete) { + Scanner scanner = new Scanner(System.in); + System.out.print("Are you sure you want to delete all the attachments which are not linked to any work items?\n" + "Enter Yes to continue\n"); //$NON-NLS-1$ //$NON-NLS-2$ + String confirm = scanner.nextLine(); + scanner.close(); + + if (!confirm.equals("Yes")) { //$NON-NLS-1$ + System.out.print(CmdLineArg.DELETE_ATTACHMENTS_WITH_NO_WI.getName() + " requested but confirmation declined"); //$NON-NLS-1$ + System.exit(systemExitCode); + } + } + } + + if (userName == null || password == null) { + throw new IllegalArgumentException("Invalid user name or password."); //$NON-NLS-1$ + } else if (serverUri == null) { + throw new IllegalArgumentException("Server uri required for the operation."); //$NON-NLS-1$ + } + + if (!cmdArgs.contains(CmdLineArg.COMMANDS)) { + throw new IllegalArgumentException( + CmdLineArg.COMMANDS.getName() + " requires one (or more) valid commands"); //$NON-NLS-1$ + } + + String[] commands = CmdLineArg.COMMANDS.getValue().split("\\,"); //$NON-NLS-1$ + + List commandsList = new ArrayList(); + + if (commands.length == 0) { + throw new IllegalArgumentException( + CmdLineArg.COMMANDS.getName() + " requires one (or more) valid commands"); //$NON-NLS-1$ + } else { + for (String command : commands) { + if (Constants.COMMAND_ANALYZE_AND_UPDATE_ATTACHMENTS.equals(command)) { + commandsList.add(command); + } else { + throw new IllegalArgumentException( + CmdLineArg.COMMANDS.getName() + " contains invalid command '" + command + "'"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + + printToConsoleAndLog("Requested commands are: " + commandsList + "."); //$NON-NLS-1$ //$NON-NLS-2$ + if (commandsList.contains(Constants.COMMAND_ANALYZE_AND_UPDATE_ATTACHMENTS)) { + printToConsoleAndLog(Constants.COMMAND_ANALYZE_AND_UPDATE_ATTACHMENTS + " started."); //$NON-NLS-1$ + AttachmentUpdateCommand updateCommand = new AttachmentUpdateCommand(update, remDeletedWILink, remMultiWILinks, addWorkItemId, delete); + analyzeAndUpdateAttachments(serverUri, userName, password, projectItemId, updateCommand); + printToConsoleAndLog(Constants.COMMAND_ANALYZE_AND_UPDATE_ATTACHMENTS + " completed."); //$NON-NLS-1$ + } + } catch (Throwable t) { + LogUtils.logError(t.toString(), t); + systemExitCode = 1; + } finally { + System.exit(systemExitCode); + } + } + + private static void printToConsoleAndLog(String message) { + System.out.println(message); + LogUtils.logInfo("-----------------------------------------------------"); //$NON-NLS-1$ + LogUtils.logInfo(message); + LogUtils.logInfo("-----------------------------------------------------"); //$NON-NLS-1$ + + } + + private static void analyzeAndUpdateAttachments(String serverUri, String userName, String password, String projectItemId, AttachmentUpdateCommand updateCommand) { + try { + IProgressMonitor monitor = new ProgressMonitor(); + ITeamRepository repository = Repository.login(monitor, serverUri, userName, password); + Attachment.analyzeAndUpdateWIAttachmentsInRepository(repository, projectItemId, updateCommand, monitor); + Attachment.printAnalysis(); + } catch (TeamRepositoryException e) { + System.out.println("Exception: " + e.getMessage()); //$NON-NLS-1$ + } finally { + TeamPlatform.shutdown(); + } + } + + private static List processArgs(String[] args) throws IllegalArgumentException { + ArrayList argList = new ArrayList(); + for (String arg : args) { + boolean found = false; + for (CmdLineArg cmd : CmdLineArg.values()) { + String[] nameVal = arg.split("\\="); //$NON-NLS-1$ + if (cmd.isEqual(nameVal[0])) { + found = true; + if (nameVal.length > 1 && !cmd.isValueRequired()) { + parseCmdException(cmd.getName() + " / " + cmd.fShortName + " requires no value"); //$NON-NLS-1$ //$NON-NLS-2$ + } else if (nameVal.length > 1) { + cmd.setValue(nameVal[1]); + } else if (cmd.isValueRequired()) { + parseCmdException(cmd.getName() + " / " + cmd.fShortName + " requires a value"); //$NON-NLS-1$ //$NON-NLS-2$ + } + argList.add(cmd); + break; + } + } + if (!found) { + parseCmdException(arg + " is an invalid argument"); //$NON-NLS-1$ + } + } + return argList; + } + + private static void parseCmdException(String message) { + System.out.println("Invalid syntax: " + message); //$NON-NLS-1$ + throw new IllegalArgumentException(message); + } + + private static void setUpLoggingLevels(Level level) { + Configurator.initialize(new DefaultConfiguration()); + Configurator.setRootLevel(level); + + if (level != Level.DEBUG) { + System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } +} \ No newline at end of file diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Attachment.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Attachment.java new file mode 100644 index 0000000..4d00347 --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Attachment.java @@ -0,0 +1,364 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * (c) Copyright IBM Corporation 2019. All Rights Reserved. + * + * Note to U.S. Government Users Restricted Rights: Use, + * duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + *******************************************************************************/ +package com.ibm.team.tap.tools.attachmentsMigrator.internal; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; + +import com.ibm.team.links.client.ILinkManager; +import com.ibm.team.links.common.IItemReference; +import com.ibm.team.links.common.ILink; +import com.ibm.team.links.common.ILinkCollection; +import com.ibm.team.links.common.ILinkQueryPage; +import com.ibm.team.links.common.IReference; +import com.ibm.team.links.common.factory.IReferenceFactory; +import com.ibm.team.process.common.IProjectArea; +import com.ibm.team.process.common.IProjectAreaHandle; +import com.ibm.team.process.internal.common.ProcessPackage; + +import com.ibm.team.repository.client.ITeamRepository; +import com.ibm.team.repository.common.IItemHandle; +import com.ibm.team.repository.common.ItemNotFoundException; +import com.ibm.team.repository.common.TeamRepositoryException; +import com.ibm.team.repository.common.UUID; +import com.ibm.team.repository.common.query.IItemQuery; +import com.ibm.team.tap.tools.attachmentsMigrator.util.AttachmentUpdateCommand; +import com.ibm.team.tap.tools.attachmentsMigrator.util.LogUtils; +import com.ibm.team.tap.tools.attachmentsMigrator.util.WIAttachmentInfo; +import com.ibm.team.workitem.client.IAuditableClient; +import com.ibm.team.workitem.client.IWorkItemClient; +import com.ibm.team.workitem.common.QueryIterator; +import com.ibm.team.workitem.common.internal.model.query.BaseAttachmentQueryModel.AttachmentQueryModel; +import com.ibm.team.workitem.common.model.IAttachment; +import com.ibm.team.workitem.common.model.IAttachmentHandle; +import com.ibm.team.workitem.common.model.IWorkItem; +import com.ibm.team.workitem.common.model.IWorkItemHandle; +import com.ibm.team.workitem.common.model.ItemProfile; +import com.ibm.team.workitem.common.model.WorkItemLinkTypes; + +public class Attachment { + private static List fWIAttachmentsAccessContextMismatch = new ArrayList(); + private static List fWIAttachmentsProjectAreaMismatch = new ArrayList(); + private static List fWIAttachmentsMultipleWIs = new ArrayList(); + private static int fWIAttachmentsMultipleWIsCount= 0; + private static List fWIAttachmentsNoWI = new ArrayList(); + private static List fWIAttachmentsWIDeleted = new ArrayList(); + private static ItemProfile SMALL_PROFILE_WITH_CONTENT= IAttachment.SMALL_PROFILE.createExtension(Arrays.asList(new String[] { IAttachment.CONTENT_PROPERTY })); + + public static String[] PROCESS_PROVIDER_PROFILE = new String[] { + ProcessPackage.eINSTANCE.getProjectArea_InternalProcessProvider().getName() }; + public static ItemProfile PROJECT_CHECK_PROFILE = ItemProfile.PROJECT_AREA_DEFAULT + .createExtension(PROCESS_PROVIDER_PROFILE); + + public static void analyzeAndUpdateWIAttachmentsInRepository(ITeamRepository repository, String projectItemId, AttachmentUpdateCommand updateCommand, IProgressMonitor monitor) + throws TeamRepositoryException { + final IAuditableClient auditableClient = getAuditableClient(repository); + final ILinkManager linkManager = getLinkManager(repository); + + boolean update = false; + boolean removeDeletedLinks = false; + boolean removeMultipleWILinks = false; + IWorkItem workItemToAddLink = null; + boolean delete = false; + + if (updateCommand != null) { + update = updateCommand.isUpdate(); + removeDeletedLinks = updateCommand.isRemoveDeletedLinks(); + removeMultipleWILinks = updateCommand.isRemoveMultipleWILinks(); + String workItemIdString = updateCommand.getWorkItemId(); + if (workItemIdString != null) { + int workItemId = Integer.parseInt(workItemIdString); + workItemToAddLink = getIWorkItemClient(repository).findWorkItemById(workItemId, IWorkItem.FULL_PROFILE, monitor); + if (workItemToAddLink == null) { + LogUtils.logError("Cannot find the specified work item " + workItemId); //$NON-NLS-1$ + return; + } + } + delete = updateCommand.isDelete(); + } + + AttachmentQueryModel model = AttachmentQueryModel.ROOT; + IItemQuery query = IItemQuery.FACTORY.newInstance(model); + if (projectItemId != null && projectItemId.length() != 0) { + UUID itemId= UUID.valueOf(projectItemId); + IProjectAreaHandle projectAreaHandle= (IProjectAreaHandle) IProjectArea.ITEM_TYPE.createItemHandle(itemId, null); + query.filter(model.projectArea()._eq(projectAreaHandle)); + } + + QueryIterator iter = auditableClient.getItemQueryIterator(query, null, null, null); + try { + while (iter.hasNext(monitor)) { + IAttachment attachment = auditableClient.resolveAuditable(iter.next(monitor), SMALL_PROFILE_WITH_CONTENT, + monitor); + IReference attachmentReference = IReferenceFactory.INSTANCE.createReferenceToItem(attachment, attachment.getName()); + + IProjectArea projectArea = auditableClient.resolveAuditable(attachment.getProjectArea(), + PROJECT_CHECK_PROFILE, monitor); + String attachmentProjectName= (projectArea != null) ? projectArea.getName() : "No Project Information"; //$NON-NLS-1$ + + ILinkQueryPage linkQueryResult = linkManager.findLinks(WorkItemLinkTypes.ATTACHMENT, attachmentReference, monitor); + + /* For each link */ + ILinkCollection allLinksFromHereOn = linkQueryResult.getAllLinksFromHereOn(); + if (allLinksFromHereOn.isEmpty()) { + if (workItemToAddLink != null) { + ILink link = saveLink(linkManager, workItemToAddLink, attachmentReference, monitor); + allLinksFromHereOn.addAll((Collection) new ArrayList(Arrays.asList(link))); + LogUtils.logInfo("Linking attachment " + attachment.getId() + " - " //$NON-NLS-1$ //$NON-NLS-2$ + + attachment.getName() + " to work item " + workItemToAddLink.getId() + "."); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + if (delete) { + deleteWorkItemAttachment(repository, attachment, monitor); + } else { + WIAttachmentInfo wiAttachmentInfo = new WIAttachmentInfo(attachmentProjectName, 0, + attachment.getName(), attachment.getId(), attachment.getContent().getRawLength()); + fWIAttachmentsNoWI.add(wiAttachmentInfo); + } + } + } + + boolean foundMultipleWI = false; + for (ILink link : allLinksFromHereOn) { + try { + IReference workItemRef = link.getSourceRef(); + if (!workItemRef.isItemReference()) { + continue; + } + + if ((allLinksFromHereOn.size() > 1) && removeMultipleWILinks && foundMultipleWI) { + deleteLink(linkManager, link, monitor); + continue; + } + + IItemHandle referencedItem = ((IItemReference) workItemRef).getReferencedItem(); + if (referencedItem instanceof IWorkItemHandle) { + IWorkItem workItem = auditableClient.resolveAuditable((IWorkItemHandle) referencedItem, + IWorkItem.DEFAULT_PROFILE, monitor); + if (allLinksFromHereOn.size() > 1) { + foundMultipleWI = true; + if (!removeMultipleWILinks) { + WIAttachmentInfo wiAttachmentInfo = new WIAttachmentInfo(attachmentProjectName, workItem.getId(), + attachment.getName(), attachment.getId(), attachment.getContent().getRawLength()); + fWIAttachmentsMultipleWIs.add(wiAttachmentInfo); + } else { + LogUtils.logInfo("Multiple work item links to attachment " + attachment.getId() + " - " //$NON-NLS-1$ //$NON-NLS-2$ + + attachment.getName() + " ... retaining link to work item " + workItem.getId() + "."); //$NON-NLS-1$ //$NON-NLS-2$ + checkAndUpdateWorkItemAttachment(repository, workItem, attachment, attachmentProjectName, update, monitor); + } + } else { + checkAndUpdateWorkItemAttachment(repository, workItem, attachment, attachmentProjectName, update, monitor); + } + } + } catch (ItemNotFoundException e) { + if (removeDeletedLinks) { + deleteLink(linkManager, link, monitor); + } else { + WIAttachmentInfo wiAttachmentInfo = new WIAttachmentInfo(attachmentProjectName, 0, + attachment.getName(), attachment.getId(), attachment.getContent().getRawLength()); + fWIAttachmentsWIDeleted.add(wiAttachmentInfo); + } + } + } + if (foundMultipleWI) { + fWIAttachmentsMultipleWIsCount++; + } + } + } finally { + iter.close(); + } + } + + private static void checkAndUpdateWorkItemAttachment(ITeamRepository repository, IWorkItem workItem, IAttachment attachment, + String projectName, boolean update, IProgressMonitor monitor) throws TeamRepositoryException { + boolean saveAttachment = false; + IWorkItemClient workItemClient = getIWorkItemClient(repository); + + if (update) { + attachment = (IAttachment) attachment.getWorkingCopy(); + } + + if (!isSameAccessContext(workItem, attachment)) { + if (update) { + LogUtils.logInfo("Updating context for attachment " + attachment.getId() + " - " + attachment.getName() + " to context of work item " + workItem.getId() + "."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + saveAttachment = updateAttachmentContext(attachment, workItem.getContextId()); + } else { + WIAttachmentInfo wiAttachmentInfo = new WIAttachmentInfo(projectName, workItem.getId(), + attachment.getName(), attachment.getId(), attachment.getContent().getRawLength()); + fWIAttachmentsAccessContextMismatch.add(wiAttachmentInfo); + } + } + + final IAuditableClient auditableClient = getAuditableClient(repository); + IProjectArea attachmentProjectArea = auditableClient.resolveAuditable(attachment.getProjectArea(), PROJECT_CHECK_PROFILE, monitor); + IProjectArea wiProjectArea = auditableClient.resolveAuditable(workItem.getProjectArea(), PROJECT_CHECK_PROFILE, monitor); + + if (wiProjectArea != null && attachmentProjectArea != null && !wiProjectArea.getItemId().equals(attachmentProjectArea.getItemId())) { + if (update) { + LogUtils.logInfo("Updating project area for attachment " + attachment.getId() + " - " + attachment.getName() + " from project area - " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + attachmentProjectArea.getName() + " to the project area of work item " + workItem.getId() + " - " + //$NON-NLS-1$ //$NON-NLS-2$ + wiProjectArea.getName() + "."); //$NON-NLS-1$ + saveAttachment = updateAttachmentProject(attachment, wiProjectArea); + } else { + WIAttachmentInfo wiAttachmentInfo = new WIAttachmentInfo(attachmentProjectArea.getName(), workItem.getId(), + attachment.getName(), attachment.getId(), attachment.getContent().getRawLength()); + fWIAttachmentsProjectAreaMismatch.add(wiAttachmentInfo); + } + } else if (wiProjectArea != null && attachmentProjectArea == null) { + if (update) { + LogUtils.logInfo("Updating project area for attachment " + attachment.getId() + " - " + attachment.getName() + //$NON-NLS-1$ //$NON-NLS-2$ + " to the project area of work item " + workItem.getId() + " - " + //$NON-NLS-1$ //$NON-NLS-2$ + wiProjectArea.getName() + "."); //$NON-NLS-1$ + saveAttachment = updateAttachmentProject(attachment, wiProjectArea); + } else { + WIAttachmentInfo wiAttachmentInfo = new WIAttachmentInfo(null, workItem.getId(), + attachment.getName(), attachment.getId(), attachment.getContent().getRawLength()); + fWIAttachmentsProjectAreaMismatch.add(wiAttachmentInfo); + } + } + + if (saveAttachment) { + workItemClient.saveAttachment(attachment, new NullProgressMonitor()); + } + } + + private static void deleteWorkItemAttachment(ITeamRepository repository, IAttachment attachment, IProgressMonitor monitor) throws TeamRepositoryException { + IWorkItemClient workItemClient = getIWorkItemClient(repository); + LogUtils.logInfo("Deleting attachment " + attachment.getId() + " - " + attachment.getName()); //$NON-NLS-1$ //$NON-NLS-2$ + workItemClient.deleteAttachment(attachment, monitor); + } + + private static ILink saveLink(ILinkManager linkManager, IWorkItem workItem, IReference reference, IProgressMonitor monitor) throws TeamRepositoryException { + // Attachment links are ignored in Work Item History + // See, com.ibm.team.workitem.service.internal.WorkItemHistoryService.isValidLinkTypeForHistory(ILinkType) + IReference workItemReference = IReferenceFactory.INSTANCE.createReferenceToItem(workItem, workItem.getHTMLSummary().getPlainText()); + ILink link= linkManager.createLink(WorkItemLinkTypes.ATTACHMENT, workItemReference, reference); + linkManager.saveLink(link, monitor); + return link; + } + + private static void deleteLink(ILinkManager linkManager, ILink link, IProgressMonitor monitor) throws TeamRepositoryException { + // Attachment links are ignored in Work Item History + // See, com.ibm.team.workitem.service.internal.WorkItemHistoryService.isValidLinkTypeForHistory(ILinkType) + linkManager.deleteLink(link, monitor); + LogUtils.logInfo("Deleting link: sourceRef " + link.getSourceRef().getComment() + " targetRef: " + link.getTargetRef().getComment() + "."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + private static boolean isSameAccessContext(IWorkItem workItem, IAttachment attachment) { + UUID workItemContextId = workItem.getContextId(); + UUID attachmentContextId = attachment.getContextId(); + + return workItemContextId.equals(attachmentContextId); + } + + private static boolean updateAttachmentProject(IAttachment attachment, IProjectArea projectArea) throws TeamRepositoryException { + if (projectArea != null) { + ((com.ibm.team.workitem.common.internal.model.Attachment)attachment).setProjectArea(projectArea); + return true; + } + return false; + } + + private static boolean updateAttachmentContext(IAttachment attachment, UUID newContext) throws TeamRepositoryException { + if (newContext != null) { + attachment.setContextId(newContext); + return true; + } + return false; + } + + private static IAuditableClient getAuditableClient(ITeamRepository repository) { + return (IAuditableClient) repository.getClientLibrary(IAuditableClient.class); + } + + private static ILinkManager getLinkManager(ITeamRepository repository) { + return (ILinkManager) repository.getClientLibrary(ILinkManager.class); + } + + private static IWorkItemClient getIWorkItemClient(ITeamRepository repository) { + return (IWorkItemClient) repository.getClientLibrary(IWorkItemClient.class); + } + + public static void printAnalysis() { + if (!fWIAttachmentsAccessContextMismatch.isEmpty()) { + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + LogUtils.logInfo("Attachments with out the same access context as the work item: " + fWIAttachmentsAccessContextMismatch.size()); //$NON-NLS-1$ + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + for (WIAttachmentInfo wiAttachmentInfo : fWIAttachmentsAccessContextMismatch) { + LogUtils.logInfo("Attachment " + wiAttachmentInfo.getAttachmentId() + " - " //$NON-NLS-1$ //$NON-NLS-2$ + + wiAttachmentInfo.getAttachmentName() + " linked to work item " + wiAttachmentInfo.getWorkItemId() //$NON-NLS-1$ + + " in project " + wiAttachmentInfo.getProjectName()); //$NON-NLS-1$ + } + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + } + + if (!fWIAttachmentsMultipleWIs.isEmpty()) { + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + LogUtils.logInfo("Attachments linked to multiple work items: " + fWIAttachmentsMultipleWIsCount); //$NON-NLS-1$ + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + for (WIAttachmentInfo wiAttachmentInfo : fWIAttachmentsMultipleWIs) { + LogUtils.logInfo("Attachment " + wiAttachmentInfo.getAttachmentId() + " - " //$NON-NLS-1$ //$NON-NLS-2$ + + wiAttachmentInfo.getAttachmentName() + " linked to work item " + wiAttachmentInfo.getWorkItemId() //$NON-NLS-1$ + + " in project " + wiAttachmentInfo.getProjectName()); //$NON-NLS-1$ + } + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + } + + if (!fWIAttachmentsProjectAreaMismatch.isEmpty()) { + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + LogUtils.logInfo("Attachments in different project than the work item: " + fWIAttachmentsProjectAreaMismatch.size()); //$NON-NLS-1$ + LogUtils.logInfo("----------------------------------------------------------------------"); //$NON-NLS-1$ + for (WIAttachmentInfo wiAttachmentInfo : fWIAttachmentsProjectAreaMismatch) { + LogUtils.logInfo("Attachment " + wiAttachmentInfo.getAttachmentId() + " - " //$NON-NLS-1$ //$NON-NLS-2$ + + wiAttachmentInfo.getAttachmentName() + " linked to work item " + wiAttachmentInfo.getWorkItemId() //$NON-NLS-1$ + + " in project " + wiAttachmentInfo.getProjectName()); //$NON-NLS-1$ + } + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + } + + long totalBytes= 0; + if (!fWIAttachmentsNoWI.isEmpty()) { + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + LogUtils.logInfo("Attachments linked to no work items: " + fWIAttachmentsNoWI.size()); //$NON-NLS-1$ + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + for (WIAttachmentInfo wiAttachmentInfo : fWIAttachmentsNoWI) { + LogUtils.logInfo("Attachment " + wiAttachmentInfo.getAttachmentId() + " - " //$NON-NLS-1$ //$NON-NLS-2$ + + wiAttachmentInfo.getAttachmentName() + " in project " + wiAttachmentInfo.getProjectName() + " with size " + processRawByteCount(wiAttachmentInfo.getContentLength())); //$NON-NLS-1$ //$NON-NLS-2$ + totalBytes+= wiAttachmentInfo.getContentLength(); + } + LogUtils.logInfo("Total attachments size: " + processRawByteCount(totalBytes)); //$NON-NLS-1$ + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + } + + if (!fWIAttachmentsWIDeleted.isEmpty()) { + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + LogUtils.logInfo("Attachments linked to deleted work items: " + fWIAttachmentsWIDeleted.size()); //$NON-NLS-1$ + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + totalBytes= 0; + for (WIAttachmentInfo wiAttachmentInfo : fWIAttachmentsWIDeleted) { + LogUtils.logInfo("Attachment " + wiAttachmentInfo.getAttachmentId() + " - " //$NON-NLS-1$ //$NON-NLS-2$ + + wiAttachmentInfo.getAttachmentName() + " in project " + wiAttachmentInfo.getProjectName() + " with size " + processRawByteCount(wiAttachmentInfo.getContentLength())); //$NON-NLS-1$ //$NON-NLS-2$ + totalBytes+= wiAttachmentInfo.getContentLength(); + } + LogUtils.logInfo("Total attachments size: " + processRawByteCount(totalBytes)); //$NON-NLS-1$ + LogUtils.logInfo("-----------------------------------------------------------------------"); //$NON-NLS-1$ + } + } + + public static String processRawByteCount(long bytes) { + int unit= 1000; + if (bytes < unit) return bytes + " B"; //$NON-NLS-1$ + int exponent= (int) (Math.log(bytes) / Math.log(unit)); + String prefix= "KMGTPE".charAt(exponent - 1) + ""; //$NON-NLS-1$ //$NON-NLS-2$ + return String.format("%.1f %sB", bytes / Math.pow(unit, exponent), prefix); //$NON-NLS-1$ + } +} diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Project.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Project.java new file mode 100644 index 0000000..e103267 --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Project.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * (c) Copyright IBM Corporation 2019. All Rights Reserved. + * + * Note to U.S. Government Users Restricted Rights: Use, + * duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + *******************************************************************************/ +package com.ibm.team.tap.tools.attachmentsMigrator.internal; + +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; + +import com.ibm.team.process.client.IProcessClientService; +import com.ibm.team.process.client.IProcessItemService; +import com.ibm.team.process.common.IProjectArea; +import com.ibm.team.repository.client.ITeamRepository; +import com.ibm.team.repository.common.TeamRepositoryException; +import com.ibm.team.workitem.common.internal.util.CollectionUtils; + +public class Project { + + @SuppressWarnings("unchecked") + public static List findAllProjects(ITeamRepository repository, IProgressMonitor monitor) + throws TeamRepositoryException { + IProcessItemService service = (IProcessItemService) repository.getClientLibrary(IProcessItemService.class); + return CollectionUtils.removeNulls(service.findAllProjectAreas(IProcessClientService.ALL_PROPERTIES, monitor)); + } + +} diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Repository.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Repository.java new file mode 100644 index 0000000..851764b --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/internal/Repository.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * (c) Copyright IBM Corporation 2019. All Rights Reserved. + * + * Note to U.S. Government Users Restricted Rights: Use, + * duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + *******************************************************************************/ +package com.ibm.team.tap.tools.attachmentsMigrator.internal; + +import org.eclipse.core.runtime.IProgressMonitor; + +import com.ibm.team.repository.client.ITeamRepository; +import com.ibm.team.repository.client.TeamPlatform; +import com.ibm.team.repository.client.ITeamRepository.ILoginHandler; +import com.ibm.team.repository.client.ITeamRepository.ILoginHandler.ILoginInfo; +import com.ibm.team.repository.common.TeamRepositoryException; + +/** + * Repository related commands + */ +public class Repository { + + public static ITeamRepository login(IProgressMonitor monitor, String serverUri, String user, String password) + throws TeamRepositoryException { + if (!TeamPlatform.isStarted()) { + TeamPlatform.startup(); + } + + ITeamRepository repository = TeamPlatform.getTeamRepositoryService().getTeamRepository(serverUri); + repository.registerLoginHandler(new LoginHandler(user, password)); + monitor.subTask("Contacting " + repository.getRepositoryURI() + "..."); //$NON-NLS-1$ //$NON-NLS-2$ + repository.login(monitor); + monitor.subTask("User " + user + " has logged in to " + repository.getRepositoryURI()); //$NON-NLS-1$ //$NON-NLS-2$ + return repository; + } + + /** + * Internal login handler to perform the login to the repository + * + */ + private static class LoginHandler implements ILoginHandler, ILoginInfo { + + private String fUserId; + private String fPassword; + + private LoginHandler(String userId, String password) { + fUserId = userId; + fPassword = password; + } + + public String getUserId() { + return fUserId; + } + + public String getPassword() { + return fPassword; + } + + public ILoginInfo challenge(ITeamRepository repository) { + return this; + } + } +} diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/AttachmentUpdateCommand.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/AttachmentUpdateCommand.java new file mode 100644 index 0000000..522b09a --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/AttachmentUpdateCommand.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * (c) Copyright IBM Corporation 2019. All Rights Reserved. + * + * Note to U.S. Government Users Restricted Rights: Use, + * duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + *******************************************************************************/ +package com.ibm.team.tap.tools.attachmentsMigrator.util; + +public class AttachmentUpdateCommand { + private boolean fUpdate; + private boolean fRemoveDeletedLinks; + private boolean fRemoveMultipleWILinks; + private String fAddWorkItemId; + private boolean fDelete; + + public AttachmentUpdateCommand(boolean update, boolean removeDeletedLinks, boolean removeMultipleWILinks, String workItemId, boolean delete) { + fUpdate= update; + fRemoveDeletedLinks= removeDeletedLinks; + fRemoveMultipleWILinks= removeMultipleWILinks; + fAddWorkItemId = workItemId; + fDelete = delete; + } + + public boolean isUpdate() { + return fUpdate; + } + + public boolean isRemoveDeletedLinks() { + return fRemoveDeletedLinks; + } + + public boolean isRemoveMultipleWILinks() { + return fRemoveMultipleWILinks; + } + + public String getWorkItemId() { + return fAddWorkItemId; + } + + public boolean isDelete() { + return fDelete; + } +} diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/Constants.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/Constants.java new file mode 100644 index 0000000..6e6a00a --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/Constants.java @@ -0,0 +1,14 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * © Copyright IBM Corporation 2019. All Rights Reserved. + * + * U.S. Government Users Restricted Rights: + * Use, duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + ******************************************************************************/ +package com.ibm.team.tap.tools.attachmentsMigrator.util; + +public final class Constants { + // Commands + public static final String COMMAND_ANALYZE_AND_UPDATE_ATTACHMENTS= "analyzeAndUpdateAttachments"; //$NON-NLS-1$ +} \ No newline at end of file diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/LogUtils.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/LogUtils.java new file mode 100644 index 0000000..0c03d0d --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/LogUtils.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * © Copyright IBM Corporation 2019,2024. All Rights Reserved. + * + * U.S. Government Users Restricted Rights: + * Use, duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + ******************************************************************************/ +package com.ibm.team.tap.tools.attachmentsMigrator.util; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.appender.RollingFileAppender; +import org.apache.logging.log4j.core.config.Configurator; +import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; +import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder; +import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; + +import com.ibm.team.tap.tools.attachmentsMigrator.AttachmentMigrationUtility; + +/** + *

+ * Apache Log4j logger utilities. + *

+ * + */ +public class LogUtils { + + private static Logger fLogger= null; + private static RollingFileAppender fRollingFileAppender; + private static Logger fRootLogger; + + // 50 MB + private static long MAX_FILE_SIZE= 50000000; + private static int MAX_BACKUP_INDEX= 10; + + private static Logger getLogger() { + + if (fLogger == null) { + fLogger= LogManager.getLogger(AttachmentMigrationUtility.class); + } + + return fLogger; + } + + public static void setLogFile(String file) { + + ConfigurationBuilder builder = ConfigurationBuilderFactory.newConfigurationBuilder(); + builder.setConfigurationName("Default"); + LayoutComponentBuilder layout = builder.newLayout("PatternLayout") + .addAttribute("pattern", "%d{dd MMM yyyy HH:mm:ss,SSSZ} [%t] %5p %c: %m%n"); + AppenderComponentBuilder appender = builder.newAppender("TRS Validator Utility log file appender", "File") + .addAttribute("fileName", file) + .add(layout); + builder.add(appender); + Configurator.reconfigure(builder.build()); + + } + + public static void logDebug(String message) { + getLogger().debug(message); + } + + public static void logDebug(String message, Throwable throwable) { + getLogger().debug(message, throwable); + } + + public static void logTrace(String message) { + getLogger().trace(message); + } + + public static void logTrace(String message, Throwable throwable) { + getLogger().trace(message, throwable); + } + + public static void logInfo(String message) { + getLogger().info(message); + } + + public static void logInfo(String message, Throwable throwable) { + getLogger().info(message, throwable); + } + + public static void logWarning(String message) { + getLogger().warn(message); + } + + public static void logWarning(String message, Throwable throwable) { + getLogger().warn(message, throwable); + } + + public static void logError(String message) { + getLogger().error(message); + } + + public static void logError(String message, Throwable throwable) { + getLogger().error(message, throwable); + } + + public static void logFatal(String message) { + getLogger().fatal(message); + } + + public static void logFatal(String message, Throwable throwable) { + getLogger().fatal(message, throwable); + } +} diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/ProgressMonitor.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/ProgressMonitor.java new file mode 100644 index 0000000..61cd0ff --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/ProgressMonitor.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * (c) Copyright IBM Corporation 2019. All Rights Reserved. + * + * Note to U.S. Government Users Restricted Rights: Use, + * duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + *******************************************************************************/ +package com.ibm.team.tap.tools.attachmentsMigrator.util; + +import org.eclipse.core.runtime.IProgressMonitor; + +public class ProgressMonitor implements IProgressMonitor { + + public void beginTask(String name, int totalWork) { + print(name); + } + + public void done() { + } + + public void internalWorked(double work) { + } + + public boolean isCanceled() { + return false; + } + + public void setCanceled(boolean value) { + } + + public void setTaskName(String name) { + print(name); + } + + public void subTask(String name) { + print(name); + } + + public void worked(int work) { + } + + private void print(String name) { + if (name != null && !"".equals(name)) //$NON-NLS-1$ + System.out.println(name); + } +} diff --git a/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/WIAttachmentInfo.java b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/WIAttachmentInfo.java new file mode 100644 index 0000000..20fdd25 --- /dev/null +++ b/com.ibm.team.tap.tools.attachmentsMigrator/src/com/ibm/team/tap/tools/attachmentsMigrator/util/WIAttachmentInfo.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Licensed Materials - Property of IBM + * (c) Copyright IBM Corporation 2019. All Rights Reserved. + * + * Note to U.S. Government Users Restricted Rights: Use, + * duplication or disclosure restricted by GSA ADP Schedule + * Contract with IBM Corp. + *******************************************************************************/ +package com.ibm.team.tap.tools.attachmentsMigrator.util; + +public class WIAttachmentInfo { + private String fProjectName; + private int fWorkItemId; + private String fAttachmentName; + private int fAttachmentId; + private long fContentLength; + + public WIAttachmentInfo(String projectName, int workItemId, String attachmentName, int attachmentId, long contentLength) { + fProjectName= projectName; + fWorkItemId= workItemId; + fAttachmentName= attachmentName; + fAttachmentId= attachmentId; + fContentLength= contentLength; + } + + public String getAttachmentName() { + return fAttachmentName; + } + + public int getAttachmentId() { + return fAttachmentId; + } + + public int getWorkItemId() { + return fWorkItemId; + } + + public String getProjectName() { + return fProjectName; + } + + public long getContentLength() { + return fContentLength; + } +}