Package org.jnode.build

Source Code of org.jnode.build.BootFloppyBuilder

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* 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 org.jnode.build;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
import org.jnode.driver.ApiNotFoundException;
import org.jnode.driver.Device;
import org.jnode.driver.DriverException;
import org.jnode.driver.block.BlockDeviceAPI;
import org.jnode.driver.block.FileDevice;
import org.jnode.fs.FSDirectory;
import org.jnode.fs.FSEntry;
import org.jnode.fs.FSFile;
import org.jnode.fs.FileSystemException;
import org.jnode.fs.fat.FatFileSystem;
import org.jnode.fs.fat.FatFileSystemType;
import org.jnode.fs.fat.GrubFatFormatter;
import org.jnode.util.FileUtils;

/**
* Builder for the boot floppy (in fact, it's not a floppy but a cdrom image in the iso format).
*
* @author epr
*/
public class BootFloppyBuilder extends Task {

    private File destFile;

    private String stage1ResourceName;

    private String stage2ResourceName;

    private ArrayList<FileSet> fileSets = new ArrayList<FileSet>();

    /**
     * Build the boot floppy.
     *
     * @throws BuildException
     */
    public void execute() throws BuildException {

        try {
            if (isExecuteNeeded()) {
                createImage();
            }
        } catch (Throwable ex) {
            ex.printStackTrace(System.err);
            throw new BuildException(ex);
        }
    }

    protected boolean isExecuteNeeded() {
        final long lmDest = destFile.lastModified();
        return (getLastModified() > lmDest);
    }

    /**
     * Create the actual bootfloppy.
     *
     * @throws IOException
     * @throws DriverException
     * @throws FileSystemException
     */
    public void createImage() throws IOException, DriverException,
        FileSystemException {

        final FileDevice newFd = new FileDevice(destFile, "rw");
        try {
            newFd.setLength(getDeviceLength());
            formatDevice(newFd);
            final Device sysDev = getSystemDevice(newFd);
            final BlockDeviceAPI sysDevApi = sysDev
                .getAPI(BlockDeviceAPI.class);
            copySystemFiles(sysDev);
            sysDevApi.flush();
        } catch (ApiNotFoundException ex) {
            final IOException ioe = new IOException("BlockDeviceAPI not found on device");
            ioe.initCause(ex);
            throw ioe;
        } finally {
            newFd.close();
        }
    }

    /**
     * Format the given device.
     *
     * @param dev
     * @throws IOException
     */
    protected void formatDevice(Device dev) throws IOException {
        GrubFatFormatter ff = createFormatter();
        try {
            ff.format(dev.getAPI(BlockDeviceAPI.class));
        } catch (ApiNotFoundException ex) {
            final IOException ioe = new IOException("BlockDeviceAPI not found on device");
            ioe.initCause(ex);
            throw ioe;
        }
    }

    /**
     * Gets the device the system files must be copied onto. This enabled a
     * disk to be formatted with partitions.
     *
     * @param rootDevice
     * @return BlockDevice
     */
    protected Device getSystemDevice(Device rootDevice) {
        return rootDevice;
    }

    /**
     * Copy the system files to the given device.
     *
     * @param device
     * @throws IOException
     * @throws FileSystemException
     */
    protected void copySystemFiles(Device device) throws IOException,
        FileSystemException {
        final FatFileSystem fs = new FatFileSystem(device, false, new FatFileSystemType());

        for (FileSet fset : fileSets) {
            processFileSet(fs, fset);
        }

        fs.close();
    }

    private void processFileSet(FatFileSystem fs, FileSet fset) throws IOException {
        final DirectoryScanner ds = fset.getDirectoryScanner(getProject());
        final String[] dirs = ds.getIncludedDirectories();
        for (int i = 0; i < dirs.length; i++) {
            getOrCreateDir(fs, dirs[i]);
        }
        final String[] files = ds.getIncludedFiles();
        for (int i = 0; i < files.length; i++) {
            final String fn = files[i];
            final int idx = fn.lastIndexOf(File.separatorChar);
            final FSDirectory dir;
            final String name;
            if (idx >= 0) {
                dir = getOrCreateDir(fs, fn.substring(0, idx));
                name = fn.substring(idx + 1);
            } else {
                dir = getOrCreateDir(fs, "");
                name = fn;
            }
            final File f = new File(ds.getBasedir(), fn);
            addFile(dir, f, name);
        }
    }

    /**
     * Gets the latest modification date for all of the parameter fileSets.
     *
     * @return the latest modification date.
     */
    protected long getLastModified() {
        long lm = 0l;
        for (FileSet fset : fileSets) {
            lm = Math.max(lm, getLastModified(fset));
        }
        return lm;
    }

    private long getLastModified(FileSet fset) {
        final DirectoryScanner ds = fset.getDirectoryScanner(getProject());
        final File baseDir = ds.getBasedir();
        long lm = 0l;
        final String[] dirs = ds.getIncludedDirectories();
        for (int i = 0; i < dirs.length; i++) {
            lm = Math.max(lm, new File(baseDir, dirs[i]).lastModified());
        }
        final String[] files = ds.getIncludedFiles();
        for (int i = 0; i < files.length; i++) {
            lm = Math.max(lm, new File(baseDir, files[i]).lastModified());
        }
        return lm;

    }

    private FSDirectory getOrCreateDir(FatFileSystem fs, String dirName)
        throws IOException {
        FSDirectory dir = fs.getRootDir();
        while (dirName.length() > 0) {
            final int idx = dirName.indexOf(File.separatorChar);
            final String part;
            if (idx >= 0) {
                part = dirName.substring(0, idx);
                dirName = dirName.substring(idx + 1);
            } else {
                part = dirName;
                dirName = "";
            }
            FSEntry entry;
            try {
                entry = dir.getEntry(part);
            } catch (IOException ex) {
                // Ignore
                entry = null;
            }
            if (entry == null) {
                entry = dir.addDirectory(part);
            }
            dir = entry.getDirectory();
        }
        return dir;
    }

    /**
     * Add a given file to a given directory with a given filename.
     *
     * @param dir
     * @param src
     * @param fname
     * @throws IOException
     */
    private void addFile(FSDirectory dir, File src, String fname)
        throws IOException {

        long size = src.length();
        /*
         * log.info( "Adding " + src + " as " + fname + " size " + (size /
         * 1024) + "Kb");
         */

        //final byte[] buf = new byte[ (int) size];
        final ByteBuffer buf = ByteBuffer.allocate((int) size);
        InputStream is = new FileInputStream(src);
        FileUtils.copy(is, buf.array());
        is.close();

        final FSFile fh = dir.addFile(fname).getFile();
        fh.setLength(size);
        //fh.write(0, buf, 0, buf.length);
        fh.write(0, buf);

        log("Added " + src + " as " + fname + " size " + (size / 1024) + "Kb");
    }

    /**
     * Returns the destFile.
     *
     * @return File
     */
    public File getDestFile() {
        return destFile;
    }

    /**
     * Sets the destFile.
     *
     * @param destFile The destFile to set
     */
    public void setDestFile(File destFile) {
        this.destFile = destFile;
    }

    protected GrubFatFormatter createFormatter() throws IOException {
        return new GrubFatFormatter(0, stage1ResourceName, stage2ResourceName);
    }

    protected long getDeviceLength() {
        return 1440 * 1024;
    }

    /**
     * @return Returns the stage1ResourceName.
     */
    public final String getStage1ResourceName() {
        return this.stage1ResourceName;
    }

    /**
     * @param stage1ResourceName The stage1ResourceName to set.
     */
    public final void setStage1ResourceName(String stage1ResourceName) {
        this.stage1ResourceName = stage1ResourceName;
    }

    /**
     * @return Returns the stage2ResourceName.
     */
    public final String getStage2ResourceName() {
        return this.stage2ResourceName;
    }

    /**
     * @param stage2ResourceName The stage2ResourceName to set.
     */
    public final void setStage2ResourceName(String stage2ResourceName) {
        this.stage2ResourceName = stage2ResourceName;
    }

    /**
     * Create and add a fileset to this task.
     *
     * @return the fileset created
     */
    public FileSet createFileset() {
        final FileSet fs = new FileSet();
        fileSets.add(fs);
        return fs;
    }
}
TOP

Related Classes of org.jnode.build.BootFloppyBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.