Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* IzPack - Copyright 2001-2012 Julien Ponge, All Rights Reserved.
*
* http://izpack.org/
* http://izpack.codehaus.org/
*
* Copyright 2007 Dennis Reil
* Copyright 2012 Tim Anderson
*
* Licensed 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 com.izforge.izpack.compiler.packager.impl;
import com.izforge.izpack.api.adaptator.IXMLElement;
import com.izforge.izpack.api.data.Pack;
import com.izforge.izpack.api.data.PackFile;
import com.izforge.izpack.api.data.XPackFile;
import com.izforge.izpack.api.rules.RulesEngine;
import com.izforge.izpack.compiler.data.CompilerData;
import com.izforge.izpack.compiler.listener.PackagerListener;
import com.izforge.izpack.compiler.merge.CompilerPathResolver;
import com.izforge.izpack.core.io.FileSpanningOutputStream;
import com.izforge.izpack.api.data.PackInfo;
import com.izforge.izpack.merge.MergeManager;
import com.izforge.izpack.merge.resolve.MergeableResolver;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.*;
import java.util.jar.JarOutputStream;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
/**
* An {@link com.izforge.izpack.compiler.packager.IPackager} that packs everything into multiple volumes.
*
*
* Here's an example how to specify an installer which will create multiple volumes. In this example the volumes shall
* be CDs with 650 megabytes. There will be an additional free space of 150 megabytes on the first volume.
*
* This will result in the creation of an installer.jar and multiple installer.pak* files.
* The installer.jar plus installer.pak plus the additional resources have to be copied on the first volume,
* each installer.pak.<number> on several volumes.
*
* {@code
*
*
*
*
*
*
*
* }
*
*
* @author Dennis Reil,
* @author Tim Anderson
*/
public class MultiVolumePackager extends PackagerBase
{
/**
* The maximum size of the first volume, in bytes.
*/
private long maxFirstVolumeSize = FileSpanningOutputStream.DEFAULT_VOLUME_SIZE;
/**
* The maximum volume size for subsequent volumes, in bytes.
*/
private long maxVolumeSize = FileSpanningOutputStream.DEFAULT_VOLUME_SIZE;
/**
* The configuration attribute to specify the volume size.
*/
private static final String VOLUME_SIZE = "volumesize";
/**
* The configuration attribute to specify the first volume free space size.
*/
private static final String FIRST_VOLUME_FREE_SPACE = "firstvolumefreespace";
/**
* The logger.
*/
private static final Logger logger = Logger.getLogger(MultiVolumePackager.class.getName());
/**
* Constructs a MultiVolumePackager.
*
* @param properties the properties
* @param listener the packager listener
* @param mergeManager the merge manager
* @param pathResolver the path resolver
* @param mergeableResolver the mergeable resolver
* @param compilerData the compiler data
*/
public MultiVolumePackager(Properties properties, PackagerListener listener, JarOutputStream installerJar,
MergeManager mergeManager, CompilerPathResolver pathResolver,
MergeableResolver mergeableResolver, CompilerData compilerData, RulesEngine rulesEngine)
{
super(properties, listener, installerJar, mergeManager, pathResolver, mergeableResolver,
compilerData, rulesEngine);
}
/**
* Sets the maximum size of the first volume.
*
* Defaults to {@link FileSpanningOutputStream#DEFAULT_VOLUME_SIZE}.
*
* @param size the maximum size of the first volume, in bytes
*/
public void setMaxFirstVolumeSize(long size)
{
maxFirstVolumeSize = size;
}
/**
* Sets the maximum volume size for all volumes bar the first.
*
* Defaults to {@link FileSpanningOutputStream#DEFAULT_VOLUME_SIZE}.
*
* @param size the maximum volume size, in bytes
*/
public void setMaxVolumeSize(long size)
{
maxVolumeSize = size;
}
/**
* Parses configuration information.
*
* This determines the {@link #setMaxFirstVolumeSize(long) maximum size of the first volume}, and
* {@link #setMaxVolumeSize(long) maximum size of subsequent volumes} from the firstvolumefreespace
* and volumesize attributes.
*
* @param data the xml-element packaging from the install.xml
*/
public void addConfigurationInformation(IXMLElement data)
{
if (data != null)
{
long freeSpace = Long.valueOf(data.getAttribute(FIRST_VOLUME_FREE_SPACE, "0"));
long size = Long.valueOf(data.getAttribute(VOLUME_SIZE, Long.toString(maxVolumeSize)));
setMaxFirstVolumeSize(size - freeSpace);
setMaxVolumeSize(size);
}
}
/**
* Writes packs to one or more .pak volumes.
*
* Pack meta-data is written to the installer jar.
*
* @throws IOException for any I/O error
*/
@Override
protected void writePacks(JarOutputStream installerJar) throws IOException
{
String classname = getClass().getSimpleName();
// propagate the configuration to the variables, for debugging purposes
getVariables().setProperty(classname + "." + FIRST_VOLUME_FREE_SPACE, Long.toString(maxFirstVolumeSize));
getVariables().setProperty(classname + "." + VOLUME_SIZE, Long.toString(maxVolumeSize));
List packs = getPacksList();
final int count = packs.size();
sendMsg("Writing " + count + " Pack" + (count > 1 ? "s" : "") + " into installer");
logger.fine("Writing " + count + " Pack" + (count > 1 ? "s" : "") + " into installer");
logger.fine("First volume size: " + maxFirstVolumeSize);
logger.fine("Subsequent volume size: " + maxVolumeSize);
File volume = new File(getInfo().getInstallerBase() + ".pak").getAbsoluteFile();
int volumes = writePacks(installerJar, packs, volume);
// write metadata for reading in volumes
logger.fine("Written " + volumes + " volumes");
installerJar.putNextEntry(new ZipEntry(RESOURCES_PATH + "volumes.info"));
ObjectOutputStream out = new ObjectOutputStream(installerJar);
out.writeInt(volumes);
out.writeUTF(volume.getName());
out.flush();
installerJar.closeEntry();
// Now that we know sizes, write pack metadata to primary jar.
installerJar.putNextEntry(new ZipEntry(PACKSINFO_RESOURCE_PATH));
out = new ObjectOutputStream(installerJar);
out.writeObject(packs);
out.flush();
installerJar.closeEntry();
}
/**
* Writes packs to one or more .pak volumes.
*
* @param packs the packs to write
* @param volume the first volume
* @return the no. of volumes written
*/
private int writePacks(JarOutputStream installerJar, List packs, File volume) throws IOException
{
FileSpanningOutputStream volumes = new FileSpanningOutputStream(volume, maxFirstVolumeSize, maxVolumeSize);
File targetDir = volume.getParentFile();
if (targetDir == null)
{
throw new IOException("Cannot determine parent directory of " + volume);
}
for (PackInfo packInfo : packs)
{
writePack(installerJar, packInfo, volumes, targetDir);
}
volumes.flush();
volumes.close();
return volumes.getVolumes();
}
/**
* Writes a pack.
*
* Pack information is written to the installer jar, while the actual files are written to the volumes.
*
* @param packInfo the pack information
* @param volumes the volumes
* @param targetDir the target directory for loosefiles
* @throws IOException for any I/O error
*/
private void writePack(JarOutputStream installerJar, PackInfo packInfo, FileSpanningOutputStream volumes, File targetDir) throws IOException
{
Pack pack = packInfo.getPack();
pack.setFileSize(0);
String name = pack.getName();
sendMsg("Writing Pack: " + name, PackagerListener.MSG_VERBOSE);
logger.fine("Writing Pack: " + name);
ZipEntry entry = new ZipEntry(RESOURCES_PATH + "packs/pack-" + name);
installerJar.putNextEntry(entry);
ObjectOutputStream packStream = new ObjectOutputStream(installerJar);
writePackFiles(packInfo, volumes, pack, packStream, targetDir);
// Cleanup
packStream.flush();
}
/**
* Writes the pack files.
*
* The file data is written to volumes, whilst the meta-data is written to packStream.
*
* @param packInfo the pack information
* @param volumes the volumes to write to
* @param pack the pack
* @param packStream the stream to write the pack meta-data to
* @param targetDir the target directory for loose files
* @throws IOException for any I/O error
*/
private void writePackFiles(PackInfo packInfo, FileSpanningOutputStream volumes, Pack pack,
ObjectOutputStream packStream, File targetDir) throws IOException
{
Set files = packInfo.getPackFiles();
Map xFiles = new LinkedHashMap();
for (PackFile packfile : files)
{
XPackFile pf = new XPackFile(packfile);
File file = packInfo.getFile(packfile);
logger.fine("Next file: " + file.getAbsolutePath());
if (!pf.isDirectory())
{
if (!pack.isLoose())
{
writePackFile(file, volumes, pf);
}
else
{
// just copy the file to the target directory
FileUtils.copyFile(file, new File(targetDir, pf.getRelativeSourcePath()));
}
}
xFiles.put(pf, file);
// even if not written, it counts towards pack size
pack.addFileSize(pf.length());
}
// Replace the PackFile objects by the corresponding XPackFile objects to be written to the packs.info resource
Map packFilesMap = packInfo.getPackFilesMap();
packFilesMap.clear();
packFilesMap.putAll(xFiles);
if (pack.getFileSize() > pack.getSize())
{
pack.setSize(pack.getFileSize());
}
}
/**
* Writes a pack file to the volumes.
*
* @param file the file to write
* @param volumes the volumes
* @param packFile the pack file
* @throws IOException for any I/O error
*/
private void writePackFile(File file, FileSpanningOutputStream volumes, XPackFile packFile) throws IOException
{
long beforePosition = volumes.getFilePointer();
packFile.setArchiveFilePosition(beforePosition);
// write the file to the volumes
int volumeCount = volumes.getVolumes();
FileInputStream in = FileUtils.openInputStream(file);
try
{
long bytesWritten = IOUtils.copyLarge(in, volumes);
long afterPosition = volumes.getFilePointer();
logger.fine("File (" + packFile.getFile() + ") " + beforePosition + " <-> " + afterPosition);
if (volumes.getFilePointer() != (beforePosition + bytesWritten))
{
logger.fine("file: " + file.getName());
logger.fine("(Filepos/BytesWritten/ExpectedNewFilePos/NewFilePointer) ("
+ beforePosition + "/" + bytesWritten + "/" + (beforePosition + bytesWritten)
+ "/" + volumes.getFilePointer() + ")");
logger.fine("Volumes (before/after) (" + volumeCount + "/" + volumes.getVolumes() + ")");
throw new IOException("Error new file pointer is illegal");
}
if (bytesWritten != packFile.length())
{
throw new IOException("File size mismatch when reading " + file);
}
}
finally
{
IOUtils.closeQuietly(in);
}
}
}