001package org.apache.archiva.repository.metadata; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.ArrayList; 023import java.util.List; 024 025import org.apache.commons.lang.StringUtils; 026import org.apache.archiva.model.ArchivaModelCloner; 027import org.apache.archiva.model.ArchivaRepositoryMetadata; 028import org.apache.archiva.model.Plugin; 029import org.apache.archiva.model.SnapshotVersion; 030 031/** 032 * RepositoryMetadataMerge 033 * 034 * 035 */ 036public class RepositoryMetadataMerge 037{ 038 public static ArchivaRepositoryMetadata merge( final ArchivaRepositoryMetadata mainMetadata, 039 final ArchivaRepositoryMetadata sourceMetadata ) 040 throws RepositoryMetadataException 041 { 042 if ( mainMetadata == null ) 043 { 044 throw new RepositoryMetadataException( "Cannot merge a null main project." ); 045 } 046 047 if ( sourceMetadata == null ) 048 { 049 throw new RepositoryMetadataException( "Cannot copy to a null parent project." ); 050 } 051 052 ArchivaRepositoryMetadata merged = new ArchivaRepositoryMetadata(); 053 054 merged.setGroupId( merge( mainMetadata.getGroupId(), sourceMetadata.getGroupId() ) ); 055 merged.setArtifactId( merge(mainMetadata.getArtifactId(), sourceMetadata.getArtifactId())); 056 merged.setVersion( merge(mainMetadata.getVersion(), sourceMetadata.getVersion()) ); 057 merged.setReleasedVersion( merge( mainMetadata.getReleasedVersion(), sourceMetadata.getReleasedVersion() ) ); 058 merged.setSnapshotVersion( merge( mainMetadata.getSnapshotVersion(), sourceMetadata.getSnapshotVersion() ) ); 059 merged.setAvailableVersions( mergeAvailableVersions( mainMetadata.getAvailableVersions(), sourceMetadata.getAvailableVersions() ) ); 060 merged.setPlugins( mergePlugins( mainMetadata.getPlugins(), sourceMetadata.getPlugins() ) ); 061 062 //Don't set if merge was not possible 063 long lastUpdated = mergeTimestamp( mainMetadata.getLastUpdated(), sourceMetadata.getLastUpdated()); 064 if (lastUpdated > -1) 065 { 066 merged.setLastUpdated( Long.toString(lastUpdated) ); 067 } 068 069 return merged; 070 } 071 072 private static boolean empty( String val ) 073 { 074 if ( val == null ) 075 { 076 return true; 077 } 078 079 return ( val.trim().length() <= 0 ); 080 } 081 082 private static long mergeTimestamp(String mainTimestamp, String sourceTimestamp) 083 { 084 if (sourceTimestamp == null && mainTimestamp != null) 085 { 086 return convertTimestampToLong(mainTimestamp); 087 } 088 089 if (mainTimestamp == null && sourceTimestamp != null) 090 { 091 return convertTimestampToLong(sourceTimestamp); 092 } 093 094 if (sourceTimestamp == null && mainTimestamp == null) 095 { 096 return -1; 097 } 098 099 return mergeTimestamp(convertTimestampToLong(mainTimestamp), convertTimestampToLong(sourceTimestamp)); 100 } 101 102 private static long mergeTimestamp(long mainTimestamp, long sourceTimestamp) 103 { 104 return Math.max( mainTimestamp, sourceTimestamp ); 105 } 106 107 private static SnapshotVersion merge( SnapshotVersion mainSnapshotVersion, SnapshotVersion sourceSnapshotVersion ) 108 { 109 if ( sourceSnapshotVersion == null ) 110 { 111 return mainSnapshotVersion; 112 } 113 114 if ( mainSnapshotVersion == null ) 115 { 116 return ArchivaModelCloner.clone( sourceSnapshotVersion ); 117 } 118 119 SnapshotVersion merged = new SnapshotVersion(); 120 121 long mainSnapshotLastUpdated = convertTimestampToLong(mainSnapshotVersion.getTimestamp()); 122 long sourceSnapshotLastUpdated = convertTimestampToLong(sourceSnapshotVersion.getTimestamp()); 123 124 long lastUpdated = mergeTimestamp(mainSnapshotLastUpdated, sourceSnapshotLastUpdated); 125 126 if (lastUpdated == mainSnapshotLastUpdated) 127 { 128 merged.setTimestamp(mainSnapshotVersion.getTimestamp()); 129 merged.setBuildNumber(mainSnapshotVersion.getBuildNumber()); 130 } 131 else 132 { 133 merged.setTimestamp(sourceSnapshotVersion.getTimestamp()); 134 merged.setBuildNumber(sourceSnapshotVersion.getBuildNumber()); 135 } 136 137 return merged; 138 } 139 140 private static long convertTimestampToLong(String timestamp) 141 { 142 if (timestamp == null) 143 { 144 return -1; 145 } 146 147 return getLongFromTimestampSafely(StringUtils.replace(timestamp, ".", "")); 148 } 149 150 private static long getLongFromTimestampSafely( String timestampString ) 151 { 152 try 153 { 154 return Long.parseLong(timestampString); 155 } 156 catch (NumberFormatException e) 157 { 158 return -1; 159 } 160 } 161 162 private static String merge( String main, String source ) 163 { 164 if ( empty( main ) && !empty( source ) ) 165 { 166 return source; 167 } 168 169 return main; 170 } 171 172 private static List<Plugin> mergePlugins(List<Plugin> mainPlugins, List<Plugin> sourcePlugins) 173 { 174 if ( sourcePlugins == null ) 175 { 176 return mainPlugins; 177 } 178 179 if ( mainPlugins == null ) 180 { 181 return clonePlugins( sourcePlugins ); 182 } 183 184 List<Plugin> merged = clonePlugins( mainPlugins ); 185 186 for ( Plugin plugin : sourcePlugins ) 187 { 188 if ( !merged.contains( plugin ) ) 189 { 190 merged.add( plugin ); 191 } 192 } 193 194 return merged; 195 } 196 197 /** 198 * Clones a list of plugins. 199 * 200 * This method exists because ArchivaModelCloner.clonePlugins() 201 * only works with artifact references. 202 * 203 * @param plugins 204 * @return list of cloned plugins 205 */ 206 private static List<Plugin> clonePlugins(List<Plugin> plugins) 207 { 208 if (plugins == null) 209 { 210 return null; 211 } 212 213 List<Plugin> result = new ArrayList<>(); 214 215 for (Plugin plugin : plugins) 216 { 217 Plugin clonedPlugin = new Plugin(); 218 clonedPlugin.setArtifactId(plugin.getArtifactId()); 219 clonedPlugin.setName(plugin.getName()); 220 clonedPlugin.setPrefix(plugin.getPrefix()); 221 result.add(plugin); 222 } 223 224 return result; 225 } 226 227 private static List<String> mergeAvailableVersions( List<String> mainAvailableVersions, List<String> sourceAvailableVersions ) 228 { 229 if ( sourceAvailableVersions == null ) 230 { 231 return mainAvailableVersions; 232 } 233 234 if ( mainAvailableVersions == null ) 235 { 236 return ArchivaModelCloner.cloneAvailableVersions( sourceAvailableVersions ); 237 } 238 239 List<String> merged = ArchivaModelCloner.cloneAvailableVersions( mainAvailableVersions ); 240 241 for ( String sourceVersion : sourceAvailableVersions ) 242 { 243 if ( !merged.contains( sourceVersion ) ) 244 { 245 merged.add( sourceVersion ); 246 } 247 } 248 249 return merged; 250 } 251}