001: /*
002: * @(#)DirMetaDataIO.java
003: *
004: * Copyright (C) 2002-2004 Matt Albrecht
005: * groboclown@users.sourceforge.net
006: * http://groboutils.sourceforge.net
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a
009: * copy of this software and associated documentation files (the "Software"),
010: * to deal in the Software without restriction, including without limitation
011: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
012: * and/or sell copies of the Software, and to permit persons to whom the
013: * Software is furnished to do so, subject to the following conditions:
014: *
015: * The above copyright notice and this permission notice shall be included in
016: * all copies or substantial portions of the Software.
017: *
018: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
021: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
023: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
024: * DEALINGS IN THE SOFTWARE.
025: */
026:
027: package net.sourceforge.groboutils.codecoverage.v2.datastore;
028:
029: import java.io.BufferedReader;
030: import java.io.BufferedWriter;
031: import java.io.File;
032: import java.io.FileReader;
033: import java.io.FileWriter;
034: import java.io.IOException;
035:
036: import net.sourceforge.groboutils.codecoverage.v2.IAnalysisModule;
037: import net.sourceforge.groboutils.util.io.v1.ExtensionFilenameFilter;
038:
039: /**
040: * Accesses the meta-data at the I/O level in a directory structure.
041: *
042: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
043: * @version $Date: 2004/04/15 05:48:26 $
044: * @since December 15, 2002
045: * @see ZipMetaDataReader
046: */
047: class DirMetaDataIO {
048: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
049: .getLogger(DirMetaDataIO.class);
050:
051: private static final String MODULE_SET_FILENAME = "moduleset.txt";
052: private static final String CLASS_FILE_EXT = ".classdata.txt";
053: private static final String MARK_FILE_EXT = ".classmarks.txt";
054:
055: private File basedir;
056: private static final ExtensionFilenameFilter CLASS_FILE_FILTER = new ExtensionFilenameFilter(
057: CLASS_FILE_EXT, true);
058: static {
059: CLASS_FILE_FILTER.allowsDirectories(false);
060: }
061:
062: public DirMetaDataIO(File dir) throws IOException {
063: if (dir == null) {
064: throw new IllegalArgumentException("No null args.");
065: }
066: if (dir.exists() && !dir.isDirectory()) {
067: throw new IllegalArgumentException("File " + dir
068: + " is not a directory.");
069: }
070: if (!dir.exists()) {
071: dir.mkdir();
072: }
073: this .basedir = dir;
074: }
075:
076: /**
077: *
078: */
079: public AnalysisModuleSet getAnalysisModuleSet() throws IOException {
080: checkClosed();
081: AnalysisModuleSetIO amsr = new AnalysisModuleSetIO();
082: AnalysisModuleSet ams;
083: File amsf = getAnalysisModuleSetFile();
084: if (!amsf.exists()) {
085: ams = new AnalysisModuleSet();
086: } else {
087: BufferedReader fr = new BufferedReader(new FileReader(amsf));
088: try {
089: ams = amsr.readAnalysisModuleSet(fr);
090: } finally {
091: fr.close();
092: }
093: }
094: return ams;
095: }
096:
097: /**
098: *
099: */
100: public void putAnalysisModuleSet(AnalysisModuleSet ams)
101: throws IOException {
102: if (ams == null) {
103: throw new IllegalArgumentException("no null args");
104: }
105: checkClosed();
106: AnalysisModuleSetIO amsw = new AnalysisModuleSetIO();
107: File amsf = getAnalysisModuleSetFile();
108: BufferedWriter bw = new BufferedWriter(new FileWriter(amsf));
109: try {
110: amsw.writeAnalysisModuleSet(ams, bw);
111: } finally {
112: bw.close();
113: }
114: }
115:
116: /**
117: *
118: */
119: public String[] getClassSigsForAnalysisModule(IAnalysisModule am)
120: throws IOException {
121: if (am == null) {
122: throw new IllegalArgumentException("no null args");
123: }
124: checkClosed();
125: File amDir = getAnalysisModuleDir(am);
126: String names[] = amDir.list(CLASS_FILE_FILTER);
127: for (int i = 0; i < names.length; ++i) {
128: names[i] = names[i].substring(0, names[i].length()
129: - CLASS_FILE_EXT.length());
130: }
131: return names;
132: }
133:
134: /**
135: *
136: */
137: public ClassRecord getClassRecord(IAnalysisModule am,
138: String classSig) throws IOException {
139: return getClassRecord(getAnalysisModuleSet(), am, classSig);
140: }
141:
142: /**
143: * If the class record does not exist, then <tt>null</tt> is returned.
144: */
145: public ClassRecord getClassRecord(AnalysisModuleSet ams,
146: IAnalysisModule am, String classSig) throws IOException {
147: if (am == null || classSig == null || ams == null) {
148: throw new IllegalArgumentException("no null args");
149: }
150: checkClosed();
151: File cf = getClassDataFileForModule(am, classSig);
152: ClassRecordIO crr = new ClassRecordIO();
153: BufferedReader fr;
154: try {
155: fr = new BufferedReader(new FileReader(cf));
156: } catch (java.io.FileNotFoundException fnfe) {
157: LOG.warn("Couldn't find the file '" + cf
158: + "' containing the class details.");
159: return null;
160: }
161:
162: ClassRecord cr;
163: try {
164: cr = crr.readClass(ams, fr);
165: } finally {
166: fr.close();
167: }
168:
169: // read marks
170: File mcf = getClassMarkFileForModule(am, cr.getClassSignature());
171: try {
172: fr = new BufferedReader(new FileReader(mcf));
173: } catch (java.io.FileNotFoundException fnfe) {
174: LOG.warn("Could not find file '" + mcf
175: + "' containing marks.");
176: return cr;
177: }
178:
179: try {
180: crr.readMarks(cr, fr);
181: } finally {
182: fr.close();
183: }
184:
185: return cr;
186: }
187:
188: /**
189: *
190: */
191: public void putClassRecord(IAnalysisModule am, ClassRecord cr)
192: throws IOException {
193: if (am == null || cr == null) {
194: throw new IllegalArgumentException("no null args");
195: }
196: checkClosed();
197: File cf = getClassDataFileForModule(am, cr.getClassSignature());
198: ClassRecordIO crw = new ClassRecordIO();
199: BufferedWriter fw = new BufferedWriter(new FileWriter(cf));
200: try {
201: crw.writeClass(cr, fw);
202: } finally {
203: fw.close();
204: }
205:
206: // write marks
207: File mcf = getClassMarkFileForModule(am, cr.getClassSignature());
208: fw = new BufferedWriter(new FileWriter(mcf));
209: try {
210: crw.writeMarksForAnalysisModule(cr, am, fw);
211: } finally {
212: fw.close();
213: }
214: }
215:
216: /**
217: *
218: */
219: public void deleteClassRecord(IAnalysisModule am, ClassRecord cr)
220: throws IOException {
221: if (am == null || cr == null) {
222: throw new IllegalArgumentException("no null args");
223: }
224: checkClosed();
225: File cf = getClassDataFileForModule(am, cr.getClassSignature());
226: if (cf.exists()) {
227: cf.delete();
228: }
229: }
230:
231: /**
232: *
233: */
234: private File getAnalysisModuleSetFile() {
235: File moduleSetFile = new File(this .basedir, MODULE_SET_FILENAME);
236: return moduleSetFile;
237: }
238:
239: /**
240: *
241: */
242: private File getAnalysisModuleDir(IAnalysisModule am)
243: throws IOException {
244: File newDir = new File(this .basedir, am.getMeasureName());
245: if (newDir.exists() && !newDir.isDirectory()) {
246: throw new IOException("Expected measure directory '"
247: + newDir + "', but it isn't a directory.");
248: }
249: if (!newDir.exists()) {
250: newDir.mkdir();
251: }
252: return newDir;
253: }
254:
255: /**
256: *
257: */
258: private File getClassDataFileForModule(IAnalysisModule am,
259: String classSig) throws IOException {
260: File mf = getAnalysisModuleDir(am);
261: File cf = new File(mf, classSig + CLASS_FILE_EXT);
262: return cf;
263: }
264:
265: /**
266: *
267: */
268: private File getClassMarkFileForModule(IAnalysisModule am,
269: String classSig) throws IOException {
270: File mf = getAnalysisModuleDir(am);
271: File cf = new File(mf, classSig + MARK_FILE_EXT);
272: return cf;
273: }
274:
275: /**
276: * This can be called multiple times without error.
277: */
278: public void close() throws IOException {
279: LOG.debug("Closing DirMetaDataIO.");
280: this .basedir = null;
281: }
282:
283: /**
284: *
285: */
286: private void checkClosed() throws IOException {
287: if (isClosed()) {
288: throw new IOException("Directory storage has been closed.");
289: }
290: }
291:
292: /**
293: *
294: */
295: boolean isClosed() {
296: return (this .basedir == null);
297: }
298:
299: protected void finalize() throws Throwable {
300: Exception ex = null;
301: if (!isClosed()) {
302: ex = new IllegalStateException("Did not close writer.");
303: close();
304: }
305:
306: super .finalize();
307:
308: // class-based post condition
309: if (ex != null) {
310: throw ex;
311: }
312: }
313: }
|