Source Code Cross Referenced for ClassArgParser.java in  » Database-ORM » openjpa » org » apache » openjpa » lib » meta » 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 » Database ORM » openjpa » org.apache.openjpa.lib.meta 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one
003:         * or more contributor license agreements.  See the NOTICE file
004:         * distributed with this work for additional information
005:         * regarding copyright ownership.  The ASF licenses this file
006:         * to you under the Apache License, Version 2.0 (the
007:         * "License"); you may not use this file except in compliance
008:         * with the License.  You may obtain a copy of the License at
009:         *
010:         * http://www.apache.org/licenses/LICENSE-2.0
011:         *
012:         * Unless required by applicable law or agreed to in writing,
013:         * software distributed under the License is distributed on an
014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015:         * KIND, either express or implied.  See the License for the
016:         * specific language governing permissions and limitations
017:         * under the License.    
018:         */
019:        package org.apache.openjpa.lib.meta;
020:
021:        import java.io.BufferedReader;
022:        import java.io.File;
023:        import java.io.FileInputStream;
024:        import java.io.FileNotFoundException;
025:        import java.io.FileReader;
026:        import java.io.IOException;
027:        import java.io.InputStream;
028:        import java.io.InputStreamReader;
029:        import java.io.Reader;
030:        import java.security.AccessController;
031:        import java.security.PrivilegedActionException;
032:        import java.util.ArrayList;
033:        import java.util.Collection;
034:        import java.util.Collections;
035:        import java.util.HashMap;
036:        import java.util.Iterator;
037:        import java.util.List;
038:        import java.util.Map;
039:
040:        import org.apache.commons.lang.exception.NestableRuntimeException;
041:        import org.apache.openjpa.lib.util.Files;
042:        import org.apache.openjpa.lib.util.J2DoPrivHelper;
043:        import org.apache.openjpa.lib.util.Localizer;
044:        import serp.bytecode.lowlevel.ConstantPoolTable;
045:        import serp.util.Strings;
046:
047:        /**
048:         * Parser used to resolve arguments into java classes.
049:         * Interprets command-line args as either class names, .class files or
050:         * resources, .java files or resources, or metadata files or resources
051:         * conforming to the common format defined by {@link CFMetaDataParser}.
052:         * Transforms the information in these args into {@link Class} instances.
053:         * Note that when parsing .java files, only the main class in the file
054:         * is detected. Other classes defined in the file, such as inner classes,
055:         * are not added to the returned classes list.
056:         *
057:         * @author Abe White
058:         * @nojavadoc
059:         */
060:        public class ClassArgParser {
061:
062:            private static final int TOKEN_EOF = -1;
063:            private static final int TOKEN_NONE = 0;
064:            private static final int TOKEN_PACKAGE = 1;
065:            private static final int TOKEN_CLASS = 2;
066:            private static final int TOKEN_PACKAGE_NOATTR = 3;
067:            private static final int TOKEN_CLASS_NOATTR = 4;
068:
069:            private static final Localizer _loc = Localizer
070:                    .forPackage(ClassArgParser.class);
071:
072:            private ClassLoader _loader = null;
073:            private char[] _packageAttr = "name".toCharArray();
074:            private char[] _classAttr = "name".toCharArray();
075:            private char[][] _beginElements = { { 'p' }, { 'c' } };
076:            private char[][] _endElements = { "ackage".toCharArray(),
077:                    "lass".toCharArray() };
078:
079:            /**
080:             * The class loader with which to load parsed classes.
081:             */
082:            public ClassLoader getClassLoader() {
083:                return _loader;
084:            }
085:
086:            /**
087:             * The class loader with which to load parsed classes.
088:             */
089:            public void setClassLoader(ClassLoader loader) {
090:                _loader = loader;
091:            }
092:
093:            /**
094:             * Set the the relevant metadata file structure so that metadata files
095:             * containing class names can be parsed. Null attribute names indicate
096:             * that the text content of the element contains the data.
097:             */
098:            public void setMetaDataStructure(String packageElementName,
099:                    String packageAttributeName, String[] classElementNames,
100:                    String classAttributeName) {
101:                // calculate how many chars deep we have to go to identify each element
102:                // name as unique.  this is extremely inefficient for large N, but
103:                // should never be called for more than a few elements
104:                char[] buf = new char[classElementNames.length + 1];
105:                int charIdx = 0;
106:                for (; true; charIdx++) {
107:                    for (int i = 0; i < buf.length; i++) {
108:                        if (i == 0) {
109:                            if (charIdx == packageElementName.length())
110:                                throw new UnsupportedOperationException(_loc
111:                                        .get("cant-diff-elems").getMessage());
112:                            buf[i] = packageElementName.charAt(charIdx);
113:                        } else {
114:                            if (charIdx == classElementNames[i - 1].length())
115:                                throw new UnsupportedOperationException(_loc
116:                                        .get("cant-diff-elems").getMessage());
117:                            buf[i] = classElementNames[i - 1].charAt(charIdx);
118:                        }
119:                    }
120:                    if (charsUnique(buf))
121:                        break;
122:                }
123:
124:                _packageAttr = (packageAttributeName == null) ? null
125:                        : packageAttributeName.toCharArray();
126:                _classAttr = (classAttributeName == null) ? null
127:                        : classAttributeName.toCharArray();
128:                _beginElements = new char[classElementNames.length + 1][];
129:                _endElements = new char[classElementNames.length + 1][];
130:                _beginElements[0] = packageElementName
131:                        .substring(0, charIdx + 1).toCharArray();
132:                _endElements[0] = packageElementName.substring(charIdx + 1)
133:                        .toCharArray();
134:                for (int i = 0; i < classElementNames.length; i++) {
135:                    _beginElements[i + 1] = classElementNames[i].substring(0,
136:                            charIdx + 1).toCharArray();
137:                    _endElements[i + 1] = classElementNames[i].substring(
138:                            charIdx + 1).toCharArray();
139:                }
140:            }
141:
142:            /**
143:             * Return true if all characters in given buffer are unique.
144:             */
145:            private static boolean charsUnique(char[] buf) {
146:                for (int i = buf.length - 1; i >= 0; i--)
147:                    for (int j = 0; j < i; j++)
148:                        if (buf[j] == buf[i])
149:                            return false;
150:                return true;
151:            }
152:
153:            /**
154:             * Return the {@link Class} representation of the class(es) named in the
155:             * given arg.
156:             *
157:             * @param arg a class name, .java file, .class file, or metadata
158:             * file naming the type(s) to act on
159:             */
160:            public Class[] parseTypes(String arg) {
161:                String[] names = parseTypeNames(arg);
162:                Class[] objs = new Class[names.length];
163:                for (int i = 0; i < names.length; i++)
164:                    objs[i] = Strings.toClass(names[i], _loader);
165:                return objs;
166:            }
167:
168:            /**
169:             * Return the {@link Class} representation of the class(es) named in the
170:             * given metadatas.
171:             */
172:            public Class[] parseTypes(MetaDataIterator itr) {
173:                String[] names = parseTypeNames(itr);
174:                Class[] objs = new Class[names.length];
175:                for (int i = 0; i < names.length; i++)
176:                    objs[i] = Strings.toClass(names[i], _loader);
177:                return objs;
178:            }
179:
180:            /**
181:             * Return a mapping of each metadata resource to an array of its
182:             * contained classes.
183:             */
184:            public Map mapTypes(MetaDataIterator itr) {
185:                Map map = mapTypeNames(itr);
186:                Map.Entry entry;
187:                String[] names;
188:                Class[] objs;
189:                for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
190:                    entry = (Map.Entry) i.next();
191:                    names = (String[]) entry.getValue();
192:                    objs = new Class[names.length];
193:                    for (int j = 0; j < names.length; j++)
194:                        objs[j] = Strings.toClass(names[j], _loader);
195:                    entry.setValue(objs);
196:                }
197:                return map;
198:            }
199:
200:            /**
201:             * Return the names of the class(es) from the given arg.
202:             *
203:             * @param arg a class name, .java file, .class file, or metadata
204:             * file naming the type(s) to act on
205:             * @throws IllegalArgumentException with appropriate message on error
206:             */
207:            public String[] parseTypeNames(String arg) {
208:                if (arg == null)
209:                    return new String[0];
210:
211:                try {
212:                    File file = Files.getFile(arg, _loader);
213:                    if (arg.endsWith(".class"))
214:                        return new String[] { getFromClassFile(file) };
215:                    if (arg.endsWith(".java"))
216:                        return new String[] { getFromJavaFile(file) };
217:                    if (((Boolean) AccessController.doPrivileged(J2DoPrivHelper
218:                            .existsAction(file))).booleanValue()) {
219:                        Collection col = getFromMetaDataFile(file);
220:                        return (String[]) col.toArray(new String[col.size()]);
221:                    }
222:                } catch (Exception e) {
223:                    throw new NestableRuntimeException(_loc.get("class-arg",
224:                            arg).getMessage(), e);
225:                }
226:
227:                // must be a class name
228:                return new String[] { arg };
229:            }
230:
231:            /**
232:             * Return the names of the class(es) from the given metadatas.
233:             */
234:            public String[] parseTypeNames(MetaDataIterator itr) {
235:                if (itr == null)
236:                    return new String[0];
237:
238:                List names = new ArrayList();
239:                Object source = null;
240:                try {
241:                    while (itr.hasNext()) {
242:                        source = itr.next();
243:                        appendTypeNames(source, itr.getInputStream(), names);
244:                    }
245:                } catch (Exception e) {
246:                    throw new NestableRuntimeException(_loc.get("class-arg",
247:                            source).getMessage(), e);
248:                }
249:                return (String[]) names.toArray(new String[names.size()]);
250:            }
251:
252:            /**
253:             * Parse the names in the given metadata iterator stream, closing the
254:             * stream on completion.
255:             */
256:            private void appendTypeNames(Object source, InputStream in,
257:                    List names) throws IOException {
258:                try {
259:                    if (source.toString().endsWith(".class"))
260:                        names.add(getFromClass(in));
261:                    names.addAll(getFromMetaData(new InputStreamReader(in)));
262:                } finally {
263:                    try {
264:                        in.close();
265:                    } catch (IOException ioe) {
266:                    }
267:                }
268:            }
269:
270:            /**
271:             * Return a mapping of each metadata resource to an array of its contained
272:             * class names.
273:             */
274:            public Map mapTypeNames(MetaDataIterator itr) {
275:                if (itr == null)
276:                    return Collections.EMPTY_MAP;
277:
278:                Map map = new HashMap();
279:                Object source = null;
280:                List names = new ArrayList();
281:                try {
282:                    while (itr.hasNext()) {
283:                        source = itr.next();
284:                        appendTypeNames(source, itr.getInputStream(), names);
285:                        if (!names.isEmpty())
286:                            map.put(source, (String[]) names
287:                                    .toArray(new String[names.size()]));
288:                        names.clear();
289:                    }
290:                } catch (Exception e) {
291:                    throw new NestableRuntimeException(_loc.get("class-arg",
292:                            source).getMessage(), e);
293:                }
294:                return map;
295:            }
296:
297:            /**
298:             * Returns the class named in the given .class file.
299:             */
300:            private String getFromClassFile(File file) throws IOException {
301:                FileInputStream fin = null;
302:                try {
303:                    fin = (FileInputStream) AccessController
304:                            .doPrivileged(J2DoPrivHelper
305:                                    .newFileInputStreamAction(file));
306:                    return getFromClass(fin);
307:                } catch (PrivilegedActionException pae) {
308:                    throw (FileNotFoundException) pae.getException();
309:                } finally {
310:                    if (fin != null)
311:                        try {
312:                            fin.close();
313:                        } catch (IOException ioe) {
314:                        }
315:                }
316:            }
317:
318:            /**
319:             * Returns the class name in the given .class bytecode.
320:             */
321:            private String getFromClass(InputStream in) throws IOException {
322:                ConstantPoolTable table = new ConstantPoolTable(in);
323:                int idx = table.getEndIndex();
324:                idx += 2; // access flags
325:                int clsEntry = table.readUnsignedShort(idx);
326:                int utfEntry = table.readUnsignedShort(table.get(clsEntry));
327:                return table.readString(table.get(utfEntry)).replace('/', '.');
328:            }
329:
330:            /**
331:             * Returns the class named in the given .java file.
332:             */
333:            private String getFromJavaFile(File file) throws IOException {
334:                BufferedReader in = null;
335:                try {
336:                    // find the line with the package declaration
337:                    in = new BufferedReader(new FileReader(file));
338:                    String line;
339:                    StringBuffer pack = null;
340:                    while ((line = in.readLine()) != null) {
341:                        line = line.trim();
342:                        if (line.startsWith("package ")) {
343:                            line = line.substring(8).trim();
344:
345:                            // strip off anything beyond the package declaration
346:                            pack = new StringBuffer();
347:                            for (int i = 0; i < line.length(); i++) {
348:                                if (Character.isJavaIdentifierPart(line
349:                                        .charAt(i))
350:                                        || line.charAt(i) == '.')
351:                                    pack.append(line.charAt(i));
352:                                else
353:                                    break;
354:                            }
355:                            break;
356:                        }
357:                    }
358:
359:                    // strip '.java'
360:                    String clsName = file.getName();
361:                    clsName = clsName.substring(0, clsName.length() - 5);
362:
363:                    // prefix with package
364:                    if (pack != null && pack.length() > 0)
365:                        clsName = pack + "." + clsName;
366:
367:                    return clsName;
368:                } finally {
369:                    if (in != null)
370:                        try {
371:                            in.close();
372:                        } catch (IOException ioe) {
373:                        }
374:                }
375:            }
376:
377:            /**
378:             * Returns the classes named in the given common format metadata file.
379:             */
380:            private Collection getFromMetaDataFile(File file)
381:                    throws IOException {
382:                FileReader in = null;
383:                try {
384:                    in = new FileReader(file);
385:                    return getFromMetaData(in);
386:                } finally {
387:                    if (in != null)
388:                        try {
389:                            in.close();
390:                        } catch (IOException ioe) {
391:                        }
392:                }
393:            }
394:
395:            /**
396:             * Returns the classes named in the given common format metadata stream.
397:             */
398:            private Collection getFromMetaData(Reader xml) throws IOException {
399:                Collection names = new ArrayList();
400:                BufferedReader in = new BufferedReader(xml);
401:
402:                boolean comment = false;
403:                int token = TOKEN_NONE;
404:                String pkg = "";
405:                String name;
406:                read: for (int ch = 0, last = 0, last2 = 0; ch == '<'
407:                        || (ch = in.read()) != -1; last2 = last, last = ch) {
408:                    // handle comments
409:                    if (comment && last2 == '-' && last == '-' && ch == '>') {
410:                        comment = false;
411:                        continue;
412:                    }
413:                    if (comment) {
414:                        if (ch == '<') {
415:                            ch = in.read();
416:                            if (ch == -1)
417:                                break read;
418:                        }
419:                        continue;
420:                    }
421:                    if (last2 == '<' && last == '!' && ch == '-') {
422:                        comment = true;
423:                        continue;
424:                    }
425:
426:                    // if not an element start, skip it
427:                    if (ch != '<')
428:                        continue;
429:                    token = TOKEN_NONE; // reset token
430:                    last = ch; // update needed for comment detection
431:                    ch = readThroughWhitespace(in);
432:                    if (ch == '/' || ch == '!' || ch == '?')
433:                        continue;
434:
435:                    // read element name; look for packages and classes
436:                    token = readElementToken(ch, in);
437:                    switch (token) {
438:                    case TOKEN_EOF:
439:                        break read;
440:                    case TOKEN_PACKAGE:
441:                        pkg = readAttribute(in, _packageAttr);
442:                        if (pkg == null)
443:                            break read;
444:                        break;
445:                    case TOKEN_PACKAGE_NOATTR:
446:                        pkg = readElementText(in);
447:                        if (pkg == null)
448:                            break read;
449:                        ch = '<'; // reading element text reads to next '<'
450:                        break;
451:                    case TOKEN_CLASS:
452:                        name = readAttribute(in, _classAttr);
453:                        if (name == null)
454:                            break read;
455:                        if (pkg.length() > 0 && name.indexOf('.') == -1)
456:                            names.add(pkg + "." + name);
457:                        else
458:                            names.add(name);
459:                        break;
460:                    case TOKEN_CLASS_NOATTR:
461:                        name = readElementText(in);
462:                        if (name == null)
463:                            break read;
464:                        ch = '<'; // reading element text reads to next '<'
465:                        if (pkg.length() > 0 && name.indexOf('.') == -1)
466:                            names.add(pkg + "." + name);
467:                        else
468:                            names.add(name);
469:                        break;
470:                    }
471:                }
472:                return names;
473:            }
474:
475:            /**
476:             * Read the name of the current XML element and return the matching token.
477:             */
478:            private int readElementToken(int ch, Reader in) throws IOException {
479:                // look through the beginning element names to find what element this
480:                // might be(if any)
481:                int matchIdx = -1;
482:                int matched = 0;
483:                int dq = 0;
484:                for (int beginIdx = 0; beginIdx < _beginElements[0].length; beginIdx++) {
485:                    if (beginIdx != 0)
486:                        ch = in.read();
487:                    if (ch == -1)
488:                        return TOKEN_EOF;
489:
490:                    matched = 0;
491:                    for (int i = 0; i < _beginElements.length; i++) {
492:                        if ((dq & (2 << i)) != 0)
493:                            continue;
494:
495:                        if (ch == _beginElements[i][beginIdx]) {
496:                            matchIdx = i;
497:                            matched++;
498:                        } else
499:                            dq |= 2 << i;
500:                    }
501:
502:                    if (matched == 0)
503:                        break;
504:                }
505:                if (matched != 1)
506:                    return TOKEN_NONE;
507:
508:                // make sure the rest of the element name matches
509:                char[] match = _endElements[matchIdx];
510:                for (int i = 0; i < match.length; i++) {
511:                    ch = in.read();
512:                    if (ch == -1)
513:                        return TOKEN_EOF;
514:                    if (ch != match[i])
515:                        return TOKEN_NONE;
516:                }
517:
518:                // read the next char to make sure we finished the element name
519:                ch = in.read();
520:                if (ch == -1)
521:                    return TOKEN_EOF;
522:                if (ch == '>') {
523:                    if (matchIdx == 0 && _packageAttr == null)
524:                        return TOKEN_PACKAGE_NOATTR;
525:                    if (matchIdx != 0 && _classAttr == null)
526:                        return TOKEN_CLASS_NOATTR;
527:                } else if (Character.isWhitespace((char) ch)) {
528:                    if (matchIdx == 0 && _packageAttr != null)
529:                        return TOKEN_PACKAGE;
530:                    if (matchIdx != 0 && _classAttr != null)
531:                        return TOKEN_CLASS;
532:                }
533:                return TOKEN_NONE;
534:            }
535:
536:            /**
537:             * Read the attribute with the given name in chars of the current XML
538:             * element.
539:             */
540:            private String readAttribute(Reader in, char[] name)
541:                    throws IOException {
542:                int expected = 0;
543:                for (int ch, last = 0; true; last = ch) {
544:                    ch = in.read();
545:                    if (ch == -1)
546:                        return null;
547:                    if (ch == '>')
548:                        return "";
549:
550:                    // if not expected char or still looking for 'n' and previous
551:                    // char is not whitespace, keep looking
552:                    if (ch != name[expected]
553:                            || (expected == 0 && last != 0 && !Character
554:                                    .isWhitespace((char) last))) {
555:                        expected = 0;
556:                        continue;
557:                    }
558:
559:                    // found expected char; have we found the whole "name"?
560:                    expected++;
561:                    if (expected == name.length) {
562:                        // make sure the next char is '='
563:                        ch = readThroughWhitespace(in);
564:                        if (ch == -1)
565:                            return null;
566:                        if (ch != '=') {
567:                            expected = 0;
568:                            continue;
569:                        }
570:
571:                        // toss out any subsequent whitespace and the next char, which
572:                        // is the opening quote for the attr value, then read until the
573:                        // closing quote
574:                        readThroughWhitespace(in);
575:                        return readAttributeValue(in);
576:                    }
577:                }
578:            }
579:
580:            /**
581:             * Read the current text value until the next element.
582:             */
583:            private String readElementText(Reader in) throws IOException {
584:                StringBuffer buf = null;
585:                int ch;
586:                while (true) {
587:                    ch = in.read();
588:                    if (ch == -1)
589:                        return null;
590:                    if (ch == '<')
591:                        break;
592:                    if (Character.isWhitespace((char) ch))
593:                        continue;
594:                    if (buf == null)
595:                        buf = new StringBuffer();
596:                    buf.append((char) ch);
597:                }
598:                return (buf == null) ? "" : buf.toString();
599:            }
600:
601:            /**
602:             * Read until the next non-whitespace character.
603:             */
604:            private int readThroughWhitespace(Reader in) throws IOException {
605:                int ch;
606:                while (true) {
607:                    ch = in.read();
608:                    if (ch == -1 || !Character.isWhitespace((char) ch))
609:                        return ch;
610:                }
611:            }
612:
613:            /**
614:             * Return the current attribute value.
615:             */
616:            private String readAttributeValue(Reader in) throws IOException {
617:                StringBuffer buf = new StringBuffer();
618:                int ch;
619:                while (true) {
620:                    ch = in.read();
621:                    if (ch == -1)
622:                        return null;
623:                    if (ch == '\'' || ch == '"')
624:                        return buf.toString();
625:                    buf.append((char) ch);
626:                }
627:            }
628:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.