1 /*
2 * ModeShape (http://www.modeshape.org)
3 * See the COPYRIGHT.txt file distributed with this work for information
4 * regarding copyright ownership. Some portions may be licensed
5 * to Red Hat, Inc. under one or more contributor license agreements.
6 * See the AUTHORS.txt file in the distribution for a full listing of
7 * individual contributors.
8 *
9 * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10 * is licensed to you under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * ModeShape is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this software; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23 */
24 package org.modeshape.graph.connector.path;
25
26 import java.io.ByteArrayInputStream;
27 import java.io.IOException;
28 import java.io.ObjectInputStream;
29 import java.util.Enumeration;
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.UUID;
33 import javax.naming.BinaryRefAddr;
34 import javax.naming.RefAddr;
35 import javax.naming.Reference;
36 import javax.naming.StringRefAddr;
37 import net.jcip.annotations.ThreadSafe;
38 import org.modeshape.common.util.CheckArg;
39 import org.modeshape.graph.connector.RepositoryContext;
40 import org.modeshape.graph.connector.RepositorySourceException;
41 import org.modeshape.graph.connector.path.cache.NoCachePolicy;
42 import org.modeshape.graph.connector.path.cache.PathCachePolicy;
43 import org.modeshape.graph.connector.path.cache.PathRepositoryCache;
44
45 /**
46 * Basic implementation of the trivial {@link PathRepositorySource} methods and the {@link org.modeshape.graph.connector.path path
47 * repository cache life cycle}.
48 */
49 @ThreadSafe
50 public abstract class AbstractPathRepositorySource implements PathRepositorySource {
51
52 private static final long serialVersionUID = 1L;
53
54 /**
55 * The default UUID that is used for root nodes in a store.
56 */
57 public static final String DEFAULT_ROOT_NODE_UUID = "cafebabe-cafe-babe-cafe-babecafebabe";
58
59 /**
60 * The default number of times that a request that failed due to system error should be retried
61 */
62 public static final int DEFAULT_RETRY_LIMIT = 0;
63
64 /**
65 * The default cache policy for this repository source (no caching)
66 */
67 public static final PathCachePolicy DEFAULT_CACHE_POLICY = new NoCachePolicy();
68
69 protected int retryLimit = DEFAULT_RETRY_LIMIT;
70 protected String name;
71
72 protected transient RepositoryContext repositoryContext;
73 protected transient UUID rootNodeUuid = UUID.fromString(DEFAULT_ROOT_NODE_UUID);
74 protected transient PathCachePolicy cachePolicy = DEFAULT_CACHE_POLICY;
75
76 private transient PathRepositoryCache repositoryCache = new PathRepositoryCache(cachePolicy);
77
78 /**
79 * {@inheritDoc}
80 *
81 * @see org.modeshape.graph.connector.path.PathRepositorySource#areUpdatesAllowed()
82 */
83 public boolean areUpdatesAllowed() {
84 return false;
85 }
86
87 /**
88 * {@inheritDoc}
89 *
90 * @see org.modeshape.graph.connector.path.PathRepositorySource#getRepositoryContext()
91 */
92 public RepositoryContext getRepositoryContext() {
93 return repositoryContext;
94 }
95
96 /**
97 * {@inheritDoc}
98 *
99 * @see org.modeshape.graph.connector.RepositorySource#initialize(RepositoryContext)
100 */
101 public void initialize( RepositoryContext context ) throws RepositorySourceException {
102 CheckArg.isNotNull(context, "context");
103 this.repositoryContext = context;
104 }
105
106 /**
107 * {@inheritDoc}
108 *
109 * @see org.modeshape.graph.connector.path.PathRepositorySource#getCachePolicy()
110 */
111 public PathCachePolicy getCachePolicy() {
112 return this.cachePolicy;
113 }
114
115 /**
116 * Sets the cache policy for the repository and replaces the path repository cache with a new path repository cache tied to
117 * the new cache policy
118 *
119 * @param cachePolicy the new cache policy; may not be null
120 */
121 public void setCachePolicy( PathCachePolicy cachePolicy ) {
122 CheckArg.isNotNull(cachePolicy, "cachePolicy");
123
124 PathRepositoryCache oldCache = repositoryCache;
125 this.cachePolicy = cachePolicy;
126 this.repositoryCache = new PathRepositoryCache(cachePolicy);
127
128 oldCache.close();
129 }
130
131 /**
132 * @return rootNodeUuid
133 */
134 public UUID getRootNodeUuid() {
135 return rootNodeUuid;
136 }
137
138 /**
139 * @param rootNodeUuid Sets rootNodeUuid to the specified value.
140 * @throws IllegalArgumentException if the string value cannot be converted to UUID
141 */
142 public void setRootNodeUuid( String rootNodeUuid ) {
143 if (rootNodeUuid != null && rootNodeUuid.trim().length() == 0) rootNodeUuid = DEFAULT_ROOT_NODE_UUID;
144 this.rootNodeUuid = UUID.fromString(rootNodeUuid);
145 }
146
147 /**
148 * {@inheritDoc}
149 *
150 * @see org.modeshape.graph.connector.RepositorySource#close()
151 */
152 public void close() {
153 }
154
155 /**
156 * {@inheritDoc}
157 *
158 * @see org.modeshape.graph.connector.RepositorySource#getName()
159 */
160 public String getName() {
161 return name;
162 }
163
164 /**
165 * Sets the name of the repository source. The name should be unique among loaded repository sources.
166 *
167 * @param name the new name for the repository source; may not be empty
168 */
169 public void setName( String name ) {
170 if (name != null) {
171 name = name.trim();
172 if (name.length() == 0) name = null;
173 }
174
175 this.name = name;
176 }
177
178 /**
179 * {@inheritDoc}
180 *
181 * @see org.modeshape.graph.connector.RepositorySource#getRetryLimit()
182 */
183 public int getRetryLimit() {
184 return retryLimit;
185 }
186
187 /**
188 * {@inheritDoc}
189 *
190 * @see org.modeshape.graph.connector.RepositorySource#setRetryLimit(int limit)
191 */
192 public void setRetryLimit( int limit ) {
193 this.retryLimit = limit < 0 ? 0 : limit;
194 }
195
196 /**
197 * Extracts the values from the given reference, automatically translating {@link BinaryRefAddr} instances into the
198 * deserialized classes that they represent.
199 *
200 * @param ref the reference from which the values should be extracted
201 * @return a map of value names to values from the reference
202 * @throws IOException if there is an error deserializing a {@code BinaryRefAddr}
203 * @throws ClassNotFoundException if a serialized class cannot be deserialized because its class is not in the classpath
204 */
205 protected Map<String, Object> valuesFrom( Reference ref ) throws IOException, ClassNotFoundException {
206 Map<String, Object> values = new HashMap<String, Object>();
207
208 Enumeration<?> en = ref.getAll();
209 while (en.hasMoreElements()) {
210 RefAddr subref = (RefAddr)en.nextElement();
211 if (subref instanceof StringRefAddr) {
212 String key = subref.getType();
213 Object value = subref.getContent();
214 if (value != null) values.put(key, value.toString());
215 } else if (subref instanceof BinaryRefAddr) {
216 String key = subref.getType();
217 Object value = subref.getContent();
218 if (value instanceof byte[]) {
219 // Deserialize ...
220 ByteArrayInputStream bais = new ByteArrayInputStream((byte[])value);
221 ObjectInputStream ois = new ObjectInputStream(bais);
222 value = ois.readObject();
223 values.put(key, value);
224 }
225 }
226 }
227
228 return values;
229 }
230
231 /**
232 * @return the active path repository cache; never null
233 */
234 public PathRepositoryCache getPathRepositoryCache() {
235 return repositoryCache;
236 }
237 }