1 package net.sf.statsvn.util;
2
3 import java.io.FileInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7 import java.util.ArrayList;
8 import java.util.List;
9
10 import net.sf.statcvs.util.LookaheadReader;
11 import net.sf.statsvn.output.SvnConfigurationOptions;
12
13 /**
14 * Utilities class that manages calls to svn propget. Used to find binary files.
15 *
16 * @author Jason Kealey <jkealey@shade.ca>
17 *
18 * @version $Id: SvnPropgetUtils.java 394 2009-08-10 20:08:46Z jkealey $
19 */
20 public class SvnPropgetUtils implements ISvnPropgetProcessor {
21
22 protected List binaryFiles;
23
24 protected ISvnProcessor processor;
25
26 /**
27 * Invokes propget via the svn propget via the command line.
28 */
29 public SvnPropgetUtils(ISvnProcessor processor) {
30 this.processor = processor;
31 }
32
33 protected ISvnProcessor getProcessor() {
34 return processor;
35 }
36
37 /**
38 * Get the svn:mime-types for all files, latest revision.
39 *
40 * @return the inputstream from which to read the information.
41 */
42 protected synchronized ProcessUtils getFileMimeTypes() {
43 return getFileMimeTypes(null, null);
44 }
45
46 /**
47 * Get the svn:mime-type for a certain file (leave null for all files).
48 *
49 * @param revision
50 * revision for which to query;
51 * @param filename
52 * the filename (or null for all files)
53 * @return the inputstream from which to read the information.
54 */
55 protected synchronized ProcessUtils getFileMimeTypes(final String revision, final String filename) {
56 String svnPropgetCommand = "svn propget svn:mime-type";
57 if (revision != null && revision.length() > 0) {
58 svnPropgetCommand += " -r " + revision;
59 }
60
61 if (filename != null && filename.length() > 0) {
62 svnPropgetCommand += " " + StringUtils.replace(" ", "%20", getProcessor().getInfoProcessor().relativePathToUrl(filename));
63
64 if (revision != null && revision.length() > 0) {
65 svnPropgetCommand += "@" + revision;
66 }
67 } else {
68 svnPropgetCommand += " -R ";
69 }
70
71 svnPropgetCommand += SvnCommandHelper.getAuthString();
72
73 try {
74 return ProcessUtils.call(svnPropgetCommand);
75 } catch (final Exception e) {
76 SvnConfigurationOptions.getTaskLogger().info(e.toString());
77 return null;
78 }
79 }
80
81
82
83
84 public List getBinaryFiles() {
85 if (binaryFiles == null) {
86 ProcessUtils pUtils = null;
87 try {
88 pUtils = getFileMimeTypes();
89 loadBinaryFiles(pUtils);
90 } finally {
91 if (pUtils != null) {
92 try {
93 pUtils.close();
94 } catch (final IOException e) {
95 SvnConfigurationOptions.getTaskLogger().info(e.toString());
96 }
97 }
98 }
99 }
100
101 return binaryFiles;
102 }
103
104
105 /**
106 * Loads the list of binary files from the input stream equivalent to an svn
107 * propget command.
108 *
109 * @param path
110 * a file on disk which contains the results of an svn propget
111 */
112 public void loadBinaryFiles(final String path) throws IOException
113 {
114 final InputStream stream = new FileInputStream(path);
115 final ProcessUtils pUtils = new ProcessUtils();
116 try {
117 pUtils.setInputStream(stream);
118 loadBinaryFiles(pUtils);
119 } finally {
120 pUtils.close();
121 }
122 }
123 /**
124 * Loads the list of binary files from the input stream equivalent to an svn
125 * propget command.
126 *
127 * @param stream
128 * stream equivalent to an svn propget command
129 */
130 protected void loadBinaryFiles(final ProcessUtils pUtils) {
131 binaryFiles = new ArrayList();
132 final LookaheadReader mimeReader = new LookaheadReader(new InputStreamReader(pUtils.getInputStream()));
133 try {
134 while (mimeReader.hasNextLine()) {
135 mimeReader.nextLine();
136 final String file = getBinaryFilename(mimeReader.getCurrentLine(), false);
137 if (file != null) {
138 binaryFiles.add(file);
139 }
140 }
141 if (pUtils.hasErrorOccured()) {
142 throw new IOException(pUtils.getErrorMessage());
143 }
144 } catch (final IOException e) {
145 SvnConfigurationOptions.getTaskLogger().info(e.getMessage());
146 }
147 }
148
149
150
151
152 public boolean isBinaryFile(final String revision, final String filename) {
153 ProcessUtils pUtils = null;
154 try {
155 pUtils = getFileMimeTypes(revision, filename);
156 final LookaheadReader mimeReader = new LookaheadReader(new InputStreamReader(pUtils.getInputStream()));
157 while (mimeReader.hasNextLine()) {
158 mimeReader.nextLine();
159 final String file = getBinaryFilename(mimeReader.getCurrentLine(), true);
160 if (file != null && file.equals(filename)) {
161 return true;
162 }
163 }
164 } catch (final IOException e) {
165 SvnConfigurationOptions.getTaskLogger().info(e.toString());
166 } finally {
167 if (pUtils != null) {
168 try {
169 pUtils.close();
170 } catch (final IOException e) {
171 SvnConfigurationOptions.getTaskLogger().info(e.toString());
172 }
173 }
174 }
175
176 return false;
177 }
178
179 /**
180 * Given a string such as: "lib\junit.jar - application/octet-stream" or
181 * "svn:\\host\repo\lib\junit.jar - application/octet-stream" will return
182 * the filename if the mime type is binary (doesn't end with text/*)
183 *
184 * Will return the filename with / was a directory seperator.
185 *
186 * @param currentLine
187 * the line obtained from svn propget svn:mime-type
188 * @param removeRoot
189 * if true, will remove any repository prefix
190 * @return should return lib\junit.jar in both cases, given that
191 * removeRoot==true in the second case.
192 */
193 protected String getBinaryFilename(final String currentLine, final boolean removeRoot) {
194
195 String line = removeRoot ? currentLine : currentLine.replace('\\', '/');
196
197
198
199 final String octetStream = " - application/octet-stream";
200
201 if (line.endsWith(octetStream) || line.lastIndexOf(" - text/") < 0 && line.lastIndexOf(" - text/") == line.lastIndexOf(" - ")
202 && line.lastIndexOf(" - ") >= 0) {
203 line = line.substring(0, line.lastIndexOf(" - "));
204 if (removeRoot) {
205 line = getProcessor().getInfoProcessor().urlToRelativePath(line);
206 }
207 return line;
208 }
209
210 return null;
211 }
212
213 }