You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by og...@apache.org on 2009/04/23 00:57:04 UTC

svn commit: r767705 [14/31] - in /maven/mercury/trunk/mercury-core: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/maven/ src/main/java/org/apache/maven/mercury/ src/main/java/org/apache/maven/mer...

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,362 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.client.retrieve;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.maven.mercury.crypto.api.StreamObserver;
+import org.apache.maven.mercury.crypto.api.StreamObserverException;
+import org.apache.maven.mercury.crypto.api.StreamObserverFactory;
+import org.apache.maven.mercury.crypto.api.StreamVerifierException;
+import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
+import org.apache.maven.mercury.logging.IMercuryLogger;
+import org.apache.maven.mercury.logging.MercuryLoggerManager;
+import org.apache.maven.mercury.spi.http.client.DestinationRealmResolver;
+import org.apache.maven.mercury.spi.http.client.HttpClientException;
+import org.apache.maven.mercury.transport.api.Binding;
+import org.apache.maven.mercury.transport.api.Server;
+import org.mortbay.jetty.client.HttpClient;
+
+public class DefaultRetriever implements Retriever
+{
+    private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( DefaultRetriever.class );
+    
+    private HttpClient _httpClient;
+    private Set<Server> _servers = new HashSet<Server>();
+
+    public DefaultRetriever()
+        throws HttpClientException
+    {
+        // TODO take the default settings for now
+        _httpClient = new HttpClient();
+        _httpClient.setConnectorType( HttpClient.CONNECTOR_SELECT_CHANNEL );
+        try
+        {
+            //TODO: What are all the reasons that the httpclient couldn't start up correctly?
+            _httpClient.start();
+        }
+        catch ( Exception e )
+        {
+            throw new HttpClientException( null, "Unable to start http client.", e );
+        }
+    }
+
+    public DefaultRetriever( HttpClient client )
+        throws HttpClientException
+    {
+        // TODO take the default settings for now
+        _httpClient = client;
+        try
+        {
+            if ( !_httpClient.isStarted() )
+            {
+                _httpClient.start();
+            }
+        }
+        catch ( Exception e )
+        {
+            throw new HttpClientException( null, "unable to start http client", e );
+        }
+    }
+                           
+    public void setServers (Set<Server>servers)
+    {
+        _servers.clear();
+        _servers.addAll(servers);
+        _httpClient.setRealmResolver(new DestinationRealmResolver(_servers));
+    }
+    
+    public Set<Server> getServers()
+    {
+        return _servers;
+    }
+
+    /**
+     * Retrieve a set of artifacts and wait until all retrieved successfully
+     * or an error occurs.
+     * <p/>
+     * Note: whilst this method is synchronous for the caller, the implementation
+     * will be asynchronous so many artifacts are fetched in parallel.
+     *
+     * @param request
+     * @return the list of errors, if any
+     */
+    public RetrievalResponse retrieve( RetrievalRequest request )
+    {
+        final RetrievalResponse[] response = new RetrievalResponse[]{null};
+
+        retrieve( request, new RetrievalCallback()
+        {
+            public void onComplete( RetrievalResponse r )
+            {
+                synchronized ( response )
+                {
+                    response[0] = r;
+                    response.notify();
+                }
+            }
+        } );
+
+        synchronized ( response )
+        {
+            try
+            {
+                while ( response[0] == null )
+                {
+                    response.wait();
+                }
+            }
+            catch ( InterruptedException e )
+            {
+                return null;
+            }
+            return response[0];
+        }
+    }
+
+    /**
+     * Retrieve a set of artifacts without waiting for the results.
+     * When all results have been obtained (or an error occurs) the
+     * RetrievalResponse will be called.
+     *
+     * @param request
+     * @param callback
+     */
+    public void retrieve( final RetrievalRequest request, final RetrievalCallback callback )
+    {
+        if ( request == null )
+        {
+            throw new IllegalArgumentException( "No request" );
+        }
+
+        if ( callback == null )
+        {
+            throw new IllegalArgumentException( "No callback" );
+        }
+
+        final AtomicInteger count = new AtomicInteger( request.getBindings().size() );
+
+        final List<RetrievalTarget> targets = new ArrayList<RetrievalTarget>( request.getBindings().size() );
+        final DefaultRetrievalResponse response = new DefaultRetrievalResponse();
+
+        Binding[] bindings = new Binding[request.getBindings().size()];
+        request.getBindings().toArray( bindings );
+
+        for ( int i = 0; i < bindings.length && count.get() > 0; i++ )
+        {
+            final Binding binding = bindings[i];
+            
+            RetrievalTarget target = null;
+            try
+            {
+                Server server = resolveServer(binding);
+                Set<StreamObserver> observers = createStreamObservers( server, binding.isExempt() );
+                
+                target = new RetrievalTarget( server, DefaultRetriever.this, binding, request.getValidators(), observers )
+                {
+                    public void onComplete()
+                    {
+                        //got the file, check the checksum
+                        boolean checksumOK = false;
+                        try
+                        {
+                          checksumOK = verifyChecksum();
+                          if ( !checksumOK )
+                          {
+                              response.add( new HttpClientException( binding, "Checksum failed") );
+                          }
+                        }
+                        catch( StreamVerifierException e )
+                        {
+                          response.add( new HttpClientException( binding, e.getMessage()) );
+                        }
+
+                        //if the file checksum is ok, then apply the validators
+                        if ( checksumOK )
+                        {
+                            List<String> validateErrors = new ArrayList<String>();
+                            if ( !validate( validateErrors ) )
+                            {
+                                for ( String s : validateErrors )
+                                {
+                                    response.add( new HttpClientException( binding, s ) );
+                                }
+                            }
+                        }
+
+                        if ( DefaultRetriever.this.isComplete( count, request, response, targets ) )
+                        {
+                            callback.onComplete( response );
+                        }
+                    }
+
+                    public void onError( HttpClientException exception )
+                    {
+                        response.add( exception );
+                        if ( DefaultRetriever.this.isComplete( count, request, response, targets ) )
+                        {
+                            callback.onComplete( response );
+                        }
+                    }
+                };
+
+                targets.add( target );
+            }
+            catch ( Exception e )
+            {
+                response.add( new HttpClientException( binding, e ) );
+                if ( isComplete( count, request, response, targets ) )
+                {
+                    callback.onComplete( response );
+                }
+            }
+        }
+
+        for ( final RetrievalTarget target : targets )
+        {
+            target.retrieve(); //go get the remote file
+        }
+    }
+
+    private boolean isComplete( AtomicInteger count,
+                                RetrievalRequest request,
+                                RetrievalResponse response,
+                                List<RetrievalTarget> targets )
+    {
+        boolean completor = count.decrementAndGet() == 0;
+        
+        if ( !completor && request.isFailFast() && response.getExceptions().size() > 0 )
+        {
+            completor = count.getAndSet( 0 ) > 0;
+        }
+
+        if ( completor )
+        {
+            if ( response.getExceptions().size() == 0 )
+            {
+                for ( RetrievalTarget t : targets )
+                {
+                    if ( t != null )
+                    {
+                        t.move();
+                    }
+                }
+            }
+
+            for ( RetrievalTarget t : targets )
+            {
+                t.cleanup();
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Get the jetty async client
+     *
+     * @return
+     */
+    public HttpClient getHttpClient()
+    {
+        return _httpClient;
+    }
+    
+    private Server resolveServer (Binding binding)
+    throws MalformedURLException
+    {
+        if (binding.getRemoteResource() == null)
+        return null;
+        
+        URL bindingURL = binding.getRemoteResource();
+        if (_servers == null)
+            return null;
+        
+        Iterator<Server> itor = _servers.iterator();
+        Server server = null;
+        while(itor.hasNext() && server==null)
+        {
+            Server s = itor.next();
+            if (bindingURL.getProtocol().equalsIgnoreCase(s.getURL().getProtocol()) 
+                    && bindingURL.getHost().equalsIgnoreCase(s.getURL().getHost())
+                    && bindingURL.getPort() == s.getURL().getPort())
+                server = s;
+        }
+        return server;
+    }
+    
+    private Set<StreamObserver> createStreamObservers (Server server, boolean exempt )
+    throws StreamObserverException
+    {
+        HashSet<StreamObserver> observers = new HashSet<StreamObserver>();
+        
+        if( server == null )
+          return observers;
+        
+        if ( (!exempt) && server.hasReaderStreamVerifierFactories() )
+        {
+            Set<StreamVerifierFactory> factories = server.getReaderStreamVerifierFactories();
+            for( StreamVerifierFactory f:factories )
+            {
+                observers.add( f.newInstance() );
+            }
+        }
+
+        if ( server.hasReaderStreamObserverFactories() )
+        {
+            Set<StreamObserverFactory> factories = server.getReaderStreamObserverFactories();
+            for( StreamObserverFactory f:factories )
+            {
+                observers.add( f.newInstance() );
+            }
+        }
+        return observers;
+    }
+    
+    public void stop()
+    {
+        if( _httpClient == null )
+            return;
+        
+        if( _httpClient.isStopped() || _httpClient.isStopping() )
+            return;
+        
+        try
+        {
+            _httpClient.stop();
+        }
+        catch ( Exception e )
+        {
+            LOG.error( e.getMessage() );
+        }
+            
+    }
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,184 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.client.retrieve;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.maven.mercury.crypto.api.StreamObserver;
+import org.apache.maven.mercury.logging.IMercuryLogger;
+import org.apache.maven.mercury.logging.MercuryLoggerManager;
+import org.apache.maven.mercury.spi.http.client.FileExchange;
+import org.apache.maven.mercury.spi.http.client.HttpClientException;
+import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
+import org.apache.maven.mercury.spi.http.client.ObservableOutputStream;
+import org.apache.maven.mercury.transport.api.Binding;
+import org.apache.maven.mercury.transport.api.Server;
+import org.mortbay.io.Buffer;
+import org.mortbay.io.BufferUtil;
+import org.mortbay.jetty.HttpHeaders;
+import org.mortbay.jetty.HttpMethods;
+import org.mortbay.jetty.client.HttpClient;
+
+
+/**
+ * FileGetExchange
+ * <p/>
+ * Make an asynchronous request to download a file and stream its bytes to a file.
+ * When all bytes have been received onFileComplete will be called.
+ * <p/>
+ * As an optimization, the file that is being downloaded can have it's
+ * SHA-1 digest calculated as it is being streamed down.
+ */
+public abstract class FileGetExchange extends FileExchange
+{
+    private static final IMercuryLogger log = MercuryLoggerManager.getLogger(FileGetExchange.class);
+    private OutputStream _outputStream;
+    private Set<StreamObserver> _observers = new HashSet<StreamObserver>();
+    int _contentLength = -1;
+    
+    /**
+     * Constructor.
+     *
+     * @param binding        the remote file to fetch
+     * @param localFile      the local file location to store the remote file
+     * @param observers      observers of the io stream
+     * @param client         async http client
+     */
+    public FileGetExchange( Server server, Binding binding, File localFile, Set<StreamObserver> observers, HttpClient client )
+    {
+        super( server, binding, localFile, client );
+
+        if( observers != null && ! observers.isEmpty() )
+            _observers.addAll(observers);
+    }
+
+
+    /** Start the retrieval. */
+    public void send()
+    {
+        setMethod( HttpMethods.GET );
+        super.send();
+    }
+
+    protected void onResponseHeader(Buffer name, Buffer value) throws IOException
+    {
+        int header = HttpHeaders.CACHE.getOrdinal(value);
+        switch (header)
+        {
+            case HttpHeaders.CONTENT_LENGTH_ORDINAL:
+                _contentLength = BufferUtil.toInt(value);
+                for (StreamObserver o:_observers)
+                {
+                    o.setLength(_contentLength);
+                }
+                if (log.isDebugEnabled())
+                    log.debug("GET of "+_contentLength +" bytes");
+                break;
+            case HttpHeaders.LAST_MODIFIED_ORDINAL:
+                for (StreamObserver o:_observers)
+                {
+                    o.setLastModified(BufferUtil.to8859_1_String(value));
+                }
+                break;
+        }
+    }
+    
+
+    protected void onResponseComplete()
+    {
+        //All bytes of file have been received
+        try
+        {
+            if (_outputStream != null)
+                _outputStream.close();
+            
+            if ( _status == HttpServletResponse.SC_NOT_FOUND )
+            {
+                onFileError( _url, new FileNotFoundException( "File not found on remote server" ) );
+                return;
+            }
+            else if ( _status != HttpServletResponse.SC_OK )
+            {
+                onFileError( _url, new Exception( "Http status code=" + _status ) );
+                return;
+            }
+
+            onFileComplete( _url, _localFile );
+        }
+        catch ( Exception e )
+        {
+            onFileError( _url, new HttpClientException( _binding, e.getLocalizedMessage() ) );
+        }
+    }
+
+
+    /**
+     * Stream the downloaded bytes to a file
+     *
+     * @see org.mortbay.jetty.client.HttpExchange$ContentExchange#onResponseContent(org.sonatype.io.Buffer)
+     */
+    protected void onResponseContent( Buffer content )
+        throws IOException
+    {
+        try
+        {
+            OutputStream os = getOutputStream();
+            content.writeTo( os );
+        }
+        catch ( NoSuchAlgorithmException e )
+        {
+            throw new IOException( e.getLocalizedMessage() );
+        }
+    }
+
+
+    /**
+     * Get an output stream for the file contents. A digest can be optionally calculated
+     * for the file contents as they are being streamed.
+     *
+     * @return OutputStream for file contents
+     * @throws IOException              if io error occurs
+     * @throws NoSuchAlgorithmException if the SHA-1 algorithm is not supported
+     */
+    protected OutputStream getOutputStream()
+        throws IOException, NoSuchAlgorithmException
+    {
+        if ( _outputStream == null )
+        {
+            OutputStream os = null;
+            if (_binding.isFile())
+                os = new FileOutputStream( _localFile );
+            else if (_binding.isInMemory())
+                os = _binding.getLocalOutputStream();
+            
+            ObservableOutputStream oos = new ObservableOutputStream( os );
+            oos.addObservers(_observers);
+            _outputStream = oos;
+        }
+        return _outputStream;
+    }
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalCallback.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalCallback.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalCallback.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalCallback.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.client.retrieve;
+
+/**
+ * Classes that implement this method will be notified when a given job has
+ * been completed and validated.
+ */
+public interface RetrievalCallback
+{
+    /**
+     * Callback for asynchronous version of Retriever.retrieve.
+     *
+     * @param response empty if all artifacts retrieved ok, list of exceptions otherwise
+     */
+    public abstract void onComplete( RetrievalResponse response );
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalCallback.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalCallback.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalRequest.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalRequest.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalRequest.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalRequest.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.client.retrieve;
+
+import java.util.Set;
+
+import org.apache.maven.mercury.spi.http.validate.Validator;
+import org.apache.maven.mercury.transport.api.Binding;
+
+
+/**
+ * RetrievalRequest
+ * <p/>
+ * A set of files to retrieve from remote locations
+ * and a set of validators to apply to them.
+ */
+public interface RetrievalRequest
+{    
+    Set<Binding> getBindings();
+
+    boolean isFailFast();
+    
+    Set<Validator> getValidators();
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalRequest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalRequest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalResponse.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalResponse.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalResponse.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalResponse.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.client.retrieve;
+
+import java.util.Set;
+
+import org.apache.maven.mercury.spi.http.client.HttpClientException;
+
+
+/**
+ * RetrievalResponse
+ * <p/>
+ * Response from a request to download a set of files.
+ */
+public interface RetrievalResponse
+{
+    /**
+     * The set will be empty if the operation completed successfully,
+     * or will contain a single entry if the Request is failFast, otherwise
+     * there will be one exception for every Binding in the Request.
+     *
+     * @return
+     */
+    Set<HttpClientException> getExceptions();
+    
+    boolean hasExceptions();
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalResponse.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,482 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.client.retrieve;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.maven.mercury.crypto.api.StreamObserver;
+import org.apache.maven.mercury.crypto.api.StreamVerifier;
+import org.apache.maven.mercury.crypto.api.StreamVerifierException;
+import org.apache.maven.mercury.logging.IMercuryLogger;
+import org.apache.maven.mercury.logging.MercuryLoggerManager;
+import org.apache.maven.mercury.spi.http.client.FileExchange;
+import org.apache.maven.mercury.spi.http.client.HttpClientException;
+import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
+import org.apache.maven.mercury.spi.http.client.SecureSender;
+import org.apache.maven.mercury.spi.http.validate.Validator;
+import org.apache.maven.mercury.transport.api.Binding;
+import org.apache.maven.mercury.transport.api.Server;
+import org.mortbay.jetty.HttpHeaders;
+import org.mortbay.jetty.client.HttpExchange;
+
+
+
+/**
+ * RetrievalTarget
+ * <p/>
+ * A RetrievalTarget is a remote file that must be downloaded locally, checksummed
+ * and then atomically moved to its final location. The RetrievalTarget encapsulates
+ * the temporary local file to which the remote file is downloaded, and also the
+ * retrieval of the checksum file(s) and the checksum calculation(s).
+ */
+public abstract class RetrievalTarget
+{
+    private static final IMercuryLogger log = MercuryLoggerManager.getLogger( RetrievalTarget.class );
+    public static final String __PREFIX = "JTY_";
+    public static final String __TEMP_SUFFIX = ".tmp";
+    public static final int __START_STATE = 1;
+    public static final int __REQUESTED_STATE = 2;
+    public static final int __READY_STATE = 3;
+
+    protected int _checksumState;
+    protected int _targetState;
+    
+    protected Server _server;
+    protected HttpClientException _exception;
+    protected Binding _binding;
+    protected File _tempFile;
+    protected DefaultRetriever _retriever;
+    protected boolean _complete;
+    protected HttpExchange _exchange;
+    protected Set<Validator> _validators;
+    protected Set<StreamObserver> _observers = new HashSet<StreamObserver>();
+    protected List<StreamVerifier> _verifiers = new ArrayList<StreamVerifier>();
+    protected Map<StreamVerifier, String> _verifierMap = new HashMap<StreamVerifier, String>();
+ 
+    
+    public abstract void onComplete();
+
+    public abstract void onError( HttpClientException exception );
+
+    /**
+     * Constructor
+     *
+     * @param binding
+     * @param callback
+     */
+    public RetrievalTarget( Server server, DefaultRetriever retriever, Binding binding, Set<Validator> validators, Set<StreamObserver> observers )
+    {
+        if ( binding == null || 
+                (binding.getRemoteResource() == null) || 
+                (binding.isFile() && (binding.getLocalFile() == null)) ||
+                (binding.isInMemory() && (binding.getLocalOutputStream() == null)))
+        {
+            throw new IllegalArgumentException( "Nothing to retrieve" );
+        }
+        _server = server;
+        _retriever = retriever;
+        _binding = binding;
+        _validators = validators;
+       
+        //sift out the potential checksum verifiers
+        for (StreamObserver o: observers)
+        {
+            if (StreamVerifier.class.isAssignableFrom(o.getClass()))
+                _verifiers.add((StreamVerifier)o);
+            else
+                _observers.add(o);
+        }
+        
+        if (_binding.isFile())
+        {
+            _tempFile = new File( _binding.getLocalFile().getParentFile(),
+                                  __PREFIX + _binding.getLocalFile().getName() + __TEMP_SUFFIX );        
+            _tempFile.deleteOnExit();
+            if ( !_tempFile.getParentFile().exists() )
+            {
+                _tempFile.getParentFile().mkdirs();
+            }
+
+            if ( _tempFile.exists() )
+            {
+                onError( new HttpClientException( binding, "File exists " + _tempFile.getAbsolutePath() ) );
+            }
+            else if ( !_tempFile.getParentFile().canWrite() )
+            {
+                onError( new HttpClientException( binding,
+                        "Unable to write to dir " + _tempFile.getParentFile().getAbsolutePath() ) );
+            }
+        }
+    }
+
+   
+
+    public File getTempFile()
+    {
+        return _tempFile;
+    }
+
+    public String getUrl()
+    {
+        return _binding.getRemoteResource().toExternalForm();
+    }
+
+
+    /** Start by getting the appropriate checksums */
+    public void retrieve()
+    {
+        //if there are no checksum verifiers configured, proceed directly to get the file
+        if (_verifiers.size() == 0)
+        {
+            _checksumState = __READY_STATE;
+            updateTargetState(__START_STATE, null);
+        }
+        else
+        {
+            _checksumState = __START_STATE;
+            updateChecksumState(-1, null);
+        }
+    }
+
+
+    /** Move the temporary file to its final location */
+    public boolean move()
+    {
+        if (_binding.isFile())
+        {
+            boolean ok = _tempFile.renameTo( _binding.getLocalFile() );
+            if (log.isDebugEnabled())
+                log.debug("Renaming "+_tempFile.getAbsolutePath()+" to "+_binding.getLocalFile().getAbsolutePath()+": "+ok);
+            return ok;
+        }
+        else
+            return true;
+    }
+
+    /** Cleanup temp files */
+    public synchronized void cleanup()
+    {
+        deleteTempFile();
+        if ( _exchange != null )
+        {
+            _exchange.cancel();
+        }
+    }
+
+    public synchronized boolean isComplete()
+    {
+        return _complete;
+    }
+
+    public String toString()
+    {
+        return "T:" + _binding.getRemoteResource() + ":" + _targetState + ":" + _checksumState + ":" + _complete;
+    }
+
+    private void updateChecksumState (int index, Throwable ex)
+    {
+        if ( _exception == null && ex != null )
+        {
+            if ( ex instanceof HttpClientException )
+            {
+                _exception = (HttpClientException) ex;
+            }
+            else
+            {
+                _exception = new HttpClientException( _binding, ex );
+            }
+        }
+        
+        if (ex != null)
+        {
+            _checksumState = __READY_STATE;
+            onError(_exception);
+        }
+        else
+        {     
+            boolean proceedWithTargetFile = false;
+            if (index >= 0)
+            {
+                //check if the just-completed retrieval means that we can stop trying to download checksums 
+                StreamVerifier v = _verifiers.get(index);
+                if (_verifierMap.containsKey(v) && v.getAttributes().isSufficient())
+                    proceedWithTargetFile = true;
+            }
+
+            index++;
+            
+            if ((index < _verifiers.size()) && !proceedWithTargetFile)
+            {
+                retrieveChecksum(index);
+            }
+            else
+            {
+                _checksumState = __READY_STATE;
+
+                //finished retrieving all possible checksums. Add all verifiers
+                //that had matching checksums into the observers list
+                _observers.addAll(_verifierMap.keySet());
+
+                //now get the file now we have the checksum sorted out
+                updateTargetState( __START_STATE, null );
+            }
+        }
+    }
+    
+    
+   
+   
+
+    /**
+     * Check the actual checksum against the expected checksum
+     *
+     * @return
+     * @throws StreamVerifierException 
+     */
+    public boolean verifyChecksum()
+    throws StreamVerifierException
+    {
+        boolean ok = true;
+        
+        synchronized (_verifierMap)
+        {
+            Iterator<Map.Entry<StreamVerifier, String>> itor = _verifierMap.entrySet().iterator();
+            while (itor.hasNext() && ok)
+            {               
+                Map.Entry<StreamVerifier, String> e = itor.next();
+                ok = e.getKey().verifySignature();
+            }
+        }
+        
+        return ok;
+    }
+        
+    
+
+    public boolean validate( List<String> errors )
+    {
+        if ( _validators == null || _validators.isEmpty() )
+        {
+            return true;
+        }
+
+        String ext =  _binding.getRemoteResource().toString();
+        if (ext.endsWith("/"))
+            ext = ext.substring(0, ext.length()-1);
+        
+        int i = ext.lastIndexOf( "." );
+        ext = ( i > 0 ? ext.substring( i + 1 ) : "" );
+
+        for ( Validator v : _validators )
+        {
+            String vExt = v.getFileExtension();
+            if ( vExt.equalsIgnoreCase( ext ) )
+            {
+                try
+                {
+                    if (_binding.isFile())
+                    {
+                        if ( !v.validate( _tempFile.getCanonicalPath(), errors ) )
+                        {
+                            return false;
+                        }
+                    }
+                    else if (_binding.isInMemory())
+                    {
+                        //TODO Validation on in memory content?
+                        //v.validate(_binding.getInboundContent()) 
+                    }
+                }
+                catch ( IOException e )
+                {
+                    errors.add( e.getMessage() );
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+  
+
+    protected synchronized void updateTargetState( int state, Throwable ex )
+    {
+        _targetState = state;
+        if ( _exception == null && ex != null )
+        {
+            if ( ex instanceof HttpClientException )
+            {
+                _exception = (HttpClientException) ex;
+            }
+            else
+            {
+                _exception = new HttpClientException( _binding, ex );
+            }
+        }
+
+        if ( _targetState == __START_STATE )
+        {
+            _exchange = retrieveTargetFile();
+        }
+        //if both checksum and target file are ready, we're ready to return callback
+        else if (_targetState == __READY_STATE )
+        {
+            _complete = true;
+            if ( _exception == null )
+            {
+                onComplete();
+            }
+            else
+            {
+                onError( _exception );
+            }
+        }
+    }
+
+    /** Asynchronously fetch the checksum for the target file. */
+    private HttpExchange retrieveChecksum(final int index)
+    {    
+        HttpExchange exchange = new HttpExchange.ContentExchange()
+        {
+            protected void onException( Throwable ex )
+            {
+                //if the checksum is mandatory, then propagate the exception and stop processing
+                if (!_verifiers.get(index).getAttributes().isLenient())
+                {
+                    updateChecksumState(index, ex);
+                }
+                else
+                    updateChecksumState(index, null);
+                
+            }
+
+            protected void onResponseComplete() throws IOException
+            {
+                super.onResponseComplete();
+                StreamVerifier v = _verifiers.get(index);
+                
+                if ( getResponseStatus() == HttpServletResponse.SC_OK )
+                {
+                    //We got a checksum so match it up with the verifier it is for
+                    synchronized (_verifierMap)
+                    {
+                        if( v.getAttributes().isSufficient() )
+                            _verifierMap.clear(); //remove all other entries, we only need one checksum
+                        
+                        String actualSignature = getResponseContent().trim(); 
+                        try
+                        { // Oleg: verifier need to be loaded upfront
+                          v.initSignature( actualSignature );
+                        }
+                        catch( StreamVerifierException e )
+                        {
+                          throw new IOException(e.getMessage());
+                        }
+                        _verifierMap.put( v, actualSignature );
+                    }
+                    updateChecksumState(index, null);
+                }
+                else 
+                {
+                    if (!v.getAttributes().isLenient()) 
+                    {
+                        //checksum file MUST be present, fail
+                        updateChecksumState(index, new Exception ("Mandatory checksum file not found "+this.getURI()));
+                    }
+                    else
+                        updateChecksumState(index, null);
+                }
+            }
+        };
+        
+        exchange.setURL( getChecksumFileURLAsString( _verifiers.get(index)) );
+
+        try
+        {
+            SecureSender.send(_server, _retriever.getHttpClient(), exchange);
+        }
+        catch ( Exception ex )
+        {
+            updateChecksumState(index, ex);
+        }
+        return exchange;
+    }
+
+
+    /** Asynchronously fetch the target file. */
+    private HttpExchange retrieveTargetFile()
+    {
+        updateTargetState( __REQUESTED_STATE, null );
+
+        //get the file, calculating the digest for it on the fly
+        FileExchange exchange = new FileGetExchange( _server, _binding, getTempFile(), _observers, _retriever.getHttpClient() )
+        {
+            public void onFileComplete( String url, File localFile )
+            {
+                //we got the target file ok, so tell our main callback
+                _targetState = __READY_STATE;
+                updateTargetState( __READY_STATE, null );
+            }
+
+            public void onFileError( String url, Exception e )
+            {
+                //an error occurred whilst fetching the file, return an error
+                _targetState = __READY_STATE;
+                updateTargetState( __READY_STATE, e );
+            }
+        };
+
+        if( _server != null && _server.hasUserAgent() )
+          exchange.setRequestHeader( HttpHeaders.USER_AGENT, _server.getUserAgent() );
+
+        exchange.send();
+        return exchange;
+    }
+
+    private String getChecksumFileURLAsString (StreamVerifier verifier)
+    {
+        String extension = verifier.getAttributes().getExtension();
+        if (extension.charAt(0) != '.')
+            extension = "."+extension;
+        return _binding.getRemoteResource().toString() + extension;
+    }
+
+    private boolean deleteTempFile()
+    {
+        if ( _tempFile != null && _tempFile.exists() )
+        {
+            boolean ok =  _tempFile.delete();
+            if (log.isDebugEnabled())
+                log.debug("Deleting file "+_tempFile.getAbsolutePath()+" : "+ok);
+            return ok;
+        }
+        return false;
+    }
+    
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.client.retrieve;
+
+/**
+ * Retriever
+ * <p/>
+ * Component to retrieve a set of remote files as an atomic operation.
+ */
+public interface Retriever
+{
+    /**
+     * Retrieve a set of artifacts and wait until all retrieved successfully
+     * or an error occurs.
+     * <p/>
+     * Note: whilst this method is synchronous for the caller, the implementation
+     * will be asynchronous so many artifacts are fetched in parallel.
+     *
+     * @param request
+     * @return
+     */
+    RetrievalResponse retrieve( RetrievalRequest request );
+
+
+    /**
+     * Retrieve a set of artifacts without waiting for the results.
+     * When all results have been obtained (or an error occurs) the
+     * RetrievalResponse will be called.
+     *
+     * @param request
+     * @param callback
+     */
+    void retrieve( RetrievalRequest request, RetrievalCallback callback );
+    
+    /**
+     * stop and release all resources
+     * @throws Exception 
+     */
+    void stop();
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/PomValidator.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/PomValidator.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/PomValidator.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/PomValidator.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.validate;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.codehaus.plexus.util.FileUtils;
+
+public class PomValidator implements Validator
+{
+    public String getFileExtension()
+    {
+        return "pom";
+    }
+
+    public boolean validate(String stagedFile, List<String> errors)
+    {
+        try
+        {
+            String file = FileUtils.fileRead( stagedFile );
+
+            if ( file.contains( "<project>" ) )
+            {
+                return true;
+            }
+            else
+            {
+                errors.add( "file not valid" );
+            }
+        }
+        catch ( IOException ioe )
+        {
+            errors.add( "ioe" );
+        }
+
+        return false;
+    }
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/PomValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/PomValidator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/Validator.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/Validator.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/Validator.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/Validator.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.spi.http.validate;
+
+import java.util.List;
+
+/**
+ * Validator
+ * <p/>
+ * Interface for validating mercury content prior to completion
+ */
+public interface Validator
+{
+    /**
+     * The file extension the validator will process
+     *
+     * @return String file extension
+     */
+    public String getFileExtension();
+
+    /**
+     * validation for a given file target with errors being able to be logged in the list
+     *
+     * @param stagedFile
+     * @param errors
+     * @return true if target file is valid
+     */
+    public boolean validate( String stagedFile, List<String> errors );
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/Validator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/spi/http/validate/Validator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/AbstractTransport.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/AbstractTransport.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/AbstractTransport.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/AbstractTransport.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,47 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.transport.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+/**
+ * Helper parent of transport implementations. Common for read and write transports
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public abstract class AbstractTransport
+{
+  private Collection<Server> _servers = Collections.synchronizedSet( new HashSet< Server >() );
+  
+  public void setServers( Collection<Server> servers )
+  {
+    _servers = servers;
+  }
+  
+  public Collection<Server> getServers()
+  {
+    return _servers;
+  }
+  
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/AbstractTransport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/AbstractTransport.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Binding.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Binding.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Binding.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Binding.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,204 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.maven.mercury.transport.api;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+
+import org.apache.maven.mercury.logging.IMercuryLogger;
+import org.apache.maven.mercury.logging.MercuryLoggerManager;
+
+/**
+ * Binding <p/> A Binding represents a remote uri whose contents are to be
+ * downloaded and stored in a locally, or a local resource whose contents are to
+ * be uploaded to the remote uri.
+ */
+public class Binding
+{
+  private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( Binding.class );
+  
+  protected URL                 remoteResource;
+
+  protected File                localFile;
+
+  /** 
+   * inbound in-memory binding for reading remote content.
+   * It is created by the constructor
+   */
+  protected ByteArrayOutputStream localOS;
+
+  /**
+   * this is outbound in-memory binding. IS is passed by the client
+   */
+  protected InputStream         localIS;
+  
+  /** indicates that this transfer is exempt from stream verification */
+  boolean exempt = false;
+
+  protected Exception error;
+
+  public Binding()
+  {
+  }
+
+  public Binding( URL remoteUrl, File localFile)
+  {
+    this.remoteResource = remoteUrl;
+    this.localFile = localFile;
+  }
+
+  public Binding( URL remoteUrl, File localFile, boolean exempt )
+  {
+      this( remoteUrl,localFile );
+      this.exempt = exempt;
+  }
+
+  /** 
+   * this is in-memory binding for writing remote content into localOS
+   * 
+   * @param remoteUrl
+   * @param lenientChecksum
+   */
+  public Binding( URL remoteUrl )
+  {
+    this.remoteResource = remoteUrl;
+    // let's assume 4k on average
+    this.localOS = new ByteArrayOutputStream( 4*1024 );
+  }
+
+  public Binding( URL remoteUrl, boolean exempt )
+  {
+    this( remoteUrl );
+    this.exempt = exempt;
+  }
+
+  /**
+   * outbound constructor - send contents of the stream to remoteUrl
+   * 
+   * @param remoteUrl
+   * @param is
+   */
+  public Binding( URL remoteUrl, InputStream is )
+  {
+    this.remoteResource = remoteUrl;
+    this.localIS = is;
+  }
+  public Binding( URL remoteUrl, InputStream is, boolean exempt )
+  {
+    this( remoteUrl, is );
+    this.exempt = exempt;
+  }
+
+  /**
+   * inbound constructor - read contents of the remoteUrl to the stream
+   * 
+   * @param remoteUrl
+   * @param is
+   */
+  public Binding( URL remoteUrl, ByteArrayOutputStream os )
+  {
+    this.remoteResource = remoteUrl;
+    this.localOS = os;
+  }
+
+  public Binding( URL remoteUrl, ByteArrayOutputStream os, boolean exempt  )
+  {
+    this( remoteUrl, os );
+    this.exempt = exempt;
+  }
+
+  public URL getRemoteResource()
+  {
+    return remoteResource;
+  }
+
+  public void setRemoteResource( URL remoteResource )
+  {
+    this.remoteResource = remoteResource;
+  }
+
+  public Exception getError()
+  {
+    return error;
+  }
+
+  public void setError( Exception error )
+  {
+    this.error = error;
+  }
+  
+  public boolean isInMemory()
+  {
+    return (!isFile() && (localIS != null || localOS != null));
+  }
+  
+  public boolean isFile()
+  {
+    return localFile != null;
+  }
+  
+  public boolean isExempt()
+  {
+      return exempt;
+  }
+  
+  public void setExempt( boolean exempt )
+  {
+      this.exempt = exempt;
+  }
+  
+  public byte [] getInboundContent()
+  {
+    if( localOS != null )
+      return localOS.toByteArray();
+    
+    return null;
+  }
+  
+  public OutputStream getLocalOutputStream()
+  {
+      return localOS;
+  }
+  
+  public InputStream getLocalInputStream()
+  {
+      return localIS;
+  }
+  
+  public File getLocalFile ()
+  {
+      return localFile;
+  }
+
+  @Override
+  public String toString()
+  {
+    return '['
+            + (exempt ? "(exempt)" : "")
+            + (remoteResource == null ? "null URL" : remoteResource.toString() )+" <=> "
+            + (localFile == null ?  ( localIS == null ? (localOS == null ? "null local Res" : localOS) : "localIS" ) : localFile.getAbsolutePath() )
+            +']'
+    ;
+  }
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Binding.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Binding.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Credentials.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Credentials.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Credentials.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Credentials.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,88 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.transport.api;
+
+/**
+ * supplies credentials to the server
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class Credentials
+{
+  private String user;
+  private String pass;
+  
+  private byte [] cert;
+  
+  public Credentials( String user, String pass )
+  {
+    this.user = user;
+    this.pass = pass;
+  }
+  
+  public Credentials( byte [] cert, String user, String pass )
+  {
+    this( user, pass );
+    this.cert = cert;
+  }
+  
+  public Credentials( byte [] cert )
+  {
+    this.cert = cert;
+  }
+
+  public String getUser()
+  {
+    return user;
+  }
+
+  public void setUser( String user )
+  {
+    this.user = user;
+  }
+
+  public String getPass()
+  {
+    return pass;
+  }
+
+  public void setPass( String pass )
+  {
+    this.pass = pass;
+  }
+
+  public byte [] getCertificate()
+  {
+    return cert;
+  }
+  
+  public boolean isCertificate()
+  {
+    return cert != null && cert.length > 1;
+  }
+
+  public void setCertificate( byte [] cert )
+  {
+    this.cert = cert;
+  }
+  
+  
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Credentials.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Credentials.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Initializable.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Initializable.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Initializable.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Initializable.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,33 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.transport.api;
+
+/**
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public interface Initializable
+{
+  public void init()
+  throws InitializationException
+  ;
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Initializable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Initializable.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/InitializationException.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/InitializationException.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/InitializationException.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/InitializationException.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,72 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.transport.api;
+
+/**
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class InitializationException
+    extends Exception
+{
+
+  /**
+   * 
+   */
+  public InitializationException()
+  {
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param message
+   */
+  public InitializationException(
+      String message )
+  {
+    super( message );
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param cause
+   */
+  public InitializationException(
+      Throwable cause )
+  {
+    super( cause );
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param message
+   * @param cause
+   */
+  public InitializationException(
+      String message,
+      Throwable cause )
+  {
+    super( message, cause );
+    // TODO Auto-generated constructor stub
+  }
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/InitializationException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/InitializationException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Messages.properties
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Messages.properties?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Messages.properties (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Messages.properties Wed Apr 22 22:56:48 2009
@@ -0,0 +1,20 @@
+#
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+#
+
+repo.null.url.normalize=cannot normalize (or even have) null url.

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Messages.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Messages.properties
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ReaderTransport.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ReaderTransport.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ReaderTransport.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ReaderTransport.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,39 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.transport.api;
+
+import java.util.Collection;
+
+/**
+ * generic Transport interface - allows client to read data from a remote repository
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public interface ReaderTransport
+extends Initializable
+{
+  public TransportTransaction read( TransportTransaction trx )
+  throws TransportException;
+  
+  public void setServers( Collection<Server> servers );
+  
+  public Collection<Server> getServers();
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ReaderTransport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ReaderTransport.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Server.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Server.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Server.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Server.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,280 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file                                                                                            
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.mercury.transport.api;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Set;
+
+import org.apache.maven.mercury.crypto.api.StreamObserverFactory;
+import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+public class Server
+{
+    private static final Language _LANG = new DefaultLanguage( Server.class );
+
+    private String id;
+
+    private URL url;
+
+    private Credentials serverCredentials;
+
+    private URL proxy;
+
+    private Credentials proxyCredentials;
+
+    private boolean requireEncryption = false;
+
+    private boolean requireTrustedServer = false;
+
+    private Set<StreamObserverFactory> writerStreamObserverFactories;
+
+    private Set<StreamObserverFactory> readerStreamObserverFactories;
+
+    private Set<StreamVerifierFactory> writerStreamVerifierFactories;
+
+    private Set<StreamVerifierFactory> readerStreamVerifierFactories;
+
+    private String userAgent;
+
+    public static String normalizeUrl( String url )
+    {
+        if ( url == null )
+            throw new IllegalArgumentException( _LANG.getMessage( "repo.null.url.normalize" ) );
+
+        int pos = url.indexOf( "://" );
+
+        StringBuilder sb = new StringBuilder();
+
+        if ( pos == -1 )
+            sb.append( url );
+        else
+            sb.append( url.substring( pos + 3 ) );
+
+        int len = sb.length();
+
+        if ( len > 0 && sb.charAt( len - 1 ) == '/' )
+            sb.deleteCharAt( len - 1 );
+
+        return sb.toString();
+    }
+
+    public Server( URL url )
+    {
+        if ( url == null )
+            throw new IllegalArgumentException( "URL: " + url );
+
+        String ustr = url.toString();
+
+        if ( ustr.endsWith( "/" ) )
+            try
+            {
+                this.url = new URL( ustr.substring( 0, ustr.length() - 1 ) );
+            }
+            catch ( MalformedURLException e )
+            {
+                throw new IllegalArgumentException( e.getMessage() );
+            }
+        else
+            this.url = url;
+        
+        this.id = normalizeUrl( url.toString() );
+        
+    }
+
+    public Server( String id, URL url )
+    {
+        this( url );
+
+        this.id = id;
+    }
+
+    public Server( String id, URL url, boolean requireEncryption, boolean requireTrustedServer )
+    {
+        this( id, url );
+
+        this.requireEncryption = requireEncryption;
+        this.requireTrustedServer = requireTrustedServer;
+    }
+
+    public Server( String id, URL url, boolean requireEncryption, boolean requireTrustedServer,
+                   Credentials serverCredentials )
+    {
+        this( id, url, requireEncryption, requireTrustedServer );
+        this.serverCredentials = serverCredentials;
+    }
+
+    public Server( String id, URL url, boolean requireEncryption, boolean requireTrustedServer,
+                   Credentials serverCredentials, URL proxy )
+    {
+        this( id, url, requireEncryption, requireTrustedServer, serverCredentials );
+        this.proxy = proxy;
+    }
+
+    public Server( String id, URL url, boolean requireEncryption, boolean requireTrustedServer,
+                   Credentials serverCredentials, URL proxy, Credentials proxyCredentials )
+    {
+        this( id, url, requireEncryption, requireTrustedServer, serverCredentials, proxy );
+        this.proxyCredentials = proxyCredentials;
+    }
+
+    public String getId()
+    {
+        return id;
+    }
+
+    public boolean hasUserAgent()
+    {
+        return userAgent != null;
+    }
+
+    public String getUserAgent()
+    {
+        return userAgent;
+    }
+
+    public void setUserAgent( String userAgent )
+    {
+        this.userAgent = userAgent;
+    }
+
+    public void setURL( URL url )
+    {
+        this.url = url;
+    }
+
+    public URL getURL()
+    {
+        return this.url;
+    }
+
+    public Credentials getServerCredentials()
+    {
+        return this.serverCredentials;
+    }
+
+    public void setServerCredentials( Credentials cred )
+    {
+        this.serverCredentials = cred;
+    }
+
+    public URL getProxy()
+    {
+        return this.proxy;
+    }
+
+    public boolean hasProxy()
+    {
+        return this.proxy != null;
+    }
+
+    public void setProxy( URL proxy )
+    {
+        this.proxy = proxy;
+    }
+
+    public Credentials getProxyCredentials()
+    {
+        return this.proxyCredentials;
+    }
+
+    public void setProxyCredentials( Credentials user )
+    {
+        this.proxyCredentials = user;
+    }
+
+    public boolean hasWriterStreamVerifierFactories()
+    {
+        return writerStreamVerifierFactories != null && writerStreamVerifierFactories.size() > 0;
+    }
+
+    public Set<StreamVerifierFactory> getWriterStreamVerifierFactories()
+    {
+        return writerStreamVerifierFactories;
+    }
+
+    public void setWriterStreamVerifierFactories( Set<StreamVerifierFactory> factories )
+    {
+        writerStreamVerifierFactories = factories;
+    }
+
+    public boolean hasReaderStreamVerifierFactories()
+    {
+        return readerStreamVerifierFactories != null && readerStreamVerifierFactories.size() > 0;
+    }
+
+    public Set<StreamVerifierFactory> getReaderStreamVerifierFactories()
+    {
+        return readerStreamVerifierFactories;
+    }
+
+    public void setReaderStreamVerifierFactories( Set<StreamVerifierFactory> factories )
+    {
+        readerStreamVerifierFactories = factories;
+    }
+
+    public boolean hasWriterStreamObserverFactories()
+    {
+        return writerStreamObserverFactories != null && writerStreamObserverFactories.size() > 0;
+    }
+
+    public Set<StreamObserverFactory> getWriterStreamObserverFactories()
+    {
+        return writerStreamObserverFactories;
+    }
+
+    public void setWriterStreamObserverFactories( Set<StreamObserverFactory> factories )
+    {
+        writerStreamObserverFactories = factories;
+    }
+
+    public boolean hasReaderStreamObserverFactories()
+    {
+        return readerStreamObserverFactories != null && readerStreamObserverFactories.size() > 0;
+    }
+
+    public Set<StreamObserverFactory> getReaderStreamObserverFactories()
+    {
+        return readerStreamObserverFactories;
+    }
+
+    public void setReaderStreamObserverFactories( Set<StreamObserverFactory> factories )
+    {
+        readerStreamObserverFactories = factories;
+    }
+
+    public boolean isRequireEncryption()
+    {
+        return requireEncryption;
+    }
+
+    public boolean isRequireTrustedServer()
+    {
+        return requireTrustedServer;
+    }
+
+    @Override
+    public String toString()
+    {
+        return id + ": " + url;
+    }
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Server.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/Server.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ServerContainer.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ServerContainer.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ServerContainer.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ServerContainer.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,31 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.transport.api;
+
+/**
+ * common interface for transports to obtain their servers from Collection's
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public interface ServerContainer
+{
+  public Server getServer();
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ServerContainer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/ServerContainer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/TransportException.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/TransportException.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/TransportException.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/TransportException.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,72 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.transport.api;
+
+/**
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class TransportException
+    extends Exception
+{
+
+  /**
+   * 
+   */
+  public TransportException()
+  {
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param message
+   */
+  public TransportException(
+      String message )
+  {
+    super( message );
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param cause
+   */
+  public TransportException(
+      Throwable cause )
+  {
+    super( cause );
+    // TODO Auto-generated constructor stub
+  }
+
+  /**
+   * @param message
+   * @param cause
+   */
+  public TransportException(
+      String message,
+      Throwable cause )
+  {
+    super( message, cause );
+    // TODO Auto-generated constructor stub
+  }
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/TransportException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/transport/api/TransportException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision