Source Code Cross Referenced for SimpleFile.java in  » Workflow-Engines » pegasus-2.1.0 » org » griphyn » common » catalog » replica » 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 » Workflow Engines » pegasus 2.1.0 » org.griphyn.common.catalog.replica 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * This file or a portion of this file is licensed under the terms of
0003:         * the Globus Toolkit Public License, found in file GTPL, or at
0004:         * http://www.globus.org/toolkit/download/license.html. This notice must
0005:         * appear in redistributions of this file, with or without modification.
0006:         *
0007:         * Redistributions of this Software, with or without modification, must
0008:         * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
0009:         * some other similar material which is provided with the Software (if
0010:         * any).
0011:         *
0012:         * Copyright 1999-2004 University of Chicago and The University of
0013:         * Southern California. All rights reserved.
0014:         */
0015:
0016:        package org.griphyn.common.catalog.replica;
0017:
0018:        import java.io.*;
0019:        import java.util.*;
0020:        import java.util.regex.*;
0021:        import org.griphyn.common.util.Boolean;
0022:        import org.griphyn.common.util.Escape;
0023:        import org.griphyn.common.util.Currently;
0024:        import org.griphyn.common.catalog.Catalog;
0025:        import org.griphyn.common.catalog.ReplicaCatalog;
0026:        import org.griphyn.common.catalog.ReplicaCatalogEntry;
0027:
0028:        /**
0029:         * This class implements a replica catalog on top of a simple file which
0030:         * contains two or more columns. It is neither transactionally safe, nor
0031:         * advised to use for production purposes in any way. Multiple
0032:         * concurrent instances <b>will clobber</b> each other!<p>
0033:         *
0034:         * The site attribute should be specified whenever possible. The
0035:         * attribute key for the site attribute is "pool". For the shell
0036:         * planner, its value will always be "local".<p>
0037:         *
0038:         * The class is permissive in what inputs it accepts. The LFN may or may
0039:         * not be quoted. If it contains linear whitespace, quotes, backslash or
0040:         * an equality sign, it must be quoted and escaped. Ditto for the PFN.
0041:         * The attribute key-value pairs are separated by an equality sign
0042:         * without any whitespaces. The value may be in quoted. The LFN
0043:         * sentiments about quoting apply.<p>
0044:         *
0045:         * <pre>
0046:         * LFN PFN
0047:         * LFN PFN a=b [..]
0048:         * LFN PFN a="b" [..]
0049:         * "LFN w/LWS" "PFN w/LWS" [..]
0050:         * </pre>
0051:         *
0052:         * The class is strict when producing (storing) results. The LFN and PFN
0053:         * are only quoted and escaped, if necessary. The attribute values are
0054:         * always quoted and escaped.
0055:         *
0056:         * @author Jens-S. Vöckler
0057:         * @version $Revision: 216 $
0058:         */
0059:        public class SimpleFile implements  ReplicaCatalog {
0060:            /**
0061:             * Records the quoting mode for LFNs and PFNs. If false, only quote as
0062:             * necessary. If true, always quote all LFNs and PFNs.
0063:             */
0064:            protected boolean m_quote = false;
0065:
0066:            /**
0067:             * Records the name of the on-disk representation.
0068:             */
0069:            protected String m_filename = null;
0070:
0071:            /**
0072:             * Maintains a memory slurp of the file representation.
0073:             */
0074:            protected Map m_lfn = null;
0075:
0076:            /**
0077:             * Default empty constructor creates an object that is not yet connected
0078:             * to any database. You must use support methods to connect before this
0079:             * instance becomes usable.
0080:             *
0081:             * @see #connect( Properties )
0082:             */
0083:            public SimpleFile() {
0084:                // make connection defunc
0085:                m_lfn = null;
0086:                m_filename = null;
0087:            }
0088:
0089:            /**
0090:             * Provides the final states and associated messages.
0091:             *
0092:             * <pre>
0093:             * ---+----+--------------------
0094:             * F1 | 17 | final state, no record
0095:             * F2 | 16 | final state, valid record
0096:             * E1 | 18 | premature end
0097:             * E2 | 19 | illegal character
0098:             * E3 | 20 | incomplete record
0099:             * E4 | 21 | unterminated string
0100:             * </pre>
0101:             */
0102:            private static final String c_final[] = { "OK", "noop",
0103:                    "premature end of record", "illegal character @",
0104:                    "incomplete record", "missing closing quote" };
0105:
0106:            /**
0107:             * Contains the state transition tables. The notes a through c mark
0108:             * similar states:
0109:             * <pre>
0110:             *      | EOS | lws |  =  | ""  | \\  | else|
0111:             * -----+-----+-----+-----+-----+-----+-----+--------------
0112:             *    0 | F1,-|  0,-|  E2 |  3,-|  E2 | 1,Sl| skip initial ws
0113:             * a  1 |  E3 | 2,Fl|  E2 |  E2 |  E2 | 1,Sl| LFN w/o quotes
0114:             *    2 |  E3 |  2,-|  E2 |  6,-|  E2 | 5,Sp| skip ws between LFN and PFN
0115:             * b  3 |  E4 | 3,Sl| 3,Sl| 2,Fl|  4,-| 3,Sl| LFN in quotes
0116:             * c  4 |  E4 | 3,Sl| 3,Sl| 3,Sl| 3,Sl| 3,Sl| LFN backslash escape
0117:             * -----+-----+-----+-----+-----+-----+-----+--------------
0118:             * a  5 |F2,Fp| 8,Fp|  E2 |  E2 |  E2 | 5,Sp| PFN w/o quotes
0119:             * b  6 |  E4 | 6,Sp| 6,Sp| 8,Fp|  7,-| 6,Sp| PFN in quotes
0120:             * c  7 |  E4 | 6,Sp| 6,Sp| 6,Sp| 6,Sp| 6,Sp| PFN backslash escape
0121:             *    8 | F2,-|  8,-|  E2 |  E2 |  E2 | 9,Sk| skip ws before attributes
0122:             *    9 |  E1 |  E2 |10,Fk|  E2 |  E2 | 9,Sk| attribute key
0123:             *   10 |  E1 |  E2 |  E2 | 12,-|  E2 |11,Sv| equals sign
0124:             * -----+-----+-----+-----+-----+-----+-----+--------------
0125:             * a 11 |F2,Fv| 8,Fv|  E2 |  E2 |  E2 |11,Sv| value w/o quotes
0126:             * b 12 |  E4 |12,Sv|12,Sv| 8,Fv| 13,-|12,Sv| value in quotes
0127:             * c 13 |  E4 |12,Sv|12,Sv|12,Sv|12,Sv|12,Sv| value backslash escape
0128:             * </pre>
0129:             */
0130:            private static final short c_state[][] = { { 17, 0, 19, 3, 19, 1 }, //  0
0131:                    { 20, 2, 19, 19, 19, 1 }, //  1
0132:                    { 20, 2, 19, 6, 19, 5 }, //  2
0133:                    { 21, 3, 3, 2, 4, 3 }, //  3
0134:                    { 21, 3, 3, 3, 3, 3 }, //  4
0135:
0136:                    { 16, 8, 19, 19, 19, 5 }, //  5
0137:                    { 21, 6, 6, 8, 7, 6 }, //  6
0138:                    { 21, 6, 6, 6, 6, 6 }, //  7
0139:                    { 16, 8, 19, 19, 19, 9 }, //  8
0140:                    { 18, 19, 10, 19, 19, 9 }, //  9
0141:                    { 18, 19, 19, 12, 19, 11 }, // 10
0142:
0143:                    { 16, 8, 19, 19, 19, 11 }, // 11
0144:                    { 21, 12, 12, 8, 13, 12 }, // 12
0145:                    { 21, 12, 12, 12, 12, 12 } }; // 13
0146:
0147:            /**
0148:             * Contains the actions to perform upon each state transition including
0149:             * transition into self state.
0150:             *
0151:             * <pre>
0152:             *    |   |
0153:             * ---+---+-------------------------------------------
0154:             *  - | 0 | no op
0155:             *  S*| 1 | append to sb
0156:             *  Fl| 2 | lfn := sb
0157:             *  Fp| 3 | pfn := sb
0158:             *  Fk| 4 | key := sb
0159:             *  Fv| 5 | value := sb
0160:             * </pre>
0161:             */
0162:            private static final short c_action[][] = { { 0, 0, 0, 0, 0, 1 }, //  0
0163:                    { 0, 2, 0, 0, 0, 1 }, //  1 a
0164:                    { 0, 0, 0, 0, 0, 1 }, //  2
0165:                    { 0, 1, 1, 2, 0, 1 }, //  3 b
0166:                    { 0, 1, 1, 1, 1, 1 }, //  4 c
0167:
0168:                    { 3, 3, 0, 0, 0, 1 }, //  5 a
0169:                    { 0, 1, 1, 3, 0, 1 }, //  6 b
0170:                    { 0, 1, 1, 1, 1, 1 }, //  7 c
0171:                    { 0, 0, 0, 0, 0, 1 }, //  8
0172:                    { 0, 0, 4, 0, 0, 1 }, //  9
0173:                    { 0, 0, 0, 0, 0, 1 }, // 10
0174:
0175:                    { 5, 5, 0, 0, 0, 1 }, // 11 a
0176:                    { 0, 1, 1, 5, 0, 1 }, // 12 b
0177:                    { 0, 1, 1, 1, 1, 1 } }; // 13 c
0178:
0179:            /**
0180:             * Parses a line from the file replica catalog
0181:             *
0182:             * @param line is the line to parse
0183:             * @param lineno is the line number of this line
0184:             * @return true if a valid element was generated
0185:             */
0186:            public boolean parse(String line, int lineno) {
0187:                char ch = ' ';
0188:                String lfn = null;
0189:                String pfn = null;
0190:                String key = null;
0191:                Map attr = new TreeMap();
0192:                short input, state = 0;
0193:                int i = 0;
0194:                StringBuffer sb = new StringBuffer();
0195:
0196:                while (state < 16) {
0197:                    if (line.length() <= i) {
0198:                        ch = ' ';
0199:                        input = 0;
0200:                    } // EOS
0201:                    else
0202:                        switch ((ch = line.charAt(i))) {
0203:                        case ' ':
0204:                            input = 1;
0205:                            break;
0206:                        case '\t':
0207:                            input = 1;
0208:                            break;
0209:                        case '=':
0210:                            input = 2;
0211:                            break;
0212:                        case '"':
0213:                            input = 3;
0214:                            break;
0215:                        case '\\':
0216:                            input = 4;
0217:                            break;
0218:                        default:
0219:                            input = 5;
0220:                            break;
0221:                        }
0222:                    i++;
0223:
0224:                    // perform action
0225:                    switch (c_action[state][input]) {
0226:                    case 0: // noop
0227:                        break;
0228:                    case 1: // append to sb
0229:                        sb.append(ch);
0230:                        break;
0231:                    case 2: // sb to lfn
0232:                        lfn = sb.toString();
0233:                        sb = new StringBuffer();
0234:                        break;
0235:                    case 3: // sb to pfn
0236:                        pfn = sb.toString();
0237:                        sb = new StringBuffer();
0238:                        break;
0239:                    case 4: // sb to key
0240:                        key = sb.toString();
0241:                        sb = new StringBuffer();
0242:                        break;
0243:                    case 5: // sb to value
0244:                        attr.put(key, sb.toString());
0245:                        sb = new StringBuffer();
0246:                        break;
0247:                    }
0248:
0249:                    // goto new state
0250:                    state = c_state[state][input];
0251:                }
0252:
0253:                if (state > 17) {
0254:                    // error report
0255:                    sb = new StringBuffer(i + 1);
0256:                    for (int j = 1; j < i; ++j)
0257:                        sb.append(' ');
0258:                    sb.append('^');
0259:
0260:                    // FIXME: log it somewhere
0261:                    System.err.println("While parsing line " + lineno + ": "
0262:                            + c_final[state - 16].replace('@', ch)
0263:                            + ", ignoring line");
0264:                    System.err.println(line);
0265:                    System.err.println(sb);
0266:                    return false;
0267:                } else {
0268:                    // valid entry
0269:                    if (state == 16)
0270:                        insert(lfn, new ReplicaCatalogEntry(pfn, attr));
0271:                    return true;
0272:                }
0273:            }
0274:
0275:            /**
0276:             * Reads the on-disk map file into memory.
0277:             *
0278:             * @param filename is the name of the file to read.
0279:             * @return true, if the in-memory data structures appear sound.
0280:             */
0281:            public boolean connect(String filename) {
0282:                // sanity check
0283:                if (filename == null)
0284:                    return false;
0285:                m_filename = filename;
0286:                m_lfn = new LinkedHashMap();
0287:
0288:                try {
0289:                    File f = new File(filename);
0290:                    if (f.exists()) {
0291:                        LineNumberReader lnr = new LineNumberReader(
0292:                                new FileReader(f));
0293:                        String line;
0294:                        while ((line = lnr.readLine()) != null) {
0295:                            if (line.length() == 0 || line.charAt(0) == '#')
0296:                                continue;
0297:                            parse(line, lnr.getLineNumber());
0298:                        }
0299:
0300:                        lnr.close();
0301:                    }
0302:                } catch (IOException ioe) {
0303:                    m_lfn = null;
0304:                    m_filename = null;
0305:                    throw new RuntimeException(ioe); // re-throw
0306:                }
0307:
0308:                return true;
0309:            }
0310:
0311:            /**
0312:             * Establishes a connection to the database from the properties.
0313:             * You will need to specify a "file" property to point to the
0314:             * location of the on-disk instance. If the property "quote" is
0315:             * set to a true value, LFNs and PFNs are always quoted. By default,
0316:             * and if false, LFNs and PFNs are only quoted as necessary.
0317:             *
0318:             * @param props is the property table with sufficient settings to
0319:             * establish a link with the database.
0320:             * @return true if connected, false if failed to connect.
0321:             *
0322:             * @throws Error subclasses for runtime errors in the class loader.
0323:             */
0324:            public boolean connect(Properties props) {
0325:                // quote mode
0326:                m_quote = Boolean.parse(props.getProperty("quote"));
0327:
0328:                if (props.containsKey("file"))
0329:                    return connect(props.getProperty("file"));
0330:                return false;
0331:            }
0332:
0333:            /**
0334:             * Quotes a string only if necessary. This methods first determines,
0335:             * if a strings requires quoting, because it contains whitespace, an
0336:             * equality sign, quotes, or a backslash. If not, the string is not
0337:             * quoted. If the input contains forbidden characters, it is placed
0338:             * into quotes and quote and backslash are backslash escaped.<p>
0339:             * However, if the property "quote" had a <code>true</code> value
0340:             * when connecting to the database, output will always be quoted.
0341:             *
0342:             * @param e is the Escape instance used to escape strings.
0343:             * @param s is the string that may require quoting
0344:             * @return either the original string, or a newly allocated instance
0345:             * to an escaped string.
0346:             */
0347:            public String quote(Escape e, String s) {
0348:                String result = null;
0349:
0350:                if (s == null || s.length() == 0) {
0351:                    // empty string short-cut
0352:                    result = (m_quote ? "\"\"" : s);
0353:                } else {
0354:                    // string has content
0355:                    boolean flag = m_quote;
0356:                    for (int i = 0; i < s.length() && !flag; ++i) {
0357:                        // Note: loop will never trigger, if m_quote is true
0358:                        char ch = s.charAt(i);
0359:                        flag = (ch == '"' || ch == '\\' || ch == '=' || Character
0360:                                .isWhitespace(ch));
0361:                    }
0362:
0363:                    result = (flag ? '"' + e.escape(s) + '"' : s);
0364:                }
0365:
0366:                // single point of exit
0367:                return result;
0368:            }
0369:
0370:            /**
0371:             * This operation will dump the in-memory representation back onto
0372:             * disk. The store operation is strict in what it produces. The LFN
0373:             * and PFN records are only quoted, if they require quotes, because
0374:             * they contain special characters. The attributes are <b>always</b>
0375:             * quoted and thus quote-escaped.
0376:             */
0377:            public void close() {
0378:                String newline = System.getProperty("line.separator", "\r\n");
0379:                Escape e = new Escape("\"\\", '\\');
0380:
0381:                // sanity check
0382:                if (m_lfn == null)
0383:                    return;
0384:
0385:                try {
0386:                    // open
0387:                    Writer out = new BufferedWriter(new FileWriter(m_filename));
0388:
0389:                    // write header
0390:                    out.write("# file-based replica catalog: "
0391:                            + Currently.iso8601(false, true, true, new Date()));
0392:                    out.write(newline);
0393:
0394:                    // write data
0395:                    for (Iterator i = m_lfn.keySet().iterator(); i.hasNext();) {
0396:                        String lfn = (String) i.next();
0397:                        Collection c = (Collection) m_lfn.get(lfn);
0398:                        if (c != null) {
0399:                            for (Iterator j = c.iterator(); j.hasNext();) {
0400:                                ReplicaCatalogEntry rce = (ReplicaCatalogEntry) j
0401:                                        .next();
0402:                                out.write(quote(e, lfn));
0403:                                out.write(' ');
0404:                                out.write(quote(e, rce.getPFN()));
0405:                                for (Iterator k = rce.getAttributeIterator(); k
0406:                                        .hasNext();) {
0407:                                    String key = (String) k.next();
0408:                                    String value = (String) rce
0409:                                            .getAttribute(key);
0410:                                    out.write(' ');
0411:                                    out.write(key);
0412:                                    out.write("=\"");
0413:                                    out.write(e.escape(value));
0414:                                    out.write('"');
0415:                                }
0416:
0417:                                // finalize record/line
0418:                                out.write(newline);
0419:                            }
0420:                        }
0421:                    }
0422:
0423:                    // close
0424:                    out.close();
0425:                } catch (IOException ioe) {
0426:                    // FIXME: blurt message somewhere sane
0427:                    System.err.println(ioe.getMessage());
0428:                } finally {
0429:                    m_lfn.clear();
0430:                    m_lfn = null;
0431:                    m_filename = null;
0432:                }
0433:            }
0434:
0435:            /**
0436:             * Predicate to check, if the connection with the catalog's
0437:             * implementation is still active. This helps determining, if it makes
0438:             * sense to call <code>close()</code>.
0439:             *
0440:             * @return true, if the implementation is disassociated, false otherwise.
0441:             * @see #close()
0442:             */
0443:            public boolean isClosed() {
0444:                return (m_lfn == null);
0445:            }
0446:
0447:            /**
0448:             * Retrieves the entry for a given filename and site handle from the
0449:             * replica catalog.
0450:             *
0451:             * @param lfn is the logical filename to obtain information for.
0452:             * @param handle is the resource handle to obtain entries for.
0453:             * @return the (first) matching physical filename, or
0454:             * <code>null</code> if no match was found.
0455:             */
0456:            public String lookup(String lfn, String handle) {
0457:                Collection c = (Collection) m_lfn.get(lfn);
0458:                if (c == null)
0459:                    return null;
0460:
0461:                for (Iterator i = c.iterator(); i.hasNext();) {
0462:                    ReplicaCatalogEntry rce = (ReplicaCatalogEntry) i.next();
0463:                    String pool = rce.getResourceHandle();
0464:                    if (pool == null && handle == null || pool != null
0465:                            && handle != null && pool.equals(handle))
0466:                        return rce.getPFN();
0467:                }
0468:                return null;
0469:            }
0470:
0471:            /**
0472:             * Retrieves all entries for a given LFN from the replica catalog.
0473:             * Each entry in the result set is a tuple of a PFN and all its
0474:             * attributes.
0475:             *
0476:             * @param lfn is the logical filename to obtain information for.
0477:             * @return a collection of replica catalog entries
0478:             * @see ReplicaCatalogEntry
0479:             */
0480:            public Collection lookup(String lfn) {
0481:                Collection c = (Collection) m_lfn.get(lfn);
0482:                if (c == null)
0483:                    return new ArrayList();
0484:                else
0485:                    return new ArrayList(c);
0486:            }
0487:
0488:            /**
0489:             * Retrieves all entries for a given LFN from the replica catalog.
0490:             * Each entry in the result set is just a PFN string. Duplicates
0491:             * are reduced through the set paradigm.
0492:             *
0493:             * @param lfn is the logical filename to obtain information for.
0494:             * @return a set of PFN strings
0495:             */
0496:            public Set lookupNoAttributes(String lfn) {
0497:                Set result = new TreeSet();
0498:                Collection c = (Collection) m_lfn.get(lfn);
0499:
0500:                if (c != null) {
0501:                    for (Iterator i = c.iterator(); i.hasNext();) {
0502:                        result.add(((ReplicaCatalogEntry) i.next()).getPFN());
0503:                    }
0504:                }
0505:
0506:                // done
0507:                return result;
0508:            }
0509:
0510:            /**
0511:             * Retrieves multiple entries for a given logical filename, up to the
0512:             * complete catalog. Retrieving full catalogs should be harmful, but
0513:             * may be helpful in an online display or portal.
0514:             *
0515:             * @param lfns is a set of logical filename strings to look up.
0516:             * @return a map indexed by the LFN. Each value is a collection
0517:             * of replica catalog entries for the LFN.
0518:             * @see org.griphyn.common.catalog.ReplicaCatalogEntry
0519:             */
0520:            public Map lookup(Set lfns) {
0521:                Map result = new HashMap();
0522:                if (lfns == null || lfns.size() == 0)
0523:                    return result;
0524:
0525:                for (Iterator i = lfns.iterator(); i.hasNext();) {
0526:                    String lfn = (String) i.next();
0527:                    Collection c = (Collection) m_lfn.get(lfn);
0528:                    if (c == null)
0529:                        result.put(lfn, new ArrayList());
0530:                    else
0531:                        result.put(lfn, new ArrayList(c));
0532:                }
0533:
0534:                // done
0535:                return result;
0536:            }
0537:
0538:            /**
0539:             * Retrieves multiple entries for a given logical filename, up to the
0540:             * complete catalog. Retrieving full catalogs should be harmful, but
0541:             * may be helpful in an online display or portal.
0542:             *
0543:             * @param lfns is a set of logical filename strings to look up.
0544:             * @return a map indexed by the LFN. Each value is a set
0545:             * of PFN strings.
0546:             */
0547:            public Map lookupNoAttributes(Set lfns) {
0548:                Map result = new HashMap();
0549:                if (lfns == null || lfns.size() == 0)
0550:                    return result;
0551:
0552:                for (Iterator i = lfns.iterator(); i.hasNext();) {
0553:                    Set value = new TreeSet();
0554:                    String lfn = (String) i.next();
0555:                    Collection c = (Collection) m_lfn.get(lfn);
0556:                    if (c != null) {
0557:                        for (Iterator j = c.iterator(); j.hasNext();) {
0558:                            value
0559:                                    .add(((ReplicaCatalogEntry) j.next())
0560:                                            .getPFN());
0561:                        }
0562:                    }
0563:                    result.put(lfn, value);
0564:                }
0565:
0566:                // done
0567:                return result;
0568:            }
0569:
0570:            /**
0571:             * Retrieves multiple entries for a given logical filename, up to the
0572:             * complete catalog. Retrieving full catalogs should be harmful, but
0573:             * may be helpful in online display or portal.<p>
0574:             *
0575:             * @param lfns is a set of logical filename strings to look up.
0576:             * @param handle is the resource handle, restricting the LFNs.
0577:             * @return a map indexed by the LFN. Each value is a collection
0578:             * of replica catalog entries (all attributes).
0579:             * @see ReplicaCatalogEntry
0580:             */
0581:            public Map lookup(Set lfns, String handle) {
0582:                Map result = new HashMap();
0583:                if (lfns == null || lfns.size() == 0)
0584:                    return result;
0585:
0586:                for (Iterator i = lfns.iterator(); i.hasNext();) {
0587:                    String lfn = (String) i.next();
0588:                    Collection c = (Collection) m_lfn.get(lfn);
0589:                    if (c != null) {
0590:                        List value = new ArrayList();
0591:
0592:                        for (Iterator j = c.iterator(); j.hasNext();) {
0593:                            ReplicaCatalogEntry rce = (ReplicaCatalogEntry) j
0594:                                    .next();
0595:                            String pool = rce.getResourceHandle();
0596:                            if (pool == null && handle == null || pool != null
0597:                                    && handle != null && pool.equals(handle))
0598:                                value.add(rce);
0599:                        }
0600:
0601:                        // only put found LFNs into result
0602:                        result.put(lfn, value);
0603:                    }
0604:                }
0605:
0606:                // done
0607:                return result;
0608:            }
0609:
0610:            /**
0611:             * Retrieves multiple entries for a given logical filename, up to the
0612:             * complete catalog. Retrieving full catalogs should be harmful, but
0613:             * may be helpful in online display or portal.<p>
0614:             *
0615:             * @param lfns is a set of logical filename strings to look up.
0616:             * @param handle is the resource handle, restricting the LFNs.
0617:             * @return a map indexed by the LFN. Each value is a set of
0618:             * physical filenames.
0619:             */
0620:            public Map lookupNoAttributes(Set lfns, String handle) {
0621:                Map result = new HashMap();
0622:                if (lfns == null || lfns.size() == 0)
0623:                    return result;
0624:
0625:                for (Iterator i = lfns.iterator(); i.hasNext();) {
0626:                    String lfn = (String) i.next();
0627:                    Collection c = (Collection) m_lfn.get(lfn);
0628:                    if (c != null) {
0629:                        List value = new ArrayList();
0630:
0631:                        for (Iterator j = c.iterator(); j.hasNext();) {
0632:                            ReplicaCatalogEntry rce = (ReplicaCatalogEntry) j
0633:                                    .next();
0634:                            String pool = rce.getResourceHandle();
0635:                            if (pool == null && handle == null || pool != null
0636:                                    && handle != null && pool.equals(handle))
0637:                                value.add(rce.getPFN());
0638:                        }
0639:
0640:                        // only put found LFNs into result
0641:                        result.put(lfn, value);
0642:                    }
0643:                }
0644:
0645:                // done
0646:                return result;
0647:            }
0648:
0649:            /**
0650:             * Retrieves multiple entries for a given logical filename, up to the
0651:             * complete catalog. Retrieving full catalogs should be harmful, but
0652:             * may be helpful in online display or portal.
0653:             *
0654:             * @param constraints is mapping of keys 'lfn', 'pfn', or any
0655:             * attribute name, e.g. the resource handle 'pool', to a string that
0656:             * has some meaning to the implementing system. This can be a SQL
0657:             * wildcard for queries, or a regular expression for Java-based memory
0658:             * collections. Unknown keys are ignored. Using an empty map requests
0659:             * the complete catalog.
0660:             * @return a map indexed by the LFN. Each value is a collection
0661:             * of replica catalog entries.
0662:             * @see ReplicaCatalogEntry
0663:             */
0664:            public Map lookup(Map constraints) {
0665:                if (constraints == null || constraints.size() == 0) {
0666:                    // return everything
0667:                    return Collections.unmodifiableMap(m_lfn);
0668:
0669:                } else if (constraints.size() == 1
0670:                        && constraints.containsKey("lfn")) {
0671:                    // return matching LFNs
0672:                    Pattern p = Pattern
0673:                            .compile((String) constraints.get("lfn"));
0674:                    Map result = new HashMap();
0675:                    for (Iterator i = m_lfn.entrySet().iterator(); i.hasNext();) {
0676:                        Map.Entry e = (Map.Entry) i.next();
0677:                        String lfn = (String) e.getKey();
0678:                        if (p.matcher(lfn).matches())
0679:                            result.put(lfn, e.getValue());
0680:                    }
0681:                    return result;
0682:
0683:                } else {
0684:                    // FIXME: Implement!
0685:                    throw new RuntimeException("method not implemented");
0686:                }
0687:            }
0688:
0689:            /**
0690:             * Lists all logical filenames in the catalog.
0691:             *
0692:             * @return A set of all logical filenames known to the catalog.
0693:             */
0694:            public Set list() {
0695:                return new TreeSet(m_lfn.keySet());
0696:            }
0697:
0698:            /**
0699:             * Lists a subset of all logical filenames in the catalog.
0700:             *
0701:             * @param constraint is a constraint for the logical filename only. It
0702:             * is a string that has some meaning to the implementing system. This
0703:             * can be a SQL wildcard for queries, or a regular expression for
0704:             * Java-based memory collections.
0705:             * @return A set of logical filenames that match. The set may be empty
0706:             */
0707:            public Set list(String constraint) {
0708:                Set result = new TreeSet();
0709:                Pattern p = Pattern.compile(constraint);
0710:
0711:                for (Iterator i = m_lfn.keySet().iterator(); i.hasNext();) {
0712:                    String lfn = (String) i.next();
0713:                    if (p.matcher(lfn).matches())
0714:                        result.add(lfn);
0715:                }
0716:
0717:                // done
0718:                return result;
0719:            }
0720:
0721:            /**
0722:             * Inserts a new mapping into the replica catalog. Any existing
0723:             * mapping of the same LFN and PFN will be replaced, including all its
0724:             * attributes.
0725:             *
0726:             * @param lfn is the logical filename under which to book the entry.
0727:             * @param tuple is the physical filename and associated PFN attributes.
0728:             *
0729:             * @return number of insertions, should always be 1. On failure,
0730:             * throw an exception, don't use zero.
0731:             */
0732:            public int insert(String lfn, ReplicaCatalogEntry tuple) {
0733:                if (lfn == null || tuple == null)
0734:                    throw new NullPointerException();
0735:
0736:                Collection c = null;
0737:                if (m_lfn.containsKey(lfn)) {
0738:                    boolean seen = false;
0739:                    String pfn = tuple.getPFN();
0740:                    c = (Collection) m_lfn.get(lfn);
0741:                    for (Iterator i = c.iterator(); i.hasNext() && !seen;) {
0742:                        ReplicaCatalogEntry rce = (ReplicaCatalogEntry) i
0743:                                .next();
0744:                        if ((seen = pfn.equals(rce.getPFN()))) {
0745:                            try {
0746:                                i.remove();
0747:                            } catch (UnsupportedOperationException uoe) {
0748:                                return 0;
0749:                            }
0750:                        }
0751:                    }
0752:                } else {
0753:                    c = new ArrayList();
0754:                    m_lfn.put(lfn, c);
0755:                }
0756:                c.add(tuple);
0757:
0758:                return 1;
0759:            }
0760:
0761:            /**
0762:             * Inserts a new mapping into the replica catalog. This is a
0763:             * convenience function exposing the resource handle. Internally, the
0764:             * <code>ReplicaCatalogEntry</code> element will be contructed, and
0765:             * passed to the appropriate insert function.
0766:             *
0767:             * @param lfn is the logical filename under which to book the entry.
0768:             * @param pfn is the physical filename associated with it.
0769:             * @param handle is a resource handle where the PFN resides.
0770:             * @return number of insertions, should always be 1. On failure,
0771:             * throw an exception, don't use zero.
0772:             * @see #insert( String, ReplicaCatalogEntry )
0773:             * @see ReplicaCatalogEntry
0774:             */
0775:            public int insert(String lfn, String pfn, String handle) {
0776:                if (lfn == null || pfn == null || handle == null)
0777:                    throw new NullPointerException();
0778:                return insert(lfn, new ReplicaCatalogEntry(pfn, handle));
0779:            }
0780:
0781:            /**
0782:             * Inserts multiple mappings into the replica catalog. The input is a
0783:             * map indexed by the LFN. The value for each LFN key is a collection
0784:             * of replica catalog entries. Note that this operation will replace
0785:             * existing entries.
0786:             *
0787:             * @param x is a map from logical filename string to list of replica
0788:             * catalog entries.
0789:             * @return the number of insertions.
0790:             * @see org.griphyn.common.catalog.ReplicaCatalogEntry
0791:             */
0792:            public int insert(Map x) {
0793:                int result = 0;
0794:
0795:                // shortcut sanity
0796:                if (x == null || x.size() == 0)
0797:                    return result;
0798:
0799:                for (Iterator i = x.keySet().iterator(); i.hasNext();) {
0800:                    String lfn = (String) i.next();
0801:                    Object val = x.get(lfn);
0802:                    if (val instanceof  ReplicaCatalogEntry) {
0803:                        // permit misconfigured clients
0804:                        result += insert(lfn, (ReplicaCatalogEntry) val);
0805:                    } else {
0806:                        // this is how it should have been
0807:                        for (Iterator j = ((Collection) val).iterator(); j
0808:                                .hasNext();) {
0809:                            ReplicaCatalogEntry rce = (ReplicaCatalogEntry) j
0810:                                    .next();
0811:                            result += insert(lfn, rce);
0812:                        }
0813:                    }
0814:                }
0815:
0816:                return result;
0817:            }
0818:
0819:            /**
0820:             * Deletes a specific mapping from the replica catalog. We don't care
0821:             * about the resource handle. More than one entry could theoretically
0822:             * be removed. Upon removal of an entry, all attributes associated
0823:             * with the PFN also evaporate (cascading deletion).
0824:             *
0825:             * @param lfn is the logical filename in the tuple.
0826:             * @param pfn is the physical filename in the tuple.
0827:             * @return the number of removed entries.
0828:             */
0829:            public int delete(String lfn, String pfn) {
0830:                int result = 0;
0831:                if (lfn == null || pfn == null)
0832:                    return result;
0833:
0834:                Collection c = (Collection) m_lfn.get(lfn);
0835:                if (c == null)
0836:                    return result;
0837:
0838:                List l = new ArrayList();
0839:                for (Iterator i = c.iterator(); i.hasNext();) {
0840:                    ReplicaCatalogEntry rce = (ReplicaCatalogEntry) i.next();
0841:                    if (!rce.getPFN().equals(pfn))
0842:                        l.add(rce);
0843:                }
0844:
0845:                // anything removed?
0846:                if (l.size() != c.size()) {
0847:                    result = c.size() - l.size();
0848:                    m_lfn.put(lfn, l);
0849:                }
0850:
0851:                // done
0852:                return result;
0853:            }
0854:
0855:            /**
0856:             * Deletes multiple mappings into the replica catalog. The input is a
0857:             * map indexed by the LFN. The value for each LFN key is a collection
0858:             * of replica catalog entries. On setting matchAttributes to false, all entries
0859:             * having matching lfn pfn mapping to an entry in the Map are deleted.
0860:             * However, upon removal of an entry, all attributes associated with the pfn
0861:             * also evaporate (cascaded deletion).
0862:             *
0863:             * @param x                is a map from logical filename string to list of
0864:             *                         replica catalog entries.
0865:             * @param matchAttributes  whether mapping should be deleted only if all
0866:             *                         attributes match.
0867:             *
0868:             * @return the number of deletions.
0869:             * @see ReplicaCatalogEntry
0870:             */
0871:            public int delete(Map x, boolean matchAttributes) {
0872:                throw new java.lang.UnsupportedOperationException(
0873:                        "delete(Map,boolean) not implemented as yet");
0874:            }
0875:
0876:            /**
0877:             * Attempts to see, if all keys in the partial replica catalog entry are
0878:             * contained in the full replica catalog entry.
0879:             *
0880:             * @param full is the full entry to check against.
0881:             * @param part is the partial entry to check with.
0882:             * @return true, if contained, false if not contained.
0883:             */
0884:            private boolean matchMe(ReplicaCatalogEntry full,
0885:                    ReplicaCatalogEntry part) {
0886:                if (full.getPFN().equals(part.getPFN())) {
0887:                    for (Iterator i = part.getAttributeIterator(); i.hasNext();) {
0888:                        if (!full.hasAttribute((String) i.next()))
0889:                            return false;
0890:                    }
0891:                    return true;
0892:                } else {
0893:                    return false;
0894:                }
0895:            }
0896:
0897:            /**
0898:             * Deletes a very specific mapping from the replica catalog. The LFN
0899:             * must be matches, the PFN, and all PFN attributes specified in the
0900:             * replica catalog entry. More than one entry could theoretically be
0901:             * removed. Upon removal of an entry, all attributes associated with
0902:             * the PFN also evaporate (cascading deletion).
0903:             *
0904:             * @param lfn is the logical filename in the tuple.
0905:             * @param tuple is a description of the PFN and its attributes.
0906:             * @return the number of removed entries, either 0 or 1.
0907:             */
0908:            public int delete(String lfn, ReplicaCatalogEntry tuple) {
0909:                int result = 0;
0910:                if (lfn == null || tuple == null)
0911:                    return result;
0912:
0913:                Collection c = (Collection) m_lfn.get(lfn);
0914:                if (c == null)
0915:                    return result;
0916:
0917:                List l = new ArrayList();
0918:                for (Iterator i = c.iterator(); i.hasNext();) {
0919:                    ReplicaCatalogEntry rce = (ReplicaCatalogEntry) i.next();
0920:                    if (!matchMe(rce, tuple))
0921:                        l.add(rce);
0922:                }
0923:
0924:                // anything removed?
0925:                if (l.size() != c.size()) {
0926:                    result = c.size() - l.size();
0927:                    m_lfn.put(lfn, l);
0928:                }
0929:
0930:                // done
0931:                return result;
0932:            }
0933:
0934:            /**
0935:             * Looks for a match of an attribute value in a replica catalog
0936:             * entry.
0937:             *
0938:             * @param rce is the replica catalog entry
0939:             * @param name is the attribute key to match
0940:             * @param value is the value to match against
0941:             * @return true, if a match was found.
0942:             */
0943:            private boolean hasMatchingAttr(ReplicaCatalogEntry rce,
0944:                    String name, Object value) {
0945:                if (rce.hasAttribute(name))
0946:                    return rce.getAttribute(name).equals(value);
0947:                else
0948:                    return value == null;
0949:            }
0950:
0951:            /**
0952:             * Deletes all PFN entries for a given LFN from the replica catalog
0953:             * where the PFN attribute is found, and matches exactly the object
0954:             * value. This method may be useful to remove all replica entries that
0955:             * have a certain MD5 sum associated with them. It may also be harmful
0956:             * overkill.
0957:             *
0958:             * @param lfn is the logical filename to look for.
0959:             * @param name is the PFN attribute name to look for.
0960:             * @param value is an exact match of the attribute value to match.
0961:             * @return the number of removed entries.
0962:             */
0963:            public int delete(String lfn, String name, Object value) {
0964:                int result = 0;
0965:                if (lfn == null || name == null)
0966:                    return result;
0967:
0968:                Collection c = (Collection) m_lfn.get(lfn);
0969:                if (c == null)
0970:                    return result;
0971:
0972:                List l = new ArrayList();
0973:                for (Iterator i = c.iterator(); i.hasNext();) {
0974:                    ReplicaCatalogEntry rce = (ReplicaCatalogEntry) i.next();
0975:                    if (!hasMatchingAttr(rce, name, value))
0976:                        l.add(rce);
0977:                }
0978:
0979:                // anything removed?
0980:                if (l.size() != c.size()) {
0981:                    result = c.size() - l.size();
0982:                    m_lfn.put(lfn, l);
0983:                }
0984:
0985:                // done
0986:                return result;
0987:            }
0988:
0989:            /**
0990:             * Deletes all PFN entries for a given LFN from the replica catalog
0991:             * where the resource handle is found. Karan requested this
0992:             * convenience method, which can be coded like
0993:             * <pre>
0994:             *  delete( lfn, RESOURCE_HANDLE, handle )
0995:             * </pre>
0996:             *
0997:             * @param lfn is the logical filename to look for.
0998:             * @param handle is the resource handle
0999:             * @return the number of entries removed.
1000:             */
1001:            public int deleteByResource(String lfn, String handle) {
1002:                return delete(lfn, ReplicaCatalogEntry.RESOURCE_HANDLE, handle);
1003:            }
1004:
1005:            /**
1006:             * Removes all mappings for an LFN from the replica catalog.
1007:             *
1008:             * @param lfn is the logical filename to remove all mappings for.
1009:             * @return the number of removed entries.
1010:             */
1011:            public int remove(String lfn) {
1012:                Collection c = (Collection) m_lfn.remove(lfn);
1013:                if (c == null)
1014:                    return 0;
1015:                else
1016:                    return c.size();
1017:            }
1018:
1019:            /**
1020:             * Removes all mappings for a set of LFNs.
1021:             *
1022:             * @param lfns is a set of logical filename to remove all mappings for.
1023:             * @return the number of removed entries.
1024:             * @see #remove( String )
1025:             */
1026:            public int remove(Set lfns) {
1027:                int result = 0;
1028:
1029:                // sanity checks
1030:                if (lfns == null || lfns.size() == 0)
1031:                    return result;
1032:
1033:                for (Iterator i = lfns.iterator(); i.hasNext();) {
1034:                    String lfn = (String) i.next();
1035:                    result += remove(lfn);
1036:                }
1037:
1038:                // done
1039:                return result;
1040:            }
1041:
1042:            /**
1043:             * Removes all entries from the replica catalog where the PFN attribute
1044:             * is found, and matches exactly the object value.
1045:             *
1046:             * @param name is the PFN attribute key to look for.
1047:             * @param value is an exact match of the attribute value to match.
1048:             * @return the number of removed entries.
1049:             */
1050:            public int removeByAttribute(String name, Object value) {
1051:                int result = 0;
1052:
1053:                for (Iterator i = m_lfn.keySet().iterator(); i.hasNext();) {
1054:                    String lfn = (String) i.next();
1055:                    Collection c = (Collection) m_lfn.get(lfn);
1056:                    if (c != null) {
1057:                        List l = new ArrayList();
1058:                        for (Iterator j = c.iterator(); j.hasNext();) {
1059:                            ReplicaCatalogEntry rce = (ReplicaCatalogEntry) j
1060:                                    .next();
1061:                            if (!hasMatchingAttr(rce, name, value))
1062:                                l.add(rce);
1063:                        }
1064:                        if (l.size() != c.size()) {
1065:                            result += (c.size() - l.size());
1066:                            m_lfn.put(lfn, l);
1067:                        }
1068:                    }
1069:                }
1070:
1071:                // done
1072:                return result;
1073:            }
1074:
1075:            /**
1076:             * Removes all entries associated with a particular resource handle.
1077:             * This is useful, if a site goes offline. It is a convenience method,
1078:             * which calls the generic <code>removeByAttribute</code> method.
1079:             *
1080:             * @param handle is the site handle to remove all entries for.
1081:             * @return the number of removed entries.
1082:             * @see #removeByAttribute( String, Object )
1083:             */
1084:            public int removeByAttribute(String handle) {
1085:                return removeByAttribute(ReplicaCatalogEntry.RESOURCE_HANDLE,
1086:                        handle);
1087:            }
1088:
1089:            /**
1090:             * Removes everything. Use with caution!
1091:             *
1092:             * @return the number of removed entries.
1093:             */
1094:            public int clear() {
1095:                int result = m_lfn.size();
1096:                m_lfn.clear();
1097:                return result;
1098:            }
1099:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.