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 package org.archive.crawler.settings;
27
28 import java.lang.ref.Reference;
29 import java.lang.ref.WeakReference;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33
34 import javax.management.AttributeNotFoundException;
35 import javax.management.InvalidAttributeValueException;
36 import javax.management.MBeanAttributeInfo;
37 import javax.management.MBeanInfo;
38
39 import java.util.concurrent.CopyOnWriteArrayList;
40
41 /*** This class holds the data for a ComplexType for a settings object.
42 *
43 * @author John Erik Halse
44 */
45 public class DataContainer extends HashMap<String,Object> {
46
47 private static final long serialVersionUID = 2089160108643429282L;
48
49 /*** The ComplexType for which this DataContainer keeps data */
50 private ComplexType complexType;
51
52 /*** The Settings object for which this data is valid */
53 private Reference<CrawlerSettings> settings;
54
55 /*** The attributes defined for this DataContainers combination of
56 * ComplexType and CrawlerSettings.
57 */
58 private List<MBeanAttributeInfo> attributes;
59
60 /*** All attributes that have their value set for this DataContainers
61 * combination of ComplexType and CrawlerSettings. This includes overrides.
62 */
63 private Map<String,MBeanAttributeInfo> attributeNames;
64
65 /*** Create a data container for a module.
66 *
67 * @param settings Settings to use.
68 * @param module the module to create the data container for.
69 */
70 public DataContainer(CrawlerSettings settings, ComplexType module) {
71 super();
72 this.settings = new WeakReference<CrawlerSettings>(settings);
73 this.complexType = module;
74 attributes =
75 new CopyOnWriteArrayList<MBeanAttributeInfo>();
76 attributeNames = new HashMap<String,MBeanAttributeInfo>();
77 }
78
79 /*** Add a new element to the data container.
80 *
81 * @param type the element to add.
82 * @param index index at which the specified element is to be inserted.
83 * @throws InvalidAttributeValueException
84 */
85 public void addElementType(Type type, int index)
86 throws InvalidAttributeValueException {
87
88 if (attributeNames.containsKey(type.getName())) {
89 throw new IllegalArgumentException(
90 "Duplicate field: " + type.getName());
91 }
92 if (type.getDefaultValue() == null) {
93 throw new InvalidAttributeValueException(
94 "null is not allowed as default value for attribute '"
95 + type.getName() + "' in class '"
96 + complexType.getClass().getName() + "'");
97 }
98 MBeanAttributeInfo attribute = new ModuleAttributeInfo(type);
99 attributes.add(index, attribute);
100
101 try {
102 put(type.getName(), attribute, type.getDefaultValue());
103 } catch (InvalidAttributeValueException e) {
104 e.printStackTrace();
105 } catch (AttributeNotFoundException e) {
106 e.printStackTrace();
107 }
108 }
109
110 /*** Appends the specified element to the end of this data container.
111 *
112 * @param type the element to add.
113 * @throws InvalidAttributeValueException
114 */
115 public void addElementType(Type type) throws InvalidAttributeValueException {
116
117 addElementType(type, attributes.size());
118 }
119
120 public MBeanInfo getMBeanInfo() {
121 MBeanAttributeInfo attrs[] = (MBeanAttributeInfo[]) attributes
122 .toArray(new MBeanAttributeInfo[0]);
123 MBeanInfo info = new MBeanInfo(complexType.getClass().getName(),
124 complexType.getDescription(), attrs, null, null, null);
125 return info;
126 }
127
128 protected List<MBeanAttributeInfo> getLocalAttributeInfoList() {
129 return attributes;
130 }
131
132 protected boolean hasAttributes() {
133 return !attributes.isEmpty();
134 }
135
136 public int size() {
137 return attributes.size();
138 }
139
140 protected MBeanAttributeInfo getAttributeInfo(String name) {
141 return (MBeanAttributeInfo) attributeNames.get(name);
142 }
143
144 protected void copyAttributeInfo(String name, DataContainer destination) {
145 if (this != destination) {
146 ModuleAttributeInfo attribute = (ModuleAttributeInfo) attributeNames.get(name);
147 destination.attributeNames.put(name, new ModuleAttributeInfo(attribute));
148 }
149 }
150
151 protected boolean copyAttribute(String name, DataContainer destination)
152 throws InvalidAttributeValueException, AttributeNotFoundException {
153 if (this != destination) {
154 ModuleAttributeInfo attribute = (ModuleAttributeInfo) attributeNames
155 .get(name);
156
157 if (attribute == null) {
158 return false;
159 } else {
160 int index = attributes.indexOf(attribute);
161 if (index != -1 && !destination.attributes.contains(attribute)) {
162 destination.attributes.add(index, attribute);
163 }
164 destination.put(attribute.getName(), attribute, get(attribute
165 .getName()));
166 }
167 }
168 return true;
169 }
170
171 public Object put(String key, Object value) {
172 throw new UnsupportedOperationException();
173 }
174
175 public Object get(Object key) {
176 throw new UnsupportedOperationException();
177 }
178
179
180
181
182 protected Object put(String key, MBeanAttributeInfo info, Object value)
183 throws InvalidAttributeValueException, AttributeNotFoundException {
184 attributeNames.put(key, info);
185 return super.put(key, value);
186 }
187
188
189
190
191 public Object get(String key) throws AttributeNotFoundException {
192 Object res = super.get(key);
193 if (res == null && complexType.definitionMap.get(key) == null) {
194 throw new AttributeNotFoundException(key);
195 }
196 return res;
197 }
198
199 /*** Move an attribute up one place in the list.
200 *
201 * @param key name of attribute to move.
202 * @return true if attribute was moved, false if attribute was already
203 * at the top.
204 * @throws AttributeNotFoundException is thrown if there is no attribute
205 * with the submitted key.
206 */
207 protected boolean moveElementUp(String key)
208 throws AttributeNotFoundException {
209 MBeanAttributeInfo element = getAttributeInfo(key);
210 if (element == null) {
211 throw new AttributeNotFoundException(key);
212 }
213
214 int prevIndex = attributes.indexOf(element);
215 if (prevIndex == 0) {
216 return false;
217 }
218
219 attributes.remove(prevIndex);
220 attributes.add(prevIndex-1, element);
221
222 return true;
223 }
224
225 /*** Move an attribute down one place in the list.
226 *
227 * @param key name of attribute to move.
228 * @return true if attribute was moved, false if attribute was already
229 * at bottom.
230 * @throws AttributeNotFoundException is thrown if there is no attribute
231 * with the submitted key.
232 */
233 protected boolean moveElementDown(String key)
234 throws AttributeNotFoundException {
235 MBeanAttributeInfo element = getAttributeInfo(key);
236 if (element == null) { throw new AttributeNotFoundException(key); }
237
238 int prevIndex = attributes.indexOf(element);
239 if (prevIndex == attributes.size() - 1) { return false; }
240
241 attributes.remove(prevIndex);
242 attributes.add(prevIndex + 1, element);
243
244 return true;
245 }
246
247 /***
248 * Remove an attribute from the DataContainer.
249 *
250 * @param key name of the attribute to remove.
251 * @return the element that was removed.
252 * @throws AttributeNotFoundException is thrown if there is no attribute
253 * with the submitted key.
254 */
255 protected Object removeElement(String key) throws AttributeNotFoundException {
256 MBeanAttributeInfo element = getAttributeInfo(key);
257 if (element == null) {
258 throw new AttributeNotFoundException(key);
259 }
260
261 attributes.remove(element);
262 attributeNames.remove(element.getName());
263 return super.remove(element.getName());
264 }
265
266 /*** Get the ComplexType for which this DataContainer keeps data.
267 *
268 * @return the ComplexType for which this DataContainer keeps data.
269 */
270 protected ComplexType getComplexType() {
271 return complexType;
272 }
273
274 /*** Get the settings object for which this DataContainers data are valid.
275 *
276 * @return the settings object for which this DataContainers data are valid.
277 */
278 protected CrawlerSettings getSettings() {
279 return (CrawlerSettings) settings.get();
280 }
281
282 }