View Javadoc

1   /* DataContainer
2    *
3    * $Id: DataContainer.java 4661 2006-09-25 23:11:16Z paul_jack $
4    *
5    * Created on Dec 17, 2003
6    *
7    * Copyright (C) 2003 Internet Archive.
8    *
9    * This file is part of the Heritrix web crawler (crawler.archive.org).
10   *
11   * Heritrix is free software; you can redistribute it and/or modify
12   * it under the terms of the GNU Lesser Public License as published by
13   * the Free Software Foundation; either version 2.1 of the License, or
14   * any later version.
15   *
16   * Heritrix is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU Lesser Public License for more details.
20   *
21   * You should have received a copy of the GNU Lesser Public License
22   * along with Heritrix; if not, write to the Free Software
23   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         //attributeNames.put(type.getName(), attribute);
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     /* (non-Javadoc)
180      * @see java.util.Map#put(java.lang.Object, java.lang.Object)
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     /* (non-Javadoc)
189      * @see java.util.Map#get(java.lang.Object)
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 }