Source Code Cross Referenced for Manifest.java in  » Build » ANT » org » apache » tools » ant » taskdefs » 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 » Build » ANT » org.apache.tools.ant.taskdefs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         *
0017:         */
0018:
0019:        package org.apache.tools.ant.taskdefs;
0020:
0021:        import java.io.BufferedReader;
0022:        import java.io.IOException;
0023:        import java.io.InputStream;
0024:        import java.io.InputStreamReader;
0025:        import java.io.PrintWriter;
0026:        import java.io.Reader;
0027:        import java.io.StringWriter;
0028:        import java.io.UnsupportedEncodingException;
0029:        import java.util.Enumeration;
0030:        import java.util.Hashtable;
0031:        import java.util.Vector;
0032:        import org.apache.tools.ant.BuildException;
0033:        import org.apache.tools.ant.util.FileUtils;
0034:
0035:        /**
0036:         * Holds the data of a jar manifest.
0037:         *
0038:         * Manifests are processed according to the
0039:         * {@link <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html">Jar
0040:         * file specification.</a>}.
0041:         * Specifically, a manifest element consists of
0042:         * a set of attributes and sections. These sections in turn may contain
0043:         * attributes. Note in particular that this may result in manifest lines
0044:         * greater than 72 bytes being wrapped and continued on the next
0045:         * line. If an application can not handle the continuation mechanism, it
0046:         * is a defect in the application, not this task.
0047:         *
0048:         *
0049:         * @since Ant 1.4
0050:         */
0051:        public class Manifest {
0052:            /** The standard manifest version header */
0053:            public static final String ATTRIBUTE_MANIFEST_VERSION = "Manifest-Version";
0054:
0055:            /** The standard Signature Version header */
0056:            public static final String ATTRIBUTE_SIGNATURE_VERSION = "Signature-Version";
0057:
0058:            /** The Name Attribute is the first in a named section */
0059:            public static final String ATTRIBUTE_NAME = "Name";
0060:
0061:            /** The From Header is disallowed in a Manifest */
0062:            public static final String ATTRIBUTE_FROM = "From";
0063:
0064:            /** The Class-Path Header is special - it can be duplicated */
0065:            public static final String ATTRIBUTE_CLASSPATH = "Class-Path";
0066:
0067:            /** Default Manifest version if one is not specified */
0068:            public static final String DEFAULT_MANIFEST_VERSION = "1.0";
0069:
0070:            /** The max length of a line in a Manifest */
0071:            public static final int MAX_LINE_LENGTH = 72;
0072:
0073:            /**
0074:             * Max length of a line section which is continued. Need to allow
0075:             * for the CRLF.
0076:             */
0077:            public static final int MAX_SECTION_LENGTH = MAX_LINE_LENGTH - 2;
0078:
0079:            /** The End-Of-Line marker in manifests */
0080:            public static final String EOL = "\r\n";
0081:            /** Error for attributes */
0082:            public static final String ERROR_FROM_FORBIDDEN = "Manifest attributes should not start "
0083:                    + "with \"" + ATTRIBUTE_FROM + "\" in \"";
0084:
0085:            /** Encoding to be used for JAR files. */
0086:            public static final String JAR_ENCODING = "UTF-8";
0087:
0088:            /**
0089:             * An attribute for the manifest.
0090:             * Those attributes that are not nested into a section will be added to the "Main" section.
0091:             */
0092:            public static class Attribute {
0093:
0094:                /**
0095:                 * Maximum length of the name to have the value starting on the same
0096:                 * line as the name. This to stay under 72 bytes total line length
0097:                 * (including CRLF).
0098:                 */
0099:                private static final int MAX_NAME_VALUE_LENGTH = 68;
0100:
0101:                /**
0102:                 * Maximum length of the name according to the jar specification.
0103:                 * In this case the first line will have 74 bytes total line length
0104:                 * (including CRLF). This conflicts with the 72 bytes total line length
0105:                 * max, but is the only possible conclusion from the manifest specification, if
0106:                 * names with 70 bytes length are allowed, have to be on the first line, and
0107:                 * have to be followed by ": ".
0108:                 */
0109:                private static final int MAX_NAME_LENGTH = 70;
0110:
0111:                /** The attribute's name */
0112:                private String name = null;
0113:
0114:                /** The attribute's value */
0115:                private Vector values = new Vector();
0116:
0117:                /**
0118:                 * For multivalued attributes, this is the index of the attribute
0119:                 * currently being defined.
0120:                 */
0121:                private int currentIndex = 0;
0122:
0123:                /**
0124:                 * Construct an empty attribute */
0125:                public Attribute() {
0126:                }
0127:
0128:                /**
0129:                 * Construct an attribute by parsing a line from the Manifest
0130:                 *
0131:                 * @param line the line containing the attribute name and value
0132:                 *
0133:                 * @throws ManifestException if the line is not valid
0134:                 */
0135:                public Attribute(String line) throws ManifestException {
0136:                    parse(line);
0137:                }
0138:
0139:                /**
0140:                 * Construct a manifest by specifying its name and value
0141:                 *
0142:                 * @param name the attribute's name
0143:                 * @param value the Attribute's value
0144:                 */
0145:                public Attribute(String name, String value) {
0146:                    this .name = name;
0147:                    setValue(value);
0148:                }
0149:
0150:                /**
0151:                 * @see java.lang.Object#hashCode
0152:                 * @return a hashcode based on the key and values.
0153:                 */
0154:                public int hashCode() {
0155:                    int hashCode = 0;
0156:
0157:                    if (name != null) {
0158:                        hashCode += getKey().hashCode();
0159:                    }
0160:
0161:                    hashCode += values.hashCode();
0162:                    return hashCode;
0163:                }
0164:
0165:                /**
0166:                 * @param rhs the object to check for equality.
0167:                 * @see java.lang.Object#equals
0168:                 * @return true if the key and values are the same.
0169:                 */
0170:                public boolean equals(Object rhs) {
0171:                    if (rhs == null || rhs.getClass() != getClass()) {
0172:                        return false;
0173:                    }
0174:
0175:                    if (rhs == this ) {
0176:                        return true;
0177:                    }
0178:
0179:                    Attribute rhsAttribute = (Attribute) rhs;
0180:                    String lhsKey = getKey();
0181:                    String rhsKey = rhsAttribute.getKey();
0182:                    if ((lhsKey == null && rhsKey != null)
0183:                            || (lhsKey != null && rhsKey == null)
0184:                            || !lhsKey.equals(rhsKey)) {
0185:                        return false;
0186:                    }
0187:
0188:                    return values.equals(rhsAttribute.values);
0189:                }
0190:
0191:                /**
0192:                 * Parse a line into name and value pairs
0193:                 *
0194:                 * @param line the line to be parsed
0195:                 *
0196:                 * @throws ManifestException if the line does not contain a colon
0197:                 * separating the name and value
0198:                 */
0199:                public void parse(String line) throws ManifestException {
0200:                    int index = line.indexOf(": ");
0201:                    if (index == -1) {
0202:                        throw new ManifestException(
0203:                                "Manifest line \""
0204:                                        + line
0205:                                        + "\" is not valid as it does not "
0206:                                        + "contain a name and a value separated by ': ' ");
0207:                    }
0208:                    name = line.substring(0, index);
0209:                    setValue(line.substring(index + 2));
0210:                }
0211:
0212:                /**
0213:                 * Set the Attribute's name; required
0214:                 *
0215:                 * @param name the attribute's name
0216:                 */
0217:                public void setName(String name) {
0218:                    this .name = name;
0219:                }
0220:
0221:                /**
0222:                 * Get the Attribute's name
0223:                 *
0224:                 * @return the attribute's name.
0225:                 */
0226:                public String getName() {
0227:                    return name;
0228:                }
0229:
0230:                /**
0231:                 * Get the attribute's Key - its name in lower case.
0232:                 *
0233:                 * @return the attribute's key.
0234:                 */
0235:                public String getKey() {
0236:                    if (name == null) {
0237:                        return null;
0238:                    }
0239:                    return name.toLowerCase();
0240:                }
0241:
0242:                /**
0243:                 * Set the Attribute's value; required
0244:                 *
0245:                 * @param value the attribute's value
0246:                 */
0247:                public void setValue(String value) {
0248:                    if (currentIndex >= values.size()) {
0249:                        values.addElement(value);
0250:                        currentIndex = values.size() - 1;
0251:                    } else {
0252:                        values.setElementAt(value, currentIndex);
0253:                    }
0254:                }
0255:
0256:                /**
0257:                 * Get the Attribute's value.
0258:                 *
0259:                 * @return the attribute's value.
0260:                 */
0261:                public String getValue() {
0262:                    if (values.size() == 0) {
0263:                        return null;
0264:                    }
0265:
0266:                    String fullValue = "";
0267:                    for (Enumeration e = getValues(); e.hasMoreElements();) {
0268:                        String value = (String) e.nextElement();
0269:                        fullValue += value + " ";
0270:                    }
0271:                    return fullValue.trim();
0272:                }
0273:
0274:                /**
0275:                 * Add a new value to this attribute - making it multivalued.
0276:                 *
0277:                 * @param value the attribute's additional value
0278:                 */
0279:                public void addValue(String value) {
0280:                    currentIndex++;
0281:                    setValue(value);
0282:                }
0283:
0284:                /**
0285:                 * Get all the attribute's values.
0286:                 *
0287:                 * @return an enumeration of the attributes values
0288:                 */
0289:                public Enumeration getValues() {
0290:                    return values.elements();
0291:                }
0292:
0293:                /**
0294:                 * Add a continuation line from the Manifest file.
0295:                 *
0296:                 * When lines are too long in a manifest, they are continued on the
0297:                 * next line by starting with a space. This method adds the continuation
0298:                 * data to the attribute value by skipping the first character.
0299:                 *
0300:                 * @param line the continuation line.
0301:                 */
0302:                public void addContinuation(String line) {
0303:                    String currentValue = (String) values
0304:                            .elementAt(currentIndex);
0305:                    setValue(currentValue + line.substring(1));
0306:                }
0307:
0308:                /**
0309:                 * Write the attribute out to a print writer.
0310:                 *
0311:                 * @param writer the Writer to which the attribute is written
0312:                 *
0313:                 * @throws IOException if the attribute value cannot be written
0314:                 */
0315:                public void write(PrintWriter writer) throws IOException {
0316:                    for (Enumeration e = getValues(); e.hasMoreElements();) {
0317:                        writeValue(writer, (String) e.nextElement());
0318:                    }
0319:                }
0320:
0321:                /**
0322:                 * Write a single attribute value out
0323:                 *
0324:                 * @param writer the Writer to which the attribute is written
0325:                 * @param value the attribute value
0326:                 *
0327:                 * @throws IOException if the attribute value cannot be written
0328:                 */
0329:                private void writeValue(PrintWriter writer, String value)
0330:                        throws IOException {
0331:                    String line = null;
0332:                    int nameLength = name.getBytes(JAR_ENCODING).length;
0333:                    if (nameLength > MAX_NAME_VALUE_LENGTH) {
0334:                        if (nameLength > MAX_NAME_LENGTH) {
0335:                            throw new IOException(
0336:                                    "Unable to write manifest line " + name
0337:                                            + ": " + value);
0338:                        }
0339:                        writer.print(name + ": " + EOL);
0340:                        line = " " + value;
0341:                    } else {
0342:                        line = name + ": " + value;
0343:                    }
0344:                    while (line.getBytes(JAR_ENCODING).length > MAX_SECTION_LENGTH) {
0345:                        // try to find a MAX_LINE_LENGTH byte section
0346:                        int breakIndex = MAX_SECTION_LENGTH;
0347:                        if (breakIndex >= line.length()) {
0348:                            breakIndex = line.length() - 1;
0349:                        }
0350:                        String section = line.substring(0, breakIndex);
0351:                        while (section.getBytes(JAR_ENCODING).length > MAX_SECTION_LENGTH
0352:                                && breakIndex > 0) {
0353:                            breakIndex--;
0354:                            section = line.substring(0, breakIndex);
0355:                        }
0356:                        if (breakIndex == 0) {
0357:                            throw new IOException(
0358:                                    "Unable to write manifest line " + name
0359:                                            + ": " + value);
0360:                        }
0361:                        writer.print(section + EOL);
0362:                        line = " " + line.substring(breakIndex);
0363:                    }
0364:                    writer.print(line + EOL);
0365:                }
0366:            }
0367:
0368:            /**
0369:             * A manifest section - you can nest attribute elements into sections.
0370:             * A section consists of a set of attribute values,
0371:             * separated from other sections by a blank line.
0372:             */
0373:            public static class Section {
0374:                /** Warnings for this section */
0375:                private Vector warnings = new Vector();
0376:
0377:                /**
0378:                 * The section's name if any. The main section in a
0379:                 * manifest is unnamed.
0380:                 */
0381:                private String name = null;
0382:
0383:                /** The section's attributes.*/
0384:                private Hashtable attributes = new Hashtable();
0385:
0386:                /** Index used to retain the attribute ordering */
0387:                private Vector attributeIndex = new Vector();
0388:
0389:                /**
0390:                 * The name of the section; optional -default is the main section.
0391:                 * @param name the section's name
0392:                 */
0393:                public void setName(String name) {
0394:                    this .name = name;
0395:                }
0396:
0397:                /**
0398:                 * Get the Section's name.
0399:                 *
0400:                 * @return the section's name.
0401:                 */
0402:                public String getName() {
0403:                    return name;
0404:                }
0405:
0406:                /**
0407:                 * Read a section through a reader.
0408:                 *
0409:                 * @param reader the reader from which the section is read
0410:                 *
0411:                 * @return the name of the next section if it has been read as
0412:                 *         part of this section - This only happens if the
0413:                 *         Manifest is malformed.
0414:                 *
0415:                 * @throws ManifestException if the section is not valid according
0416:                 *         to the JAR spec
0417:                 * @throws IOException if the section cannot be read from the reader.
0418:                 */
0419:                public String read(BufferedReader reader)
0420:                        throws ManifestException, IOException {
0421:                    Attribute attribute = null;
0422:                    while (true) {
0423:                        String line = reader.readLine();
0424:                        if (line == null || line.length() == 0) {
0425:                            return null;
0426:                        }
0427:                        if (line.charAt(0) == ' ') {
0428:                            // continuation line
0429:                            if (attribute == null) {
0430:                                if (name != null) {
0431:                                    // a continuation on the first line is a
0432:                                    // continuation of the name - concatenate this
0433:                                    // line and the name
0434:                                    name += line.substring(1);
0435:                                } else {
0436:                                    throw new ManifestException(
0437:                                            "Can't start an "
0438:                                                    + "attribute with a continuation line "
0439:                                                    + line);
0440:                                }
0441:                            } else {
0442:                                attribute.addContinuation(line);
0443:                            }
0444:                        } else {
0445:                            attribute = new Attribute(line);
0446:                            String nameReadAhead = addAttributeAndCheck(attribute);
0447:                            // refresh attribute in case of multivalued attributes.
0448:                            attribute = getAttribute(attribute.getKey());
0449:                            if (nameReadAhead != null) {
0450:                                return nameReadAhead;
0451:                            }
0452:                        }
0453:                    }
0454:                }
0455:
0456:                /**
0457:                 * Merge in another section
0458:                 *
0459:                 * @param section the section to be merged with this one.
0460:                 *
0461:                 * @throws ManifestException if the sections cannot be merged.
0462:                 */
0463:                public void merge(Section section) throws ManifestException {
0464:                    if (name == null && section.getName() != null
0465:                            || name != null
0466:                            && !(name.equalsIgnoreCase(section.getName()))) {
0467:                        throw new ManifestException("Unable to merge sections "
0468:                                + "with different names");
0469:                    }
0470:
0471:                    Enumeration e = section.getAttributeKeys();
0472:                    Attribute classpathAttribute = null;
0473:                    while (e.hasMoreElements()) {
0474:                        String attributeName = (String) e.nextElement();
0475:                        Attribute attribute = section
0476:                                .getAttribute(attributeName);
0477:                        if (attributeName.equalsIgnoreCase(ATTRIBUTE_CLASSPATH)) {
0478:                            if (classpathAttribute == null) {
0479:                                classpathAttribute = new Attribute();
0480:                                classpathAttribute.setName(ATTRIBUTE_CLASSPATH);
0481:                            }
0482:                            Enumeration cpe = attribute.getValues();
0483:                            while (cpe.hasMoreElements()) {
0484:                                String value = (String) cpe.nextElement();
0485:                                classpathAttribute.addValue(value);
0486:                            }
0487:                        } else {
0488:                            // the merge file always wins
0489:                            storeAttribute(attribute);
0490:                        }
0491:                    }
0492:
0493:                    if (classpathAttribute != null) {
0494:                        // the merge file *always* wins, even for Class-Path
0495:                        storeAttribute(classpathAttribute);
0496:                    }
0497:
0498:                    // add in the warnings
0499:                    Enumeration warnEnum = section.warnings.elements();
0500:                    while (warnEnum.hasMoreElements()) {
0501:                        warnings.addElement(warnEnum.nextElement());
0502:                    }
0503:                }
0504:
0505:                /**
0506:                 * Write the section out to a print writer.
0507:                 *
0508:                 * @param writer the Writer to which the section is written
0509:                 *
0510:                 * @throws IOException if the section cannot be written
0511:                 */
0512:                public void write(PrintWriter writer) throws IOException {
0513:                    if (name != null) {
0514:                        Attribute nameAttr = new Attribute(ATTRIBUTE_NAME, name);
0515:                        nameAttr.write(writer);
0516:                    }
0517:                    Enumeration e = getAttributeKeys();
0518:                    while (e.hasMoreElements()) {
0519:                        String key = (String) e.nextElement();
0520:                        Attribute attribute = getAttribute(key);
0521:                        attribute.write(writer);
0522:                    }
0523:                    writer.print(EOL);
0524:                }
0525:
0526:                /**
0527:                 * Get a attribute of the section
0528:                 *
0529:                 * @param attributeName the name of the attribute
0530:                 * @return a Manifest.Attribute instance if the attribute is
0531:                 *         single-valued, otherwise a Vector of Manifest.Attribute
0532:                 *         instances.
0533:                 */
0534:                public Attribute getAttribute(String attributeName) {
0535:                    return (Attribute) attributes.get(attributeName
0536:                            .toLowerCase());
0537:                }
0538:
0539:                /**
0540:                 * Get the attribute keys.
0541:                 *
0542:                 * @return an Enumeration of Strings, each string being the lower case
0543:                 *         key of an attribute of the section.
0544:                 */
0545:                public Enumeration getAttributeKeys() {
0546:                    return attributeIndex.elements();
0547:                }
0548:
0549:                /**
0550:                 * Get the value of the attribute with the name given.
0551:                 *
0552:                 * @param attributeName the name of the attribute to be returned.
0553:                 *
0554:                 * @return the attribute's value or null if the attribute does not exist
0555:                 *         in the section
0556:                 */
0557:                public String getAttributeValue(String attributeName) {
0558:                    Attribute attribute = getAttribute(attributeName
0559:                            .toLowerCase());
0560:                    if (attribute == null) {
0561:                        return null;
0562:                    }
0563:                    return attribute.getValue();
0564:                }
0565:
0566:                /**
0567:                 * Remove the given attribute from the section
0568:                 *
0569:                 * @param attributeName the name of the attribute to be removed.
0570:                 */
0571:                public void removeAttribute(String attributeName) {
0572:                    String key = attributeName.toLowerCase();
0573:                    attributes.remove(key);
0574:                    attributeIndex.removeElement(key);
0575:                }
0576:
0577:                /**
0578:                 * Add an attribute to the section.
0579:                 *
0580:                 * @param attribute the attribute to be added to the section
0581:                 *
0582:                 * @exception ManifestException if the attribute is not valid.
0583:                 */
0584:                public void addConfiguredAttribute(Attribute attribute)
0585:                        throws ManifestException {
0586:                    String check = addAttributeAndCheck(attribute);
0587:                    if (check != null) {
0588:                        throw new BuildException(
0589:                                "Specify the section name using "
0590:                                        + "the \"name\" attribute of the <section> element rather "
0591:                                        + "than using a \"Name\" manifest attribute");
0592:                    }
0593:                }
0594:
0595:                /**
0596:                 * Add an attribute to the section
0597:                 *
0598:                 * @param attribute the attribute to be added.
0599:                 *
0600:                 * @return the value of the attribute if it is a name
0601:                 *         attribute - null other wise
0602:                 *
0603:                 * @exception ManifestException if the attribute already
0604:                 *            exists in this section.
0605:                 */
0606:                public String addAttributeAndCheck(Attribute attribute)
0607:                        throws ManifestException {
0608:                    if (attribute.getName() == null
0609:                            || attribute.getValue() == null) {
0610:                        throw new BuildException(
0611:                                "Attributes must have name and value");
0612:                    }
0613:                    if (attribute.getKey().equalsIgnoreCase(ATTRIBUTE_NAME)) {
0614:                        warnings
0615:                                .addElement("\""
0616:                                        + ATTRIBUTE_NAME
0617:                                        + "\" attributes "
0618:                                        + "should not occur in the main section and must be the "
0619:                                        + "first element in all other sections: \""
0620:                                        + attribute.getName() + ": "
0621:                                        + attribute.getValue() + "\"");
0622:                        return attribute.getValue();
0623:                    }
0624:
0625:                    if (attribute.getKey().startsWith(
0626:                            ATTRIBUTE_FROM.toLowerCase())) {
0627:                        warnings.addElement(ERROR_FROM_FORBIDDEN
0628:                                + attribute.getName() + ": "
0629:                                + attribute.getValue() + "\"");
0630:                    } else {
0631:                        // classpath attributes go into a vector
0632:                        String attributeKey = attribute.getKey();
0633:                        if (attributeKey.equalsIgnoreCase(ATTRIBUTE_CLASSPATH)) {
0634:                            Attribute classpathAttribute = (Attribute) attributes
0635:                                    .get(attributeKey);
0636:
0637:                            if (classpathAttribute == null) {
0638:                                storeAttribute(attribute);
0639:                            } else {
0640:                                warnings
0641:                                        .addElement("Multiple Class-Path attributes "
0642:                                                + "are supported but violate the Jar "
0643:                                                + "specification and may not be correctly "
0644:                                                + "processed in all environments");
0645:                                Enumeration e = attribute.getValues();
0646:                                while (e.hasMoreElements()) {
0647:                                    String value = (String) e.nextElement();
0648:                                    classpathAttribute.addValue(value);
0649:                                }
0650:                            }
0651:                        } else if (attributes.containsKey(attributeKey)) {
0652:                            throw new ManifestException("The attribute \""
0653:                                    + attribute.getName()
0654:                                    + "\" may not occur more "
0655:                                    + "than once in the same section");
0656:                        } else {
0657:                            storeAttribute(attribute);
0658:                        }
0659:                    }
0660:                    return null;
0661:                }
0662:
0663:                /**
0664:                 * Clone this section
0665:                 *
0666:                 * @return the cloned Section
0667:                 * @since Ant 1.5.2
0668:                 */
0669:                public Object clone() {
0670:                    Section cloned = new Section();
0671:                    cloned.setName(name);
0672:                    Enumeration e = getAttributeKeys();
0673:                    while (e.hasMoreElements()) {
0674:                        String key = (String) e.nextElement();
0675:                        Attribute attribute = getAttribute(key);
0676:                        cloned.storeAttribute(new Attribute(
0677:                                attribute.getName(), attribute.getValue()));
0678:                    }
0679:                    return cloned;
0680:                }
0681:
0682:                /**
0683:                 * Store an attribute and update the index.
0684:                 *
0685:                 * @param attribute the attribute to be stored
0686:                 */
0687:                private void storeAttribute(Attribute attribute) {
0688:                    if (attribute == null) {
0689:                        return;
0690:                    }
0691:                    String attributeKey = attribute.getKey();
0692:                    attributes.put(attributeKey, attribute);
0693:                    if (!attributeIndex.contains(attributeKey)) {
0694:                        attributeIndex.addElement(attributeKey);
0695:                    }
0696:                }
0697:
0698:                /**
0699:                 * Get the warnings for this section.
0700:                 *
0701:                 * @return an Enumeration of warning strings.
0702:                 */
0703:                public Enumeration getWarnings() {
0704:                    return warnings.elements();
0705:                }
0706:
0707:                /**
0708:                 * @see java.lang.Object#hashCode
0709:                 * @return a hash value based on the attributes.
0710:                 */
0711:                public int hashCode() {
0712:                    return attributes.hashCode();
0713:                }
0714:
0715:                /**
0716:                 * @see java.lang.Object#equals
0717:                 * @param rhs the object to check for equality.
0718:                 * @return true if the attributes are the same.
0719:                 */
0720:                public boolean equals(Object rhs) {
0721:                    if (rhs == null || rhs.getClass() != getClass()) {
0722:                        return false;
0723:                    }
0724:
0725:                    if (rhs == this ) {
0726:                        return true;
0727:                    }
0728:
0729:                    Section rhsSection = (Section) rhs;
0730:
0731:                    return attributes.equals(rhsSection.attributes);
0732:                }
0733:            }
0734:
0735:            /** The version of this manifest */
0736:            private String manifestVersion = DEFAULT_MANIFEST_VERSION;
0737:
0738:            /** The main section of this manifest */
0739:            private Section mainSection = new Section();
0740:
0741:            /** The named sections of this manifest */
0742:            private Hashtable sections = new Hashtable();
0743:
0744:            /** Index of sections - used to retain order of sections in manifest */
0745:            private Vector sectionIndex = new Vector();
0746:
0747:            /**
0748:             * Construct a manifest from Ant's default manifest file.
0749:             *
0750:             * @return the default manifest.
0751:             * @exception BuildException if there is a problem loading the
0752:             *            default manifest
0753:             */
0754:            public static Manifest getDefaultManifest() throws BuildException {
0755:                InputStream in = null;
0756:                InputStreamReader insr = null;
0757:                try {
0758:                    String defManifest = "/org/apache/tools/ant/defaultManifest.mf";
0759:                    in = Manifest.class.getResourceAsStream(defManifest);
0760:                    if (in == null) {
0761:                        throw new BuildException(
0762:                                "Could not find default manifest: "
0763:                                        + defManifest);
0764:                    }
0765:                    try {
0766:                        insr = new InputStreamReader(in, "UTF-8");
0767:                        Manifest defaultManifest = new Manifest(insr);
0768:                        Attribute createdBy = new Attribute("Created-By",
0769:                                System.getProperty("java.vm.version") + " ("
0770:                                        + System.getProperty("java.vm.vendor")
0771:                                        + ")");
0772:                        defaultManifest.getMainSection().storeAttribute(
0773:                                createdBy);
0774:                        return defaultManifest;
0775:                    } catch (UnsupportedEncodingException e) {
0776:                        insr = new InputStreamReader(in);
0777:                        return new Manifest(insr);
0778:                    }
0779:                } catch (ManifestException e) {
0780:                    throw new BuildException("Default manifest is invalid !!",
0781:                            e);
0782:                } catch (IOException e) {
0783:                    throw new BuildException("Unable to read default manifest",
0784:                            e);
0785:                } finally {
0786:                    FileUtils.close(insr);
0787:                    FileUtils.close(in);
0788:                }
0789:            }
0790:
0791:            /** Construct an empty manifest */
0792:            public Manifest() {
0793:                manifestVersion = null;
0794:            }
0795:
0796:            /**
0797:             * Read a manifest file from the given reader
0798:             *
0799:             * @param r is the reader from which the Manifest is read
0800:             *
0801:             * @throws ManifestException if the manifest is not valid according
0802:             *         to the JAR spec
0803:             * @throws IOException if the manifest cannot be read from the reader.
0804:             */
0805:            public Manifest(Reader r) throws ManifestException, IOException {
0806:                BufferedReader reader = new BufferedReader(r);
0807:                // This should be the manifest version
0808:                String nextSectionName = mainSection.read(reader);
0809:                String readManifestVersion = mainSection
0810:                        .getAttributeValue(ATTRIBUTE_MANIFEST_VERSION);
0811:                if (readManifestVersion != null) {
0812:                    manifestVersion = readManifestVersion;
0813:                    mainSection.removeAttribute(ATTRIBUTE_MANIFEST_VERSION);
0814:                }
0815:
0816:                String line = null;
0817:                while ((line = reader.readLine()) != null) {
0818:                    if (line.length() == 0) {
0819:                        continue;
0820:                    }
0821:
0822:                    Section section = new Section();
0823:                    if (nextSectionName == null) {
0824:                        Attribute sectionName = new Attribute(line);
0825:                        if (!sectionName.getName().equalsIgnoreCase(
0826:                                ATTRIBUTE_NAME)) {
0827:                            throw new ManifestException(
0828:                                    "Manifest sections should "
0829:                                            + "start with a \""
0830:                                            + ATTRIBUTE_NAME
0831:                                            + "\" attribute and not \""
0832:                                            + sectionName.getName() + "\"");
0833:                        }
0834:                        nextSectionName = sectionName.getValue();
0835:                    } else {
0836:                        // we have already started reading this section
0837:                        // this line is the first attribute. set it and then
0838:                        // let the normal read handle the rest
0839:                        Attribute firstAttribute = new Attribute(line);
0840:                        section.addAttributeAndCheck(firstAttribute);
0841:                    }
0842:
0843:                    section.setName(nextSectionName);
0844:                    nextSectionName = section.read(reader);
0845:                    addConfiguredSection(section);
0846:                }
0847:            }
0848:
0849:            /**
0850:             * Add a section to the manifest
0851:             *
0852:             * @param section the manifest section to be added
0853:             *
0854:             * @exception ManifestException if the secti0on is not valid.
0855:             */
0856:            public void addConfiguredSection(Section section)
0857:                    throws ManifestException {
0858:                String sectionName = section.getName();
0859:                if (sectionName == null) {
0860:                    throw new BuildException("Sections must have a name");
0861:                }
0862:                sections.put(sectionName, section);
0863:                if (!sectionIndex.contains(sectionName)) {
0864:                    sectionIndex.addElement(sectionName);
0865:                }
0866:            }
0867:
0868:            /**
0869:             * Add an attribute to the manifest - it is added to the main section.
0870:             *
0871:             * @param attribute the attribute to be added.
0872:             *
0873:             * @exception ManifestException if the attribute is not valid.
0874:             */
0875:            public void addConfiguredAttribute(Attribute attribute)
0876:                    throws ManifestException {
0877:                if (attribute.getKey() == null || attribute.getValue() == null) {
0878:                    throw new BuildException(
0879:                            "Attributes must have name and value");
0880:                }
0881:                if (attribute.getKey().equalsIgnoreCase(
0882:                        ATTRIBUTE_MANIFEST_VERSION)) {
0883:                    manifestVersion = attribute.getValue();
0884:                } else {
0885:                    mainSection.addConfiguredAttribute(attribute);
0886:                }
0887:            }
0888:
0889:            /**
0890:             * Merge the contents of the given manifest into this manifest
0891:             *
0892:             * @param other the Manifest to be merged with this one.
0893:             *
0894:             * @throws ManifestException if there is a problem merging the
0895:             *         manifest according to the Manifest spec.
0896:             */
0897:            public void merge(Manifest other) throws ManifestException {
0898:                merge(other, false);
0899:            }
0900:
0901:            /**
0902:             * Merge the contents of the given manifest into this manifest
0903:             *
0904:             * @param other the Manifest to be merged with this one.
0905:             * @param overwriteMain whether to overwrite the main section
0906:             *        of the current manifest
0907:             *
0908:             * @throws ManifestException if there is a problem merging the
0909:             *         manifest according to the Manifest spec.
0910:             */
0911:            public void merge(Manifest other, boolean overwriteMain)
0912:                    throws ManifestException {
0913:                if (other != null) {
0914:                    if (overwriteMain) {
0915:                        mainSection = (Section) other.mainSection.clone();
0916:                    } else {
0917:                        mainSection.merge(other.mainSection);
0918:                    }
0919:
0920:                    if (other.manifestVersion != null) {
0921:                        manifestVersion = other.manifestVersion;
0922:                    }
0923:
0924:                    Enumeration e = other.getSectionNames();
0925:                    while (e.hasMoreElements()) {
0926:                        String sectionName = (String) e.nextElement();
0927:                        Section ourSection = (Section) sections
0928:                                .get(sectionName);
0929:                        Section otherSection = (Section) other.sections
0930:                                .get(sectionName);
0931:                        if (ourSection == null) {
0932:                            if (otherSection != null) {
0933:                                addConfiguredSection((Section) otherSection
0934:                                        .clone());
0935:                            }
0936:                        } else {
0937:                            ourSection.merge(otherSection);
0938:                        }
0939:                    }
0940:                }
0941:            }
0942:
0943:            /**
0944:             * Write the manifest out to a print writer.
0945:             *
0946:             * @param writer the Writer to which the manifest is written
0947:             *
0948:             * @throws IOException if the manifest cannot be written
0949:             */
0950:            public void write(PrintWriter writer) throws IOException {
0951:                writer.print(ATTRIBUTE_MANIFEST_VERSION + ": "
0952:                        + manifestVersion + EOL);
0953:                String signatureVersion = mainSection
0954:                        .getAttributeValue(ATTRIBUTE_SIGNATURE_VERSION);
0955:                if (signatureVersion != null) {
0956:                    writer.print(ATTRIBUTE_SIGNATURE_VERSION + ": "
0957:                            + signatureVersion + EOL);
0958:                    mainSection.removeAttribute(ATTRIBUTE_SIGNATURE_VERSION);
0959:                }
0960:                mainSection.write(writer);
0961:
0962:                // add it back
0963:                if (signatureVersion != null) {
0964:                    try {
0965:                        Attribute svAttr = new Attribute(
0966:                                ATTRIBUTE_SIGNATURE_VERSION, signatureVersion);
0967:                        mainSection.addConfiguredAttribute(svAttr);
0968:                    } catch (ManifestException e) {
0969:                        // shouldn't happen - ignore
0970:                    }
0971:                }
0972:
0973:                Enumeration e = sectionIndex.elements();
0974:                while (e.hasMoreElements()) {
0975:                    String sectionName = (String) e.nextElement();
0976:                    Section section = getSection(sectionName);
0977:                    section.write(writer);
0978:                }
0979:            }
0980:
0981:            /**
0982:             * Convert the manifest to its string representation
0983:             *
0984:             * @return a multiline string with the Manifest as it
0985:             *         appears in a Manifest file.
0986:             */
0987:            public String toString() {
0988:                StringWriter sw = new StringWriter();
0989:                try {
0990:                    write(new PrintWriter(sw));
0991:                } catch (IOException e) {
0992:                    return null;
0993:                }
0994:                return sw.toString();
0995:            }
0996:
0997:            /**
0998:             * Get the warnings for this manifest.
0999:             *
1000:             * @return an enumeration of warning strings
1001:             */
1002:            public Enumeration getWarnings() {
1003:                Vector warnings = new Vector();
1004:
1005:                Enumeration warnEnum = mainSection.getWarnings();
1006:                while (warnEnum.hasMoreElements()) {
1007:                    warnings.addElement(warnEnum.nextElement());
1008:                }
1009:
1010:                // create a vector and add in the warnings for all the sections
1011:                Enumeration e = sections.elements();
1012:                while (e.hasMoreElements()) {
1013:                    Section section = (Section) e.nextElement();
1014:                    Enumeration e2 = section.getWarnings();
1015:                    while (e2.hasMoreElements()) {
1016:                        warnings.addElement(e2.nextElement());
1017:                    }
1018:                }
1019:
1020:                return warnings.elements();
1021:            }
1022:
1023:            /**
1024:             * @see java.lang.Object#hashCode
1025:             * @return a hashcode based on the version, main and sections.
1026:             */
1027:            public int hashCode() {
1028:                int hashCode = 0;
1029:
1030:                if (manifestVersion != null) {
1031:                    hashCode += manifestVersion.hashCode();
1032:                }
1033:                hashCode += mainSection.hashCode();
1034:                hashCode += sections.hashCode();
1035:
1036:                return hashCode;
1037:            }
1038:
1039:            /**
1040:             * @see java.lang.Object#equals
1041:             * @param rhs the object to check for equality.
1042:             * @return true if the version, main and sections are the same.
1043:             */
1044:            public boolean equals(Object rhs) {
1045:                if (rhs == null || rhs.getClass() != getClass()) {
1046:                    return false;
1047:                }
1048:
1049:                if (rhs == this ) {
1050:                    return true;
1051:                }
1052:
1053:                Manifest rhsManifest = (Manifest) rhs;
1054:                if (manifestVersion == null) {
1055:                    if (rhsManifest.manifestVersion != null) {
1056:                        return false;
1057:                    }
1058:                } else if (!manifestVersion.equals(rhsManifest.manifestVersion)) {
1059:                    return false;
1060:                }
1061:
1062:                if (!mainSection.equals(rhsManifest.mainSection)) {
1063:                    return false;
1064:                }
1065:
1066:                return sections.equals(rhsManifest.sections);
1067:            }
1068:
1069:            /**
1070:             * Get the version of the manifest
1071:             *
1072:             * @return the manifest's version string
1073:             */
1074:            public String getManifestVersion() {
1075:                return manifestVersion;
1076:            }
1077:
1078:            /**
1079:             * Get the main section of the manifest
1080:             *
1081:             * @return the main section of the manifest
1082:             */
1083:            public Section getMainSection() {
1084:                return mainSection;
1085:            }
1086:
1087:            /**
1088:             * Get a particular section from the manifest
1089:             *
1090:             * @param name the name of the section desired.
1091:             * @return the specified section or null if that section
1092:             * does not exist in the manifest
1093:             */
1094:            public Section getSection(String name) {
1095:                return (Section) sections.get(name);
1096:            }
1097:
1098:            /**
1099:             * Get the section names in this manifest.
1100:             *
1101:             * @return an Enumeration of section names
1102:             */
1103:            public Enumeration getSectionNames() {
1104:                return sectionIndex.elements();
1105:            }
1106:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.