Package net.rim.tumbler.file

Source Code of net.rim.tumbler.file.FileManager

/*
* Copyright 2010-2011 Research In Motion Limited.
*
* 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 net.rim.tumbler.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import net.rim.tumbler.exception.PackageException;
import net.rim.tumbler.session.BBWPProperties;
import net.rim.tumbler.session.SessionManager;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class FileManager {
    private BBWPProperties           _bbwpProperties;
    private Vector<String>           _outputFiles;
    private Vector<String>           _extensionClasses;
   
    private static final String         EOL = System.getProperty("line.separator");
    private static final String         FILE_SEP = System.getProperty("file.separator");
    private static final String         STANDARD_OUTPUT = "StandardInstall";
    private static final String         OTA_OUTPUT = "OTAInstall";
    private static final String         EXTENSION_DIRECTORY = "extension";
   
    public FileManager(BBWPProperties bbwpProperties) {
        _bbwpProperties = bbwpProperties;
        _outputFiles = new Vector<String>();
        _extensionClasses = new Vector<String>();
    }
   
    public List<String> getFiles() {
        return _outputFiles;
    }

    public void cleanOutput() {
        String outputDir = SessionManager.getInstance().getOutputFolder();
        String archiveName = SessionManager.getInstance().getArchiveName();
        deleteDirectory(new File(outputDir + FILE_SEP + FileManager.OTA_OUTPUT));
        deleteDirectory(new File(outputDir + FILE_SEP + FileManager.STANDARD_OUTPUT));
        (new File(outputDir + FILE_SEP + archiveName + ".jar")).delete();
        (new File(outputDir + FILE_SEP + archiveName + ".rapc")).delete();
    }
   
    public void cleanSource() {
        deleteDirectory(new File(SessionManager.getInstance().getSourceFolder()));
    }
   
    public void prepare() throws Exception {
        // clean out source folder
        deleteDirectory(new File(SessionManager.getInstance().getSourceFolder()));
        (new File(SessionManager.getInstance().getSourceFolder())).mkdirs();
       
        // copy templates
        try {
            TemplateWrapper templateWrapper = new TemplateWrapper(_bbwpProperties);
            _outputFiles.addAll(templateWrapper.writeAllTemplates(
                    SessionManager.getInstance().getSourceFolder()));
        } catch (IOException ex) {
            throw new PackageException("EXCEPTION_IO_TEMPLATES");
        }
       
        // extract archive
        ZipFile zip = new ZipFile(new File(SessionManager.getInstance().getWidgetArchive()).getAbsolutePath());
        Enumeration<?> en = zip.entries();
        String sourceFolder = SessionManager.getInstance().getSourceFolder();
        while (en.hasMoreElements()) {
            // create output file name
            ZipEntry ze = (ZipEntry) en.nextElement();
            if (ze.isDirectory())
                continue;           
           
            String zipEntryName = ze.getName();
            File zipEntryFile = new File(ze.getName());
            boolean isRoot = zipEntryFile.getParent() == null;
            String fname = sourceFolder + FILE_SEP + zipEntryFile.getPath();
           
            // extract file
            InputStream is = new BufferedInputStream(zip.getInputStream(ze));
            File fi = new File(fname);
            if (!fi.getParentFile().isDirectory() || !fi.getParentFile().exists())
                fi.getParentFile().mkdirs();
            OutputStream fos = new BufferedOutputStream(new FileOutputStream(fname));
            int bytesRead;
            while ((bytesRead = is.read()) != -1)
                fos.write(bytesRead);
            fos.close();       
           
            if (zipEntryName.startsWith("ext") && zipEntryName.endsWith(".jar")) {
                populateExtension(fname);
            } else {
                // HACK for icon files not displayed properly if similar named files exist in sub folders
                if (!isRoot) {
                    _outputFiles.add(0, fname);
                } else {
                    _outputFiles.add(fname);
                }
            }
        }
    }
   
    // Generate .jdp and .jdw files
    public void generateProjectFiles(
            String sourceDir,
            String codName,
            String appName,
            String appVersion,
            String appVendor,
            String contentSource,
            String backgroundSource,
            boolean isStartupEnabled,
            Vector<String> icons,
            Vector<String> hoverIcons,
            List<String> inputFiles,
            List<String> libraryFiles)
            throws IOException {
        String fileName;
        BufferedWriter writer;

        // jdw file
        fileName = sourceDir + FILE_SEP + codName + ".jdw";
        writer = new BufferedWriter(new FileWriter(fileName));

        writer.write("## RIM Java Development Environment" + EOL);
        writer.write("# RIM Workspace file" + EOL);
        writer.write("#" + EOL);
        writer.write("# This file is generated and managed by BlackBerry developer tools."+ EOL);
        writer.write("# It SHOULD NOT BE modified manually." + EOL);
        writer.write("#" + EOL);
        writer.write("[BuildConfigurations" + EOL);
        writer.write("Debug" + EOL);
        writer.write("Release" + EOL);
        writer.write("]" + EOL);
        writer.write("DependenciesInWorkspace=0" + EOL);
        writer.write("[ImplicitRules" + EOL);
        writer.write("]" + EOL);
        writer.write("[Imports" + EOL);
        writer.write("]" + EOL);
        writer.write("[Projects" + EOL);
        writer.write(codName + ".jdp" + EOL);
       
        // Alternate entry project
        if(backgroundSource!=null&&isStartupEnabled) {
            writer.write("runOnStartup.jdp" + EOL);
        }
       
        writer.write("]" + EOL);
        writer.write("[ReleaseActiveProjects" + EOL);
        writer.write(codName + ".jdp" + EOL);
        writer.write("]" + EOL);
        writer.close();

        // jdp file
        fileName = sourceDir + FILE_SEP + codName + ".jdp";
        writer = new BufferedWriter(new FileWriter(fileName));

        writer.write("## RIM Java Development Environment" + EOL);
        writer.write("# RIM Project file" + EOL);
        writer.write("#" + EOL);
        writer.write("# This file is generated and managed by BlackBerry developer tools."+ EOL);
        writer.write("# It SHOULD NOT BE modified manually." + EOL);
        writer.write("#" + EOL);
        writer.write("AddOn=0" + EOL);
        writer.write("AlwaysBuild=0" + EOL);
        writer.write("[AlxImports" + EOL);
        writer.write("]" + EOL);
        writer.write("AutoRestart=0" + EOL);
        writer.write("[ClassProtection" + EOL);
        writer.write("]" + EOL);
        writer.write("[CustomBuildFiles" + EOL);
        writer.write("]" + EOL);
        writer.write("[CustomBuildRules" + EOL);
        writer.write("]" + EOL);
        writer.write("[DefFiles" + EOL);
        writer.write("]" + EOL);
        writer.write("[DependsOn" + EOL);
        writer.write("]" + EOL);
        writer.write("ExcludeFromBuildAll=0" + EOL);
        writer.write("Exported=0" + EOL);

        writer.write("[Files" + EOL);
        for (int i = 0; i < inputFiles.size(); ++i) {
            String inputFile = inputFiles.get(i);
            inputFile = inputFile.substring(sourceDir.length() + 1);
            writer.write(inputFile + EOL);
        }
        writer.write("]" + EOL);

        writer.write("HaveAlxImports=0" + EOL);
        writer.write("HaveDefs=0" + EOL);
        writer.write("HaveImports=1" + EOL);

        writer.write("[Icons" + EOL);
        if (icons != null) {
            for (int i = 0; i < icons.size(); ++i) {
                writer.write(icons.elementAt(i) + EOL);
            }
        }
        writer.write("]" + EOL);

        writer.write("[ImplicitRules" + EOL);
        writer.write("]" + EOL);

        writer.write("[Imports" + EOL);
        for (int i = 0; i < libraryFiles.size(); ++i) {
            String libraryFile = libraryFiles.get(i);
            writer.write(libraryFile + EOL);
        }
        writer.write("]" + EOL);

        writer.write("Listing=0" + EOL);
        if(contentSource!=null) {
            writer.write("MidletClass=rim:foreground"+EOL);
        } else {
            writer.write("MidletClass="+EOL);
        }
        writer.write("Options=-quiet -deprecation" + EOL);
        writer.write("OutputFileName=" + codName + EOL);
        writer.write("[PackageProtection" + EOL);
        writer.write("]" + EOL);
        writer.write("Platform=0" + EOL);
        writer.write("RibbonPosition=0" + EOL);

        writer.write("[RolloverIcons" + EOL);
        if (hoverIcons != null) {
            for (int i = 0; i < hoverIcons.size(); ++i) {
                writer.write(hoverIcons.elementAt(i) + EOL);
            }
        }
        writer.write("]" + EOL);

        writer.write("RunOnStartup=0" + EOL);
        writer.write("StartupTier=7" + EOL);
       
        if(contentSource!=null&&contentSource.length()!=0) {
            writer.write("SystemModule=0" + EOL);
        } else {
            writer.write("SystemModule=1" + EOL);
        }
       
        writer.write("Title=" + appName + EOL);
        writer.write("Type=0" + EOL);
        if (appVendor != null) { writer.write("Vendor=" + appVendor + EOL); }
        writer.write("Version=" + appVersion + EOL);

        writer.close();
       
        //Alternate jdp file
       
        //Do not generate the alternate jdp file if it isn't required
        if(backgroundSource==null||!isStartupEnabled) {
            return;
        }
       
        fileName = sourceDir + FILE_SEP + "runOnStartup.jdp";
        writer = new BufferedWriter(new FileWriter(fileName));

        writer.write("## RIM Java Development Environment" + EOL);
        writer.write("# RIM Project file" + EOL);
        writer.write("#" + EOL);
        writer.write("# This file is generated and managed by BlackBerry developer tools."+ EOL);
        writer.write("# It SHOULD NOT BE modified manually." + EOL);
        writer.write("#" + EOL);
        writer.write("AddOn=0" + EOL);
        writer.write("AlwaysBuild=0" + EOL);
        writer.write("[AlxImports" + EOL);
        writer.write("]" + EOL);
        writer.write("AutoRestart=0" + EOL);
        writer.write("[ClassProtection" + EOL);
        writer.write("]" + EOL);
        writer.write("[CustomBuildFiles" + EOL);
        writer.write("]" + EOL);
        writer.write("[CustomBuildRules" + EOL);
        writer.write("]" + EOL);
        writer.write("[DefFiles" + EOL);
        writer.write("]" + EOL);
        writer.write("[DependsOn" + EOL);
        writer.write("]" + EOL);
        writer.write("EntryFor="+codName+EOL);
        writer.write("ExcludeFromBuildAll=0" + EOL);
        writer.write("Exported=0" + EOL);

        writer.write("[Files" + EOL);
        writer.write("]" + EOL);

        writer.write("HaveAlxImports=0" + EOL);
        writer.write("HaveDefs=0" + EOL);
        writer.write("HaveImports=1" + EOL);

        writer.write("[Icons" + EOL);
        writer.write("]" + EOL);

        writer.write("[ImplicitRules" + EOL);
        writer.write("]" + EOL);

        writer.write("[Imports" + EOL);
        writer.write("]" + EOL);

        writer.write("Listing=0" + EOL);
       
        writer.write("MidletClass=rim:runOnStartup"+EOL);
        writer.write("Options=-quiet -deprecation" + EOL);
        writer.write("OutputFileName=" + codName + EOL);
        writer.write("[PackageProtection" + EOL);
        writer.write("]" + EOL);
        writer.write("Platform=0" + EOL);
        writer.write("RibbonPosition=0" + EOL);

        writer.write("[RolloverIcons" + EOL);
        if (hoverIcons != null) {
            for (int i = 0; i < hoverIcons.size(); ++i) {
                writer.write(hoverIcons.elementAt(i) + EOL);
            }
        }
        writer.write("]" + EOL);
        writer.write("RunOnStartup=1" + EOL);
        writer.write("StartupTier=7" + EOL);
        writer.write("SystemModule=1" + EOL);
        writer.write("Title=" + appName + EOL);
        writer.write("Type=3" + EOL);
        if (appVendor != null) { writer.write("Vendor=" + appVendor + EOL); }
        writer.write("Version=" + appVersion + EOL);

        writer.close();
       
        return;
    }
   
    public void writeToSource(byte[] fileToWrite, String relativeFile) throws Exception {
        try {
            String s = SessionManager.getInstance().getSourceFolder() + FILE_SEP + relativeFile;
            if (!new File(s).exists()) {
                new File(s).getParentFile().mkdirs();
            }      
            FileOutputStream fos = new FileOutputStream(s);
            fos.write(fileToWrite);  
            fos.close();
           
            _outputFiles.add(s);
        }
        catch (Exception e) {
            throw new PackageException(e, relativeFile);
        }
    }

    /**
     * Copies output files from source for the specified file extensions.
     *
     * @param standardOutputs file extensions for standard outputs.
     * @param otaOutputs file extensions for OTA outputs.
     */
    public void copyOutputsFromSource(String[] standardOutputs, String[] otaOutputs)
        throws Exception
    {
        // TODO: verify for missing files
        String sourceFolder = SessionManager.getInstance().getSourceFolder();
        String outputFolder = SessionManager.getInstance().getOutputFolder();
        String archiveName = SessionManager.getInstance().getArchiveName();
        createOutputDirs(outputFolder);
       
        // Standard output
        File from, to;
        for (String ext : standardOutputs) {
            from = new File(sourceFolder + FILE_SEP + archiveName + ext);
            to = new File(outputFolder + FILE_SEP + FileManager.STANDARD_OUTPUT + FILE_SEP + archiveName + ext);
            copyFile(from, to);
        }
       
        // OTA output
        for (String ext : otaOutputs) {
            from = new File(sourceFolder + FILE_SEP + archiveName + ext);
            to = new File(outputFolder + FILE_SEP + FileManager.OTA_OUTPUT + FILE_SEP + archiveName + ext);
            copyFile(from, to);
        }
        from = new File(sourceFolder + FILE_SEP +  archiveName + ".cod");
        expandCod(from);
    }
   
    private void expandCod(File codFile) throws Exception {

        // if the codFile can be unzipped,
        // then the cod is too big and actually in the zip format with smaller
        // cods inside
        // otherwise, the cod is already a good cod

        ZipFile zipFile;

        // check for file's existence
        if (!codFile.exists()) {
            throw new PackageException("EXCEPTION_COD_NOT_FOUND");
        } else {
            try {
                zipFile = new ZipFile(codFile);
                zipFile.close();
            } catch (Exception e) {
                return; // this is a not a zip file and thus, not a big cod
            }
        }

        FileInputStream fis = new FileInputStream(codFile);
        CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32());
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(
                checksum));

        ZipEntry entry;
        BufferedOutputStream dest = null;
        final int BUFFER_SIZE = 1024;      


        while ((entry = zis.getNextEntry()) != null) {
            int count;
            byte data[] = new byte[BUFFER_SIZE];
           
            File f = new File(
                    SessionManager.getInstance().getOutputFolder()
                    + FILE_SEP
                    + "OTAInstall"
                    + FILE_SEP + entry.getName());
           
            f.getParentFile().mkdirs();
            f.createNewFile();
           
            // write the files to the disk
            FileOutputStream fos = new FileOutputStream(f);
            dest = new BufferedOutputStream(fos, BUFFER_SIZE);
            while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) {
                dest.write(data, 0, count);
            }
           
            dest.flush();
            dest.close();
        }

        zis.close();
    }
    // Copy a file
    public static void copyFile(File in, File out) throws IOException {
        // Create parent directories
        if (out.getAbsolutePath().lastIndexOf(File.separator) > 0) {
            String parentDirectory = out.getAbsolutePath().substring(0, out.getAbsolutePath().lastIndexOf(File.separator));
            new File(parentDirectory).mkdirs();
        }
       
        FileChannel inChannel = new FileInputStream(in).getChannel();
        FileChannel outChannel = new FileOutputStream(out).getChannel();
        try {
            // windows is limited to 64mb chunks
            long size = inChannel.size();
            long position = 0;
            while (position < size)
                position += inChannel
                        .transferTo(position, 67076096, outChannel);
        } finally {
            if (inChannel != null)
                inChannel.close();
            if (outChannel != null)
                outChannel.close();
        }
    }
   
    private void createOutputDirs(String outputFolder)
    {
        File standardInstallDir = new File(outputFolder + File.separator + FileManager.STANDARD_OUTPUT);
        File otaInstallDir = new File(outputFolder + File.separator + FileManager.OTA_OUTPUT);
       
        if (!(standardInstallDir.exists() && standardInstallDir.isDirectory())) {
            standardInstallDir.mkdirs();
        }

        if (!(otaInstallDir.exists() && otaInstallDir.isDirectory())) {
            otaInstallDir.mkdirs();        
        }     
    }

    // delete a dir
    private boolean deleteDirectory(File dir) {
        // remove files first
        if (dir.exists() && dir.isDirectory()) {
            String[] children = dir.list();
            for (String child : children) {
                if (!deleteDirectory(new File(dir, child)))
                    return false;
            }
        }
        if (dir.exists()) {
            // then remove the directory
            return dir.delete();
        }
        return false;
    }   
   
    private void populateExtension(String extensionArchive) throws Exception {
        // create the extension directory
        String extensionPath = SessionManager.getInstance().getSourceFolder() + FILE_SEP + EXTENSION_DIRECTORY  + FILE_SEP;
        (new File(extensionPath)).mkdirs();
       
        // extract all resource files in archive
        ZipFile zip = new ZipFile(new File(extensionArchive).getAbsolutePath());
        Enumeration<?> en = zip.entries();
        while (en.hasMoreElements()) {
            ZipEntry ze = (ZipEntry) en.nextElement();
            if (ze.isDirectory())
                continue;
           
            String zipEntryName = ze.getName();
            File zipEntryFile = new File(zipEntryName);
            String fname = extensionPath + zipEntryFile.getPath();

            InputStream is = zip.getInputStream(ze);
            File fi = new File(fname);
            if (!fi.getParentFile().isDirectory() || !fi.getParentFile().exists())
                fi.getParentFile().mkdirs();
            FileOutputStream fos = new FileOutputStream(fname);
            int bytesRead;
            while ((bytesRead = is.read()) != -1)
                fos.write(bytesRead);
            fos.close();
           
            _outputFiles.add(fname);
           
            if (zipEntryName.equals("library.xml")) {
                is = zip.getInputStream(ze);
               
                int size;
                byte[] buffer = new byte[4096];

                ByteArrayOutputStream os = new ByteArrayOutputStream();
                BufferedOutputStream bos = new BufferedOutputStream(os, buffer.length);

                while ((size = is.read(buffer, 0, buffer.length)) != -1) {
                    bos.write(buffer, 0, size);
                }

                bos.flush();
                bos.close();
               
                try {
                    byte[] bytes = os.toString().trim().getBytes();
           
                    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder builder = builderFactory.newDocumentBuilder();

                    // parse the xml file
                    Document doc = builder.parse(new ByteArrayInputStream(bytes));
                    doc.getDocumentElement().normalize();
                   
                    Node nodeExtension = (Node) doc.getElementsByTagName("extension").item(0);
                    NodeList childNodes = nodeExtension.getChildNodes();
                    for (int i = 0; i < childNodes.getLength(); i++) {
                        Node node = childNodes.item(i);

                        if (node.getNodeType() == Node.ELEMENT_NODE) {
                            if (node.getNodeName().equals("entryClass")) {
                                NodeList list = node.getChildNodes();
                                for (int j = 0; j < list.getLength(); j++) {
                                    Node n = list.item(j);
                                    if (n.getNodeType() == Node.TEXT_NODE) {
                                        if (!n.getNodeValue().trim().equals("")) {
                                            _extensionClasses.add(n.getNodeValue().trim());
                                        }
                                    }
                                }
                            }
                        }
                    }
                } catch (SAXException saxEx) {
                    throw new Exception("EXCEPTION_LIBRARYXML_BADXML", saxEx);
                }
            }     
        }
    }
   
    public Vector<String> getExtensionClasses() {
        return _extensionClasses;
   

    /**
     * Returns either <code>msWindows</code> or <code>macOsx</code> based
     * on the host platform. Supports <code>null</code> for either or both
     * inputs.
     */
    public static String selectOnPlatform(String msWindows, String macOsx) {
        String os = System.getProperty("os.name").toLowerCase();
        return os.indexOf( "win" ) >= 0
            ? msWindows
            : macOsx;
    }

    /**
     * Returns a copy of <code>path</code> with trailing separator characters
     * removed. For example:
     * <pre>
     *     removeTrailingSeparators("/foo/bar/") returns "/foo/bar"
     * </pre>
     * Here, a separator character is <code>'/'</code> or <code>'\\'</code>.
     * Also, here, a separator character is considered trailing only if there exists
     * a non-separator character somewhere before it in the string. For example:
     * <pre>
     *     removeTrailingSeparators("/") returns "/"
     *     removeTrailingSeparators("//") returns "//"
     *     removeTrailingSeparators("//foo") returns "//foo"
     *     removeTrailingSeparators("//foo/") returns "//foo"
     * </pre>
     *
     * @param path the input string possibly ending in one or more separator characters.
     *
     * @return a copy of <code>path</code> with trailing separator characters
     * removed.
     */
    public static String removeTrailingSeparators(String path) {
        boolean nonSeparatorFound = false;
        int len = path.length();
        int i;

        for (i = len - 1; i >= 0; i--) {
            if (path.charAt(i) != '/' && path.charAt(i) != '\\') {
                nonSeparatorFound = true;
                break;
            }
        }

        return path.substring(0, (nonSeparatorFound ? i+1 : len));
    }
}
TOP

Related Classes of net.rim.tumbler.file.FileManager

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.