Source Code Cross Referenced for AccessRuleFile.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) 


001:        /*
002:         * $Id: AccessRuleFile.java,v 1.39 2007/09/18 08:45:06 agoubard Exp $
003:         *
004:         * Copyright 2003-2007 Orange Nederland Breedband B.V.
005:         * See the COPYRIGHT file for redistribution and use restrictions.
006:         */
007:        package org.xins.server;
008:
009:        import java.io.BufferedReader;
010:        import java.io.FileNotFoundException;
011:        import java.io.FileReader;
012:        import java.io.IOException;
013:        import java.util.ArrayList;
014:        import java.util.List;
015:        import java.util.StringTokenizer;
016:
017:        import org.xins.common.MandatoryArgumentChecker;
018:        import org.xins.common.Utils;
019:        import org.xins.common.io.FileWatcher;
020:        import org.xins.common.text.TextUtils;
021:        import org.xins.common.text.ParseException;
022:
023:        /**
024:         * Collection of access rules that are read from a separate file.
025:         *
026:         * <p>An <code>AccessRuleFile</code> instance is constructed using a
027:         * descriptor and a file watch interval. The descriptor is a character string
028:         * that is parsed to determine which file should be parsed and monitored for
029:         * changes. Such a descriptor must match the following pattern:
030:         *
031:         * <blockquote><code>file&nbsp;<em>filename</em></code></blockquote>
032:         *
033:         * where <em>filename</em> is the name of the file to parse and watch.
034:         *
035:         * <p>The file watch interval is specified in seconds. At the specified
036:         * interval, the file will be checked for modifications. If there are any
037:         * modifications, then the file is reloaded and the access rules are
038:         * re-applied.
039:         *
040:         * <p>If the file watch interval is set to <code>0</code>, then the watching
041:         * is disabled, and no automatic reloading will be performed.
042:         *
043:         * @version $Revision: 1.39 $ $Date: 2007/09/18 08:45:06 $
044:         * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
045:         * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
046:         *
047:         * @since XINS 1.1.0
048:         */
049:        public class AccessRuleFile implements  AccessRuleContainer {
050:
051:            /**
052:             * The ACL file.
053:             */
054:            private String _file;
055:
056:            /**
057:             * The interval used to check the ACL file for modification.
058:             */
059:            private int _interval;
060:
061:            /**
062:             * Watcher for the ACL file.
063:             */
064:            private FileWatcher _fileWatcher;
065:
066:            /**
067:             * The list of rules. Cannot be <code>null</code>.
068:             */
069:            private AccessRuleContainer[] _rules;
070:
071:            /**
072:             * String representation of this object. Cannot be <code>null</code>.
073:             */
074:            private final String _asString;
075:
076:            /**
077:             * Flag that indicates whether this object is disposed.
078:             */
079:            private boolean _disposed;
080:
081:            /**
082:             * Constructs a new <code>AccessRuleFile</code> based on a descriptor and
083:             * a file watch interval.
084:             *
085:             * <p>If the specified interval is <code>0</code>, then no watching will be
086:             * performed.
087:             *
088:             * @param descriptor
089:             *    the access rule file descriptor, the character string to parse,
090:             *    cannot be <code>null</code>.
091:             *
092:             * @param interval
093:             *    the interval to check the ACL file for modifications, in seconds,
094:             *    must be &gt;= 0.
095:             *
096:             * @throws ParseException
097:             *    If the token is incorrectly formatted.
098:             *
099:             * @throws IllegalArgumentException
100:             *    if <code>descriptor == null || interval &lt; 0</code>.
101:             */
102:            public AccessRuleFile(String descriptor, int interval)
103:                    throws IllegalArgumentException, ParseException {
104:
105:                // Check preconditions
106:                MandatoryArgumentChecker.check("descriptor", descriptor);
107:                if (interval < 0) {
108:                    throw new IllegalArgumentException("interval (" + interval
109:                            + ") < 0");
110:                }
111:
112:                // First token must be 'file'
113:                StringTokenizer tokenizer = new StringTokenizer(descriptor,
114:                        " \t\n\r");
115:                String token = nextToken(descriptor, tokenizer);
116:                if (!"file".equals(token)) {
117:                    throw new ParseException("First token of descriptor is \""
118:                            + token + "\", instead of \"file\".");
119:                }
120:
121:                // First try parsing the file as it is
122:                _file = nextToken(descriptor, tokenizer);
123:                try {
124:                    parseAndApply(_file, interval);
125:
126:                    // File not found
127:                } catch (FileNotFoundException fnfe) {
128:                    String message = "File \"" + _file
129:                            + "\" cannot be opened for reading.";
130:                    ParseException pe = new ParseException(message, fnfe, null);
131:                    throw pe;
132:
133:                    // I/O error reading from the file not found
134:                } catch (IOException ioe) {
135:                    String message = "Cannot parse the file \"" + _file
136:                            + "\" due to an I/O error.";
137:                    ParseException pe = new ParseException(message, ioe, null);
138:                    throw pe;
139:                }
140:
141:                // Store the interval
142:                _interval = interval;
143:
144:                // Create and start a file watch thread, if the interval is not zero
145:                if (interval > 0) {
146:                    FileListener fileListener = new FileListener();
147:                    _fileWatcher = new FileWatcher(_file, interval,
148:                            fileListener);
149:                    _fileWatcher.start();
150:                }
151:
152:                // Generate the string representation
153:                _asString = "file " + _file;
154:            }
155:
156:            /**
157:             * Returns the next token in the descriptor.
158:             *
159:             * @param descriptor
160:             *    the original descriptor, useful when constructing the message for a
161:             *    {@link ParseException}, when appropriate, should not be
162:             *    <code>null</code>.
163:             *
164:             * @param tokenizer
165:             *    the {@link StringTokenizer} to retrieve the next token from, cannot be
166:             *    <code>null</code>.
167:             *
168:             * @return
169:             *    the next token, never <code>null</code>.
170:             *
171:             * @throws ParseException
172:             *    if <code>tokenizer.{@link StringTokenizer#hasMoreTokens()
173:             *    hasMoreTokens}() == false</code>.
174:             */
175:            private static String nextToken(String descriptor,
176:                    StringTokenizer tokenizer) throws ParseException {
177:
178:                if (!tokenizer.hasMoreTokens()) {
179:                    String message = "The string \""
180:                            + descriptor
181:                            + "\" is invalid as an access rule file descriptor. "
182:                            + "More tokens expected.";
183:                    throw new ParseException(message);
184:                } else {
185:                    return tokenizer.nextToken();
186:                }
187:            }
188:
189:            /**
190:             * Determines if the specified IP address is allowed to access the
191:             * specified function, returning a <code>Boolean</code> object or
192:             * <code>null</code>.
193:             *
194:             * <p>This method finds the first matching rule and then returns the
195:             * <em>allow</em> property of that rule (see
196:             * {@link AccessRule#isAllowRule()}). If there is no matching rule, then
197:             * <code>null</code> is returned.
198:             *
199:             * @param ip
200:             *    the IP address, cannot be <code>null</code>.
201:             *
202:             * @param functionName
203:             *    the name of the function, cannot be <code>null</code>.
204:             *
205:             * @param conventionName
206:             *    the name of the calling convention to match, can be <code>null</code>.
207:             *
208:             * @return
209:             *    {@link Boolean#TRUE} if the specified IP address is allowed to access
210:             *    the specified function, {@link Boolean#FALSE} if it is disallowed
211:             *    access or <code>null</code> if there is no match.
212:             *
213:             * @throws IllegalArgumentException
214:             *    if <code>ip == null || functionName == null</code>.
215:             *
216:             * @throws ParseException
217:             *    if the specified IP address is malformed.
218:             *
219:             * @since XINS 2.1.
220:             */
221:            public Boolean isAllowed(String ip, String functionName,
222:                    String conventionName) throws IllegalArgumentException,
223:                    ParseException {
224:
225:                // Check state
226:                if (_disposed) {
227:                    String detail = "This AccessRuleFile is disposed.";
228:                    Utils.logProgrammingError(detail);
229:                    throw new IllegalStateException(detail);
230:                }
231:
232:                // Check arguments
233:                MandatoryArgumentChecker.check("ip", ip, "functionName",
234:                        functionName);
235:
236:                // Find a matching rule and see if the call is allowed
237:                int count = _rules == null ? 0 : _rules.length;
238:                Boolean allowed = null;
239:                for (int i = 0; i < count && allowed == null; i++) {
240:                    allowed = _rules[i].isAllowed(ip, functionName,
241:                            conventionName);
242:                }
243:
244:                return allowed;
245:            }
246:
247:            /**
248:             * Disposes this access rule. All claimed resources are freed as much as
249:             * possible.
250:             *
251:             * <p>Once disposed, the {@link #isAllowed} method should no longer be
252:             * called.
253:             *
254:             * @throws IllegalStateException
255:             *    if {@link #dispose()} has been called previously
256:             *    (<em>since XINS 1.3.0</em>).
257:             */
258:            public void dispose() throws IllegalStateException {
259:
260:                // Check state
261:                if (_disposed) {
262:                    String detail = "This AccessRuleFile is already disposed.";
263:                    Utils.logProgrammingError(detail);
264:                    throw new IllegalStateException(detail);
265:                }
266:
267:                // Dispose all children
268:                int count = _rules == null ? 0 : _rules.length;
269:                for (int i = 0; i < count; i++) {
270:                    AccessRuleContainer rule = _rules[i];
271:                    if (rule != null) {
272:                        try {
273:                            rule.dispose();
274:                        } catch (Throwable exception) {
275:                            Utils.logIgnoredException(exception);
276:                        }
277:                    }
278:                }
279:                _rules = null;
280:
281:                // Stop the file watcher
282:                if (_fileWatcher != null) {
283:                    try {
284:                        _fileWatcher.end();
285:                    } catch (Throwable exception) {
286:                        Utils.logIgnoredException(exception);
287:                    }
288:                    _fileWatcher = null;
289:                }
290:
291:                // Mark this object as disposed
292:                _disposed = true;
293:            }
294:
295:            /**
296:             * Reads and parses the specified ACL file and then applies it to this
297:             * <code>AccessRuleFile</code> instance.
298:             *
299:             * @param file
300:             *    the file to open, read and parse, cannot be <code>null</code>.
301:             *
302:             * @param interval
303:             *    the interval for checking the ACL file for modifications, in
304:             *    milliseconds.
305:             *
306:             * @throws IllegalArgumentException
307:             *    if <code>file == null || interval &lt; 0</code>.
308:             *
309:             * @throws ParseException
310:             *    if the file could not be parsed successfully.
311:             *
312:             * @throws IOException
313:             *    if there was an I/O error while reading from the file.
314:             */
315:            private void parseAndApply(String file, int interval)
316:                    throws IllegalArgumentException, ParseException,
317:                    IOException {
318:
319:                // Check preconditions
320:                MandatoryArgumentChecker.check("file", file);
321:                if (interval < 0) {
322:                    throw new IllegalArgumentException("interval < 0");
323:                }
324:
325:                // Buffer the input from the file
326:                FileReader fileReader = new FileReader(file);
327:                BufferedReader buffReader = null;
328:                try {
329:                    buffReader = new BufferedReader(fileReader);
330:
331:                    // Delegate
332:                    parseAndApply(file, buffReader, interval);
333:
334:                    // Always close the streams
335:                } finally {
336:                    try {
337:                        fileReader.close();
338:                    } catch (Throwable exception) {
339:                        Utils.logIgnoredException(exception);
340:                    }
341:                    if (buffReader != null) {
342:                        try {
343:                            buffReader.close();
344:                        } catch (Throwable exception) {
345:                            Utils.logIgnoredException(exception);
346:                        }
347:                    }
348:                }
349:            }
350:
351:            /**
352:             * Parses the specified ACL file (already opened) and then applies it to
353:             * this <code>AccessRuleFile</code> instance.
354:             *
355:             * @param file
356:             *    the name of the opened file, should not be <code>null</code>.
357:             *
358:             * @param reader
359:             *    input stream for the file, should not be <code>null</code>.
360:             *
361:             * @param interval
362:             *    the interval for checking the ACL file for modifications, in
363:             *    milliseconds.
364:             *
365:             * @throws NullPointerException
366:             *    if <code>file == null || reader == null</code>.
367:             *
368:             * @throws ParseException
369:             *    if the file could not be parsed successfully.
370:             *
371:             * @throws IOException
372:             *    if there was an I/O error while reading from the file.
373:             */
374:            private void parseAndApply(String file, BufferedReader reader,
375:                    int interval) throws NullPointerException, ParseException,
376:                    IOException {
377:
378:                // Loop through the file, line by line
379:                List rules = new ArrayList(25);
380:                int lineNumber = 0;
381:                String nextLine = "";
382:                while (reader.ready() && nextLine != null) {
383:
384:                    // Read the next line and remove leading/trailing whitespace
385:                    nextLine = TextUtils.trim(reader.readLine(), null);
386:
387:                    // Increase the line number (so it's 1-based)
388:                    lineNumber++;
389:
390:                    // Skip comments and empty lines
391:                    if (nextLine == null || nextLine.startsWith("#")) {
392:                        // ignore
393:
394:                        // Plain access rule
395:                    } else if (nextLine.startsWith("allow")
396:                            || nextLine.startsWith("deny")) {
397:                        rules.add(AccessRule.parseAccessRule(nextLine));
398:
399:                        // File reference
400:                    } else if (nextLine.startsWith("file")) {
401:
402:                        // Make sure the file does not include itself
403:                        if (nextLine.substring(5).equals(file)) {
404:                            String detail = "The access rule file \"" + file
405:                                    + "\" includes itself.";
406:                            throw new ParseException(detail);
407:                        }
408:                        rules.add(new AccessRuleFile(nextLine, interval));
409:
410:                        // Otherwise: Incorrect line
411:                    } else {
412:                        String detail = "Failed to parse \"" + file
413:                                + "\", line #" + lineNumber + ": \"" + nextLine
414:                                + "\". Expected line to start with \"#\", "
415:                                + "\"allow\", \"deny\" or \"file\".";
416:                        throw new ParseException(detail);
417:                        // XXX: Log parsing problem?
418:                    }
419:                }
420:
421:                // Copy to the instance field
422:                _rules = (AccessRuleContainer[]) rules
423:                        .toArray(new AccessRuleContainer[rules.size()]);
424:            }
425:
426:            /**
427:             * Re-initializes the ACL rules for this file.
428:             */
429:            private void reinit() {
430:
431:                // Dispose the current rules
432:                int count = _rules == null ? 0 : _rules.length;
433:                for (int i = 0; i < count; i++) {
434:                    _rules[i].dispose();
435:                }
436:                _rules = null;
437:
438:                // Parse the file and apply the rules
439:                try {
440:                    parseAndApply(_file, _interval);
441:
442:                    // If the parsing fails, then log the exception
443:                } catch (Throwable exception) {
444:                    Utils.logIgnoredException(exception);
445:                    _rules = new AccessRuleContainer[0];
446:                    // TODO: The framework re-initialization should fail
447:                }
448:            }
449:
450:            public String toString() {
451:                return _asString;
452:            }
453:
454:            /**
455:             * Listener that reloads the ACL file if it changes.
456:             *
457:             * @version $Revision: 1.39 $ $Date: 2007/09/18 08:45:06 $
458:             * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
459:             *
460:             * @since XINS 1.1.0
461:             */
462:            private final class FileListener implements  FileWatcher.Listener {
463:
464:                /**
465:                 * Constructs a new <code>FileListener</code> object.
466:                 */
467:                FileListener() {
468:                    // empty
469:                }
470:
471:                /**
472:                 * Callback method called when the configuration file is found while it
473:                 * was previously not found.
474:                 *
475:                 * <p>This will trigger re-initialization.
476:                 */
477:                public void fileFound() {
478:                    reinit();
479:                }
480:
481:                /**
482:                 * Callback method called when the configuration file is (still) not
483:                 * found.
484:                 *
485:                 * <p>The implementation of this method does not perform any actions.
486:                 */
487:                public void fileNotFound() {
488:                    Log.log_3400(_file);
489:                }
490:
491:                /**
492:                 * Callback method called when the configuration file is (still) not
493:                 * modified.
494:                 *
495:                 * <p>The implementation of this method does not perform any actions.
496:                 */
497:                public void fileNotModified() {
498:                    // empty
499:                }
500:
501:                /**
502:                 * Callback method called when the configuration file could not be
503:                 * examined due to a <code>SecurityException</code>.
504:                 * modified.
505:                 *
506:                 * <p>The implementation of this method does not perform any actions.
507:                 *
508:                 * @param exception
509:                 *    the caught security exception, should not be <code>null</code>
510:                 *    (although this is not checked).
511:                 */
512:                public void securityException(SecurityException exception) {
513:                    Log.log_3401(exception, _file);
514:                }
515:
516:                /**
517:                 * Callback method called when the configuration file is modified since
518:                 * the last time it was checked.
519:                 *
520:                 * <p>This will trigger re-initialization.
521:                 */
522:                public void fileModified() {
523:                    reinit();
524:                }
525:            }
526:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.