001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.connector.svn;
025    
026    import java.util.concurrent.TimeUnit;
027    import javax.transaction.xa.XAResource;
028    import org.jboss.dna.common.util.CheckArg;
029    import org.jboss.dna.graph.ExecutionContext;
030    import org.jboss.dna.graph.cache.CachePolicy;
031    import org.jboss.dna.graph.connector.RepositoryConnection;
032    import org.jboss.dna.graph.connector.RepositorySourceException;
033    import org.jboss.dna.graph.connector.RepositorySourceListener;
034    import org.jboss.dna.graph.property.PathFactory;
035    import org.jboss.dna.graph.property.PropertyFactory;
036    import org.jboss.dna.graph.request.Request;
037    import org.jboss.dna.graph.request.processor.RequestProcessor;
038    import org.tmatesoft.svn.core.SVNErrorCode;
039    import org.tmatesoft.svn.core.SVNErrorMessage;
040    import org.tmatesoft.svn.core.SVNException;
041    import org.tmatesoft.svn.core.SVNNodeKind;
042    import org.tmatesoft.svn.core.io.SVNRepository;
043    
044    /**
045     * The repository connection to a SVN Repository instance.
046     * 
047     * @author Serge Pagop
048     */
049    public class SVNRepositoryConnection implements RepositoryConnection {
050    
051        protected static final RepositorySourceListener NO_OP_LISTENER = new RepositorySourceListener() {
052    
053            /**
054             * {@inheritDoc}
055             */
056            public void notify( String sourceName,
057                                Object... events ) {
058                // do nothing
059            }
060        };
061    
062        private final String sourceName;
063        private final CachePolicy cachePolicy;
064        private final SVNRepository repository;
065        private final boolean updatesAllowed;
066        private RepositorySourceListener listener = NO_OP_LISTENER;
067    
068        public SVNRepositoryConnection( String sourceName,
069                                        CachePolicy cachePolicy,
070                                        boolean updatesAllowed,
071                                        SVNRepository repository ) {
072            CheckArg.isNotNull(repository, "repository");
073            CheckArg.isNotNull(sourceName, "sourceName");
074    
075            SVNNodeKind nodeKind = null;
076            try {
077                nodeKind = repository.checkPath("", -1);
078                if (nodeKind == SVNNodeKind.NONE) {
079                    SVNErrorMessage error = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
080                                                                   "No entry at URL ''{0}''",
081                                                                   repository.getLocation().getPath());
082                    throw new SVNException(error);
083                } else if (nodeKind == SVNNodeKind.UNKNOWN) {
084                    SVNErrorMessage error = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
085                                                                   "Entry at URL ''{0}'' is a file while directory was expected",
086                                                                   repository.getLocation().getPath());
087                    throw new SVNException(error);
088                } else if (nodeKind == SVNNodeKind.FILE) {
089                    SVNErrorMessage error = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
090                                                                   "Entry at URL ''{0}'' is a file while directory was expected",
091                                                                   repository.getLocation().getPath());
092                    throw new SVNException(error);
093                }
094            } catch (SVNException e) {
095                // deal with the exception
096                throw new RuntimeException(e);
097            }
098    
099            this.sourceName = sourceName;
100            this.cachePolicy = cachePolicy;
101            this.repository = repository;
102            this.updatesAllowed = updatesAllowed;
103        }
104    
105        SVNRepository getRepository() {
106            return repository;
107        }
108    
109        /**
110         * {@inheritDoc}
111         */
112        public String getSourceName() {
113            return sourceName;
114        }
115    
116        /**
117         * {@inheritDoc}
118         */
119        public CachePolicy getDefaultCachePolicy() {
120            return cachePolicy;
121        }
122    
123        /**
124         * {@inheritDoc}
125         */
126        public XAResource getXAResource() {
127            return null;
128        }
129    
130        /**
131         * {@inheritDoc}
132         */
133        public boolean ping( long time,
134                             TimeUnit unit ) {
135            try {
136                this.repository.getRepositoryRoot(true);
137            } catch (SVNException e) {
138                return false;
139            }
140            return true;
141        }
142    
143        /**
144         * {@inheritDoc}
145         */
146        public void setListener( RepositorySourceListener listener ) {
147            this.listener = listener != null ? listener : NO_OP_LISTENER;
148        }
149    
150        /**
151         * {@inheritDoc}
152         * 
153         * @see org.jboss.dna.graph.connector.RepositoryConnection#close()
154         */
155        public void close() {
156            // do not care about.
157        }
158    
159        /**
160         * {@inheritDoc}
161         * 
162         * @see org.jboss.dna.graph.connector.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
163         *      org.jboss.dna.graph.request.Request)
164         */
165        @SuppressWarnings( "unused" )
166        public void execute( final ExecutionContext context,
167                             final Request request ) throws RepositorySourceException {
168    
169            final PathFactory pathFactory = context.getValueFactories().getPathFactory();
170            final PropertyFactory propertyFactory = context.getPropertyFactory();
171    
172            RequestProcessor processor = new SVNRepositoryRequestProcessor(getSourceName(), context, repository, updatesAllowed);
173            try {
174                processor.process(request);
175            } finally {
176                processor.close();
177            }
178        }
179    
180        /**
181         * @return listener
182         */
183        protected RepositorySourceListener getListener() {
184            return this.listener;
185        }
186    }