Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 8acdde67c213585f08f0a730cda9289e2ab45265 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*******************************************************************************
 * Copyright (c) 2009 Martin Lippert and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0.
 *
 * Contributors:
 *     Martin Lippert - initial implementation
 *     Martin Lippert - caching of generated classes
 *******************************************************************************/

package org.eclipse.equinox.weaving.internal.caching;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;

/**
 * The CacheWriter is responsible to store cache items to disk. The cache items
 * are read from the given queue.
 *
 * @author Martin Lippert
 */
public class CacheWriter {

    private final Thread writerThread;

    /**
     * Create a new cache writer for the given queue of cache items
     *
     * @param cacheQueue The blocking queue that delivers the cache items to
     *            store to this cache writer
     */
    public CacheWriter(final BlockingQueue<CacheItem> cacheQueue) {
        this.writerThread = new Thread(new Runnable() {

	    @Override
            public void run() {
                try {
                    while (true) {
                        final CacheItem item = cacheQueue.take();
                        try {
                            store(item);
                        } catch (final IOException ioe) {
                            // storing in cache failed, do nothing
                        }
                    }
                } catch (final InterruptedException e) {
                }
            }
        });
        this.writerThread.setPriority(Thread.MIN_PRIORITY);
    }

    /**
     * start the cache writers work (creates a new thread to work on the queue)
     */
    public void start() {
        this.writerThread.start();
    }

    /**
     * stops the cache writer
     */
    public void stop() {
        this.writerThread.interrupt();
    }

    /**
     * store the cache item to disk
     *
     * This operation creates the appropriate directory for the cache item if it
     * does not exist
     *
     * @param item the cache item to store to disc
     * @throws IOException if an error occurs while writing to the cache
     */
    protected void store(final CacheItem item) throws IOException {

        // write out generated classes first
        final Map<String, byte[]> generatedClasses = item.getGeneratedClasses();
        if (generatedClasses != null) {
            for (final Entry<String, byte[]> entry : generatedClasses
                    .entrySet()) {
                final String className = entry.getKey();
                final byte[] classBytes = entry.getValue();
                storeSingleClass(className, classBytes, item.getDirectory());
            }
        }

        // write out the woven class
        storeSingleClass(item.getName(), item.getCachedBytes(),
                item.getDirectory());
    }

    private void storeSingleClass(final String className,
            final byte[] classBytes, final String cacheDirectory)
            throws FileNotFoundException, IOException {
        DataOutputStream outCache = null;
        FileOutputStream fosCache = null;
        try {
            final File directory = new File(cacheDirectory);
            if (!directory.exists()) {
                directory.mkdirs();
            }

            fosCache = new FileOutputStream(new File(directory, className));
            outCache = new DataOutputStream(new BufferedOutputStream(fosCache));

            outCache.write(classBytes);
        } finally {
            if (outCache != null) {
                try {
                    outCache.flush();
                    fosCache.getFD().sync();
                } catch (final IOException e) {
                    // do nothing, we tried
                }
                try {
                    outCache.close();
                } catch (final IOException e) {
                    // do nothing
                }
            }
        }
    }

}

Back to the top