3 * Copyright (C) 2009-2020 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.ce.task.projectanalysis.util.cache;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.ObjectOutputStream;
26 import java.io.OutputStream;
27 import java.io.Serializable;
28 import org.apache.commons.io.FileUtils;
29 import org.apache.commons.io.IOUtils;
30 import org.sonar.api.utils.System2;
31 import org.sonar.core.util.CloseableIterator;
34 * Serialize and deserialize objects on disk. No search capabilities, only traversal (full scan).
36 public class DiskCache<O extends Serializable> {
38 private final File file;
39 private final System2 system2;
41 public DiskCache(File file, System2 system2) {
42 this.system2 = system2;
44 OutputStream output = null;
47 // writes the serialization stream header required when calling "traverse()"
48 // on empty stream. Moreover it allows to call multiple times "newAppender()"
49 output = new ObjectOutputStream(new FileOutputStream(file));
52 } catch (IOException e) {
53 throw new IllegalStateException("Fail to write into file: " + file, e);
56 // do not hide initial exception
57 IOUtils.closeQuietly(output);
59 // raise an exception if can't close
60 system2.close(output);
65 public DiskAppender newAppender() {
66 return new DiskAppender();
69 public CloseableIterator<O> traverse() {
71 return new ObjectInputStreamIterator<>(FileUtils.openInputStream(file));
72 } catch (IOException e) {
73 throw new IllegalStateException("Fail to traverse file: " + file, e);
77 public class DiskAppender implements AutoCloseable {
78 private final ObjectOutputStream output;
80 private DiskAppender() {
82 this.output = new ObjectOutputStream(new FileOutputStream(file, true)) {
84 protected void writeStreamHeader() {
85 // do not write stream headers as it's already done in constructor of DiskCache
88 } catch (IOException e) {
89 throw new IllegalStateException("Fail to open file " + file, e);
93 public DiskAppender append(O object) {
95 output.writeObject(object);
98 } catch (IOException e) {
99 throw new IllegalStateException("Fail to write into file " + file, e);
104 public void close() {
105 system2.close(output);