Source Code Cross Referenced for ComplexType.java in  » Web-Crawler » heritrix » org » archive » crawler » settings » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Crawler » heritrix » org.archive.crawler.settings 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* ComplexType
0002:         *
0003:         * $Id: ComplexType.java 5028 2007-03-29 23:21:48Z gojomo $
0004:         *
0005:         * Created on Dec 17, 2003
0006:         *
0007:         * Copyright (C) 2004 Internet Archive.
0008:         *
0009:         * This file is part of the Heritrix web crawler (crawler.archive.org).
0010:         *
0011:         * Heritrix is free software; you can redistribute it and/or modify
0012:         * it under the terms of the GNU Lesser Public License as published by
0013:         * the Free Software Foundation; either version 2.1 of the License, or
0014:         * any later version.
0015:         *
0016:         * Heritrix is distributed in the hope that it will be useful,
0017:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0018:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0019:         * GNU Lesser Public License for more details.
0020:         *
0021:         * You should have received a copy of the GNU Lesser Public License
0022:         * along with Heritrix; if not, write to the Free Software
0023:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0024:         */
0025:        package org.archive.crawler.settings;
0026:
0027:        import java.util.ArrayList;
0028:        import java.util.HashMap;
0029:        import java.util.Iterator;
0030:        import java.util.List;
0031:        import java.util.Map;
0032:        import java.util.Stack;
0033:        import java.util.logging.Level;
0034:        import java.util.logging.Logger;
0035:
0036:        import javax.management.Attribute;
0037:        import javax.management.AttributeList;
0038:        import javax.management.AttributeNotFoundException;
0039:        import javax.management.DynamicMBean;
0040:        import javax.management.InvalidAttributeValueException;
0041:        import javax.management.MBeanAttributeInfo;
0042:        import javax.management.MBeanException;
0043:        import javax.management.MBeanInfo;
0044:        import javax.management.ReflectionException;
0045:
0046:        import org.apache.commons.httpclient.URIException;
0047:        import org.archive.crawler.datamodel.CandidateURI;
0048:        import org.archive.crawler.datamodel.CrawlOrder;
0049:        import org.archive.crawler.datamodel.CrawlURI;
0050:        import org.archive.crawler.settings.Constraint.FailedCheck;
0051:        import org.archive.net.UURI;
0052:
0053:        /** Superclass of all configurable modules.
0054:         *
0055:         * This class is in many ways the heart of the settings framework. All modules
0056:         * that should be configurable extends this class or one of its subclasses.
0057:         *
0058:         * All subclasses of this class will automatically conform to the
0059:         * JMX DynamicMBean. You could then use the {@link #getMBeanInfo()} method to
0060:         * investigate which attributes this module supports and then use the
0061:         * {@link #getAttribute(String)} and {@link #setAttribute(Attribute)} methods to
0062:         * alter the attributes values.
0063:         *
0064:         * Because the settings framework supports per domain/host settings there is
0065:         * also available context sensitive versions of the DynamicMBean methods.
0066:         * If you use the non context sensitive methods, it is the global settings
0067:         * that will be altered.
0068:         *
0069:         * @author John Erik Halse
0070:         */
0071:        public abstract class ComplexType extends Type implements  DynamicMBean {
0072:            private static Logger logger = Logger
0073:                    .getLogger("org.archive.crawler.settings.ComplexType");
0074:
0075:            private transient SettingsHandler settingsHandler;
0076:            private transient ComplexType parent;
0077:            private String description;
0078:            private String absoluteName;
0079:            protected final List<Type> definition = new ArrayList<Type>();
0080:            protected final Map<String, Type> definitionMap = new HashMap<String, Type>();
0081:            private boolean initialized = false;
0082:            private String[] preservedFields = new String[0];
0083:
0084:            /**
0085:             * Private constructor to make sure that no one
0086:             * instantiates this class with the empty constructor.
0087:             */
0088:            private ComplexType() {
0089:                super (null, null);
0090:            }
0091:
0092:            /** Creates a new instance of ComplexType.
0093:             *
0094:             * @param name the name of the element.
0095:             * @param description the description of the element.
0096:             */
0097:            public ComplexType(String name, String description) {
0098:                super (name, null);
0099:                this .description = description.intern();
0100:            }
0101:
0102:            protected void setAsOrder(SettingsHandler settingsHandler)
0103:                    throws InvalidAttributeValueException {
0104:                this .settingsHandler = settingsHandler;
0105:                this .absoluteName = "";
0106:                globalSettings().addTopLevelModule((CrawlOrder) this );
0107:                addComplexType(settingsHandler.getSettingsObject(null), this );
0108:                this .parent = null;
0109:            }
0110:
0111:            /** Get the global settings object (aka order).
0112:             *
0113:             * @return the global settings object.
0114:             */
0115:            public CrawlerSettings globalSettings() {
0116:                if (settingsHandler == null) {
0117:                    return null;
0118:                }
0119:                return settingsHandler.getSettingsObject(null);
0120:            }
0121:
0122:            public Type addElement(CrawlerSettings settings, Type type)
0123:                    throws InvalidAttributeValueException {
0124:                getOrCreateDataContainer(settings).addElementType(type);
0125:                if (type instanceof  ComplexType) {
0126:                    addComplexType(settings, (ComplexType) type);
0127:                }
0128:                return type;
0129:            }
0130:
0131:            private ComplexType addComplexType(CrawlerSettings settings,
0132:                    ComplexType object) throws InvalidAttributeValueException {
0133:
0134:                if (this .settingsHandler == null) {
0135:                    throw new IllegalStateException(
0136:                            "Can't add ComplexType to 'free' ComplexType");
0137:                }
0138:                setupVariables(object);
0139:                settings.addComplexType(object);
0140:                if (!object.initialized) {
0141:                    Iterator it = object.definition.iterator();
0142:                    while (it.hasNext()) {
0143:                        Type t = (Type) it.next();
0144:                        object.addElement(settings, t);
0145:                    }
0146:                    object.earlyInitialize(settings);
0147:                }
0148:                object.initialized = true;
0149:
0150:                return object;
0151:            }
0152:
0153:            private ComplexType replaceComplexType(CrawlerSettings settings,
0154:                    ComplexType object) throws InvalidAttributeValueException,
0155:                    AttributeNotFoundException {
0156:                if (this .settingsHandler == null) {
0157:                    throw new IllegalStateException(
0158:                            "Can't add ComplexType to 'free' ComplexType");
0159:                }
0160:                String[] preservedFields = object.getPreservedFields();
0161:
0162:                setupVariables(object);
0163:
0164:                DataContainer oldData = settings.getData(object);
0165:                settings.addComplexType(object);
0166:                DataContainer newData = settings.getData(object);
0167:
0168:                if (!object.initialized) {
0169:                    Iterator it = object.definition.iterator();
0170:                    while (it.hasNext()) {
0171:                        Type t = (Type) it.next();
0172:
0173:                        // Check if attribute should be copied from old object.
0174:                        boolean found = false;
0175:                        if (preservedFields.length > 0) {
0176:                            for (int i = 0; i < preservedFields.length; i++) {
0177:                                if (preservedFields[i].equals(t.getName())) {
0178:                                    found = true;
0179:                                    break;
0180:                                }
0181:                            }
0182:                        }
0183:                        if (found
0184:                                && oldData.copyAttribute(t.getName(), newData)) {
0185:                            if (t instanceof  ComplexType) {
0186:                                object.setupVariables((ComplexType) t);
0187:                            }
0188:                        } else {
0189:                            object.addElement(settings, t);
0190:                        }
0191:                    }
0192:                    object.earlyInitialize(settings);
0193:                }
0194:                object.initialized = true;
0195:
0196:                return object;
0197:            }
0198:
0199:            /** Set a list of attribute names that the complex type should attempt to
0200:             * preserve if the module is exchanged with an other one.
0201:             *
0202:             * @param preservedFields array of attributenames to preserve.
0203:             */
0204:            protected void setPreservedFields(String[] preservedFields) {
0205:                this .preservedFields = preservedFields;
0206:            }
0207:
0208:            /** Get a list of attribute names that the complex type should attempt to
0209:             * preserve if the module is exchanged with an other one.
0210:             *
0211:             * @return an array of attributenames to preserve.
0212:             */
0213:            protected String[] getPreservedFields() {
0214:                return this .preservedFields;
0215:            }
0216:
0217:            /** Get the active data container for this ComplexType for a specific
0218:             * settings object.
0219:             *
0220:             * If no value has been overridden on the settings object for this
0221:             * ComplexType, then it traverses up until it find a DataContainer with
0222:             * values for this ComplexType.
0223:             *
0224:             * This method should probably not be called from user code. It is a helper
0225:             * method for the settings framework.
0226:             *
0227:             * @param context Context from which we get settings.
0228:             * @return the active DataContainer.
0229:             */
0230:            protected DataContainer getDataContainerRecursive(Context context) {
0231:                if (context.settings == null) {
0232:                    return null;
0233:                }
0234:                DataContainer data = context.settings.getData(this );
0235:                if (data == null
0236:                        && context.settings.getParent(context.uri) != null) {
0237:                    context.settings = context.settings.getParent(context.uri);
0238:                    data = getDataContainerRecursive(context);
0239:                }
0240:                return data;
0241:            }
0242:
0243:            /** Get the active data container for this ComplexType for a specific
0244:             * settings object.
0245:             *
0246:             * If the key has not been overridden on the settings object for this
0247:             * ComplexType, then it traverses up until it find a DataContainer with
0248:             * the key for this ComplexType.
0249:             *
0250:             * This method should probably not be called from user code. It is a helper
0251:             * method for the settings framework.
0252:             *
0253:             * @param context the settings object for which the {@link DataContainer}
0254:             *                 is active.
0255:             * @param key the key to look for.
0256:             * @return the active DataContainer.
0257:             * @throws AttributeNotFoundException
0258:             */
0259:            protected DataContainer getDataContainerRecursive(Context context,
0260:                    String key) throws AttributeNotFoundException {
0261:                Context c = new Context(context.settings, context.uri);
0262:                DataContainer data = getDataContainerRecursive(c);
0263:                while (data != null) {
0264:                    if (data.containsKey(key)) {
0265:                        return data;
0266:                    }
0267:                    c.settings = data.getSettings().getParent(c.uri);
0268:                    data = getDataContainerRecursive(c);
0269:                }
0270:                throw new AttributeNotFoundException(key);
0271:            }
0272:
0273:            /** Sets up some variables for a new complex type.
0274:             *
0275:             * The complex type is set up to be an attribute of
0276:             * this complex type.
0277:             *
0278:             * @param object to be set up.
0279:             */
0280:            private void setupVariables(ComplexType object) {
0281:                object.parent = this ;
0282:                object.settingsHandler = getSettingsHandler();
0283:                object.absoluteName = (getAbsoluteName() + '/' + object
0284:                        .getName()).intern();
0285:            }
0286:
0287:            public SettingsHandler getSettingsHandler() {
0288:                return settingsHandler;
0289:            }
0290:
0291:            /** Get the absolute name of this ComplexType.
0292:             *
0293:             * The absolute name is like a file path with the name of the element
0294:             * prepended by all the parents names separated by slashes.
0295:             * @return Absolute name.
0296:             */
0297:            public String getAbsoluteName() {
0298:                return absoluteName;
0299:            }
0300:
0301:            /**
0302:             * Get settings object valid for a URI.
0303:             * <p/>
0304:             * This method takes an object,
0305:             * try to convert it into a {@link CrawlURI} and then tries to get the
0306:             * settings object from it. If this fails, then the global settings object
0307:             * is returned.
0308:             * <p/>
0309:             * If the requested attribute is not set on this settings
0310:             * object it tries its parent until it gets a settings object where this
0311:             * attribute is set is found. If nothing is found, global settings is
0312:             * returned.
0313:             *
0314:             * @param o possible {@link CrawlURI}.
0315:             * @param attributeName the attribute that should have a value set on the
0316:             *            returned settings object.
0317:             * @return the settings object valid for the URI.
0318:             */
0319:            Context getSettingsFromObject(Object o, String attributeName) {
0320:                Context context;
0321:                if (o == null) {
0322:                    context = null;
0323:                } else if (o instanceof  Context) {
0324:                    context = (Context) o;
0325:                } else if (o instanceof  CrawlerSettings) {
0326:                    context = new Context((CrawlerSettings) o, null);
0327:                } else if (o instanceof  UURI || o instanceof  CandidateURI) {
0328:                    // Try to get settings for URI that has no references to a
0329:                    // CrawlServer [SIC - CrawlURI may have CrawlServer -gjm]
0330:                    context = new Context();
0331:                    context.uri = (o instanceof  CandidateURI) ? ((CandidateURI) o)
0332:                            .getUURI()
0333:                            : (UURI) o;
0334:                    try {
0335:                        context.settings = getSettingsHandler().getSettings(
0336:                                context.uri.getReferencedHost(), context.uri);
0337:                    } catch (URIException e1) {
0338:                        logger.severe("Failed to get host");
0339:                    }
0340:
0341:                    if (attributeName != null) {
0342:                        try {
0343:                            context.settings = getDataContainerRecursive(
0344:                                    context, attributeName).getSettings();
0345:                        } catch (AttributeNotFoundException e) {
0346:                            // Nothing found, globals will be used
0347:                        }
0348:                    }
0349:                } else {
0350:                    logger.warning("Unknown object type: "
0351:                            + o.getClass().getName());
0352:                    context = null;
0353:                }
0354:
0355:                // if settings could not be resolved use globals.
0356:                if (context == null) {
0357:                    context = new Context(globalSettings(), null);
0358:                }
0359:                return context;
0360:            }
0361:
0362:            /** Get settings object valid for a URI.
0363:             *
0364:             * This method takes an object, try to convert it into a {@link CrawlURI}
0365:             * and then tries to get the settings object from it. If this fails, then
0366:             * the global settings object is returned.
0367:             *
0368:             * @param o possible {@link CrawlURI}.
0369:             * @return the settings object valid for the URI.
0370:             */
0371:            Context getSettingsFromObject(Object o) {
0372:                return getSettingsFromObject(o, null);
0373:            }
0374:
0375:            /** Returns true if an element is overridden for this settings object.
0376:             *
0377:             * @param settings the settings object to investigate.
0378:             * @param name the name of the element to check.
0379:             * @return true if element is overridden for this settings object, false
0380:             *              if not set here or is first defined here.
0381:             * @throws AttributeNotFoundException if element doesn't exist.
0382:             */
0383:            public boolean isOverridden(CrawlerSettings settings, String name)
0384:                    throws AttributeNotFoundException {
0385:                settings = settings == null ? globalSettings() : settings;
0386:                DataContainer data = settings.getData(this );
0387:                if (data == null || !data.containsKey(name)) {
0388:                    return false;
0389:                }
0390:
0391:                // Try to find attribute, will throw an exception if not found.
0392:                Context context = new Context(settings.getParent(), null);
0393:                getDataContainerRecursive(context, name);
0394:                return true;
0395:            }
0396:
0397:            /** Obtain the value of a specific attribute from the crawl order.
0398:             *
0399:             * If the attribute doesn't exist in the crawl order, the default
0400:             * value will be returned.
0401:             *
0402:             * @param name the name of the attribute to be retrieved.
0403:             * @return The value of the attribute retrieved.
0404:             * @throws AttributeNotFoundException
0405:             * @throws MBeanException
0406:             * @throws ReflectionException
0407:             */
0408:            public Object getAttribute(String name)
0409:                    throws AttributeNotFoundException, MBeanException,
0410:                    ReflectionException {
0411:                return getAttribute(null, name);
0412:            }
0413:
0414:            /** Obtain the value of a specific attribute that is valid for a
0415:             * specific CrawlURI.
0416:             *
0417:             * This method will try to get the attribute from the host settings
0418:             * valid for the CrawlURI. If it is not found it will traverse the
0419:             * settings up to the order and as a last resort deliver the default
0420:             * value. This is also the case if the CrawlURI is null or if the CrawlURI
0421:             * hasn't been assigned a CrawlServer.
0422:             *
0423:             * @param name the name of the attribute to be retrieved.
0424:             * @param uri the CrawlURI that this attribute should be valid for.
0425:             * @return The value of the attribute retrieved.
0426:             * @see #getAttribute(Object settings, String name)
0427:             * @throws AttributeNotFoundException
0428:             */
0429:            public Object getAttribute(String name, CrawlURI uri)
0430:                    throws AttributeNotFoundException {
0431:                return getAttribute(uri, name);
0432:            }
0433:
0434:            /**
0435:             * Obtain the value of a specific attribute that is valid for a specific
0436:             * CrawlerSettings object.<p>
0437:             * 
0438:             * This method will first try to get a settings object from the supplied
0439:             * context, then try to look up the attribute from this settings object. If
0440:             * it is not found it will traverse the settings up to the order and as a
0441:             * last resort deliver the default value.
0442:             * 
0443:             * @param context the object to get the settings from.
0444:             * @param name the name of the attribute to be retrieved.
0445:             * @return The value of the attribute retrieved.
0446:             * @see CrawlerSettings
0447:             * @throws AttributeNotFoundException
0448:             */
0449:            public Object getAttribute(Object context, String name)
0450:                    throws AttributeNotFoundException {
0451:                Context ctxt = getSettingsFromObject(context);
0452:
0453:                // If settings is not set, return the default value
0454:                if (ctxt.settings == null) {
0455:                    try {
0456:                        return ((Type) definitionMap.get(name))
0457:                                .getDefaultValue();
0458:                    } catch (NullPointerException e) {
0459:                        throw new AttributeNotFoundException(
0460:                                "Could not find attribute: " + name);
0461:                    }
0462:                }
0463:
0464:                return getDataContainerRecursive(ctxt, name).get(name);
0465:            }
0466:
0467:            /**
0468:             * Obtain the value of a specific attribute that is valid for a specific
0469:             * CrawlerSettings object.
0470:             * <p>
0471:             * 
0472:             * This method will first try to get a settings object from the supplied
0473:             * context, then try to look up the attribute from this settings object. If
0474:             * it is not found it will traverse the settings up to the order and as a
0475:             * last resort deliver the default value.
0476:             * <p>
0477:             * 
0478:             * The only difference from the {@link #getAttribute(Object, String)}is
0479:             * that this method doesn't throw any checked exceptions. If an undefined
0480:             * attribute is requested from a ComplexType, it is concidered a bug and a
0481:             * runtime exception is thrown instead.
0482:             * 
0483:             * @param context the object to get the settings from.
0484:             * @param name the name of the attribute to be retrieved.
0485:             * @return The value of the attribute retrieved.
0486:             * @see #getAttribute(Object, String)
0487:             * @see CrawlerSettings
0488:             * @throws IllegalArgumentException
0489:             */
0490:            public Object getUncheckedAttribute(Object context, String name) {
0491:                try {
0492:                    return getAttribute(context, name);
0493:                } catch (AttributeNotFoundException e) {
0494:                    throw new IllegalArgumentException("Was passed '" + name
0495:                            + "' and got this exception: " + e);
0496:                }
0497:            }
0498:
0499:            /** Obtain the value of a specific attribute that is valid for a
0500:             * specific CrawlerSettings object.
0501:             *
0502:             * This method will try to get the attribute from the supplied host
0503:             * settings object. If it is not found it will return <code>null</code>
0504:             * and not try to investigate the hierarchy of settings.
0505:             *
0506:             * @param settings the CrawlerSettings object to search for this attribute.
0507:             * @param name the name of the attribute to be retrieved.
0508:             * @return The value of the attribute retrieved or null if its not set.
0509:             * @see CrawlerSettings
0510:             * @throws AttributeNotFoundException is thrown if the attribute doesn't
0511:             *         exist.
0512:             */
0513:            public Object getLocalAttribute(CrawlerSettings settings,
0514:                    String name) throws AttributeNotFoundException {
0515:
0516:                settings = settings == null ? globalSettings() : settings;
0517:
0518:                DataContainer data = settings.getData(this );
0519:                if (data != null && data.containsKey(name)) {
0520:                    // Attribute was found return it.
0521:                    return data.get(name);
0522:                }
0523:                // Try to find the attribute, will throw an exception if not found.
0524:                Context context = new Context(settings, null);
0525:                getDataContainerRecursive(context, name);
0526:                return null;
0527:            }
0528:
0529:            /** Set the value of a specific attribute of the ComplexType.
0530:             *
0531:             * This method sets the specific attribute for the order file.
0532:             *
0533:             * @param attribute The identification of the attribute to be set and the
0534:             *                  value it is to be set to.
0535:             * @throws AttributeNotFoundException is thrown if there is no attribute
0536:             *         with this name.
0537:             * @throws InvalidAttributeValueException is thrown if the attribute is of
0538:             *         wrong type and cannot be converted to the right type.
0539:             * @throws MBeanException this is to conform to the MBean specification, but
0540:             *         this exception is never thrown, though this might change in the
0541:             *         future.
0542:             * @throws ReflectionException this is to conform to the MBean specification, but
0543:             *         this exception is never thrown, though this might change in the
0544:             *         future.
0545:             * @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute)
0546:             */
0547:            public synchronized final void setAttribute(Attribute attribute)
0548:                    throws AttributeNotFoundException,
0549:                    InvalidAttributeValueException, MBeanException,
0550:                    ReflectionException {
0551:                setAttribute(settingsHandler.getSettingsObject(null), attribute);
0552:            }
0553:
0554:            /** Set the value of a specific attribute of the ComplexType.
0555:             *
0556:             * This method is an extension to the Dynamic MBean specification so that
0557:             * it is possible to set the value for a CrawlerSettings object other than
0558:             * the settings object representing the order.
0559:             *
0560:             * @param settings the settings object for which this attributes value is valid
0561:             * @param attribute The identification of the attribute to be set and the
0562:             *                  value it is to be set to.
0563:             * @throws AttributeNotFoundException is thrown if there is no attribute
0564:             *         with this name.
0565:             * @throws InvalidAttributeValueException is thrown if the attribute is of
0566:             *         wrong type and cannot be converted to the right type.
0567:             * @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute)
0568:             */
0569:            public synchronized final void setAttribute(
0570:                    CrawlerSettings settings, Attribute attribute)
0571:                    throws InvalidAttributeValueException,
0572:                    AttributeNotFoundException {
0573:
0574:                if (settings == null) {
0575:                    settings = globalSettings();
0576:                }
0577:
0578:                DataContainer data = getOrCreateDataContainer(settings);
0579:                Object value = attribute.getValue();
0580:
0581:                ModuleAttributeInfo attrInfo = (ModuleAttributeInfo) getAttributeInfo(
0582:                        settings.getParent(), attribute.getName());
0583:
0584:                ModuleAttributeInfo localAttrInfo = (ModuleAttributeInfo) data
0585:                        .getAttributeInfo(attribute.getName());
0586:
0587:                // Check if attribute exists
0588:                if (attrInfo == null && localAttrInfo == null) {
0589:                    throw new AttributeNotFoundException(attribute.getName());
0590:                }
0591:
0592:                // Check if we are overriding and if that is allowed for this attribute
0593:                if (localAttrInfo == null) {
0594:                    if (!attrInfo.isOverrideable()) {
0595:                        throw new InvalidAttributeValueException(
0596:                                "Attribute not overrideable: "
0597:                                        + attribute.getName());
0598:                    }
0599:                    localAttrInfo = new ModuleAttributeInfo(attrInfo);
0600:                }
0601:
0602:                // Check if value is of correct type. If not, see if it is
0603:                // a string and try to turn it into right type
0604:                Class typeClass = getDefinition(attribute.getName())
0605:                        .getLegalValueType();
0606:                if (!(typeClass.isInstance(value)) && value instanceof  String) {
0607:                    try {
0608:                        value = SettingsHandler.StringToType((String) value,
0609:                                SettingsHandler
0610:                                        .getTypeName(typeClass.getName()));
0611:                    } catch (ClassCastException e) {
0612:                        throw new InvalidAttributeValueException(
0613:                                "Unable to decode string '" + value
0614:                                        + "' into type '" + typeClass.getName()
0615:                                        + "'");
0616:                    }
0617:                }
0618:
0619:                // Check if the attribute value is legal
0620:                FailedCheck error = checkValue(settings, attribute.getName(),
0621:                        value);
0622:                if (error != null) {
0623:                    if (error.getLevel() == Level.SEVERE) {
0624:                        throw new InvalidAttributeValueException(error
0625:                                .getMessage());
0626:                    } else if (error.getLevel() == Level.WARNING) {
0627:                        if (!getSettingsHandler().fireValueErrorHandlers(error)) {
0628:                            throw new InvalidAttributeValueException(error
0629:                                    .getMessage());
0630:                        }
0631:                    } else {
0632:                        getSettingsHandler().fireValueErrorHandlers(error);
0633:                    }
0634:                }
0635:
0636:                // Everything ok, set it
0637:                localAttrInfo.setType(value);
0638:                Object oldValue = data.put(attribute.getName(), localAttrInfo,
0639:                        value);
0640:
0641:                // If the attribute is a complex type other than the old value,
0642:                // make sure that all sub attributes are correctly set
0643:                if (value instanceof  ComplexType && value != oldValue) {
0644:                    ComplexType complex = (ComplexType) value;
0645:                    replaceComplexType(settings, complex);
0646:                }
0647:            }
0648:
0649:            /**
0650:             * Get the content type definition for an attribute.
0651:             *
0652:             * @param attributeName the name of the attribute to get definition for.
0653:             * @return the content type definition for the attribute.
0654:             */
0655:            Type getDefinition(String attributeName) {
0656:                return (Type) definitionMap.get(attributeName);
0657:            }
0658:
0659:            /**
0660:             * Check an attribute to see if it fulfills all the constraints set on the
0661:             * definition of this attribute.
0662:             *
0663:             * @param settings the CrawlerSettings object for which this check was
0664:             *            executed.
0665:             * @param attributeName the name of the attribute to check.
0666:             * @param value the value to check.
0667:             * @return null if everything is ok, otherwise it returns a FailedCheck
0668:             *         object with detailed information of what went wrong.
0669:             */
0670:            public FailedCheck checkValue(CrawlerSettings settings,
0671:                    String attributeName, Object value) {
0672:                return checkValue(settings, attributeName,
0673:                        getDefinition(attributeName), value);
0674:            }
0675:
0676:            FailedCheck checkValue(CrawlerSettings settings,
0677:                    String attributeName, Type definition, Object value) {
0678:                FailedCheck res = null;
0679:
0680:                // Check if value fulfills any constraints
0681:                List constraints = definition.getConstraints();
0682:                if (constraints != null) {
0683:                    for (Iterator it = constraints.iterator(); it.hasNext()
0684:                            && res == null;) {
0685:                        res = ((Constraint) it.next()).check(settings, this ,
0686:                                definition, value);
0687:                    }
0688:                }
0689:
0690:                return res;
0691:            }
0692:
0693:            /** Unset an attribute on a per host level.
0694:             *
0695:             * This methods removes an override on a per host or per domain level.
0696:             *
0697:             * @param settings the settings object for which the attribute should be
0698:             *        unset.
0699:             * @param name the name of the attribute.
0700:             * @return The removed attribute or null if nothing was removed.
0701:             * @throws AttributeNotFoundException is thrown if the attribute name
0702:             *         doesn't exist.
0703:             */
0704:            public Object unsetAttribute(CrawlerSettings settings, String name)
0705:                    throws AttributeNotFoundException {
0706:
0707:                if (settings == globalSettings()) {
0708:                    throw new IllegalArgumentException(
0709:                            "Not allowed to unset attributes in Crawl Order.");
0710:                }
0711:
0712:                DataContainer data = settings.getData(this );
0713:                if (data != null && data.containsKey(name)) {
0714:                    // Remove value
0715:                    return data.removeElement(name);
0716:                }
0717:
0718:                // Value not found. Check if we should return null or throw an exception
0719:                // This method throws an exception if not found.
0720:                Context context = new Context(settings, null);
0721:                getDataContainerRecursive(context, name);
0722:                return null;
0723:            }
0724:
0725:            private DataContainer getOrCreateDataContainer(
0726:                    CrawlerSettings settings)
0727:                    throws InvalidAttributeValueException {
0728:
0729:                // Get this ComplexType's data container for the submitted settings
0730:                DataContainer data = settings.getData(this );
0731:
0732:                // If there isn't a container, create one
0733:                if (data == null) {
0734:                    ComplexType parent = getParent();
0735:                    if (parent == null) {
0736:                        settings.addTopLevelModule((ModuleType) this );
0737:                    } else {
0738:                        DataContainer parentData = settings.getData(parent);
0739:                        if (parentData == null) {
0740:                            if (this  instanceof  ModuleType) {
0741:                                settings.addTopLevelModule((ModuleType) this );
0742:                            } else {
0743:                                settings.addTopLevelModule((ModuleType) parent);
0744:                                try {
0745:                                    parent.setAttribute(settings, this );
0746:                                } catch (AttributeNotFoundException e) {
0747:                                    logger.severe(e.getMessage());
0748:                                }
0749:                            }
0750:                        } else {
0751:                            globalSettings().getData(parent).copyAttributeInfo(
0752:                                    getName(), parentData);
0753:                        }
0754:                    }
0755:
0756:                    // Create fresh DataContainer
0757:                    data = settings.addComplexType(this );
0758:                }
0759:
0760:                // Make sure that the DataContainer references right type
0761:                if (data.getComplexType() != this ) {
0762:                    if (this  instanceof  ModuleType) {
0763:                        data = settings.addComplexType(this );
0764:                    }
0765:                }
0766:                return data;
0767:            }
0768:
0769:            /* (non-Javadoc)
0770:             * @see javax.management.DynamicMBean#getAttributes(java.lang.String[])
0771:             */
0772:            public AttributeList getAttributes(String[] name) {
0773:                return null;
0774:            }
0775:
0776:            /* (non-Javadoc)
0777:             * @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList)
0778:             */
0779:            public AttributeList setAttributes(AttributeList attributes) {
0780:                return null;
0781:            }
0782:
0783:            /* (non-Javadoc)
0784:             * @see javax.management.DynamicMBean#invoke(java.lang.String, java.lang.Object[], java.lang.String[])
0785:             */
0786:            public Object invoke(String arg0, Object[] arg1, String[] arg2)
0787:                    throws MBeanException, ReflectionException {
0788:                throw new ReflectionException(new NoSuchMethodException(
0789:                        "No methods to invoke."));
0790:            }
0791:
0792:            /* (non-Javadoc)
0793:             * @see javax.management.DynamicMBean#getMBeanInfo()
0794:             */
0795:            public MBeanInfo getMBeanInfo() {
0796:                return getMBeanInfo(globalSettings());
0797:            }
0798:
0799:            public MBeanInfo getMBeanInfo(Object context) {
0800:                MBeanAttributeInfoIterator it = getAttributeInfoIterator(context);
0801:                MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[it
0802:                        .size()];
0803:                int index = 0;
0804:                while (it.hasNext()) {
0805:                    attributes[index++] = (MBeanAttributeInfo) it.next();
0806:                }
0807:
0808:                MBeanInfo info = new MBeanInfo(getClass().getName(),
0809:                        getDescription(), attributes, null, null, null);
0810:                return info;
0811:            }
0812:
0813:            /** Get the effective Attribute info for an element of this type from
0814:             * a settings object.
0815:             *
0816:             * @param settings the settings object for which the Attribute info is
0817:             *        effective.
0818:             * @param name the name of the element to get the attribute for.
0819:             * @return the attribute info
0820:             */
0821:            public MBeanAttributeInfo getAttributeInfo(
0822:                    CrawlerSettings settings, String name) {
0823:
0824:                MBeanAttributeInfo info = null;
0825:
0826:                Context context = new Context(settings, null);
0827:                DataContainer data = getDataContainerRecursive(context);
0828:                while (data != null && info == null) {
0829:                    info = data.getAttributeInfo(name);
0830:                    if (info == null) {
0831:                        context.settings = data.getSettings().getParent();
0832:                        data = getDataContainerRecursive(context);
0833:                    }
0834:                }
0835:
0836:                return info;
0837:            }
0838:
0839:            /** Get the Attribute info for an element of this type from the global
0840:             * settings.
0841:             *
0842:             * @param name the name of the element to get the attribute for.
0843:             * @return the attribute info
0844:             */
0845:            public MBeanAttributeInfo getAttributeInfo(String name) {
0846:                return getAttributeInfo(globalSettings(), name);
0847:            }
0848:
0849:            /** Get the description of this type
0850:             *
0851:             * The description should be suitable for showing in a user interface.
0852:             *
0853:             * @return this type's description
0854:             */
0855:            public String getDescription() {
0856:                return description;
0857:            }
0858:
0859:            /** Get the parent of this ComplexType.
0860:             *
0861:             * @return the parent of this ComplexType.
0862:             */
0863:            public ComplexType getParent() {
0864:                return parent;
0865:            }
0866:
0867:            /** Set the description of this ComplexType
0868:             *
0869:             * The description should be suitable for showing in a user interface.
0870:             *
0871:             * @param string the description to set for this type.
0872:             */
0873:            public void setDescription(String string) {
0874:                description = string;
0875:            }
0876:
0877:            /* (non-Javadoc)
0878:             * @see org.archive.crawler.settings.Type#getDefaultValue()
0879:             */
0880:            public Object getDefaultValue() {
0881:                return this ;
0882:            }
0883:
0884:            /** Add a new attribute to the definition of this ComplexType.
0885:             *
0886:             * This method can only be called before the ComplexType has been
0887:             * initialized. This usally means that this method is available for
0888:             * constructors of subclasses of this class.
0889:             *
0890:             * @param type the type to add.
0891:             * @return the newly added type.
0892:             */
0893:            public Type addElementToDefinition(Type type) {
0894:                if (isInitialized()) {
0895:                    throw new IllegalStateException(
0896:                            "Elements should only be added to definition in the "
0897:                                    + "constructor.");
0898:                }
0899:                if (definitionMap.containsKey(type.getName())) {
0900:                    definition.remove(definitionMap.remove(type.getName()));
0901:                }
0902:
0903:                definition.add(type);
0904:                definitionMap.put(type.getName(), type);
0905:                return type;
0906:            }
0907:
0908:            /** Get an element definition from this complex type.
0909:             *
0910:             * This method can only be called before the ComplexType has been
0911:             * initialized. This usally means that this method is available for
0912:             * constructors of subclasses of this class.
0913:             *
0914:             * @param name name of element to get.
0915:             * @return the requested element or null if non existent.
0916:             */
0917:            public Type getElementFromDefinition(String name) {
0918:                if (isInitialized()) {
0919:                    throw new IllegalStateException(
0920:                            "Elements definition can only be accessed in the "
0921:                                    + "constructor.");
0922:                }
0923:                return (Type) definitionMap.get(name);
0924:            }
0925:
0926:            /**
0927:             * This method can only be called before the ComplexType has been
0928:             * initialized. This usually means that this method is available for
0929:             * constructors of subclasses of this class.
0930:             * @param name Name of element to remove.
0931:             * @return Element removed.
0932:             */
0933:            protected Type removeElementFromDefinition(final String name) {
0934:                if (isInitialized()) {
0935:                    throw new IllegalStateException(
0936:                            "Elements definition can only be removed in constructor.");
0937:                }
0938:                Object removedObj = this .definitionMap.remove(name);
0939:                if (removedObj != null) {
0940:                    this .definition.remove(removedObj);
0941:                }
0942:                return (Type) removedObj;
0943:            }
0944:
0945:            /** This method can be overridden in subclasses to do local
0946:             * initialisation.
0947:             *
0948:             * This method is run before the class has been updated with
0949:             * information from settings files. That implies that if you
0950:             * call getAttribute inside this method you will only get the
0951:             * default values.
0952:             *
0953:             * @param settings the CrawlerSettings object for which this
0954:             *        complex type is defined.
0955:             */
0956:            public void earlyInitialize(CrawlerSettings settings) {
0957:            }
0958:
0959:            /** Returns true if this ComplexType is initialized.
0960:             *
0961:             * @return true if this ComplexType is initialized.
0962:             */
0963:            public boolean isInitialized() {
0964:                return initialized;
0965:            }
0966:
0967:            public Object[] getLegalValues() {
0968:                return null;
0969:            }
0970:
0971:            /** Returns this object.
0972:             *
0973:             * This method is implemented to be able to treat the ComplexType as an
0974:             * subclass of {@link javax.management.Attribute}.
0975:             *
0976:             * @return this object.
0977:             * @see javax.management.Attribute#getValue()
0978:             */
0979:            public Object getValue() {
0980:                return this ;
0981:            }
0982:
0983:            class Context {
0984:                CrawlerSettings settings;
0985:                UURI uri;
0986:
0987:                Context() {
0988:                    settings = null;
0989:                    uri = null;
0990:                }
0991:
0992:                Context(CrawlerSettings settings, UURI uri) {
0993:                    this .settings = settings;
0994:                    this .uri = uri;
0995:                }
0996:            }
0997:
0998:            /** Get an Iterator over all the attributes in this ComplexType.
0999:             *
1000:             * @param context the context for which this set of attributes are valid.
1001:             * @return an iterator over all the attributes in this map.
1002:             */
1003:            public Iterator iterator(Object context) {
1004:                return new AttributeIterator(context);
1005:            }
1006:
1007:            /** Get an Iterator over all the MBeanAttributeInfo in this ComplexType.
1008:             *
1009:             * @param context the context for which this set of MBeanAttributeInfo are valid.
1010:             * @return an iterator over all the MBeanAttributeInfo in this map.
1011:             */
1012:            public MBeanAttributeInfoIterator getAttributeInfoIterator(
1013:                    Object context) {
1014:                return new MBeanAttributeInfoIterator(context);
1015:            }
1016:
1017:            /**
1018:             * Iterator over all attributes in a ComplexType.
1019:             *
1020:             * @author John Erik Halse
1021:             */
1022:            private class AttributeIterator implements  Iterator {
1023:                private Context context;
1024:                private Stack<Iterator<MBeanAttributeInfo>> attributeStack = new Stack<Iterator<MBeanAttributeInfo>>();
1025:                private Iterator currentIterator;
1026:
1027:                public AttributeIterator(Object ctxt) {
1028:                    this .context = getSettingsFromObject(ctxt);
1029:                    Context c = new Context(context.settings, context.uri);
1030:                    DataContainer data = getDataContainerRecursive(c);
1031:                    while (data != null) {
1032:                        this .attributeStack.push(data
1033:                                .getLocalAttributeInfoList().iterator());
1034:                        c.settings = data.getSettings().getParent();
1035:                        data = getDataContainerRecursive(c);
1036:                    }
1037:
1038:                    this .currentIterator = (Iterator) this .attributeStack.pop();
1039:                }
1040:
1041:                public boolean hasNext() {
1042:                    if (this .currentIterator.hasNext()) {
1043:                        return true;
1044:                    }
1045:                    if (this .attributeStack.isEmpty()) {
1046:                        return false;
1047:                    }
1048:                    this .currentIterator = (Iterator) this .attributeStack.pop();
1049:                    return this .currentIterator.hasNext();
1050:                }
1051:
1052:                public Object next() {
1053:                    hasNext();
1054:                    try {
1055:                        MBeanAttributeInfo attInfo = (MBeanAttributeInfo) this .currentIterator
1056:                                .next();
1057:                        Object attr = getAttribute(this .context, attInfo
1058:                                .getName());
1059:                        if (!(attr instanceof  Attribute)) {
1060:                            attr = new Attribute(attInfo.getName(), attr);
1061:                        }
1062:                        return attr;
1063:                    } catch (AttributeNotFoundException e) {
1064:                        // This should never happen
1065:                        e.printStackTrace();
1066:                        return null;
1067:                    }
1068:                }
1069:
1070:                public void remove() {
1071:                    throw new UnsupportedOperationException();
1072:                }
1073:            }
1074:
1075:            /**
1076:             * Iterator over all MBeanAttributeInfo for this ComplexType
1077:             *
1078:             * @author John Erik Halse
1079:             */
1080:            public class MBeanAttributeInfoIterator implements  Iterator {
1081:                private Context context;
1082:                private Stack<Iterator<MBeanAttributeInfo>> attributeStack = new Stack<Iterator<MBeanAttributeInfo>>();
1083:                private Iterator currentIterator;
1084:                private int attributeCount = 0;
1085:
1086:                public MBeanAttributeInfoIterator(Object ctxt) {
1087:                    this .context = getSettingsFromObject(ctxt);
1088:                    //Stack attributeStack = new Stack();
1089:                    //
1090:                    DataContainer data = getDataContainerRecursive(context);
1091:                    while (data != null) {
1092:                        attributeStack.push(data.getLocalAttributeInfoList()
1093:                                .iterator());
1094:                        attributeCount += data.getLocalAttributeInfoList()
1095:                                .size();
1096:                        context.settings = data.getSettings().getParent();
1097:                        data = getDataContainerRecursive(context);
1098:                    }
1099:
1100:                    this .currentIterator = (Iterator) this .attributeStack.pop();
1101:                }
1102:
1103:                public boolean hasNext() {
1104:                    if (this .currentIterator.hasNext()) {
1105:                        return true;
1106:                    }
1107:                    if (this .attributeStack.isEmpty()) {
1108:                        return false;
1109:                    }
1110:                    this .currentIterator = (Iterator) this .attributeStack.pop();
1111:                    return this .currentIterator.hasNext();
1112:                }
1113:
1114:                public Object next() {
1115:                    hasNext();
1116:                    MBeanAttributeInfo attInfo = (MBeanAttributeInfo) this .currentIterator
1117:                            .next();
1118:                    return attInfo;
1119:                }
1120:
1121:                public void remove() {
1122:                    throw new UnsupportedOperationException();
1123:                }
1124:
1125:                public int size() {
1126:                    return attributeCount;
1127:                }
1128:            }
1129:
1130:            @Override
1131:            public String toString() {
1132:                // In 1.6, toString goes into infinite loop.  Default implementation is
1133:                // return getName() + '=' + getValue() but this class returns itself
1134:                // for a value on which we do a toString... and around we go.  Short
1135:                // circuit it here.
1136:                return getName() + ": " + getClass().getName() + "@"
1137:                        + Integer.toHexString(hashCode());
1138:            }
1139:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.