edu.tsinghua.lumaqq.customface.EIPImporter.java Source code

Java tutorial

Introduction

Here is the source code for edu.tsinghua.lumaqq.customface.EIPImporter.java

Source

/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.customface;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;

import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;

import edu.tsinghua.lumaqq.ecore.face.FaceConstant;
import edu.tsinghua.lumaqq.ecore.face.FaceGroup;

/**
 * EIP?EIPPOIFS
 * POIFS???http://jakarta.apache.org/poi/poifs/fileformat.html
 * 
 * EIP?
 * 
 * 1. config, ?       
 * 2. Files, 
 * 
 * configFace.xml??
 * Files????????
 * ?wordword?
 * ?word?????0
 * Fixed???0Fixed??Faces.xml?
 * 
 * @author notXX
 * @author luma
 */
public class EIPImporter {
    private static final String CONFIG_DIRECTORY = "config";
    private static final String FILES_DIRECTORY = "files";
    private static final String CONFIG_FILE = "face.xml";
    private static final String THUMB_SUFFIX = "fixed";

    private byte[] buffer;

    private FaceEntry entry;
    private String destDir;

    private FileInputStream eipStream;
    private FaceXMLParser parser;
    private Iterator<Entry> groupIterator;
    private Iterator<Entry> faceIterator;
    private DirectoryEntry currentDir;
    private DocumentEntry currentFace;

    @SuppressWarnings("unchecked")
    public EIPImporter(String file, String destDir) {
        this.destDir = destDir;
        buffer = new byte[8192];

        POIFSFileSystem eipSystem;
        try {
            // eip
            eipStream = new FileInputStream(file);
            eipSystem = new POIFSFileSystem(eipStream);

            // 
            DirectoryEntry configDir = null, fileDir = null;
            DirectoryEntry root = eipSystem.getRoot();
            Iterator<Entry> i = root.getEntries();
            while (i.hasNext()) {
                Entry e = i.next();
                if (e.isDirectoryEntry()) {
                    if (CONFIG_DIRECTORY.equals(e.getName().toLowerCase()))
                        configDir = (DirectoryEntry) e;
                    else if (FILES_DIRECTORY.equals(e.getName().toLowerCase()))
                        fileDir = (DirectoryEntry) e;
                }
            }

            // ??
            if (configDir == null || fileDir == null)
                throw new IOException("Can't find correct directories");

            // ?face.xml
            i = configDir.getEntries();
            while (i.hasNext()) {
                Entry e = i.next();
                if (e.isDocumentEntry() && CONFIG_FILE.equals(e.getName().toLowerCase())) {
                    DocumentInputStream dis = new DocumentInputStream((DocumentEntry) e);
                    parser = new FaceXMLParser(dis);
                    dis.close();
                    break;
                }
            }

            // ??face.xml
            if (parser == null)
                throw new IOException("Can't find " + CONFIG_FILE);

            // iterator
            groupIterator = fileDir.getEntries();
            currentDir = fileDir;
            faceIterator = currentDir.getEntries();
        } catch (IOException e) {
            eipSystem = null;
            try {
                if (eipStream != null) {
                    eipStream.close();
                    eipStream = null;
                }
            } catch (IOException e1) {
            }
        }
    }

    /**
     * 
     */
    public void dispose() {
        try {
            if (eipStream != null)
                eipStream.close();
        } catch (IOException e) {
        }
    }

    /**
     * @return
     *       null??"."
     */
    @SuppressWarnings("unchecked")
    public FaceEntry getNextEntry() {
        if (currentDir == null)
            return null;

        while (true) {
            currentFace = getNextDocument();
            if (currentFace == null) {
                currentDir = getNextDir();
                if (currentDir == null)
                    return null;
                faceIterator = currentDir.getEntries();
            } else if (currentFace.getName().toLowerCase().endsWith(THUMB_SUFFIX))
                continue;
            else
                break;
        }

        entry = parser.getEntry(currentFace.getName());
        entry.groupName = currentDir.getName();
        if (entry.groupName.toLowerCase().equals(FILES_DIRECTORY))
            entry.groupName = ".";
        return entry;
    }

    /**
     * ?
     * 
     * @param g
     *       
     * @return
     *       true?
     */
    public boolean saveEntry(FaceGroup g) {
        if (g.getId() == FaceConstant.CUSTOM_HEAD_GROUP_ID)
            return saveCustomHead(g);
        else {
            FileOutputStream fos = null;
            DocumentInputStream dis = null;
            try {
                // ?
                String filename = destDir + g.getId() + '/' + entry.filename;
                fos = new FileOutputStream(filename);
                dis = new DocumentInputStream(currentFace);
                for (int i = 0; i != -1; i = dis.read(buffer, 0, buffer.length))
                    fos.write(buffer, 0, i);

                // ?
                try {
                    ImageLoader loader = new ImageLoader();
                    loader.load(filename);
                    ImageData data = loader.data[0].scaledTo(20, 20);
                    loader = new ImageLoader();
                    loader.data = new ImageData[] { data };
                    loader.save(destDir + g.getId() + '/' + entry.md5 + "fixed.bmp", SWT.IMAGE_BMP);
                } catch (SWTException e) {
                    return false;
                }

                return true;
            } catch (IOException e) {
                return false;
            } finally {
                try {
                    if (fos != null)
                        fos.close();
                    if (dis != null)
                        dis.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * ??
     * 
      * @return
      *       true??
     */
    private boolean saveCustomHead(FaceGroup g) {
        DocumentInputStream dis = null;
        try {
            // ?
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            dis = new DocumentInputStream(currentFace);
            for (int i = 0; i != -1; i = dis.read(buffer, 0, buffer.length))
                baos.write(buffer, 0, i);

            // ?ImageData
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ImageData origin = new ImageData(bais);
            ImageData data = origin.scaledTo(40, 40);

            // save 40x40 bmp
            ImageLoader saveLoader = new ImageLoader();
            saveLoader.data = new ImageData[] { data };
            saveLoader.save(destDir + g.getId() + '/' + entry.md5 + ".bmp", SWT.IMAGE_BMP);

            // save 20x20 bmp
            data = origin.scaledTo(20, 20);
            saveLoader = new ImageLoader();
            saveLoader.data = new ImageData[] { data };
            saveLoader.save(destDir + g.getId() + '/' + entry.md5 + "fixed.bmp", SWT.IMAGE_BMP);

            return true;
        } catch (SWTException e) {
            return false;
        } catch (IOException e) {
            return false;
        } finally {
            try {
                if (dis != null)
                    dis.close();
            } catch (IOException e) {
            }
        }
    }

    /**
     * @return
     *       ?document entry
     */
    private DocumentEntry getNextDocument() {
        DocumentEntry de = null;
        while (faceIterator.hasNext()) {
            Entry e = faceIterator.next();
            if (e.isDocumentEntry()) {
                de = (DocumentEntry) e;
                break;
            }
        }
        return de;
    }

    /**
     * @return
     *       
     */
    private DirectoryEntry getNextDir() {
        DirectoryEntry dir = null;
        while (groupIterator.hasNext()) {
            Entry e = groupIterator.next();
            if (e.isDirectoryEntry()) {
                dir = (DirectoryEntry) e;
                break;
            }
        }
        return dir;
    }
}