001package org.apache.archiva.repository.metadata.base; 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 org.apache.archiva.model.ArchivaRepositoryMetadata; 023import org.apache.archiva.model.Plugin; 024import org.apache.archiva.repository.metadata.RepositoryMetadataException; 025import org.apache.archiva.repository.storage.StorageAsset; 026import org.apache.archiva.xml.XMLException; 027import org.apache.archiva.xml.XMLWriter; 028import org.apache.archiva.xml.XmlUtil; 029import org.apache.commons.collections4.CollectionUtils; 030import org.apache.commons.lang3.StringUtils; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033import org.w3c.dom.Document; 034import org.w3c.dom.Element; 035 036import javax.xml.parsers.ParserConfigurationException; 037import java.io.IOException; 038import java.io.OutputStreamWriter; 039import java.io.Writer; 040import java.util.Collections; 041import java.util.Comparator; 042import java.util.Iterator; 043import java.util.List; 044 045/** 046 * RepositoryMetadataWriter 047 */ 048public class RepositoryMetadataWriter 049{ 050 private static final Logger log = LoggerFactory.getLogger(RepositoryMetadataWriter.class); 051 052 public static void write( ArchivaRepositoryMetadata metadata, StorageAsset outputFile ) 053 throws RepositoryMetadataException 054 { 055 boolean thrown = false; 056 try (OutputStreamWriter writer = new OutputStreamWriter( outputFile.getWriteStream(true))) 057 { 058 write( metadata, writer ); 059 writer.flush(); 060 } 061 catch ( IOException e ) 062 { 063 thrown = true; 064 throw new RepositoryMetadataException( 065 "Unable to write metadata file: " + outputFile.getPath() + " - " + e.getMessage(), e ); 066 } 067 finally 068 { 069 if ( thrown ) 070 { 071 try { 072 outputFile.getStorage().removeAsset(outputFile); 073 } catch (IOException e) { 074 log.error("Could not remove asset {}", outputFile); 075 } 076 } 077 } 078 } 079 080 public static void write( ArchivaRepositoryMetadata metadata, Writer writer ) 081 throws RepositoryMetadataException 082 { 083 Document doc = null; 084 try { 085 doc = XmlUtil.createDocument(); 086 } catch (ParserConfigurationException e) { 087 throw new RepositoryMetadataException("Could not create xml doc " + e.getMessage(), e); 088 } 089 090 Element root = doc.createElement( "metadata" ); 091 doc.appendChild(root); 092 093 addOptionalElementText( root, "groupId", metadata.getGroupId() ); 094 addOptionalElementText( root, "artifactId", metadata.getArtifactId() ); 095 addOptionalElementText( root, "version", metadata.getVersion() ); 096 097 if ( CollectionUtils.isNotEmpty( metadata.getPlugins() ) ) 098 { 099 Element plugins = XmlUtil.addChild(root, "plugins" ); 100 101 List<Plugin> pluginList = metadata.getPlugins(); 102 Collections.sort( pluginList, PluginComparator.INSTANCE ); 103 104 for ( Plugin plugin : metadata.getPlugins() ) 105 { 106 Element p = XmlUtil.addChild(plugins, "plugin" ); 107 XmlUtil.addChild(doc, p, "prefix" ).setTextContent( plugin.getPrefix() ); 108 XmlUtil.addChild(doc, p, "artifactId" ).setTextContent( plugin.getArtifactId() ); 109 addOptionalElementText( p, "name", plugin.getName() ); 110 } 111 } 112 113 if ( CollectionUtils.isNotEmpty( metadata.getAvailableVersions() ) // 114 || StringUtils.isNotBlank( metadata.getReleasedVersion() ) // 115 || StringUtils.isNotBlank( metadata.getLatestVersion() ) // 116 || StringUtils.isNotBlank( metadata.getLastUpdated() ) // 117 || ( metadata.getSnapshotVersion() != null ) ) 118 { 119 Element versioning = XmlUtil.addChild(root, "versioning" ); 120 121 addOptionalElementText( versioning, "latest", metadata.getLatestVersion() ); 122 addOptionalElementText( versioning, "release", metadata.getReleasedVersion() ); 123 124 if ( metadata.getSnapshotVersion() != null ) 125 { 126 Element snapshot = XmlUtil.addChild(versioning, "snapshot" ); 127 String bnum = String.valueOf( metadata.getSnapshotVersion().getBuildNumber() ); 128 addOptionalElementText( snapshot, "buildNumber", bnum ); 129 addOptionalElementText( snapshot, "timestamp", metadata.getSnapshotVersion().getTimestamp() ); 130 } 131 132 if ( CollectionUtils.isNotEmpty( metadata.getAvailableVersions() ) ) 133 { 134 Element versions = XmlUtil.addChild(versioning, "versions" ); 135 Iterator<String> it = metadata.getAvailableVersions().iterator(); 136 while ( it.hasNext() ) 137 { 138 String version = it.next(); 139 XmlUtil.addChild(versions, "version" ).setTextContent( version ); 140 } 141 } 142 143 addOptionalElementText( versioning, "lastUpdated", metadata.getLastUpdated() ); 144 } 145 146 try 147 { 148 XMLWriter.write( doc, writer ); 149 } 150 catch ( XMLException e ) 151 { 152 throw new RepositoryMetadataException( "Unable to write xml contents to writer: " + e.getMessage(), e ); 153 } 154 } 155 156 private static void addOptionalElementText( Element elem, String elemName, String text ) 157 { 158 if ( StringUtils.isBlank( text ) ) 159 { 160 return; 161 } 162 163 XmlUtil.addChild(elem, elemName ).setTextContent( text ); 164 } 165 166 private static class PluginComparator 167 implements Comparator<Plugin> 168 { 169 private static final PluginComparator INSTANCE = new PluginComparator(); 170 171 @Override 172 public int compare( Plugin plugin, Plugin plugin2 ) 173 { 174 if ( plugin.getPrefix() != null && plugin2.getPrefix() != null ) 175 { 176 return plugin.getPrefix().compareTo( plugin2.getPrefix() ); 177 } 178 if ( plugin.getName() != null && plugin2.getName() != null ) 179 { 180 return plugin.getName().compareTo( plugin2.getName() ); 181 } 182 // we assume artifactId is not null which sounds good :-) 183 return plugin.getArtifactId().compareTo( plugin2.getArtifactId() ); 184 } 185 } 186}