Source Code Cross Referenced for API.java in  » Web-Services » xins » org » xins » server » 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 Services » xins » org.xins.server 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: API.java,v 1.369 2007/09/18 08:45:06 agoubard Exp $
0003:         *
0004:         * Copyright 2003-2007 Orange Nederland Breedband B.V.
0005:         * See the COPYRIGHT file for redistribution and use restrictions.
0006:         */
0007:        package org.xins.server;
0008:
0009:        import java.io.InputStream;
0010:        import java.io.PrintWriter;
0011:        import java.io.StringWriter;
0012:        import java.util.ArrayList;
0013:        import java.util.Enumeration;
0014:        import java.util.HashMap;
0015:        import java.util.Iterator;
0016:        import java.util.List;
0017:        import java.util.Map;
0018:        import java.util.Properties;
0019:        import java.util.TimeZone;
0020:
0021:        import org.xins.common.FormattedParameters;
0022:        import org.xins.common.MandatoryArgumentChecker;
0023:        import org.xins.common.Utils;
0024:        import org.xins.common.collections.BasicPropertyReader;
0025:        import org.xins.common.collections.InvalidPropertyValueException;
0026:        import org.xins.common.collections.MissingRequiredPropertyException;
0027:        import org.xins.common.collections.PropertyReader;
0028:        import org.xins.common.manageable.BootstrapException;
0029:        import org.xins.common.manageable.DeinitializationException;
0030:        import org.xins.common.manageable.InitializationException;
0031:        import org.xins.common.manageable.Manageable;
0032:        import org.xins.common.net.IPAddressUtils;
0033:        import org.xins.common.spec.APISpec;
0034:        import org.xins.common.spec.InvalidSpecificationException;
0035:        import org.xins.common.text.DateConverter;
0036:        import org.xins.common.text.ParseException;
0037:        import org.xins.common.xml.Element;
0038:        import org.xins.common.xml.ElementBuilder;
0039:
0040:        /**
0041:         * Base class for API implementation classes.
0042:         *
0043:         * @version $Revision: 1.369 $ $Date: 2007/09/18 08:45:06 $
0044:         * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
0045:         * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
0046:         * @author <a href="mailto:tauseef.rehman@orange-ftgroup.com">Tauseef Rehman</a>
0047:         *
0048:         * @since XINS 1.0.0
0049:         */
0050:        public abstract class API extends Manageable {
0051:
0052:            /**
0053:             * Successful empty call result.
0054:             */
0055:            static final FunctionResult SUCCESSFUL_RESULT = new FunctionResult();
0056:
0057:            /**
0058:             * The runtime (initialization) property that defines the ACL (access
0059:             * control list) rules.
0060:             */
0061:            private static final String ACL_PROPERTY = "org.xins.server.acl";
0062:
0063:            /**
0064:             * The name of the bootstrap property that specifies the version of the API.
0065:             */
0066:            static final String API_VERSION_PROPERTY = "org.xins.api.version";
0067:
0068:            /**
0069:             * The name of the bootstrap property that specifies the hostname of the
0070:             * machine the package was built on.
0071:             */
0072:            private static final String BUILD_HOST_PROPERTY = "org.xins.api.build.host";
0073:
0074:            /**
0075:             * The name of the bootstrap property that specifies the time the package was
0076:             * built.
0077:             */
0078:            private static final String BUILD_TIME_PROPERTY = "org.xins.api.build.time";
0079:
0080:            /**
0081:             * The name of the bootstrap property that specifies which version of XINS was
0082:             * used to build the package.
0083:             */
0084:            private static final String BUILD_XINS_VERSION_PROPERTY = "org.xins.api.build.version";
0085:
0086:            /**
0087:             * The engine that owns this <code>API</code> object.
0088:             */
0089:            private Engine _engine;
0090:
0091:            /**
0092:             * The name of this API. Cannot be <code>null</code> and cannot be an empty
0093:             * string.
0094:             */
0095:            private final String _name;
0096:
0097:            /**
0098:             * List of registered manageable objects. See {@link #add(Manageable)}.
0099:             *
0100:             * <p />This field is initialized to a non-<code>null</code> value by the
0101:             * constructor.
0102:             */
0103:            private final List _manageableObjects;
0104:
0105:            /**
0106:             * Map that maps function names to <code>Function</code> instances.
0107:             * Contains all functions associated with this API.
0108:             *
0109:             * <p />This field is initialized to a non-<code>null</code> value by the
0110:             * constructor.
0111:             */
0112:            private final Map _functionsByName;
0113:
0114:            /**
0115:             * List of all functions. This field cannot be <code>null</code>.
0116:             */
0117:            private final List _functionList;
0118:
0119:            /**
0120:             * The build-time settings. This field is initialized exactly once by
0121:             * {@link #bootstrap(PropertyReader)}. It can be <code>null</code> before
0122:             * that.
0123:             */
0124:            private PropertyReader _buildSettings;
0125:
0126:            /**
0127:             * The {@link RuntimeProperties} containing the method to verify and access
0128:             * the defined runtime properties.
0129:             */
0130:            private RuntimeProperties _emptyProperties;
0131:
0132:            /**
0133:             * The runtime-time settings. This field is initialized by
0134:             * {@link #init(PropertyReader)}. It can be <code>null</code> before that.
0135:             */
0136:            private PropertyReader _runtimeSettings;
0137:
0138:            /**
0139:             * Timestamp indicating when this API instance was created.
0140:             */
0141:            private final long _startupTimestamp;
0142:
0143:            /**
0144:             * Last time the statistics were reset. Initially the startup timestamp.
0145:             */
0146:            private long _lastStatisticsReset;
0147:
0148:            /**
0149:             * Host name for the machine that was used for this build.
0150:             */
0151:            private String _buildHost;
0152:
0153:            /**
0154:             * Time stamp that indicates when this build was done.
0155:             */
0156:            private String _buildTime;
0157:
0158:            /**
0159:             * XINS version used to build the web application package.
0160:             */
0161:            private String _buildVersion;
0162:
0163:            /**
0164:             * The time zone used when generating dates for output.
0165:             */
0166:            private final TimeZone _timeZone;
0167:
0168:            /**
0169:             * Version of the API.
0170:             */
0171:            private String _apiVersion;
0172:
0173:            /**
0174:             * The API specific access rule list.
0175:             */
0176:            private AccessRuleList _apiAccessRuleList;
0177:
0178:            /**
0179:             * The general access rule list.
0180:             */
0181:            private AccessRuleList _accessRuleList;
0182:
0183:            /**
0184:             * The API specification.
0185:             */
0186:            private APISpec _apiSpecification;
0187:
0188:            /**
0189:             * The local IP address.
0190:             */
0191:            private String _localIPAddress;
0192:
0193:            /**
0194:             * Mapping from function name to the call ID for all meta-functions. This
0195:             * field is never <code>null</code>.
0196:             */
0197:            private final HashMap _metaFunctionCallIDs;
0198:
0199:            /**
0200:             * Flag indicating that the API is down for maintenance.
0201:             */
0202:            private boolean _apiDisabled;
0203:
0204:            /**
0205:             * Constructs a new <code>API</code> object.
0206:             *
0207:             * @param name
0208:             *    the name of the API, cannot be <code>null</code> nor can it be an
0209:             *    empty string.
0210:             *
0211:             * @throws IllegalArgumentException
0212:             *    if <code>name == null
0213:             *          || name.{@link String#length() length()} &lt; 1</code>.
0214:             */
0215:            protected API(String name) throws IllegalArgumentException {
0216:
0217:                // Check preconditions
0218:                MandatoryArgumentChecker.check("name", name);
0219:                if (name.length() < 1) {
0220:                    String message = "name.length() == " + name.length();
0221:                    throw new IllegalArgumentException(message);
0222:                }
0223:
0224:                // Initialize fields
0225:                _name = name;
0226:                _startupTimestamp = System.currentTimeMillis();
0227:                _lastStatisticsReset = _startupTimestamp;
0228:                _manageableObjects = new ArrayList(20);
0229:                _functionsByName = new HashMap(89);
0230:                _functionList = new ArrayList(80);
0231:                _emptyProperties = new RuntimeProperties();
0232:                _timeZone = TimeZone.getDefault();
0233:                _localIPAddress = IPAddressUtils.getLocalHostIPAddress();
0234:                _apiDisabled = false;
0235:
0236:                // Initialize mapping from meta-function to call ID
0237:                _metaFunctionCallIDs = new HashMap(89);
0238:                _metaFunctionCallIDs.put("_NoOp", new Counter());
0239:                _metaFunctionCallIDs.put("_GetFunctionList", new Counter());
0240:                _metaFunctionCallIDs.put("_GetStatistics", new Counter());
0241:                _metaFunctionCallIDs.put("_GetVersion", new Counter());
0242:                _metaFunctionCallIDs.put("_CheckLinks", new Counter());
0243:                _metaFunctionCallIDs.put("_GetSettings", new Counter());
0244:                _metaFunctionCallIDs.put("_DisableFunction", new Counter());
0245:                _metaFunctionCallIDs.put("_EnableFunction", new Counter());
0246:                _metaFunctionCallIDs.put("_ResetStatistics", new Counter());
0247:                _metaFunctionCallIDs.put("_ReloadProperties", new Counter());
0248:                _metaFunctionCallIDs.put("_WSDL", new Counter());
0249:                _metaFunctionCallIDs.put("_SMD", new Counter());
0250:                _metaFunctionCallIDs.put("_DisableAPI", new Counter());
0251:                _metaFunctionCallIDs.put("_EnableAPI", new Counter());
0252:            }
0253:
0254:            /**
0255:             * Gets the name of this API.
0256:             *
0257:             * @return
0258:             *    the name of this API, never <code>null</code> and never an empty
0259:             *    string.
0260:             */
0261:            public final String getName() {
0262:                return _name;
0263:            }
0264:
0265:            /**
0266:             * Gets the list of the functions of this API.
0267:             *
0268:             * @return
0269:             *    the functions of this API as a {@link List} of {@link Function} objects, never <code>null</code>.
0270:             *
0271:             * @since XINS 1.5.0.
0272:             */
0273:            public final List getFunctionList() {
0274:                return _functionList;
0275:            }
0276:
0277:            /**
0278:             * Gets the bootstrap properties specified for the API.
0279:             *
0280:             * @return
0281:             *   the bootstrap properties, cannot be <code>null</code>.
0282:             *
0283:             * @since XINS 1.5.0.
0284:             */
0285:            public PropertyReader getBootstrapProperties() {
0286:                return _buildSettings;
0287:            }
0288:
0289:            /**
0290:             * Gets the API runtime properties.
0291:             *
0292:             * @return
0293:             *   the runtime properties, cannot be <code>null</code>.
0294:             */
0295:            PropertyReader getRuntimeProperties() {
0296:                return _runtimeSettings;
0297:            }
0298:
0299:            /**
0300:             * Gets the runtime properties specified in the implementation.
0301:             *
0302:             * @return
0303:             *    the runtime properties for the API, cannot be <code>null</code>.
0304:             */
0305:            public RuntimeProperties getProperties() {
0306:
0307:                // This method is overridden by the APIImpl to return the generated
0308:                // RuntimeProperties class which contains the runtime properties.
0309:                return _emptyProperties;
0310:            }
0311:
0312:            /**
0313:             * Gets the timestamp that indicates when this <code>API</code> instance
0314:             * was created.
0315:             *
0316:             * @return
0317:             *    the time this instance was constructed, as a number of milliseconds
0318:             *    since the
0319:             *    <a href="http://en.wikipedia.org/wiki/Unix_Epoch">UNIX Epoch</a>.
0320:             */
0321:            public final long getStartupTimestamp() {
0322:                return _startupTimestamp;
0323:            }
0324:
0325:            /**
0326:             * Returns the applicable time zone.
0327:             *
0328:             * @return
0329:             *    the time zone, never <code>null</code>.
0330:             */
0331:            public final TimeZone getTimeZone() {
0332:                return _timeZone;
0333:            }
0334:
0335:            /**
0336:             * Gets the resource in the WAR file.
0337:             *
0338:             * @param path
0339:             *    the path for the resource, cannot be <code>null</code> and should start with /.
0340:             *
0341:             * @return
0342:             *    the InputStream to use to read this resource or <code>null</code> if
0343:             *    the resource cannot be found.
0344:             *
0345:             * @throws IllegalArgumentException
0346:             *    if <code>path == null</code> or if the path doesn't start with /.
0347:             *
0348:             * @since XINS 2.0.
0349:             */
0350:            public final InputStream getResourceAsStream(String path)
0351:                    throws IllegalArgumentException {
0352:                return _engine.getResourceAsStream(path);
0353:            }
0354:
0355:            /**
0356:             * Bootstraps this API (wrapper method). This method calls
0357:             * {@link #bootstrapImpl2(PropertyReader)}.
0358:             *
0359:             * @param buildSettings
0360:             *    the build-time configuration properties, not <code>null</code>.
0361:             *
0362:             * @throws IllegalStateException
0363:             *    if this API is currently not bootstraping.
0364:             *
0365:             * @throws MissingRequiredPropertyException
0366:             *    if a required property is not given.
0367:             *
0368:             * @throws InvalidPropertyValueException
0369:             *    if a property has an invalid value.
0370:             *
0371:             * @throws BootstrapException
0372:             *    if the bootstrap fails.
0373:             */
0374:            protected final void bootstrapImpl(PropertyReader buildSettings)
0375:                    throws IllegalStateException,
0376:                    MissingRequiredPropertyException,
0377:                    InvalidPropertyValueException, BootstrapException {
0378:
0379:                // Check state
0380:                Manageable.State state = getState();
0381:                if (state != BOOTSTRAPPING) {
0382:                    String message = "State is " + state + " instead of "
0383:                            + BOOTSTRAPPING + '.';
0384:                    Utils.logProgrammingError(message);
0385:                    throw new IllegalStateException(message);
0386:                }
0387:
0388:                // Log the time zone
0389:                String tzShortName = _timeZone.getDisplayName(false,
0390:                        TimeZone.SHORT);
0391:                String tzLongName = _timeZone.getDisplayName(false,
0392:                        TimeZone.LONG);
0393:                Log.log_3404(tzShortName, tzLongName);
0394:
0395:                // Store the build-time settings
0396:                _buildSettings = buildSettings;
0397:
0398:                // Get build-time properties
0399:                _apiVersion = _buildSettings.get(API_VERSION_PROPERTY);
0400:                _buildHost = _buildSettings.get(BUILD_HOST_PROPERTY);
0401:                _buildTime = _buildSettings.get(BUILD_TIME_PROPERTY);
0402:                _buildVersion = _buildSettings.get(BUILD_XINS_VERSION_PROPERTY);
0403:
0404:                Log.log_3212(_buildHost, _buildTime, _buildVersion, _name,
0405:                        _apiVersion);
0406:
0407:                // Skip check if build version is not set
0408:                if (_buildVersion == null) {
0409:                    // fall through
0410:
0411:                    // Check if build version identifies a production release of XINS
0412:                } else if (!Library.isProductionRelease(_buildVersion)) {
0413:                    Log.log_3228(_buildVersion);
0414:                }
0415:
0416:                // Let the subclass perform initialization
0417:                // TODO: What if bootstrapImpl2 throws an unexpected exception?
0418:                bootstrapImpl2(buildSettings);
0419:
0420:                // Bootstrap all instances
0421:                int count = _manageableObjects.size();
0422:                for (int i = 0; i < count; i++) {
0423:                    Manageable m = (Manageable) _manageableObjects.get(i);
0424:                    String className = m.getClass().getName();
0425:                    Log.log_3213(_name, className);
0426:                    try {
0427:                        m.bootstrap(_buildSettings);
0428:
0429:                        // Missing property
0430:                    } catch (MissingRequiredPropertyException exception) {
0431:                        Log.log_3215(_name, className, exception
0432:                                .getPropertyName(), exception.getDetail());
0433:                        throw exception;
0434:
0435:                        // Invalid property
0436:                    } catch (InvalidPropertyValueException exception) {
0437:                        Log.log_3216(_name, className, exception
0438:                                .getPropertyName(), exception
0439:                                .getPropertyValue(), exception.getReason());
0440:                        throw exception;
0441:
0442:                        // Catch BootstrapException and any other exceptions not caught
0443:                        // by previous catch statements
0444:                    } catch (Throwable exception) {
0445:
0446:                        // Log event
0447:                        Log.log_3217(exception, _name, className);
0448:
0449:                        // Throw a BootstrapException. If necessary, wrap around the
0450:                        // caught exception
0451:                        if (exception instanceof  BootstrapException) {
0452:                            throw (BootstrapException) exception;
0453:                        } else {
0454:                            throw new BootstrapException(exception);
0455:                        }
0456:                    }
0457:                }
0458:
0459:                // Bootstrap all functions
0460:                count = _functionList.size();
0461:                for (int i = 0; i < count; i++) {
0462:                    Function f = (Function) _functionList.get(i);
0463:                    String functionName = f.getName();
0464:                    Log.log_3220(_name, functionName);
0465:                    try {
0466:                        f.bootstrap(_buildSettings);
0467:
0468:                        // Missing required property
0469:                    } catch (MissingRequiredPropertyException exception) {
0470:                        Log.log_3222(_name, functionName, exception
0471:                                .getPropertyName(), exception.getDetail());
0472:                        throw exception;
0473:
0474:                        // Invalid property value
0475:                    } catch (InvalidPropertyValueException exception) {
0476:                        Log.log_3223(_name, functionName, exception
0477:                                .getPropertyName(), exception
0478:                                .getPropertyValue(), exception.getReason());
0479:                        throw exception;
0480:
0481:                        // Catch BootstrapException and any other exceptions not caught
0482:                        // by previous catch statements
0483:                    } catch (Throwable exception) {
0484:
0485:                        // Log this event
0486:                        Log.log_3224(exception, _name, functionName);
0487:
0488:                        // Throw a BootstrapException. If necessary, wrap around the
0489:                        // caught exception
0490:                        if (exception instanceof  BootstrapException) {
0491:                            throw (BootstrapException) exception;
0492:                        } else {
0493:                            throw new BootstrapException(exception);
0494:                        }
0495:                    }
0496:                }
0497:            }
0498:
0499:            /**
0500:             * Bootstraps this API (implementation method).
0501:             *
0502:             * <p />The implementation of this method in class {@link API} is empty.
0503:             * Custom subclasses can perform any necessary bootstrapping in this
0504:             * class.
0505:             *
0506:             * <p />Note that bootstrapping and initialization are different. Bootstrap
0507:             * includes only the one-time configuration of the API based on the
0508:             * build-time settings, while the initialization
0509:             *
0510:             * <p />The {@link #add(Manageable)} may be called from this method,
0511:             * and from this method <em>only</em>.
0512:             *
0513:             * @param buildSettings
0514:             *    the build-time properties, guaranteed not to be <code>null</code>.
0515:             *
0516:             * @throws MissingRequiredPropertyException
0517:             *    if a required property is not given.
0518:             *
0519:             * @throws InvalidPropertyValueException
0520:             *    if a property has an invalid value.
0521:             *
0522:             * @throws BootstrapException
0523:             *    if the bootstrap fails.
0524:             */
0525:            protected void bootstrapImpl2(PropertyReader buildSettings)
0526:                    throws MissingRequiredPropertyException,
0527:                    InvalidPropertyValueException, BootstrapException {
0528:                // empty
0529:            }
0530:
0531:            /**
0532:             * Stores a reference to the <code>Engine</code> that owns this
0533:             * <code>API</code> object.
0534:             *
0535:             * @param engine
0536:             *    the {@link Engine} instance, should not be <code>null</code>.
0537:             */
0538:            void setEngine(Engine engine) {
0539:                _engine = engine;
0540:            }
0541:
0542:            /**
0543:             * Triggers re-initialization of this API. This method is meant to be
0544:             * called by API function implementations when it is anticipated that the
0545:             * API should be re-initialized.
0546:             */
0547:            protected final void reinitializeImpl() {
0548:                _engine.initAPI();
0549:            }
0550:
0551:            /**
0552:             * Initializes this API.
0553:             *
0554:             * @param runtimeSettings
0555:             *    the runtime configuration settings, cannot be <code>null</code>.
0556:             *
0557:             * @throws MissingRequiredPropertyException
0558:             *    if a required property is missing.
0559:             *
0560:             * @throws InvalidPropertyValueException
0561:             *    if a property has an invalid value.
0562:             *
0563:             * @throws InitializationException
0564:             *    if the initialization failed for some other reason.
0565:             *
0566:             * @throws IllegalStateException
0567:             *    if this API is currently not initializing.
0568:             */
0569:            protected final void initImpl(PropertyReader runtimeSettings)
0570:                    throws MissingRequiredPropertyException,
0571:                    InvalidPropertyValueException, InitializationException,
0572:                    IllegalStateException {
0573:
0574:                Log.log_3405(_name);
0575:
0576:                // Store runtime settings
0577:                _runtimeSettings = runtimeSettings;
0578:
0579:                String propName = ConfigManager.CONFIG_RELOAD_INTERVAL_PROPERTY;
0580:                String propValue = runtimeSettings.get(propName);
0581:                int interval = ConfigManager.DEFAULT_CONFIG_RELOAD_INTERVAL;
0582:                if (propValue != null && propValue.trim().length() > 0) {
0583:                    try {
0584:                        interval = Integer.parseInt(propValue);
0585:                    } catch (NumberFormatException e) {
0586:                        String detail = "Invalid interval. Must be a non-negative integer"
0587:                                + " number (32-bit signed).";
0588:                        throw new InvalidPropertyValueException(propName,
0589:                                propValue, detail);
0590:                    }
0591:
0592:                    if (interval < 0) {
0593:                        throw new InvalidPropertyValueException(propName,
0594:                                propValue,
0595:                                "Negative interval not allowed. Use 0 to disable reloading.");
0596:                    }
0597:                }
0598:
0599:                // Initialize ACL subsystem
0600:
0601:                // First with the API specific access rule list
0602:                if (_apiAccessRuleList != null) {
0603:                    _apiAccessRuleList.dispose();
0604:                }
0605:                _apiAccessRuleList = createAccessRuleList(runtimeSettings,
0606:                        ACL_PROPERTY + '.' + _name, interval);
0607:
0608:                // Then read the generic access rule list
0609:                if (_accessRuleList != null) {
0610:                    _accessRuleList.dispose();
0611:                }
0612:                _accessRuleList = createAccessRuleList(runtimeSettings,
0613:                        ACL_PROPERTY, interval);
0614:
0615:                // Initialize the RuntimeProperties object.
0616:                getProperties().init(runtimeSettings);
0617:
0618:                // Initialize all instances
0619:                int count = _manageableObjects.size();
0620:                for (int i = 0; i < count; i++) {
0621:                    Manageable m = (Manageable) _manageableObjects.get(i);
0622:                    String className = m.getClass().getName();
0623:                    Log.log_3416(_name, className);
0624:                    try {
0625:                        m.init(runtimeSettings);
0626:
0627:                        // Missing required property
0628:                    } catch (MissingRequiredPropertyException exception) {
0629:                        Log.log_3418(_name, className, exception
0630:                                .getPropertyName(), exception.getDetail());
0631:                        throw exception;
0632:
0633:                        // Invalid property value
0634:                    } catch (InvalidPropertyValueException exception) {
0635:                        Log.log_3419(_name, className, exception
0636:                                .getPropertyName(), exception
0637:                                .getPropertyValue(), exception.getReason());
0638:                        throw exception;
0639:
0640:                        // Catch InitializationException and any other exceptions not caught
0641:                        // by previous catch statements
0642:                    } catch (Throwable exception) {
0643:
0644:                        // Log this event
0645:                        Log.log_3420(exception, _name, className);
0646:                        if (exception instanceof  InitializationException) {
0647:                            throw (InitializationException) exception;
0648:                        } else {
0649:                            throw new InitializationException(exception);
0650:                        }
0651:                    }
0652:                }
0653:
0654:                // Initialize all functions
0655:                count = _functionList.size();
0656:                for (int i = 0; i < count; i++) {
0657:                    Function f = (Function) _functionList.get(i);
0658:                    String functionName = f.getName();
0659:                    Log.log_3421(_name, functionName);
0660:                    try {
0661:                        f.init(runtimeSettings);
0662:
0663:                        // Missing required property
0664:                    } catch (MissingRequiredPropertyException exception) {
0665:                        Log.log_3423(_name, functionName, exception
0666:                                .getPropertyName(), exception.getDetail());
0667:                        throw exception;
0668:
0669:                        // Invalid property value
0670:                    } catch (InvalidPropertyValueException exception) {
0671:                        Log.log_3424(_name, functionName, exception
0672:                                .getPropertyName(), exception
0673:                                .getPropertyValue(), exception.getReason());
0674:                        throw exception;
0675:
0676:                        // Catch InitializationException and any other exceptions not caught
0677:                        // by previous catch statements
0678:                    } catch (Throwable exception) {
0679:
0680:                        // Log this event
0681:                        Log.log_3425(exception, _name, functionName);
0682:
0683:                        // Throw an InitializationException. If necessary, wrap around the
0684:                        // caught exception
0685:                        if (exception instanceof  InitializationException) {
0686:                            throw (InitializationException) exception;
0687:                        } else {
0688:                            throw new InitializationException(exception);
0689:                        }
0690:                    }
0691:                }
0692:
0693:                Log.log_3406(_name);
0694:            }
0695:
0696:            /**
0697:             * Creates the access rule list for the given property.
0698:             *
0699:             * @param runtimeSettings
0700:             *    the runtime properties, never <code>null</code>.
0701:             *
0702:             * @param aclProperty
0703:             *    the ACL property, never <code>null</code>
0704:             *
0705:             * @param interval
0706:             *    the interval in seconds to chack if the ACL file has changed and
0707:             *    should be reloaded.
0708:             *
0709:             * @return
0710:             *    the access rule list created from the property value, never <code>null</code>.
0711:             *
0712:             * @throws InvalidPropertyValueException
0713:             *    if the value for the property is invalid.
0714:             */
0715:            private AccessRuleList createAccessRuleList(
0716:                    PropertyReader runtimeSettings, String aclProperty,
0717:                    int interval) throws InvalidPropertyValueException {
0718:                String acl = runtimeSettings.get(aclProperty);
0719:
0720:                // New access control list is empty
0721:                if (acl == null || acl.trim().length() < 1) {
0722:                    if (aclProperty.equals(ACL_PROPERTY)) {
0723:                        Log.log_3426(aclProperty);
0724:                    }
0725:                    return AccessRuleList.EMPTY;
0726:
0727:                    // New access control list is non-empty
0728:                } else {
0729:
0730:                    // Parse the new ACL
0731:                    try {
0732:                        AccessRuleList accessRuleList = AccessRuleList
0733:                                .parseAccessRuleList(acl, interval);
0734:                        int ruleCount = accessRuleList.getRuleCount();
0735:                        Log.log_3427(ruleCount);
0736:                        return accessRuleList;
0737:
0738:                        // Parsing failed
0739:                    } catch (ParseException exception) {
0740:                        String exceptionMessage = exception.getMessage();
0741:                        Log.log_3428(aclProperty, acl, exceptionMessage);
0742:                        throw new InvalidPropertyValueException(aclProperty,
0743:                                acl, exceptionMessage);
0744:                    }
0745:                }
0746:            }
0747:
0748:            /**
0749:             * Adds the specified manageable object. It will not immediately be
0750:             * bootstrapped and initialized.
0751:             *
0752:             * @param m
0753:             *    the manageable object to add, not <code>null</code>.
0754:             *
0755:             * @throws IllegalStateException
0756:             *    if this API is currently not bootstrapping.
0757:             *
0758:             * @throws IllegalArgumentException
0759:             *    if <code>instance == null</code>.
0760:             */
0761:            protected final void add(Manageable m)
0762:                    throws IllegalStateException, IllegalArgumentException {
0763:
0764:                // Check state
0765:                Manageable.State state = getState();
0766:                if (state != BOOTSTRAPPING) {
0767:                    String message = "State is " + state + " instead of "
0768:                            + BOOTSTRAPPING + '.';
0769:                    Utils.logProgrammingError(message);
0770:                    throw new IllegalStateException(message);
0771:                }
0772:
0773:                // Check preconditions
0774:                MandatoryArgumentChecker.check("m", m);
0775:                String className = m.getClass().getName();
0776:
0777:                Log.log_3218(_name, className);
0778:
0779:                // Store the manageable object in the list
0780:                _manageableObjects.add(m);
0781:            }
0782:
0783:            /**
0784:             * Performs shutdown of this XINS API. This method will never throw any
0785:             * exception.
0786:             */
0787:            protected final void deinitImpl() {
0788:
0789:                // Deinitialize instances
0790:                int count = _manageableObjects.size();
0791:                for (int i = 0; i < count; i++) {
0792:                    Manageable m = (Manageable) _manageableObjects.get(i);
0793:
0794:                    String className = m.getClass().getName();
0795:
0796:                    Log.log_3603(_name, className);
0797:                    try {
0798:                        m.deinit();
0799:                    } catch (DeinitializationException exception) {
0800:                        Log.log_3605(_name, className, exception.getMessage());
0801:                    } catch (Throwable exception) {
0802:                        Log.log_3606(exception, _name, className);
0803:                    }
0804:                }
0805:                _manageableObjects.clear();
0806:
0807:                // Deinitialize functions
0808:                count = _functionList.size();
0809:                for (int i = 0; i < count; i++) {
0810:                    Function f = (Function) _functionList.get(i);
0811:
0812:                    String functionName = f.getName();
0813:
0814:                    Log.log_3607(_name, functionName);
0815:                    try {
0816:                        f.deinit();
0817:                    } catch (DeinitializationException exception) {
0818:                        Log.log_3609(_name, functionName, exception
0819:                                .getMessage());
0820:                    } catch (Throwable exception) {
0821:                        Log.log_3610(exception, _name, functionName);
0822:                    }
0823:                }
0824:            }
0825:
0826:            /**
0827:             * Callback method invoked when a function is constructed.
0828:             *
0829:             * @param function
0830:             *    the function that is added, not <code>null</code>.
0831:             *
0832:             * @throws NullPointerException
0833:             *    if <code>function == null</code>.
0834:             *
0835:             * @throws IllegalStateException
0836:             *    if this API state is incorrect.
0837:             */
0838:            final void functionAdded(Function function)
0839:                    throws NullPointerException, IllegalStateException {
0840:
0841:                // Check state
0842:                Manageable.State state = getState();
0843:                if (state != UNUSABLE) {
0844:                    String message = "State is " + state + " instead of "
0845:                            + UNUSABLE + '.';
0846:                    Utils.logProgrammingError(message);
0847:                    throw new IllegalStateException(message);
0848:                }
0849:
0850:                _functionsByName.put(function.getName(), function);
0851:                _functionList.add(function);
0852:            }
0853:
0854:            /**
0855:             * Returns the function with the specified name.
0856:             *
0857:             * @param name
0858:             *    the name of the function, will not be checked if it is
0859:             *    <code>null</code>.
0860:             *
0861:             * @return
0862:             *    the function with the specified name, or <code>null</code> if there
0863:             *    is no match.
0864:             */
0865:            final Function getFunction(String name) {
0866:                return (Function) _functionsByName.get(name);
0867:            }
0868:
0869:            /**
0870:             * Get the specification of the API.
0871:             *
0872:             * @return
0873:             *    the {@link APISpec} specification object, never <code>null</code>.
0874:             *
0875:             * @throws InvalidSpecificationException
0876:             *    if the specification cannot be found or is invalid.
0877:             *
0878:             * @since XINS 1.3.0
0879:             */
0880:            public final APISpec getAPISpecification()
0881:                    throws InvalidSpecificationException {
0882:
0883:                if (_apiSpecification == null) {
0884:                    String baseURL = _engine.getFileLocation("/WEB-INF/specs/");
0885:                    _apiSpecification = new APISpec(getClass(), baseURL);
0886:                }
0887:                return _apiSpecification;
0888:            }
0889:
0890:            /**
0891:             * Determines if the specified IP address is allowed to access the
0892:             * specified function, returning a <code>boolean</code> value.
0893:             *
0894:             * <p>This method finds the first matching rule and then returns the
0895:             * <em>allow</em> property of that rule (see
0896:             * {@link AccessRule#isAllowRule()}). If there is no matching rule, then
0897:             * <code>false</code> is returned.
0898:             *
0899:             * @param ip
0900:             *    the IP address, cannot be <code>null</code>.
0901:             *
0902:             * @param functionName
0903:             *    the name of the function, cannot be <code>null</code>.
0904:             *
0905:             * @param conventionName
0906:             *    the name of the calling convention, can be <code>null</code>.
0907:             *
0908:             * @return
0909:             *    <code>true</code> if the request is allowed, <code>false</code> if
0910:             *    the request is denied.
0911:             *
0912:             * @throws IllegalArgumentException
0913:             *    if <code>ip == null || functionName == null</code>.
0914:             *
0915:             * @since XINS 2.1.
0916:             */
0917:            public boolean allow(String ip, String functionName,
0918:                    String conventionName) throws IllegalArgumentException {
0919:
0920:                // If no property is defined only localhost is allowed
0921:                if (_apiAccessRuleList == AccessRuleList.EMPTY
0922:                        && _accessRuleList == AccessRuleList.EMPTY
0923:                        && (ip.equals("127.0.0.1") || ip
0924:                                .equals(_localIPAddress))) {
0925:                    return true;
0926:                }
0927:
0928:                // Match an access rule
0929:                Boolean allowed;
0930:                try {
0931:
0932:                    // First check with the API specific one, then use the generic one.
0933:                    allowed = _apiAccessRuleList.isAllowed(ip, functionName,
0934:                            conventionName);
0935:                    if (allowed == null) {
0936:                        allowed = _accessRuleList.isAllowed(ip, functionName,
0937:                                conventionName);
0938:                    }
0939:
0940:                    // If the IP address cannot be parsed there is a programming error
0941:                    // somewhere
0942:                } catch (ParseException exception) {
0943:                    String detail = "Malformed IP address: \"" + ip + "\".";
0944:                    throw Utils.logProgrammingError(detail, exception);
0945:                }
0946:
0947:                // If there is a match, return the allow-indication
0948:                if (allowed != null) {
0949:                    return allowed.booleanValue();
0950:                }
0951:
0952:                // No matching access rule match, do not allow
0953:                Log.log_3553(ip, functionName, conventionName);
0954:                return false;
0955:            }
0956:
0957:            /**
0958:             * Forwards a call to a function, using an IP address. The call will
0959:             * actually be handled by
0960:             * {@link Function#handleCall(long,FunctionRequest,String)}.
0961:             *
0962:             * @param start
0963:             *    the start time of the request, in milliseconds since the
0964:             *    <a href="http://en.wikipedia.org/wiki/Unix_Epoch">UNIX Epoch</a>.
0965:             *
0966:             * @param functionRequest
0967:             *    the function request, never <code>null</code>.
0968:             *
0969:             * @param ip
0970:             *    the remote IP address, never <code>null</code>.
0971:             *
0972:             * @param cc
0973:             *    the calling convention to use to handle the call, never <code>null</code>.
0974:             *
0975:             * @return
0976:             *    the result of the call, never <code>null</code>.
0977:             *
0978:             * @throws IllegalStateException
0979:             *    if this object is currently not initialized.
0980:             *
0981:             * @throws NullPointerException
0982:             *    if <code>functionRequest == null</code>.
0983:             *
0984:             * @throws NoSuchFunctionException
0985:             *    if there is no matching function for the specified request.
0986:             *
0987:             * @throws AccessDeniedException
0988:             *    if access is denied for the specified combination of IP address and
0989:             *    function name.
0990:             */
0991:            final FunctionResult handleCall(long start,
0992:                    FunctionRequest functionRequest, String ip,
0993:                    CallingConvention cc) throws IllegalStateException,
0994:                    NullPointerException, NoSuchFunctionException,
0995:                    AccessDeniedException {
0996:
0997:                // Check state first
0998:                assertUsable();
0999:
1000:                // Determine the function name
1001:                String functionName = functionRequest.getFunctionName();
1002:
1003:                // Check the access rule list
1004:                boolean allow = allow(ip, functionName, cc.getConventionName());
1005:                if (!allow) {
1006:                    throw new AccessDeniedException(ip, functionName, cc
1007:                            .getConventionName());
1008:                }
1009:
1010:                // Handle meta-functions
1011:                FunctionResult result;
1012:                if (functionName.length() > 0 && functionName.charAt(0) == '_') {
1013:
1014:                    // Determine the call ID
1015:                    int callID;
1016:                    synchronized (_metaFunctionCallIDs) {
1017:                        Counter counter = (Counter) _metaFunctionCallIDs
1018:                                .get(functionName);
1019:                        if (counter == null) {
1020:                            throw new NoSuchFunctionException(functionName);
1021:                        } else {
1022:                            callID = counter.next();
1023:                        }
1024:                    }
1025:
1026:                    // Call the meta-function
1027:                    try {
1028:                        result = callMetaFunction(functionName, functionRequest);
1029:                    } catch (Throwable exception) {
1030:                        result = handleFunctionException(start,
1031:                                functionRequest, ip, callID, exception);
1032:                    }
1033:
1034:                    // Log this transaction
1035:                    long duration = System.currentTimeMillis() - start;
1036:                    Engine.logTransaction(functionRequest, result, ip, start,
1037:                            duration);
1038:
1039:                    // Handle normal functions
1040:                } else {
1041:                    Function function = getFunction(functionName);
1042:                    if (function == null
1043:                            && !functionRequest.shouldSkipFunctionCall()) {
1044:                        throw new NoSuchFunctionException(functionName);
1045:                    }
1046:                    if (function == null) {
1047:                        Object inParams = new FormattedParameters(
1048:                                functionRequest.getParameters(),
1049:                                functionRequest.getDataElement());
1050:                        Log.log_3516(functionRequest.getFunctionName(),
1051:                                inParams);
1052:                        result = SUCCESSFUL_RESULT;
1053:                    } else {
1054:                        result = function
1055:                                .handleCall(start, functionRequest, ip);
1056:                    }
1057:                }
1058:                return result;
1059:            }
1060:
1061:            /**
1062:             * Handles a call to a meta-function.
1063:             *
1064:             * @param functionName
1065:             *    the name of the meta-function, cannot be <code>null</code> and must
1066:             *    start with the underscore character <code>'_'</code>.
1067:             *
1068:             * @param functionRequest
1069:             *    the function request, never <code>null</code>.
1070:             *
1071:             * @return
1072:             *    the result of the function call, never <code>null</code>.
1073:             *
1074:             * @throws NoSuchFunctionException
1075:             *    if there is no meta-function by the specified name.
1076:             */
1077:            private FunctionResult callMetaFunction(String functionName,
1078:                    FunctionRequest functionRequest)
1079:                    throws NoSuchFunctionException {
1080:
1081:                FunctionResult result;
1082:
1083:                // No Operation
1084:                if ("_NoOp".equals(functionName)) {
1085:                    result = SUCCESSFUL_RESULT;
1086:
1087:                    // Retrieve function list
1088:                } else if ("_GetFunctionList".equals(functionName)) {
1089:                    result = doGetFunctionList();
1090:
1091:                    // Get function call quantity and performance statistics
1092:                } else if ("_GetStatistics".equals(functionName)) {
1093:
1094:                    // Determine value of 'detailed' argument
1095:                    String detailedArg = functionRequest.getParameters().get(
1096:                            "detailed");
1097:                    boolean detailed = !"false".equals(detailedArg);
1098:
1099:                    // Get the statistics
1100:                    result = doGetStatistics(detailed);
1101:
1102:                    // Determine value of 'reset' argument
1103:                    String resetArg = functionRequest.getParameters().get(
1104:                            "reset");
1105:                    boolean reset = "true".equals(resetArg);
1106:                    if (reset) {
1107:                        doResetStatistics();
1108:                    }
1109:
1110:                    // Get version information
1111:                } else if ("_GetVersion".equals(functionName)) {
1112:                    result = doGetVersion();
1113:
1114:                    // Check links to underlying systems
1115:                } else if ("_CheckLinks".equals(functionName)) {
1116:                    result = doCheckLinks();
1117:
1118:                    // Retrieve configuration settings
1119:                } else if ("_GetSettings".equals(functionName)) {
1120:                    result = doGetSettings();
1121:
1122:                    // Disable a function
1123:                } else if ("_DisableFunction".equals(functionName)) {
1124:                    String disabledFunction = functionRequest.getParameters()
1125:                            .get("functionName");
1126:                    result = doDisableFunction(disabledFunction);
1127:
1128:                    // Enable a function
1129:                } else if ("_EnableFunction".equals(functionName)) {
1130:                    String enabledFunction = functionRequest.getParameters()
1131:                            .get("functionName");
1132:                    result = doEnableFunction(enabledFunction);
1133:
1134:                    // Reset the statistics
1135:                } else if ("_ResetStatistics".equals(functionName)) {
1136:                    result = doResetStatistics();
1137:
1138:                    // Reload the runtime properties
1139:                } else if ("_ReloadProperties".equals(functionName)) {
1140:                    _engine.reloadPropertiesIfChanged();
1141:                    result = SUCCESSFUL_RESULT;
1142:
1143:                    // Retrieve eggs
1144:                } else if ("_IWantTheEasterEggs".equals(functionName)) {
1145:                    result = SUCCESSFUL_RESULT;
1146:
1147:                    // Return the WSDL description of the API
1148:                } else if ("_WSDL".equals(functionName)) {
1149:                    result = SUCCESSFUL_RESULT;
1150:
1151:                    // Return the SMD (Simple Method Description) description of the API
1152:                } else if ("_SMD".equals(functionName)) {
1153:                    result = SUCCESSFUL_RESULT;
1154:
1155:                    // Disable the API
1156:                } else if ("_DisableAPI".equals(functionName)) {
1157:                    _apiDisabled = true;
1158:                    result = SUCCESSFUL_RESULT;
1159:
1160:                    // Enable the API
1161:                } else if ("_EnableAPI".equals(functionName)) {
1162:                    _apiDisabled = false;
1163:                    result = SUCCESSFUL_RESULT;
1164:
1165:                    // Meta-function does not exist
1166:                } else {
1167:                    throw new NoSuchFunctionException(functionName);
1168:                }
1169:
1170:                return result;
1171:            }
1172:
1173:            /**
1174:             * Handles an exception caught while a function was executed.
1175:             *
1176:             * @param start
1177:             *    the start time of the call, as milliseconds since the
1178:             *    <a href="http://en.wikipedia.org/wiki/Unix_Epoch">UNIX Epoch</a>.
1179:             *
1180:             * @param functionRequest
1181:             *    the request, never <code>null</code>.
1182:             *
1183:             * @param ip
1184:             *    the IP address of the requester, never <code>null</code>.
1185:             *
1186:             * @param callID
1187:             *    the call identifier, never <code>null</code>.
1188:             *
1189:             * @param exception
1190:             *    the exception caught, never <code>null</code>.
1191:             *
1192:             * @return
1193:             *    the call result, never <code>null</code>.
1194:             */
1195:            FunctionResult handleFunctionException(long start,
1196:                    FunctionRequest functionRequest, String ip, int callID,
1197:                    Throwable exception) {
1198:
1199:                Log.log_3500(exception, _name, callID);
1200:
1201:                // Create a set of parameters for the result
1202:                BasicPropertyReader resultParams = new BasicPropertyReader();
1203:
1204:                // Add the exception class
1205:                String exceptionClass = exception.getClass().getName();
1206:                resultParams.set("_exception.class", exceptionClass);
1207:
1208:                // Add the exception message, if any
1209:                String exceptionMessage = exception.getMessage();
1210:                if (exceptionMessage != null) {
1211:                    exceptionMessage = exceptionMessage.trim();
1212:                    if (exceptionMessage.length() > 0) {
1213:                        resultParams
1214:                                .set("_exception.message", exceptionMessage);
1215:                    }
1216:                }
1217:
1218:                // Add the stack trace, if any
1219:                StringWriter stWriter = new StringWriter(360);
1220:                PrintWriter printWriter = new PrintWriter(stWriter);
1221:                exception.printStackTrace(printWriter);
1222:                String stackTrace = stWriter.toString();
1223:                stackTrace = stackTrace.trim();
1224:                if (stackTrace.length() > 0) {
1225:                    resultParams.set("_exception.stacktrace", stackTrace);
1226:                }
1227:
1228:                return new FunctionResult("_InternalError", resultParams);
1229:            }
1230:
1231:            /**
1232:             * Returns a list of all functions in this API. Per function the name and
1233:             * the version are returned.
1234:             *
1235:             * @return
1236:             *    the call result, never <code>null</code>.
1237:             */
1238:            private final FunctionResult doGetFunctionList() {
1239:
1240:                // Initialize a builder
1241:                FunctionResult builder = new FunctionResult();
1242:
1243:                // Loop over all functions
1244:                int count = _functionList.size();
1245:                for (int i = 0; i < count; i++) {
1246:
1247:                    // Get some details about the function
1248:                    Function function = (Function) _functionList.get(i);
1249:                    String name = function.getName();
1250:                    String version = function.getVersion();
1251:                    String enabled = function.isEnabled() ? "true" : "false";
1252:
1253:                    // Add an element describing the function
1254:                    ElementBuilder functionElem = new ElementBuilder("function");
1255:                    functionElem.setAttribute("name", name);
1256:                    functionElem.setAttribute("version", version);
1257:                    functionElem.setAttribute("enabled", enabled);
1258:                    builder.add(functionElem.createElement());
1259:                }
1260:
1261:                return builder;
1262:            }
1263:
1264:            /**
1265:             * Returns the call statistics for all functions in this API.
1266:             *
1267:             * @param detailed
1268:             *    If <code>true</code>, the unsuccessful result will be returned sorted
1269:             *    per error code. Otherwise the unsuccessful result won't be displayed
1270:             *    by error code.
1271:             *
1272:             * @return
1273:             *    the call result, never <code>null</code>.
1274:             */
1275:            private final FunctionResult doGetStatistics(boolean detailed) {
1276:
1277:                // Initialize a builder
1278:                FunctionResult builder = new FunctionResult();
1279:
1280:                builder.param("startup", DateConverter.toDateString(_timeZone,
1281:                        _startupTimestamp));
1282:                builder.param("lastReset", DateConverter.toDateString(
1283:                        _timeZone, _lastStatisticsReset));
1284:                builder.param("now", DateConverter.toDateString(_timeZone,
1285:                        System.currentTimeMillis()));
1286:
1287:                // Currently available processors
1288:                Runtime rt = Runtime.getRuntime();
1289:                try {
1290:                    builder.param("availableProcessors", String.valueOf(rt
1291:                            .availableProcessors()));
1292:                } catch (NoSuchMethodError error) {
1293:                    // NOTE: Runtime.availableProcessors() is not available in Java 1.3
1294:                }
1295:
1296:                // Heap memory statistics
1297:                ElementBuilder heap = new ElementBuilder("heap");
1298:                long free = rt.freeMemory();
1299:                long total = rt.totalMemory();
1300:                heap.setAttribute("used", String.valueOf(total - free));
1301:                heap.setAttribute("free", String.valueOf(free));
1302:                heap.setAttribute("total", String.valueOf(total));
1303:                try {
1304:                    heap.setAttribute("max", String.valueOf(rt.maxMemory()));
1305:                } catch (NoSuchMethodError error) {
1306:                    // NOTE: Runtime.maxMemory() is not available in Java 1.3
1307:                }
1308:                builder.add(heap.createElement());
1309:
1310:                // Function-specific statistics
1311:                int count = _functionList.size();
1312:                for (int i = 0; i < count; i++) {
1313:                    Function function = (Function) _functionList.get(i);
1314:                    FunctionStatistics stats = function.getStatistics();
1315:
1316:                    ElementBuilder functionElem = new ElementBuilder("function");
1317:                    functionElem.setAttribute("name", function.getName());
1318:
1319:                    // Successful
1320:                    Element successful = stats.getSuccessfulElement();
1321:                    functionElem.addChild(successful);
1322:
1323:                    // Unsuccessful
1324:                    Element[] unsuccessful = stats
1325:                            .getUnsuccessfulElement(detailed);
1326:                    for (int j = 0; j < unsuccessful.length; j++) {
1327:                        functionElem.addChild(unsuccessful[j]);
1328:                    }
1329:
1330:                    builder.add(functionElem.createElement());
1331:                }
1332:
1333:                return builder;
1334:            }
1335:
1336:            /**
1337:             * Returns the XINS version.
1338:             *
1339:             * @return
1340:             *    the call result, never <code>null</code>.
1341:             */
1342:            private final FunctionResult doGetVersion() {
1343:
1344:                FunctionResult builder = new FunctionResult();
1345:
1346:                builder.param("java.version", System
1347:                        .getProperty("java.version"));
1348:                builder.param("xmlenc.version", org.znerd.xmlenc.Library
1349:                        .getVersion());
1350:                builder.param("xins.version", Library.getVersion());
1351:                builder.param("api.version", _apiVersion);
1352:
1353:                return builder;
1354:            }
1355:
1356:            /**
1357:             * Returns the links in linked system components. It uses the
1358:             * {@link CheckLinks} to connect to each link and builds a
1359:             * {@link FunctionResult} which will have the total link count and total
1360:             * link failures.
1361:             *
1362:             * @return
1363:             *    the call result, never <code>null</code>.
1364:             */
1365:            private final FunctionResult doCheckLinks() {
1366:                return CheckLinks.checkLinks(getProperties().descriptors());
1367:            }
1368:
1369:            /**
1370:             * Returns the settings.
1371:             *
1372:             * @return
1373:             *    the call result, never <code>null</code>.
1374:             */
1375:            private final FunctionResult doGetSettings() {
1376:
1377:                FunctionResult builder = new FunctionResult();
1378:
1379:                // Build settings
1380:                Iterator names = _buildSettings.getNames();
1381:                ElementBuilder build = new ElementBuilder("build");
1382:                while (names.hasNext()) {
1383:                    String key = (String) names.next();
1384:                    String value = _buildSettings.get(key);
1385:
1386:                    ElementBuilder property = new ElementBuilder("property");
1387:                    property.setAttribute("name", key);
1388:                    property.setText(value);
1389:                    build.addChild(property.createElement());
1390:                }
1391:                builder.add(build.createElement());
1392:
1393:                // Runtime settings
1394:                names = _runtimeSettings.getNames();
1395:                ElementBuilder runtime = new ElementBuilder("runtime");
1396:                while (names.hasNext()) {
1397:                    String key = (String) names.next();
1398:                    String value = _runtimeSettings.get(key);
1399:
1400:                    ElementBuilder property = new ElementBuilder("property");
1401:                    property.setAttribute("name", key);
1402:                    property.setText(value);
1403:                    runtime.addChild(property.createElement());
1404:                }
1405:                builder.add(runtime.createElement());
1406:
1407:                // System properties
1408:                Properties sysProps;
1409:                try {
1410:                    sysProps = System.getProperties();
1411:                } catch (SecurityException ex) {
1412:                    Utils.logProgrammingError(ex);
1413:                    sysProps = new Properties();
1414:                }
1415:
1416:                Enumeration e = sysProps.propertyNames();
1417:                ElementBuilder system = new ElementBuilder("system");
1418:                while (e.hasMoreElements()) {
1419:                    String key = (String) e.nextElement();
1420:                    String value = sysProps.getProperty(key);
1421:
1422:                    if (key != null && key.trim().length() > 0 && value != null
1423:                            && value.trim().length() > 0) {
1424:                        ElementBuilder property = new ElementBuilder("property");
1425:                        property.setAttribute("name", key);
1426:                        property.setText(value);
1427:                        system.addChild(property.createElement());
1428:                    }
1429:                }
1430:                builder.add(system.createElement());
1431:
1432:                return builder;
1433:            }
1434:
1435:            /**
1436:             * Enables a function.
1437:             *
1438:             * @param functionName
1439:             *    the name of the function to disable, can be <code>null</code>.
1440:             *
1441:             * @return
1442:             *    the call result, never <code>null</code>.
1443:             */
1444:            private final FunctionResult doEnableFunction(String functionName) {
1445:
1446:                // Get the name of the function to enable
1447:                if (functionName == null || functionName.length() < 1) {
1448:                    InvalidRequestResult invalidRequest = new InvalidRequestResult();
1449:                    invalidRequest.addMissingParameter("functionName");
1450:                    return invalidRequest;
1451:                }
1452:
1453:                // Get the Function object
1454:                Function function = getFunction(functionName);
1455:                if (function == null) {
1456:                    return new InvalidRequestResult();
1457:                }
1458:
1459:                // Enable or disable the function
1460:                function.setEnabled(true);
1461:
1462:                return SUCCESSFUL_RESULT;
1463:            }
1464:
1465:            /**
1466:             * Disables a function.
1467:             *
1468:             * @param functionName
1469:             *    the name of the function to disable, can be <code>null</code>.
1470:             *
1471:             * @return
1472:             *    the call result, never <code>null</code>.
1473:             */
1474:            private final FunctionResult doDisableFunction(String functionName) {
1475:
1476:                // Get the name of the function to disable
1477:                if (functionName == null || functionName.length() < 1) {
1478:                    InvalidRequestResult invalidRequest = new InvalidRequestResult();
1479:                    invalidRequest.addMissingParameter("functionName");
1480:                    return invalidRequest;
1481:                }
1482:
1483:                // Get the Function object
1484:                Function function = getFunction(functionName);
1485:                if (function == null) {
1486:                    return new InvalidRequestResult();
1487:                }
1488:
1489:                // Enable or disable the function
1490:                function.setEnabled(false);
1491:
1492:                return SUCCESSFUL_RESULT;
1493:            }
1494:
1495:            /**
1496:             * Resets the statistics.
1497:             *
1498:             * @return
1499:             *    the call result, never <code>null</code>.
1500:             */
1501:            private final FunctionResult doResetStatistics() {
1502:
1503:                // Remember when we last reset the statistics
1504:                _lastStatisticsReset = System.currentTimeMillis();
1505:
1506:                // Function-specific statistics
1507:                int count = _functionList.size();
1508:                for (int i = 0; i < count; i++) {
1509:                    Function function = (Function) _functionList.get(i);
1510:                    function.getStatistics().resetStatistics();
1511:                }
1512:                return SUCCESSFUL_RESULT;
1513:            }
1514:
1515:            /**
1516:             * Indicates whether the API is down for maintenance or not.
1517:             *
1518:             * @return
1519:             *    <code>true</code> if the API is disable, <code>false</code> otherwise.
1520:             */
1521:            boolean isDisabled() {
1522:                return _apiDisabled;
1523:            }
1524:
1525:            /**
1526:             * Thread-safe <code>int</code> counter.
1527:             *
1528:             * @version $Revision: 1.369 $ $Date: 2007/09/18 08:45:06 $
1529:             * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
1530:             */
1531:            private static final class Counter {
1532:
1533:                /**
1534:                 * The wrapped <code>int</code> number. Initially <code>0</code>.
1535:                 */
1536:                private int _value;
1537:
1538:                /**
1539:                 * Constructs a new <code>Counter</code> that initially returns the
1540:                 * value <code>0</code>.
1541:                 */
1542:                private Counter() {
1543:                    // empty
1544:                }
1545:
1546:                /**
1547:                 * Retrieves the next value. The first time <code>0</code> is returned,
1548:                 * the second time <code>1</code>, etc.
1549:                 *
1550:                 * @return
1551:                 *    the next sequence number.
1552:                 */
1553:                private synchronized int next() {
1554:                    return _value++;
1555:                }
1556:            }
1557:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.