blob: daebd3edb6b5852a5c9fdb84bfe061c651c2bafb [file] [log] [blame]
/*
* 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.felix.deploymentadmin;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.jar.Attributes.Name;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class Utils {
private static final String MANIFEST_NAME = JarFile.MANIFEST_NAME;
public static Manifest readManifest(File manifestFile) throws IOException {
InputStream is = null;
Manifest mf = null;
try {
is = new GZIPInputStream(new FileInputStream(manifestFile));
mf = new Manifest(is);
}
finally {
closeSilently(is);
}
return mf;
}
public static boolean replace(File target, File source) {
return delete(target, true /* deleteRoot */) && rename(source, target);
}
public static boolean copy(File from, File to) {
boolean result = true;
if (from.isDirectory()) {
if (!to.isDirectory()) {
if (!to.mkdirs()) {
return false;
}
File[] files = from.listFiles();
if (files == null) {
return false;
}
for (int i = 0; i < files.length; i++) {
result &= copy(files[i], new File(to, files[i].getName()));
}
}
}
else {
InputStream input = null;
OutputStream output = null;
try {
input = new FileInputStream(from);
output = new FileOutputStream(to);
byte[] buffer = new byte[4096];
for (int i = input.read(buffer); i > -1; i = input.read(buffer)) {
output.write(buffer, 0, i);
}
}
catch (IOException e) {
return false;
}
finally {
if (!closeSilently(output)) {
result = false;
}
if (!closeSilently(input)) {
result = false;
}
}
}
return result;
}
public static boolean rename(File from, File to) {
if (!from.renameTo(to)) {
if (copy(from, to)) {
if (!delete(from, true /* deleteRoot */)) {
return false;
}
}
else {
return false;
}
}
return true;
}
public static boolean delete(File root, boolean deleteRoot) {
boolean result = true;
if (root.isDirectory()) {
File[] files = root.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
result &= delete(files[i], true);
}
else {
result &= files[i].delete();
}
}
}
if (deleteRoot) {
if (root.exists()) {
result &= root.delete();
}
}
return result;
}
public static void merge(File targetIndex, File target, File sourceIndex, File source) throws IOException {
List targetFiles = readIndex(targetIndex);
List sourceFiles = readIndex(sourceIndex);
List result = new ArrayList(targetFiles);
File manifestFile = new File(source, (String) sourceFiles.remove(0));
Manifest resultManifest = Utils.readManifest(manifestFile);
resultManifest.getMainAttributes().remove(new Name(Constants.DEPLOYMENTPACKAGE_FIXPACK));
for (Iterator i = result.iterator(); i.hasNext();) {
String targetFile = (String) i.next();
if (!MANIFEST_NAME.equals(targetFile) && !resultManifest.getEntries().containsKey(targetFile)) {
i.remove();
}
}
for (Iterator iter = sourceFiles.iterator(); iter.hasNext();) {
String path = (String) iter.next();
File from = new File(source, path);
File to = new File(target, path);
if (targetFiles.contains(path)) {
if (!to.delete()) {
throw new IOException("Could not delete " + to);
}
}
else {
result.add(path);
}
if (!rename(from, to)) {
throw new IOException("Could not rename " + from + " to " + to);
}
}
targetFiles.removeAll(sourceFiles);
for (Iterator iter = resultManifest.getEntries().keySet().iterator(); iter.hasNext();) {
String path = (String) iter.next();
Attributes sourceAttribute = (Attributes) resultManifest.getEntries().get(path);
if ("true".equals(sourceAttribute.remove(new Name(Constants.DEPLOYMENTPACKAGE_MISSING)))) {
targetFiles.remove(path);
}
}
for (Iterator iter = targetFiles.iterator(); iter.hasNext();) {
String path = (String) iter.next();
File targetFile = new File(target, path);
if (!targetFile.delete()) {
throw new IOException("Could not delete " + targetFile);
}
}
GZIPOutputStream outputStream = new GZIPOutputStream(new FileOutputStream(new File(target, MANIFEST_NAME)));
try {
resultManifest.write(outputStream);
}
finally {
outputStream.close();
}
writeIndex(targetIndex, result);
}
public static List readIndex(File index) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(index));
List result = new ArrayList();
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
result.add(line);
}
return result;
}
finally {
closeSilently(reader);
}
}
static boolean closeSilently(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
}
catch (IOException exception) {
// Ignore; nothing we can do about this...
return false;
}
}
return true;
}
private static void writeIndex(File index, List input) throws IOException {
PrintWriter writer = null;
try {
writer = new PrintWriter(new FileWriter(index));
for (Iterator iterator = input.iterator(); iterator.hasNext();) {
writer.println(iterator.next());
}
}
finally {
closeSilently(writer);
}
}
}