1 /**
2  *  Copyright Terracotta, Inc.
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.ehcache.store.compound;
18
19 import net.sf.ehcache.CacheException;
20 import net.sf.ehcache.Element;
21 import net.sf.ehcache.util.PreferTCCLObjectInputStream;
22
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27
28 /**
29  * A copy strategy that can use partial (if both copy on read and copy on write are set) or full Serialization to copy the object graph
30  *
31  * @author Alex Snaps
32  * @author Ludovic Orban
33  */

34 public class ReadWriteSerializationCopyStrategy implements ReadWriteCopyStrategy<Element> {
35
36     /**
37      * @inheritDoc
38      */

39     public Element copyForWrite(Element value) {
40         if (value == null) {
41             return null;
42         } else {
43             ByteArrayOutputStream bout = new ByteArrayOutputStream();
44             ObjectOutputStream oos = null;
45
46             if (value.getObjectValue() == null) {
47                 return duplicateElementWithNewValue(value, null);
48             }
49
50             try {
51                 oos = new ObjectOutputStream(bout);
52                 oos.writeObject(value.getObjectValue());
53             } catch (Exception e) {
54                 throw new CacheException("When configured copyOnRead or copyOnWrite, a Store will only accept Serializable values", e);
55             } finally {
56                 try {
57                     if (oos != null) {
58                         oos.close();
59                     }
60                 } catch (Exception e) {
61                     //
62                 }
63             }
64
65             return duplicateElementWithNewValue(value, bout.toByteArray());
66         }
67     }
68
69     /**
70      * @inheritDoc
71      */

72     public Element copyForRead(Element storedValue) {
73         if (storedValue == null) {
74             return null;
75         } else {
76             if (storedValue.getObjectValue() == null) {
77                 return duplicateElementWithNewValue(storedValue, null);
78             }
79
80             ByteArrayInputStream bin = new ByteArrayInputStream((byte[]) storedValue.getObjectValue());
81             ObjectInputStream ois = null;
82             try {
83                 ois = new PreferTCCLObjectInputStream(bin);
84                 return duplicateElementWithNewValue(storedValue, ois.readObject());
85             } catch (Exception e) {
86                 throw new CacheException("When configured copyOnRead or copyOnWrite, a Store will only accept Serializable values", e);
87             } finally {
88                 try {
89                     if (ois != null) {
90                         ois.close();
91                     }
92                 } catch (Exception e) {
93                     //
94                 }
95             }
96         }
97     }
98
99     /**
100      * Make a duplicate of an element but using the specified value
101      *
102      * @param element  the element to duplicate
103      * @param newValue the new element's value
104      * @return the duplicated element
105      */

106     public Element duplicateElementWithNewValue(final Element element, final Object newValue) {
107         return new Element(element.getObjectKey(), newValue, element.getVersion(),
108                 element.getCreationTime(), element.getLastAccessTime(), element.getHitCount(), element.usesCacheDefaultLifespan(),
109                 element.getTimeToLive(), element.getTimeToIdle(), element.getLastUpdateTime());
110     }
111
112 }
113