/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.ant.taskdefs;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Jar;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ZipFileSet;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.zip.ZipOutputStream;
/**
* The Ant task that will build the Enterprise Subsystem Archive, this task is
* modeled based on the Ant {@link Jar} task
*
* @version $Id: $
*/
public class EsaTask extends Zip {
/* name of the subsystem */
private String symbolicName;
/* name of the subsystem */
private String name;
/* subsystem description */
private String description;
/* version of the subsystem */
private String version;
/* subsystem type */
private String type = Constants.FEATURE_TYPE;
/* the file holder of the esa manifest */
private File manifestFile;
/* Flag to indicate whether to generate manifest */
protected boolean generateManifest;
/* Used for dry runs */
protected boolean skipWriting = false;
/* Used build the subsystem content header */
private StringBuilder subsystemContent = new StringBuilder(
Constants.SUBSYSTEM_CONTENT + ":");
public EsaTask() {
super();
archiveType = "esa";
setEncoding("UTF8");
}
/**
* @param symbolicName
* the symbolicName to set
*/
public void setSymbolicName(String symbolicName) {
this.symbolicName = symbolicName;
}
/**
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @param version
* the version to set
*/
public void setVersion(String subsystemVersion) {
this.version = subsystemVersion;
}
/**
* @param type
* the type to set
*/
public void setType(String subsystemType) {
this.type = subsystemType;
}
/**
* @param manifest
* file to use the manifest to set
*/
public void setManifest(File manifestFile) {
if (!manifestFile.exists()) {
throw new BuildException("Manifest:" + manifestFile +
" does not exist", getLocation());
}
this.manifestFile = manifestFile;
}
/**
* @param generateManifest
* the generateManifest to set
*/
public void setGenerateManifest(boolean generateManifest) {
this.generateManifest = generateManifest;
}
/**
* @param skipWriting
* the skipWriting to set
*/
public void setSkipWriting(boolean skipWriting) {
this.skipWriting = skipWriting;
}
@Override
protected void zipFile(
File file, ZipOutputStream zOut, String vPath, int mode)
throws IOException {
super.zipFile(file, zOut, vPath, mode);
/*
* this handling is only for OSGi bundles and we need to exclude other
* entries
*/
if (file.isFile() &&
!Constants.SUBSYSTEM_MANIFEST_NAME.equalsIgnoreCase(vPath)) {
JarFile bundleFile = new JarFile(file);
Manifest jarManifest = bundleFile.getManifest();
if (jarManifest != null) {
Attributes mainAttributes = jarManifest.getMainAttributes();
String bundleSymbolicName =
mainAttributes.getValue(Constants.BUNDLE_SYMBOLICNAME);
String bundleVersion =
mainAttributes.getValue(Constants.BUNDLE_VERSION);
bundleFile.close();
String strSubsystemContentEntry =
bundleSymbolicName + ";version=" + bundleVersion;
subsystemContent.append(strSubsystemContentEntry);
subsystemContent.append(",");
}
}
}
@Override
protected void initZipOutputStream(ZipOutputStream zOut)
throws IOException, BuildException {
if (manifestFile != null && !generateManifest) {
zipDir(
(Resource) null, zOut, Constants.OSGI_INF_PATH,
ZipFileSet.DEFAULT_DIR_MODE, null);
zipFile(
manifestFile, zOut, Constants.SUBSYSTEM_MANIFEST_NAME,
ZipFileSet.DEFAULT_FILE_MODE);
}
}
@Override
protected void finalizeZipOutputStream(ZipOutputStream zOut)
throws IOException, BuildException {
if (!skipWriting) {
if (generateManifest) {
addNewManifest(zOut);
}
}
}
/**
* This method will add the SUBSYSTEM.MF to the esa archieve
*
* @param zOut
* -the zip output stream
*/
private void addNewManifest(ZipOutputStream zOut) {
try {
log("Generating SUBSYSTEM.MF", Project.MSG_VERBOSE);
zipDir(
(Resource) null, zOut, Constants.OSGI_INF_PATH,
ZipFileSet.DEFAULT_DIR_MODE, null);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
OutputStreamWriter osWriter = new OutputStreamWriter(bout, "UTF-8");
PrintWriter printWriter = new PrintWriter(osWriter);
// Start writing manifest content
printWriter.write(Constants.SUBSYSTEM_MANIFESTVERSION + ": " +
Constants.SUBSYSTEM_MANIFEST_VERSION_VALUE + "\n");
printWriter.write(Constants.SUBSYSTEM_SYMBOLICNAME + ": " +
symbolicName + "\n");
if (version == null) {
version = "1.0.0";
}
printWriter.write(Constants.SUBSYSTEM_VERSION + ": " + version +
"\n");
if (name == null) {
name = symbolicName;
}
printWriter.write(Constants.SUBSYSTEM_NAME + ": " + name + "\n");
printWriter.write(Constants.SUBSYSTEM_TYPE + ": " + type + "\n");
if (description != null) {
printWriter.write(Constants.SUBSYSTEM_DESCRIPTION + ": " +
description + "\n");
}
// Subsystem-content header
String subsystemContentHeader = subsystemContent.toString();
// strip the last ,
subsystemContentHeader =
subsystemContentHeader.substring(
0, (subsystemContentHeader.length() - 1)) +
"\n";
printWriter.write(subsystemContentHeader);
printWriter.close();
ByteArrayInputStream bais =
new ByteArrayInputStream(bout.toByteArray());
try {
super.zipFile(
bais, zOut, Constants.SUBSYSTEM_MANIFEST_NAME,
System.currentTimeMillis(), null,
ZipFileSet.DEFAULT_FILE_MODE);
}
finally {
// not really required
FileUtils.close(bais);
}
}
catch (IOException e) {
log("Error generating manifest", Project.MSG_ERR);
}
}
}