All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.stephenc.javaisotools.udflib.SabreUDFImageBuilder Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010. Stephen Connolly.
 * Copyright (c) 2006. Björn Stickler .
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

package com.github.stephenc.javaisotools.udflib;

import java.io.File;
import java.util.Calendar;
import java.util.Iterator;

import com.github.stephenc.javaisotools.sabre.HandlerException;
import com.github.stephenc.javaisotools.sabre.StreamHandler;
import com.github.stephenc.javaisotools.udflib.handler.DescriptorTagHandler;
import com.github.stephenc.javaisotools.udflib.handler.PaddingHandler;
import com.github.stephenc.javaisotools.udflib.handler.SerializationHandler;
import com.github.stephenc.javaisotools.udflib.handler.UDF102Handler;
import com.github.stephenc.javaisotools.udflib.handler.UDF201Handler;
import com.github.stephenc.javaisotools.udflib.handler.UDF260Handler;

public class SabreUDFImageBuilder {

    private String imageIdentifier = "SabreUDFImageBuilder Disc";

    private String applicationIdentifier = "*SabreUDFImageBuilder";
    private byte applicationIdentifierSuffix[] = new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    private int blockSize = 2048;

    private UDFImageBuilderFile rootUDFImageBuilderFile;

    public SabreUDFImageBuilder() {
        rootUDFImageBuilderFile = new UDFImageBuilderFile("");
    }

    public void setImageIdentifier(String imageIdentifier)
            throws Exception {
        if (imageIdentifier.length() > 30) {
            throw new Exception("error: image identifier length > 30 characters");
        }

        this.imageIdentifier = imageIdentifier;
    }

    public void addFileToRootDirectory(UDFImageBuilderFile myUDFImageBuilderFile)
            throws Exception {
        rootUDFImageBuilderFile.addChild(myUDFImageBuilderFile);
    }

    public void addFileToRootDirectory(File myFile)
            throws Exception {
        rootUDFImageBuilderFile.addChild(myFile);
    }

    private StreamHandler buildStreamHandlerPipeline(UDFRevision myUDFRevision, String outputFilename)
            throws HandlerException {
        // serialization handler
        StreamHandler myStreamHandler = new SerializationHandler(new File(outputFilename));

        // padding handler
        myStreamHandler = new PaddingHandler(myStreamHandler, myStreamHandler);

        // descriptor tag hander
        myStreamHandler = new DescriptorTagHandler(myStreamHandler, myStreamHandler);

        // version dependent handler
        if (myUDFRevision == UDFRevision.Revision102) {
            myStreamHandler = new UDF102Handler(myStreamHandler, myStreamHandler);
        } else if (myUDFRevision == UDFRevision.Revision201) {
            myStreamHandler = new UDF201Handler(myStreamHandler, myStreamHandler);
        } else if (myUDFRevision == UDFRevision.Revision260) {
            myStreamHandler = new UDF260Handler(myStreamHandler, myStreamHandler);
        }

        return myStreamHandler;
    }

    public void writeImage(String outputFilename, UDFRevision myUDFRevision)
            throws HandlerException {
        long recordingTimeMillis = Calendar.getInstance().getTimeInMillis();

        // preprocess all information needed for linear-output-streaming
        UDFLayoutInformation myUDFLayoutInformation = null;
        try {
            myUDFLayoutInformation = new UDFLayoutInformation(rootUDFImageBuilderFile, myUDFRevision, blockSize);
        }
        catch (Exception ex) {
            throw new HandlerException(ex);
        }

        StreamHandler myStreamHandler = buildStreamHandlerPipeline(myUDFRevision, outputFilename);

        SabreUDFElementFactory mySabreUDFElementFactory = new SabreUDFElementFactory(myStreamHandler);

        mySabreUDFElementFactory.startUDFImage();

        // write reserved area
        mySabreUDFElementFactory.startReservedArea();
        mySabreUDFElementFactory.endReservedArea();

        // write volume recognition sequence
        mySabreUDFElementFactory.startVRS();
        mySabreUDFElementFactory.endVRS();

        // write empty area between vrs and avdp (block 19 to block 256)
        mySabreUDFElementFactory.startEmptyArea();
        mySabreUDFElementFactory.doEmptyArea((256 - 19) * blockSize);
        mySabreUDFElementFactory.endEmptyArea();

        // write anchor volume descriptor pointer 1
        mySabreUDFElementFactory.startAVDP();
        mySabreUDFElementFactory.doAVDP(myUDFLayoutInformation.AVDP1Block, myUDFLayoutInformation.MVDSStartingBlock,
                myUDFLayoutInformation.RVDSStartingBlock);
        mySabreUDFElementFactory.endAVDP();

        /*
           * 		WRITE MAIN VOLUME DESCRIPTOR SEQUENCE
           */

        // write primary volume descriptor
        mySabreUDFElementFactory.startPVD();
        mySabreUDFElementFactory
                .doPVD(myUDFLayoutInformation.PVD1Block, 1, recordingTimeMillis, imageIdentifier, applicationIdentifier,
                        applicationIdentifierSuffix);
        mySabreUDFElementFactory.endPVD();

        // write partition descriptor
        mySabreUDFElementFactory.startPD();
        mySabreUDFElementFactory
                .doPD(myUDFLayoutInformation.PD1Block, 2, myUDFLayoutInformation.physicalPartitionStartingBlock,
                        myUDFLayoutInformation.physicalPartitionEndingBlock, applicationIdentifier,
                        applicationIdentifierSuffix);
        mySabreUDFElementFactory.endPD();

        // write logical volume descriptor
        mySabreUDFElementFactory.startLVD();
        mySabreUDFElementFactory.doLVD(myUDFLayoutInformation.LVD1Block, 3, myUDFLayoutInformation.LVIDSStartingBlock,
                myUDFLayoutInformation.LVIDSEndingBlock, myUDFLayoutInformation.metadataAllocationUnitSize,
                myUDFLayoutInformation.metadataAlignmentUnitSize, myUDFLayoutInformation.mainMetadataFileLocation,
                myUDFLayoutInformation.mirrorMetadataFileLocation, myUDFLayoutInformation.partitionToStoreMetadataOn,
                myUDFLayoutInformation.FSDLocation, applicationIdentifier, applicationIdentifierSuffix,
                imageIdentifier);
        mySabreUDFElementFactory.endLVD();

        // write unallocated space descriptor
        mySabreUDFElementFactory.startUSD();
        mySabreUDFElementFactory.doUSD(myUDFLayoutInformation.USD1Block, 4, 19, 256);
        mySabreUDFElementFactory.endUSD();

        // write implementation use volume descriptor
        mySabreUDFElementFactory.startIUVD();
        mySabreUDFElementFactory
                .doIUVD(myUDFLayoutInformation.IUVD1Block, 5, applicationIdentifier, applicationIdentifierSuffix,
                        imageIdentifier);
        mySabreUDFElementFactory.endIUVD();

        // write terminating descriptor
        mySabreUDFElementFactory.startTD();
        mySabreUDFElementFactory.doTD(myUDFLayoutInformation.TD1Block);
        mySabreUDFElementFactory.endTD();

        // write empty blocks for remaining main volume descriptor sequence space
        mySabreUDFElementFactory.startEmptyArea();
        mySabreUDFElementFactory.doEmptyArea(
                (int) (myUDFLayoutInformation.MVDSEndingBlock - myUDFLayoutInformation.MVDSStartingBlock - 6) *
                        blockSize);
        mySabreUDFElementFactory.endEmptyArea();

        /*
           * 		WRITE LOGICAL VOLUME INTEGRITY DESCRIPTOR SEQUENCE
           */
        // write logical volume integrity descriptor
        mySabreUDFElementFactory.startLVID();
        mySabreUDFElementFactory.doLVID(myUDFLayoutInformation.LVIDSStartingBlock + 0, recordingTimeMillis,
                myUDFLayoutInformation.fileCount, myUDFLayoutInformation.directoryCount, applicationIdentifier,
                applicationIdentifierSuffix, myUDFLayoutInformation.sizeTable, myUDFLayoutInformation.freespaceTable,
                myUDFLayoutInformation.nextUniqueId);
        mySabreUDFElementFactory.endLVID();

        // write terminating descriptor
        mySabreUDFElementFactory.startTD();
        mySabreUDFElementFactory.doTD(myUDFLayoutInformation.LVIDSStartingBlock + 1);
        mySabreUDFElementFactory.endTD();

        // write empty blocks for remaining logical volume integrity sequence space
        mySabreUDFElementFactory.startEmptyArea();
        mySabreUDFElementFactory.doEmptyArea(
                (int) (myUDFLayoutInformation.LVIDSEndingBlock - myUDFLayoutInformation.LVIDSStartingBlock - 2) *
                        blockSize);
        mySabreUDFElementFactory.endEmptyArea();

        /*
           * 		WRITE METADATA
           */

        // one empty block at the start of the partition
        mySabreUDFElementFactory.startEmptyArea();
        mySabreUDFElementFactory.doEmptyArea(blockSize);
        mySabreUDFElementFactory.endEmptyArea();

        // write main metadata file (if revision needs it)
        mySabreUDFElementFactory.startMetadataFile();
        mySabreUDFElementFactory.doMetadataFile(recordingTimeMillis, applicationIdentifier, applicationIdentifierSuffix,
                myUDFLayoutInformation, myUDFLayoutInformation.mainMetadataFileLocation, (byte) 250);
        mySabreUDFElementFactory.endMetadataFile();

        // write fileset descriptor
        mySabreUDFElementFactory.startFSD();
        mySabreUDFElementFactory
                .doFSD(myUDFLayoutInformation.FSDLocation, recordingTimeMillis, myUDFLayoutInformation.rootFELocation,
                        myUDFLayoutInformation.partitionToStoreMetadataOn, imageIdentifier);
        mySabreUDFElementFactory.endFSD();

        // write file entry elements (without their data if non-directory and non-embedded)
        Iterator myIterator = myUDFLayoutInformation.linearUDFImageBuilderFileOrdering.iterator();
        while (myIterator.hasNext()) {
            UDFImageBuilderFile myUDFImageBuilderFile = myIterator.next();

            mySabreUDFElementFactory.startFE();
            mySabreUDFElementFactory.doFE(myUDFImageBuilderFile, myUDFLayoutInformation, applicationIdentifier,
                    applicationIdentifierSuffix);
            mySabreUDFElementFactory.endFE();
        }

        // write metadata empty area (if metadata partition existent)
        mySabreUDFElementFactory.startEmptyArea();
        mySabreUDFElementFactory.doEmptyArea((int) (myUDFLayoutInformation.metadataEmptyArea * blockSize));
        mySabreUDFElementFactory.endEmptyArea();

        /*
           * 		WRITE FILEDATA
           */

        // write raw file data
        myIterator = myUDFLayoutInformation.linearUDFImageBuilderFileOrdering.iterator();
        while (myIterator.hasNext()) {
            UDFImageBuilderFile myUDFImageBuilderFile = myIterator.next();

            UDFLayoutInformation.FileEntryPosition myFileEntryPosition =
                    myUDFLayoutInformation.fileEntryPositions.get(myUDFImageBuilderFile);

            if (myUDFImageBuilderFile.getFileType() == UDFImageBuilderFile.FileType.File &&
                    myFileEntryPosition.dataBlock != -1) {
                mySabreUDFElementFactory.startRawFileData();
                mySabreUDFElementFactory.doRawFileData(myUDFImageBuilderFile.getSourceFile());
                mySabreUDFElementFactory.endRawFileData();
            }
        }

        // write mirror metadata file (if revision needs it)
        mySabreUDFElementFactory.startMetadataFile();
        mySabreUDFElementFactory.doMetadataFile(recordingTimeMillis, applicationIdentifier, applicationIdentifierSuffix,
                myUDFLayoutInformation, myUDFLayoutInformation.mirrorMetadataFileLocation, (byte) 251);
        mySabreUDFElementFactory.endMetadataFile();

        /*
           * 		WRITE RESERVE VOLUME DESCRIPTOR SEQUENCE
           */

        // write primary volume descriptor
        mySabreUDFElementFactory.startPVD();
        mySabreUDFElementFactory
                .doPVD(myUDFLayoutInformation.PVD2Block, 1, recordingTimeMillis, imageIdentifier, applicationIdentifier,
                        applicationIdentifierSuffix);
        mySabreUDFElementFactory.endPVD();

        // write partition descriptor
        mySabreUDFElementFactory.startPD();
        mySabreUDFElementFactory
                .doPD(myUDFLayoutInformation.PD2Block, 2, myUDFLayoutInformation.physicalPartitionStartingBlock,
                        myUDFLayoutInformation.physicalPartitionEndingBlock, applicationIdentifier,
                        applicationIdentifierSuffix);
        mySabreUDFElementFactory.endPD();

        // write logical volume descriptor
        mySabreUDFElementFactory.startLVD();
        mySabreUDFElementFactory.doLVD(myUDFLayoutInformation.LVD2Block, 3, myUDFLayoutInformation.LVIDSStartingBlock,
                myUDFLayoutInformation.LVIDSEndingBlock, myUDFLayoutInformation.metadataAllocationUnitSize,
                myUDFLayoutInformation.metadataAlignmentUnitSize, myUDFLayoutInformation.mainMetadataFileLocation,
                myUDFLayoutInformation.mirrorMetadataFileLocation, myUDFLayoutInformation.partitionToStoreMetadataOn,
                myUDFLayoutInformation.FSDLocation, applicationIdentifier, applicationIdentifierSuffix,
                imageIdentifier);
        mySabreUDFElementFactory.endLVD();

        // write unallocated space descriptor
        mySabreUDFElementFactory.startUSD();
        mySabreUDFElementFactory.doUSD(myUDFLayoutInformation.USD2Block, 4, 19, 256);
        mySabreUDFElementFactory.endUSD();

        // write implementation use volume descriptor
        mySabreUDFElementFactory.startIUVD();
        mySabreUDFElementFactory
                .doIUVD(myUDFLayoutInformation.IUVD2Block, 5, applicationIdentifier, applicationIdentifierSuffix,
                        imageIdentifier);
        mySabreUDFElementFactory.endIUVD();

        // write terminating descriptor
        mySabreUDFElementFactory.startTD();
        mySabreUDFElementFactory.doTD(myUDFLayoutInformation.TD2Block);
        mySabreUDFElementFactory.endTD();

        // write empty blocks for remaining main volume descriptor sequence space
        mySabreUDFElementFactory.startEmptyArea();
        mySabreUDFElementFactory.doEmptyArea(
                (int) (myUDFLayoutInformation.RVDSEndingBlock - myUDFLayoutInformation.RVDSStartingBlock - 5) *
                        blockSize);
        mySabreUDFElementFactory.endEmptyArea();

        // write anchor volume descriptor pointer 2
        mySabreUDFElementFactory.startAVDP();
        mySabreUDFElementFactory.doAVDP(myUDFLayoutInformation.AVDP2Block, myUDFLayoutInformation.MVDSStartingBlock,
                myUDFLayoutInformation.RVDSStartingBlock);
        mySabreUDFElementFactory.endAVDP();

        mySabreUDFElementFactory.endUDFImage();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy