Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
EncoderProvider |
|
| 2.2;2.2 |
1 | /* | |
2 | * Copyright (C) 1998-2000 Semiotek Inc. All Rights Reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted under the terms of either of the following | |
6 | * Open Source licenses: | |
7 | * | |
8 | * The GNU General Public License, version 2, or any later version, as | |
9 | * published by the Free Software Foundation | |
10 | * (http://www.fsf.org/copyleft/gpl.html); | |
11 | * | |
12 | * or | |
13 | * | |
14 | * The Semiotek Public License (http://webmacro.org/LICENSE.) | |
15 | * | |
16 | * This software is provided "as is", with NO WARRANTY, not even the | |
17 | * implied warranties of fitness to purpose, or merchantability. You | |
18 | * assume all risks and liabilities associated with its use. | |
19 | * | |
20 | * See www.webmacro.org for more information on the WebMacro project. | |
21 | */ | |
22 | ||
23 | package org.webmacro.util; | |
24 | ||
25 | import java.io.UnsupportedEncodingException; | |
26 | import java.util.HashMap; | |
27 | import java.util.Map; | |
28 | ||
29 | import org.webmacro.Broker; | |
30 | import org.webmacro.InitException; | |
31 | import org.webmacro.NotFoundException; | |
32 | import org.webmacro.Provider; | |
33 | import org.webmacro.ResourceException; | |
34 | ||
35 | /** | |
36 | * A provider which dispenses Encoders, which are used for encoding | |
37 | * Strings and caching the results. | |
38 | * @since 0.96 | |
39 | * @author Michael Bayne | |
40 | */ | |
41 | ||
42 | 6 | public class EncoderProvider implements Provider |
43 | { | |
44 | ||
45 | 6 | private Map _encoders = new HashMap(); |
46 | private Broker _broker; | |
47 | private Settings _config; | |
48 | ||
49 | /** | |
50 | * The provider type for this provider. Use this when calling | |
51 | * <code>Broker.getProvider()</code>. | |
52 | */ | |
53 | public static final String TYPE = "encoder"; | |
54 | ||
55 | /** | |
56 | * Return an array representing the types this provider serves up | |
57 | */ | |
58 | public String getType () | |
59 | { | |
60 | 6 | return TYPE; |
61 | } | |
62 | ||
63 | /** | |
64 | * Initialize this provider based on the specified config. Derived | |
65 | * encoder provider implementations may override this method to obtain | |
66 | * initialization parameters of their own devising, but they must be | |
67 | * sure to call super.init() in their overridden methods. | |
68 | */ | |
69 | public void init (Broker b, Settings config) throws InitException | |
70 | { | |
71 | 6 | _broker = b; |
72 | 6 | _config = config; |
73 | 6 | } |
74 | ||
75 | // Implementation note: the flush(), destroy() and get() methods are | |
76 | // instance synchronized to ensure that if _encoders is cleared via the | |
77 | // destroy() method and get() is called subsequently, we properly avoid | |
78 | // referencing the null variable. We can't synchronize on _encoders | |
79 | // because that becomes null and code that does this: | |
80 | // | |
81 | // if (_encoders != null) { | |
82 | // synchronized (_encoders) { | |
83 | // | |
84 | // is not valid because the _encoders reference could become null | |
85 | // in between those two statements. | |
86 | // | |
87 | // Additionally, the EncoderProvider is not invoked frequently enough | |
88 | // to merit a more sophisticated synchronization approach (it is only | |
89 | // called once per request when creating a FastWriter with which to | |
90 | // output the response and not even that often because FastWriter | |
91 | // instances are cached). Thus, we choose simplicity and robustness in | |
92 | // this situation. | |
93 | ||
94 | /** | |
95 | * Clear any cache this provider may be maintaining. | |
96 | */ | |
97 | public synchronized void flush () | |
98 | { | |
99 | // clean out the encoder cache | |
100 | 0 | _encoders.clear(); |
101 | 0 | } |
102 | ||
103 | /** | |
104 | * Close down this provider, freeing any allocated resources. | |
105 | */ | |
106 | public synchronized void destroy () | |
107 | { | |
108 | // clear out our reference to the encoder cache to allow it to be | |
109 | // garbage collected | |
110 | 0 | _encoders = null; |
111 | 0 | } |
112 | ||
113 | /** | |
114 | * Get the object associated with the specified query. | |
115 | */ | |
116 | public synchronized Object get (String encoding) throws ResourceException | |
117 | { | |
118 | 1734 | Encoder encoder = null; |
119 | ||
120 | // make sure we're not inadvertently being called after we've | |
121 | // already been destroy()ed | |
122 | 1734 | if (_encoders != null) |
123 | { | |
124 | 1734 | encoder = (Encoder) _encoders.get(encoding); |
125 | ||
126 | 1734 | if (encoder == null) |
127 | { | |
128 | try | |
129 | { | |
130 | // create and cache a new encoder instance for this | |
131 | // encoding if one doesn't already exist in the cache | |
132 | 12 | encoder = new Encoder(encoding); |
133 | 12 | encoder.init(_broker, _config); |
134 | 12 | _encoders.put(encoding, encoder); |
135 | } | |
136 | 0 | catch (InitException e) |
137 | { | |
138 | 0 | throw new ResourceException("Unable to initialize Encoder for " |
139 | + encoding + "; " + e); | |
140 | } | |
141 | 0 | catch (UnsupportedEncodingException uee) |
142 | { | |
143 | 0 | throw new NotFoundException("Unsupported encoding: " + |
144 | uee.getMessage()); | |
145 | 12 | } |
146 | } | |
147 | } | |
148 | 1734 | return encoder; |
149 | } | |
150 | } |