View Javadoc

1   /***
2    * Copyright (C) 2008 Jeremy Thomerson (jthomerson@users.sourceforge.net)
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package net.sf.vcaperture.model;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.tmatesoft.svn.core.SVNException;
27  import org.tmatesoft.svn.core.SVNLogEntry;
28  import org.tmatesoft.svn.core.SVNLogEntryPath;
29  import org.tmatesoft.svn.core.SVNNodeKind;
30  import org.tmatesoft.svn.core.SVNURL;
31  import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
32  import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
33  
34  /***
35   * An implementation of <tt>AbstractRepository</tt> that allows access to a Subversion repository.
36   * Internally, this implementation uses SVNKit.
37   * 
38   * @author Jeremy Thomerson (jthomerson@users.sourceforge.net)
39   * @see http://svnkit.com/
40   * @see http://subversion.tigris.org/
41   */
42  public class SVNRepository extends AbstractRepository {
43  
44  	private boolean mInitialized;
45  	private org.tmatesoft.svn.core.io.SVNRepository mRepo;
46  
47  	@Override
48  	public boolean isRevisionNewer(String name, String startingRevision) {
49  	    return Long.parseLong(name) > Long.parseLong(startingRevision);
50  	}
51  	
52  	@Override
53  	public String getLatestRevision() {
54  		init();
55  	    try {
56  	        return Long.toString(mRepo.getLatestRevision());
57          } catch (SVNException se) {
58  	        throw new RuntimeException("Error getting latest revision: " + se.getMessage(), se);
59          }
60  	}
61  	
62  	@Override
63  	public Collection<Revision> getRevisions(String startingRevision, int maxRevisions) {
64  		init();
65  		List<Revision> list = new ArrayList<Revision>();
66  		Collection<SVNLogEntry> entries = new ArrayList<SVNLogEntry>();
67  		try {
68  			long start = Long.parseLong(startingRevision);
69  			mRepo.log(new String[] { "" }, entries, start, mRepo.getLatestRevision(), true, false);
70  			LOGGER.debug("retrieved " + entries.size() + " entries");
71  			int cnt = 0;
72  			for (SVNLogEntry entry : entries) {
73  				if (cnt++ >= maxRevisions) {
74  					break;
75  				}
76  				LOGGER.debug("retrieving entry: " + entry.getRevision());
77  				Revision rev = new Revision();
78  				rev.setName(Long.toString(entry.getRevision()));
79  				rev.setCommitMessage(entry.getMessage());
80  				rev.setCommitDate(entry.getDate());
81  				rev.setAuthor(entry.getAuthor());
82  	
83  				List<RepoFileRevision> files = new ArrayList<RepoFileRevision>();
84  				for (Iterator it = entry.getChangedPaths().keySet().iterator(); it.hasNext();) {
85  					SVNLogEntryPath entryPath = (SVNLogEntryPath) entry.getChangedPaths().get(it.next());
86  					RepoFileRevision rfr = new RepoFileRevision();
87  					rfr.setAuthor(rev.getAuthor());
88  					rfr.setRelativePath(entryPath.getPath());
89  					rfr.setRevision(rev.getName());
90  					SVNNodeKind kind = mRepo.checkPath(entryPath.getPath(), entry.getRevision());
91  					rfr.setDirectory(kind == SVNNodeKind.DIR);
92  					rfr.setAction(mapAction(entryPath.getType()));
93  					if (entryPath.getType() != SVNLogEntryPath.TYPE_DELETED && kind != SVNNodeKind.DIR) {
94  						ByteArrayOutputStream baos = new ByteArrayOutputStream();
95  						mRepo.getFile(entryPath.getPath(), entry.getRevision(), new HashMap(), baos);
96  						rfr.setContents(baos.toString());
97  					}
98  					if (entryPath.getCopyPath() != null) {
99  						RepoFileRevision copy = new RepoFileRevision();
100 						copy.setRelativePath(entryPath.getCopyPath());
101 						copy.setRevision(Long.toString(entryPath.getCopyRevision()));
102 						rfr.setCopyOfRevision(copy);
103 					}
104 					files.add(rfr);
105 				}
106 				rev.setFiles(files.toArray(new RepoFileRevision[files.size()]));
107 				list.add(rev);
108 			}
109 		} catch (Exception ex) {
110 			throw new RuntimeException("Error getting revisions: " + ex.getMessage(), ex);
111 		}
112 		return list;
113 	}
114 
115 	private RepoFileAction mapAction(char type) {
116 		switch (type) {
117 	        case SVNLogEntryPath.TYPE_MODIFIED:
118 		        return RepoFileAction.MODIFIED;
119 	        case SVNLogEntryPath.TYPE_ADDED:
120 		        return RepoFileAction.ADDED;
121 	        case SVNLogEntryPath.TYPE_DELETED:
122 		        return RepoFileAction.DELETED;
123 	        default:
124 		        break;
125         }
126 	    return null;
127     }
128 
129 	private synchronized void init() {
130 		if (!isInitialized()) {
131 			DAVRepositoryFactory.setup();
132 			try {
133 				SVNURL url = SVNURL.parseURIDecoded(getURL());
134 				mRepo = SVNRepositoryFactory.create(url);
135 				LOGGER.debug("----------------------------------------------------------------------------------------------------");
136 				LOGGER.debug("Connected to SVN repository: " + getURL());
137 				LOGGER.debug("Repository Root: " + mRepo.getRepositoryRoot(true));
138 				LOGGER.debug("Repository UUID: " + mRepo.getRepositoryUUID(true));
139 				LOGGER.debug("Latest Revision: " + mRepo.getLatestRevision());
140 				LOGGER.debug("----------------------------------------------------------------------------------------------------");
141 				setInitialized(true);
142 			} catch (Exception ex) {
143 				throw new RuntimeException("Unable to create backing repository: " + ex.getMessage(), ex);
144 			}
145 		}
146 	}
147 
148 	public boolean isInitialized() {
149 		return mInitialized;
150 	}
151 
152 	public void setInitialized(boolean initialized) {
153 		mInitialized = initialized;
154 	}
155 
156 	@Override
157 	public RepoFile getFile(String relativePath) {
158 	    throw new UnsupportedOperationException("Need to implement if this method is necessary.");
159 	}
160 }