[14627] | 1 | /*
|
---|
| 2 | * Copyright 2002-2004 The Apache Software Foundation
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
| 5 | * you may not use this file except in compliance with the License.
|
---|
| 6 | * You may obtain a copy of the License at
|
---|
| 7 | *
|
---|
| 8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
| 9 | *
|
---|
| 10 | * Unless required by applicable law or agreed to in writing, software
|
---|
| 11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
| 13 | * See the License for the specific language governing permissions and
|
---|
| 14 | * limitations under the License.
|
---|
| 15 | *
|
---|
| 16 | */
|
---|
| 17 |
|
---|
| 18 | package org.apache.tools.ant.taskdefs;
|
---|
| 19 |
|
---|
| 20 | import java.io.File;
|
---|
| 21 | import java.io.FileInputStream;
|
---|
| 22 | import java.io.InputStreamReader;
|
---|
| 23 | import java.io.FileOutputStream;
|
---|
| 24 | import java.io.OutputStreamWriter;
|
---|
| 25 | import java.io.IOException;
|
---|
| 26 | import java.io.PrintWriter;
|
---|
| 27 | import org.apache.tools.ant.BuildException;
|
---|
| 28 | import org.apache.tools.ant.Project;
|
---|
| 29 | import org.apache.tools.ant.Task;
|
---|
| 30 | import org.apache.tools.ant.types.EnumeratedAttribute;
|
---|
| 31 |
|
---|
| 32 | /**
|
---|
| 33 | * Creates a manifest file for inclusion in a JAR, Ant task wrapper
|
---|
| 34 | * around {@link Manifest Manifest}. This task can be used to write a
|
---|
| 35 | * Manifest file, optionally replacing or updating an existing file.
|
---|
| 36 | *
|
---|
| 37 | *
|
---|
| 38 | * @since Ant 1.5
|
---|
| 39 | *
|
---|
| 40 | * @ant.task category="java"
|
---|
| 41 | */
|
---|
| 42 | public class ManifestTask extends Task {
|
---|
| 43 |
|
---|
| 44 | /**
|
---|
| 45 | * Holds the real data.
|
---|
| 46 | */
|
---|
| 47 | private Manifest nestedManifest = new Manifest();
|
---|
| 48 |
|
---|
| 49 | /**
|
---|
| 50 | * The file to which the manifest should be written when used as a task
|
---|
| 51 | */
|
---|
| 52 | private File manifestFile;
|
---|
| 53 |
|
---|
| 54 | /**
|
---|
| 55 | * The mode with which the manifest file is written
|
---|
| 56 | */
|
---|
| 57 | private Mode mode;
|
---|
| 58 |
|
---|
| 59 | /**
|
---|
| 60 | * The encoding of the manifest file
|
---|
| 61 | */
|
---|
| 62 | private String encoding;
|
---|
| 63 |
|
---|
| 64 | /**
|
---|
| 65 | * Helper class for Manifest's mode attribute.
|
---|
| 66 | */
|
---|
| 67 | public static class Mode extends EnumeratedAttribute {
|
---|
| 68 | /**
|
---|
| 69 | * Get Allowed values for the mode attribute.
|
---|
| 70 | *
|
---|
| 71 | * @return a String array of the allowed values.
|
---|
| 72 | */
|
---|
| 73 | public String[] getValues() {
|
---|
| 74 | return new String[] {"update", "replace"};
|
---|
| 75 | }
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 | /**
|
---|
| 79 | * Default constructor
|
---|
| 80 | */
|
---|
| 81 | public ManifestTask() {
|
---|
| 82 | mode = new Mode();
|
---|
| 83 | mode.setValue("replace");
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | /**
|
---|
| 87 | * Add a section to the manifest
|
---|
| 88 | *
|
---|
| 89 | * @param section the manifest section to be added
|
---|
| 90 | *
|
---|
| 91 | * @exception ManifestException if the section is not valid.
|
---|
| 92 | */
|
---|
| 93 | public void addConfiguredSection(Manifest.Section section)
|
---|
| 94 | throws ManifestException {
|
---|
| 95 | nestedManifest.addConfiguredSection(section);
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | /**
|
---|
| 99 | * Add an attribute to the manifest - it is added to the main section.
|
---|
| 100 | *
|
---|
| 101 | * @param attribute the attribute to be added.
|
---|
| 102 | *
|
---|
| 103 | * @exception ManifestException if the attribute is not valid.
|
---|
| 104 | */
|
---|
| 105 | public void addConfiguredAttribute(Manifest.Attribute attribute)
|
---|
| 106 | throws ManifestException {
|
---|
| 107 | nestedManifest.addConfiguredAttribute(attribute);
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 | /**
|
---|
| 111 | * The name of the manifest file to create/update.
|
---|
| 112 | * Required if used as a task.
|
---|
| 113 | * @param f the Manifest file to be written
|
---|
| 114 | */
|
---|
| 115 | public void setFile(File f) {
|
---|
| 116 | manifestFile = f;
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | /**
|
---|
| 120 | * The encoding to use for reading in an existing manifest file
|
---|
| 121 | * @param encoding the manifest file encoding.
|
---|
| 122 | */
|
---|
| 123 | public void setEncoding(String encoding) {
|
---|
| 124 | this.encoding = encoding;
|
---|
| 125 | }
|
---|
| 126 |
|
---|
| 127 | /**
|
---|
| 128 | * Update policy: either "update" or "replace"; default is "replace".
|
---|
| 129 | * @param m the mode value - update or replace.
|
---|
| 130 | */
|
---|
| 131 | public void setMode(Mode m) {
|
---|
| 132 | mode = m;
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | /**
|
---|
| 136 | * Create or update the Manifest when used as a task.
|
---|
| 137 | *
|
---|
| 138 | * @throws BuildException if the manifest cannot be written.
|
---|
| 139 | */
|
---|
| 140 | public void execute() throws BuildException {
|
---|
| 141 | if (manifestFile == null) {
|
---|
| 142 | throw new BuildException("the file attribute is required");
|
---|
| 143 | }
|
---|
| 144 |
|
---|
| 145 | Manifest toWrite = Manifest.getDefaultManifest();
|
---|
| 146 | Manifest current = null;
|
---|
| 147 | BuildException error = null;
|
---|
| 148 |
|
---|
| 149 | if (manifestFile.exists()) {
|
---|
| 150 | FileInputStream fis = null;
|
---|
| 151 | InputStreamReader isr = null;
|
---|
| 152 | try {
|
---|
| 153 | fis = new FileInputStream(manifestFile);
|
---|
| 154 | if (encoding == null) {
|
---|
| 155 | isr = new InputStreamReader(fis, "UTF-8");
|
---|
| 156 | } else {
|
---|
| 157 | isr = new InputStreamReader(fis, encoding);
|
---|
| 158 | }
|
---|
| 159 | current = new Manifest(isr);
|
---|
| 160 | } catch (ManifestException m) {
|
---|
| 161 | error = new BuildException("Existing manifest " + manifestFile
|
---|
| 162 | + " is invalid", m, getLocation());
|
---|
| 163 | } catch (IOException e) {
|
---|
| 164 | error = new BuildException("Failed to read " + manifestFile,
|
---|
| 165 | e, getLocation());
|
---|
| 166 | } finally {
|
---|
| 167 | if (isr != null) {
|
---|
| 168 | try {
|
---|
| 169 | isr.close();
|
---|
| 170 | } catch (IOException e) {
|
---|
| 171 | // ignore
|
---|
| 172 | }
|
---|
| 173 | }
|
---|
| 174 | }
|
---|
| 175 | }
|
---|
| 176 |
|
---|
| 177 | try {
|
---|
| 178 | if (mode.getValue().equals("update") && manifestFile.exists()) {
|
---|
| 179 | if (current != null) {
|
---|
| 180 | toWrite.merge(current);
|
---|
| 181 | } else if (error != null) {
|
---|
| 182 | throw error;
|
---|
| 183 | }
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | toWrite.merge(nestedManifest);
|
---|
| 187 | } catch (ManifestException m) {
|
---|
| 188 | throw new BuildException("Manifest is invalid", m, getLocation());
|
---|
| 189 | }
|
---|
| 190 |
|
---|
| 191 | if (toWrite.equals(current)) {
|
---|
| 192 | log("Manifest has not changed, do not recreate",
|
---|
| 193 | Project.MSG_VERBOSE);
|
---|
| 194 | return;
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | PrintWriter w = null;
|
---|
| 198 | try {
|
---|
| 199 | FileOutputStream fos = new FileOutputStream(manifestFile);
|
---|
| 200 | OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
|
---|
| 201 | w = new PrintWriter(osw);
|
---|
| 202 | toWrite.write(w);
|
---|
| 203 | } catch (IOException e) {
|
---|
| 204 | throw new BuildException("Failed to write " + manifestFile,
|
---|
| 205 | e, getLocation());
|
---|
| 206 | } finally {
|
---|
| 207 | if (w != null) {
|
---|
| 208 | w.close();
|
---|
| 209 | }
|
---|
| 210 | }
|
---|
| 211 | }
|
---|
| 212 |
|
---|
| 213 | }
|
---|