1
2
3
4 package org.rcfaces.core.internal.repository;
5
6 import java.io.IOException;
7 import java.util.Arrays;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.Iterator;
11 import java.util.Locale;
12 import java.util.Map;
13 import java.util.Set;
14
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17 import org.rcfaces.core.internal.Constants;
18 import org.rcfaces.core.internal.webapp.URIParameters;
19
20
21
22
23
24
25 public abstract class AbstractRepository implements IRepository {
26
27 private static final String REVISION = "$Revision: 1.2 $";
28
29 private static final long serialVersionUID = -3328226384749670660L;
30
31 private static final Log LOG = LogFactory.getLog(AbstractRepository.class);
32
33 protected static final IFile[] FILE_EMPTY_ARRAY = new IFile[0];
34
35 private static final Object[] OBJECT_EMPTY_ARRAY = new Object[0];
36
37 protected final Map filesByName = new HashMap();
38
39 protected final Map filesByURI = new HashMap();
40
41 protected final String repositoryVersion;
42
43 protected final String servletURI;
44
45 public AbstractRepository(String servletURI, String repositoryVersion) {
46 if (servletURI.length() > 0) {
47 if (servletURI.endsWith("/") && servletURI.length() > 1) {
48 servletURI = servletURI.substring(0, servletURI.length() - 1);
49
50 } else if (servletURI.startsWith("/") == false) {
51 servletURI = "/" + servletURI;
52 }
53 }
54
55 this.servletURI = servletURI;
56 this.repositoryVersion = repositoryVersion;
57 }
58
59 public final String getVersion() {
60 return repositoryVersion;
61 }
62
63 public IFile getFileByURI(String uri) {
64 return (IFile) filesByURI.get(uri);
65 }
66
67 public IFile getFileByName(String name) {
68 return (IFile) filesByName.get(name);
69 }
70
71 public IContext createContext(Locale locale) {
72 return new ContextImpl(locale);
73 }
74
75 protected abstract IContentProvider getDefaultContentProvider();
76
77
78
79
80
81
82 protected static class ContextImpl implements IContext {
83 private static final String REVISION = "$Revision: 1.2 $";
84
85 private final Set files = new HashSet(32);
86
87 private final Locale locale;
88
89 public ContextImpl(Locale locale) {
90 this.locale = locale;
91 }
92
93 public Locale getLocale() {
94 return locale;
95 }
96
97 public boolean contains(IFile file) {
98 return files.contains(file);
99 }
100
101 public boolean add(IFile file) {
102 return files.add(file);
103 }
104
105 public IContext copy() {
106 ContextImpl ctx = new ContextImpl(locale);
107 ctx.files.addAll(files);
108
109 return ctx;
110 }
111
112 public void restoreState(IRepository repository, Object state) {
113 if (state == null) {
114 return;
115 }
116
117 Object fs[] = (Object[]) state;
118 for (int i = 0; i < fs.length; i++) {
119 IFile file = ((BasicHierarchicalRepository) repository)
120 .getFileById((String) fs[i]);
121
122 if (file == null) {
123 continue;
124 }
125
126 add(file);
127 }
128 }
129
130 public Object saveState() {
131 if (files.isEmpty()) {
132 return null;
133 }
134
135 Iterator it = files.iterator();
136 Object ret[] = new Object[files.size()];
137 for (int i = 0; it.hasNext();) {
138 IFile file = (IFile) it.next();
139
140 ret[i++] = ((File) file).getId();
141 }
142
143 return ret;
144 }
145 }
146
147 protected Locale adaptLocale(Locale locale, IFile file) {
148 return locale;
149 }
150
151
152
153
154
155
156 protected class File implements IFile {
157
158 private static final String REVISION = "$Revision: 1.2 $";
159
160 private static final long serialVersionUID = -8396517787887070898L;
161
162 private final String id;
163
164 private final String filename;
165
166 private final Object unlocalizedContentLocation;
167
168 private final String unlocalizedURI;
169
170 private final IContentProvider contentProvider;
171
172 private final int hashCode;
173
174 private LocalizedFile unlocalizedFile;
175
176 private Map localizedFiles;
177
178 public File(String name, String filename, String unlocalizedURI,
179 Object unlocalizedContentLocation,
180 IContentProvider contentProvider) {
181 this.id = name;
182 this.filename = filename;
183 this.unlocalizedURI = unlocalizedURI;
184 this.unlocalizedContentLocation = unlocalizedContentLocation;
185 this.contentProvider = contentProvider;
186 this.hashCode = filename.hashCode();
187 }
188
189 public IRepository getRepository() {
190 return AbstractRepository.this;
191 }
192
193 public final String getId() {
194 return id;
195 }
196
197 public Object[] getContentReferences(Locale locale) {
198 LocalizedFile localizedFile = getLocalizedFile(locale);
199
200 return localizedFile.getContentLocations();
201 }
202
203 public String getFilename() {
204 return filename;
205 }
206
207 public IContentProvider getContentProvider() {
208 if (contentProvider != null) {
209 return contentProvider;
210 }
211
212 return computeContentProvider();
213 }
214
215 protected IContentProvider computeContentProvider() {
216 return getDefaultContentProvider();
217 }
218
219 public String getURI(Locale locale) {
220 LocalizedFile localizedFile = getLocalizedFile(locale);
221
222 return localizedFile.getURI();
223 }
224
225 protected synchronized LocalizedFile getLocalizedFile(Locale locale) {
226 if (locale == null) {
227 if (unlocalizedFile != null) {
228 return unlocalizedFile;
229 }
230
231 unlocalizedFile = new LocalizedFile(getContentProvider(), null,
232 unlocalizedURI, unlocalizedContentLocation);
233 return unlocalizedFile;
234 }
235
236 locale = adaptLocale(locale, this);
237
238 if (localizedFiles == null) {
239 localizedFiles = new HashMap(4);
240 }
241
242 LocalizedFile localizedFile = (LocalizedFile) localizedFiles
243 .get(locale);
244 if (localizedFile != null) {
245 return localizedFile;
246 }
247
248 localizedFile = new LocalizedFile(getContentProvider(), locale,
249 unlocalizedURI, unlocalizedContentLocation);
250 localizedFiles.put(locale, localizedFile);
251
252 return localizedFile;
253 }
254
255 public boolean equals(Object obj) {
256 if (obj == this) {
257 return true;
258 }
259 if (obj == null || (obj instanceof File) == false) {
260 return false;
261 }
262
263 File f = (File) obj;
264
265 return f.filename.equals(filename);
266 }
267
268 public int hashCode() {
269 return hashCode;
270 }
271 }
272
273
274
275
276
277
278 protected static class LocalizedFile {
279 private static final String REVISION = "$Revision: 1.2 $";
280
281 private final String uri;
282
283 private final Object[] contentLocations;
284
285 public LocalizedFile(IContentProvider contentProvider, Locale locale,
286 String uri, Object unlocalizedContentLocation) {
287 Object localizedContentLocation = null;
288
289 if (locale != null) {
290 URIParameters uriParameters = new URIParameters(uri);
291
292 if (locale != null) {
293 uriParameters.appendLocale(locale);
294 }
295
296 uri = uriParameters.computeParametredURI();
297 }
298
299 if (locale != null) {
300 if (unlocalizedContentLocation != null) {
301 localizedContentLocation = contentProvider
302 .searchLocalizedContentReference(
303 unlocalizedContentLocation, locale);
304
305 if (localizedContentLocation == null) {
306 locale = Constants.REPOSITORY_DEFAULT_LOCALE;
307
308 localizedContentLocation = contentProvider
309 .searchLocalizedContentReference(
310 unlocalizedContentLocation, locale);
311 }
312
313 if (localizedContentLocation != null) {
314 if (LOG.isTraceEnabled()) {
315 LOG.trace("Find localized version (" + locale
316 + ") of '" + uri + "' => "
317 + localizedContentLocation);
318
319 }
320 } else {
321 if (LOG.isTraceEnabled()) {
322 LOG.trace("Can not find localized version ("
323 + locale + ") of '" + uri + "'.");
324
325 }
326 }
327 }
328 }
329
330 if (unlocalizedContentLocation == null) {
331 contentLocations = OBJECT_EMPTY_ARRAY;
332
333 } else if (localizedContentLocation == null) {
334 contentLocations = new Object[] { unlocalizedContentLocation };
335
336 } else {
337 contentLocations = new Object[] { unlocalizedContentLocation,
338 localizedContentLocation };
339 }
340
341 if (LOG.isDebugEnabled()) {
342 LOG.debug("Content locations of " + this + " => "
343 + Arrays.asList(contentLocations));
344 }
345
346 this.uri = uri;
347 }
348
349 public Object[] getContentLocations() {
350 return contentLocations;
351 }
352
353 public String getURI() {
354 return uri;
355 }
356 }
357
358
359
360
361
362
363 public static abstract class AbstractContent implements IContent {
364 private static final String REVISION = "$Revision: 1.2 $";
365
366 public long getLastModified() throws IOException {
367 return -1;
368 }
369
370 public long getLength() throws IOException {
371 return -1;
372 }
373
374 public void release() {
375 }
376
377 }
378 }