001package org.apache.maven.artifact.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.io.File;
023import java.io.IOException;
024import java.io.Reader;
025import java.io.Writer;
026
027import org.apache.maven.artifact.Artifact;
028import org.apache.maven.artifact.metadata.ArtifactMetadata;
029import org.apache.maven.artifact.repository.ArtifactRepository;
030import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
031import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
032import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
033import org.codehaus.plexus.util.IOUtil;
034import org.codehaus.plexus.util.ReaderFactory;
035import org.codehaus.plexus.util.WriterFactory;
036import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
037
038/**
039 * Shared methods of the repository metadata handling.
040 *
041 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
042 */
043public abstract class AbstractRepositoryMetadata
044    implements RepositoryMetadata
045{
046    private Metadata metadata;
047
048    protected AbstractRepositoryMetadata( Metadata metadata )
049    {
050        this.metadata = metadata;
051    }
052
053    public String getRemoteFilename()
054    {
055        return "maven-metadata.xml";
056    }
057
058    public String getLocalFilename( ArtifactRepository repository )
059    {        
060        return "maven-metadata-" + repository.getKey() + ".xml";
061    }
062
063    public void storeInLocalRepository( ArtifactRepository localRepository,
064                                        ArtifactRepository remoteRepository )
065        throws RepositoryMetadataStoreException
066    {
067        try
068        {
069            updateRepositoryMetadata( localRepository, remoteRepository );
070        }
071        catch ( IOException e )
072        {
073            throw new RepositoryMetadataStoreException( "Error updating group repository metadata", e );
074        }
075        catch ( XmlPullParserException e )
076        {
077            throw new RepositoryMetadataStoreException( "Error updating group repository metadata", e );
078        }
079    }
080
081    protected void updateRepositoryMetadata( ArtifactRepository localRepository,
082                                             ArtifactRepository remoteRepository )
083        throws IOException, XmlPullParserException
084    {
085        MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
086
087        Metadata metadata = null;
088
089        File metadataFile = new File( localRepository.getBasedir(),
090            localRepository.pathOfLocalRepositoryMetadata( this, remoteRepository ) );
091
092        if ( metadataFile.length() == 0 )
093        {
094            metadataFile.delete();
095        }
096        else if ( metadataFile.exists() )
097        {
098            Reader reader = null;
099
100            try
101            {
102                reader = ReaderFactory.newXmlReader( metadataFile );
103
104                metadata = mappingReader.read( reader, false );
105            }
106            finally
107            {
108                IOUtil.close( reader );
109            }
110        }
111
112        boolean changed;
113
114        // If file could not be found or was not valid, start from scratch
115        if ( metadata == null )
116        {
117            metadata = this.metadata;
118
119            changed = true;
120        }
121        else
122        {
123            changed = metadata.merge( this.metadata );
124        }
125
126        // beware meta-versions!
127        String version = metadata.getVersion();
128        if ( version != null && ( Artifact.LATEST_VERSION.equals( version ) || Artifact.RELEASE_VERSION.equals(
129            version ) ) )
130        {
131            // meta-versions are not valid <version/> values...don't write them.
132            metadata.setVersion( null );
133        }
134
135        if ( changed || !metadataFile.exists() )
136        {
137            Writer writer = null;
138            try
139            {
140                metadataFile.getParentFile().mkdirs();
141                writer = WriterFactory.newXmlWriter( metadataFile );
142
143                MetadataXpp3Writer mappingWriter = new MetadataXpp3Writer();
144
145                mappingWriter.write( writer, metadata );
146            }
147            finally
148            {
149                IOUtil.close( writer );
150            }
151        }
152        else
153        {
154            metadataFile.setLastModified( System.currentTimeMillis() );
155        }
156    }
157
158    public String toString()
159    {
160        return "repository metadata for: \'" + getKey() + "\'";
161    }
162
163    protected static Metadata createMetadata( Artifact artifact,
164                                              Versioning versioning )
165    {
166        Metadata metadata = new Metadata();
167        metadata.setGroupId( artifact.getGroupId() );
168        metadata.setArtifactId( artifact.getArtifactId() );
169        metadata.setVersion( artifact.getVersion() );
170        metadata.setVersioning( versioning );
171        return metadata;
172    }
173
174    protected static Versioning createVersioning( Snapshot snapshot )
175    {
176        Versioning versioning = new Versioning();
177        versioning.setSnapshot( snapshot );
178        versioning.updateTimestamp();
179        return versioning;
180    }
181
182    public void setMetadata( Metadata metadata )
183    {
184        this.metadata = metadata;
185    }
186
187    public Metadata getMetadata()
188    {
189        return metadata;
190    }
191
192    public void merge( org.apache.maven.repository.legacy.metadata.ArtifactMetadata metadata )
193    {
194        // TODO: not sure that it should assume this, maybe the calls to addMetadata should pre-merge, then artifact replaces?
195        AbstractRepositoryMetadata repoMetadata = (AbstractRepositoryMetadata) metadata;
196        this.metadata.merge( repoMetadata.getMetadata() );
197    }
198    
199    public void merge( ArtifactMetadata metadata )
200    {
201        // TODO: not sure that it should assume this, maybe the calls to addMetadata should pre-merge, then artifact replaces?
202        AbstractRepositoryMetadata repoMetadata = (AbstractRepositoryMetadata) metadata;
203        this.metadata.merge( repoMetadata.getMetadata() );
204    }
205
206    public String extendedToString()
207    {
208        StringBuilder buffer = new StringBuilder();
209
210        buffer.append( "\nRepository Metadata\n--------------------------" );
211        buffer.append( "\nGroupId: " ).append( getGroupId() );
212        buffer.append( "\nArtifactId: " ).append( getArtifactId() );
213        buffer.append( "\nMetadata Type: " ).append( getClass().getName() );
214
215        return buffer.toString();
216    }
217
218    public int getNature()
219    {
220        return RELEASE;
221    }
222
223    public ArtifactRepositoryPolicy getPolicy( ArtifactRepository repository )
224    {
225        int nature = getNature();
226        if ( ( nature & RepositoryMetadata.RELEASE_OR_SNAPSHOT ) == RepositoryMetadata.RELEASE_OR_SNAPSHOT )
227        {
228            ArtifactRepositoryPolicy policy = new ArtifactRepositoryPolicy( repository.getReleases() );
229            policy.merge( repository.getSnapshots() );
230            return policy;
231        }
232        else if ( ( nature & RepositoryMetadata.SNAPSHOT ) != 0 )
233        {
234            return repository.getSnapshots();
235        }
236        else
237        {
238            return repository.getReleases();
239        }
240    }
241
242}