diff --git a/config/alfresco/patch-services-context.xml b/config/alfresco/patch-services-context.xml index c5ddf51870..3ec779e1f4 100644 --- a/config/alfresco/patch-services-context.xml +++ b/config/alfresco/patch-services-context.xml @@ -52,13 +52,13 @@ Sample01 A NO-OP sample patch - 0.0 + 0.0 Sample02 A NO-OP sample patch - 0.0 + 1.2 diff --git a/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java b/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java index 0972d7a365..5dfb5d352e 100644 --- a/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java +++ b/source/java/org/alfresco/repo/admin/patch/AbstractPatch.java @@ -40,7 +40,7 @@ public abstract class AbstractPatch implements Patch private static Log logger = LogFactory.getLog(AbstractPatch.class); private String id; - private String applyAfterVersion; + private String applyToVersion; private String description; /** a list of patches that this one depends on */ private List dependsOn; @@ -60,7 +60,7 @@ public abstract class AbstractPatch implements Patch StringBuilder sb = new StringBuilder(56); sb.append("Patch") .append("[id=").append(getId()) - .append(", after=").append(getApplyAfterVersion()) + .append(", after=").append(getApplyToVersion()) .append(", description=").append(getDescription()) .append("]"); return sb.toString(); @@ -88,18 +88,18 @@ public abstract class AbstractPatch implements Patch this.id = id; } - public String getApplyAfterVersion() + public String getApplyToVersion() { - return applyAfterVersion; + return applyToVersion; } /** * * @param applyAfterVersion the version of the repository after which this patch must be applied. */ - public void setApplyAfterVersion(String applyAfterVersion) + public void setApplyToVersion(String applyAfterVersion) { - this.applyAfterVersion = applyAfterVersion; + this.applyToVersion = applyAfterVersion; } public String getDescription() @@ -144,10 +144,10 @@ public abstract class AbstractPatch implements Patch " patch: " + this); } // check that the necessary properties have been set - if (id == null || applyAfterVersion == null || description == null) + if (id == null || applyToVersion == null || description == null) { throw new AlfrescoRuntimeException( - "Patch properties 'id', 'applyAfterVersion' and 'description' have not all been set on this patch: \n" + + "Patch properties 'id', 'applyToVersion' and 'description' have not all been set on this patch: \n" + " patch: " + this); } else if (transactionService == null) diff --git a/source/java/org/alfresco/repo/admin/patch/Patch.java b/source/java/org/alfresco/repo/admin/patch/Patch.java index 579fdb6feb..36be66ae71 100644 --- a/source/java/org/alfresco/repo/admin/patch/Patch.java +++ b/source/java/org/alfresco/repo/admin/patch/Patch.java @@ -29,6 +29,7 @@ import org.alfresco.service.cmr.admin.PatchException; * Patches must not be reappliable. It is up to the patch management systems * to ensure that patches are never reapplied. * + * @see org.alfresco.repo.admin.patch.AbstractPatch * @since 1.2 * @author Derek Hulley */ @@ -38,7 +39,11 @@ public interface Patch public String getDescription(); - public String getApplyAfterVersion(); + /** + * @see PatchService#applyOutstandingPatches() + * @see AbstractPatch#setApplyToVersion(String) + */ + public String getApplyToVersion(); /** * Get patches that this patch depends on diff --git a/source/java/org/alfresco/repo/admin/patch/PatchService.java b/source/java/org/alfresco/repo/admin/patch/PatchService.java index 35b3ad5c3a..cd6d46369f 100644 --- a/source/java/org/alfresco/repo/admin/patch/PatchService.java +++ b/source/java/org/alfresco/repo/admin/patch/PatchService.java @@ -50,6 +50,13 @@ public interface PatchService * Apply all outstanding patches that are relevant to the repo. * If there is a failure, then the patches that were applied will remain so, * but the process will not attempt to apply any further patches. + *

+ * Patches have a version, e.g. 1.1.1, which is the version of the repo + * after which the patch should be applied. If the repository version is 1.1.2 + * then the patch will not be applied as the repository was created with a newer version + * of the codebase, thereby rendering the patch unecessary. If the repository is at + * version 1.1 then the patch needs to be applied as the codebase of the repository + * is newer than the repository creation. * * @return Returns true if all outstanding patches were applied, or false if the process * was termintated before all patches could be applied. diff --git a/source/java/org/alfresco/repo/admin/patch/PatchServiceImpl.java b/source/java/org/alfresco/repo/admin/patch/PatchServiceImpl.java index 2a22f62f41..c974ed7b5a 100644 --- a/source/java/org/alfresco/repo/admin/patch/PatchServiceImpl.java +++ b/source/java/org/alfresco/repo/admin/patch/PatchServiceImpl.java @@ -21,7 +21,9 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.StringTokenizer; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.domain.AppliedPatch; import org.alfresco.service.cmr.admin.PatchException; import org.alfresco.service.cmr.admin.PatchInfo; @@ -184,9 +186,9 @@ public class PatchServiceImpl implements PatchService String report = null; boolean success = false; // first check whether the patch is relevant to the repo - Descriptor repo = descriptorService.getRepositoryDescriptor(); - String versionLabel = repo.getVersionLabel(); - if (versionLabel.compareTo(patch.getApplyAfterVersion()) >= 0) + Descriptor repoDescriptor = descriptorService.getRepositoryDescriptor(); + boolean applies = applies(repoDescriptor, patch); + if (!applies) { // create a dummy report StringBuilder sb = new StringBuilder(128); @@ -213,9 +215,9 @@ public class PatchServiceImpl implements PatchService appliedPatch = patchDaoService.newAppliedPatch(patch.getId()); // fill in the record's details appliedPatch.setDescription(patch.getDescription()); - appliedPatch.setApplyAfterVersion(patch.getApplyAfterVersion()); + appliedPatch.setApplyToVersion(patch.getApplyToVersion()); appliedPatch.setSucceeded(success); - appliedPatch.setAppliedOnVersion(versionLabel); + appliedPatch.setAppliedOnVersion(repoDescriptor.getVersion()); appliedPatch.setAppliedOnDate(new Date()); appliedPatch.setReport(report); // create the info for returning @@ -227,4 +229,89 @@ public class PatchServiceImpl implements PatchService } return patchInfo; } + + /** + * Check whether or not the patch should be applied to the repository, given the descriptor. + * This helper is required to + * + * @param repoDescriptor contains the version details of the repository + * @param patch the patch whos version must be checked + * @return Returns true if the patch should be applied to the repository + */ + private boolean applies(Descriptor repoDescriptor, Patch patch) + { + // resolve the version numbers of the repo + int[] repoVersions = new int[] {0, 0, 0}; + try + { + if (repoDescriptor.getVersionMajor() != null) + { + repoVersions[0] = Integer.parseInt(repoDescriptor.getVersionMajor()); + } + if (repoDescriptor.getVersionMinor() != null) + { + repoVersions[1] = Integer.parseInt(repoDescriptor.getVersionMinor()); + } + if (repoDescriptor.getVersionRevision() != null) + { + repoVersions[2] = Integer.parseInt(repoDescriptor.getVersionRevision()); + } + } + catch (NumberFormatException e) + { + throw new AlfrescoRuntimeException("Non-numeric repository version are not allowed: " + + repoDescriptor.getVersion()); + } + + // by default, the patch won't apply. All the revision numbers will have to be greater + // than that of the repo to apply + int[] applyToVersions = new int[] {0, 0, 0}; + try + { + // break the patch version up + String applyToVersion = patch.getApplyToVersion(); + StringTokenizer tokens = new StringTokenizer(applyToVersion, "."); + for (int i = 0; i < 3 && tokens.hasMoreTokens(); i++) + { + String versionStr = tokens.nextToken(); + applyToVersions[i] = Integer.parseInt(versionStr); + } + } + catch (NumberFormatException e) + { + throw new AlfrescoRuntimeException("Non-numeric patch apply version: " + patch); + } + + // compare each version number + // in the event of a match, we don't apply as the patch version is the + boolean apply = true; + for (int i = 0; i < 3; i++) + { + if (repoVersions[i] < applyToVersions[i]) + { + // repo is old and patch is newer - we definitely need to apply + apply = true; + break; + } + else if (repoVersions[i] > applyToVersions[i]) + { + // the repo version number is high enough (repo is new enough) that patch doesn't apply + apply = false; + break; + } + else + { + // so far, the two match + } + } + + // done + if (logger.isDebugEnabled()) + { + logger.debug("Patch version number check against repo version: \n" + + " repo version: " + repoDescriptor.getVersion() + "\n" + + " patch: " + patch); + } + return apply; + } } diff --git a/source/java/org/alfresco/repo/admin/patch/SamplePatch.java b/source/java/org/alfresco/repo/admin/patch/SamplePatch.java index 049ebe9f36..f92ee2d1a2 100644 --- a/source/java/org/alfresco/repo/admin/patch/SamplePatch.java +++ b/source/java/org/alfresco/repo/admin/patch/SamplePatch.java @@ -43,7 +43,7 @@ public class SamplePatch extends AbstractPatch setTransactionService(transactionService); setId("SamplePatch"); setDescription("This is a sample patch"); - setApplyAfterVersion("1.0.0"); + setApplyToVersion("1.0.0"); } /** diff --git a/source/java/org/alfresco/repo/domain/AppliedPatch.java b/source/java/org/alfresco/repo/domain/AppliedPatch.java index 3cba265d80..8f87d652b0 100644 --- a/source/java/org/alfresco/repo/domain/AppliedPatch.java +++ b/source/java/org/alfresco/repo/domain/AppliedPatch.java @@ -31,8 +31,8 @@ public interface AppliedPatch public String getDescription(); public void setDescription(String description); - public String getApplyAfterVersion(); - public void setApplyAfterVersion(String version); + public String getApplyToVersion(); + public void setApplyToVersion(String version); public boolean getSucceeded(); public void setSucceeded(boolean succeeded); diff --git a/source/java/org/alfresco/repo/domain/hibernate/AppliedPatch.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/AppliedPatch.hbm.xml index 7ec8bfa9fe..38a8df7608 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/AppliedPatch.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/AppliedPatch.hbm.xml @@ -16,7 +16,7 @@ optimistic-lock="version" > - + diff --git a/source/java/org/alfresco/repo/domain/hibernate/AppliedPatchImpl.java b/source/java/org/alfresco/repo/domain/hibernate/AppliedPatchImpl.java index 837542d17b..5bb9ecee98 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/AppliedPatchImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/AppliedPatchImpl.java @@ -76,11 +76,11 @@ public class AppliedPatchImpl implements AppliedPatch this.succeeded = succeeded; } - public String getApplyAfterVersion() + public String getApplyToVersion() { return applyAfterVersion; } - public void setApplyAfterVersion(String applyAfterVersion) + public void setApplyToVersion(String applyAfterVersion) { this.applyAfterVersion = applyAfterVersion; } diff --git a/source/java/org/alfresco/service/cmr/admin/PatchInfo.java b/source/java/org/alfresco/service/cmr/admin/PatchInfo.java index 0309a4ef05..50dfb04f26 100644 --- a/source/java/org/alfresco/service/cmr/admin/PatchInfo.java +++ b/source/java/org/alfresco/service/cmr/admin/PatchInfo.java @@ -33,7 +33,7 @@ public class PatchInfo implements Serializable private String id; private String description; - private String applyAfterVersion; + private String applyToVersion; private boolean succeeded; private String appliedOnVersion; private Date appliedOnDate; @@ -43,7 +43,7 @@ public class PatchInfo implements Serializable { this.id = id; this.description = description; - this.applyAfterVersion = applyAfterVersion; + this.applyToVersion = applyAfterVersion; this.succeeded = false; } @@ -51,7 +51,7 @@ public class PatchInfo implements Serializable { this.id = appliedPatch.getId(); this.description = appliedPatch.getDescription(); - this.applyAfterVersion = appliedPatch.getApplyAfterVersion(); + this.applyToVersion = appliedPatch.getApplyToVersion(); this.succeeded = appliedPatch.getSucceeded(); this.appliedOnVersion = appliedPatch.getAppliedOnVersion(); @@ -78,9 +78,9 @@ public class PatchInfo implements Serializable /** * @return Returns the version of the repository after which this patch must be applied */ - public String getApplyAfterVersion() + public String getApplyToVersion() { - return applyAfterVersion; + return applyToVersion; } /**