mergedoc.core.MergeManager.java Source code

Java tutorial

Introduction

Here is the source code for mergedoc.core.MergeManager.java

Source

/*
 * Copyright (c) 2003- Shinji Kashihara. All rights reserved.
 * This program are made available under the terms of the Common Public License
 * v1.0 which accompanies this distribution, and is available at cpl-v10.html.
 */
package mergedoc.core;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.swing.event.ChangeListener;
import javax.xml.parsers.SAXParser;

import mergedoc.MergeDocException;
import mergedoc.xml.ConfigManager;
import mergedoc.xml.ReplaceEntry;
import mergedoc.xml.ReplaceHandler;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.SAXException;

/**
 * ???
 * @author Shinji Kashihara
 */
public class MergeManager {

    /**  */
    private static final Log log = LogFactory.getLog(MergeManager.class);

    /**  */
    private Preference pref;

    /** ? */
    private WorkingState workingState = new WorkingState();

    /** ??? */
    private byte[] byteBuffer = new byte[4096];

    /** ? Executor */
    private ExecutorService entrySizeGetExecutor = Executors.newSingleThreadExecutor();

    /**  Future */
    private Future<Integer> entrySizeFuture;

    /**
     * ??
     */
    public MergeManager() throws MergeDocException {
    }

    /**
     * ???
     * @param pref 
     */
    public void setPreference(final Preference pref) {

        this.pref = pref;
        workingState.initialize();

        // ??????????????
        entrySizeFuture = entrySizeGetExecutor.submit(new Callable<Integer>() {

            @Override
            public Integer call() throws Exception {
                ArchiveInputStream is = null;
                try {
                    is = ArchiveInputStream.create(pref.getInputArchive());
                    int size = 0;
                    for (; is.getNextEntry() != null; size++) {
                        ;
                    }
                    return size;
                } catch (Exception e) {
                    return 0;
                } finally {
                    if (is != null) {
                        is.close();
                    }
                }
            }
        });
    }

    /**
     * ??????
     * @throws MergeDocException ?????
     * @throws IOException ????
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public void validate() throws MergeDocException, IOException, InterruptedException, ExecutionException {

        // API ??
        File docDir = pref.getDocDirectory();
        if (docDir != null && docDir.getPath().length() > 0) {
            File rootFile = new File(docDir, "allclasses-frame.html");
            if (!rootFile.exists()) {
                throw new MergeDocException(
                        "?? API ???????\n"
                                + "??? allclasses-frame.html ?\n"
                                + "?????????");
            }
        }

        // ??
        File inFile = pref.getInputArchive();
        if (inFile == null || inFile.getPath().equals("")) {
            throw new MergeDocException("???????");
        }
        if (entrySize() == 0) {
            throw new MergeDocException(
                    "?????????");
        }

        // ??
        File outFile = pref.getOutputArchive();
        if (outFile == null || outFile.getPath().equals("")) {
            throw new MergeDocException("???????");
        }
        if (outFile.equals(inFile)) {
            throw new MergeDocException(
                    "??????????\n"
                            + "?????????");
        }
        if (pref.getOutputArchive().exists()) {
            if (!outFile.canWrite()) {
                throw new MergeDocException(
                        "??????????\n"
                                + "?????????");
            }
        } else {
            try {
                outFile.createNewFile();
                outFile.delete();
            } catch (IOException e) {
                throw new MergeDocException(
                        "?????????", e);
            }
        }
    }

    /**
     * ????<br>
     * @throws MergeDocException ??????
     * @throws SAXException SAX ????
     * @throws IOException ????
     */
    public void execute() throws MergeDocException, SAXException, IOException {

        if (workingState.isCanceled()) {
            return;
        }
        ArchiveInputStream in = null;
        ZipOutputStream out = null;

        try {
            in = ArchiveInputStream.create(pref.getInputArchive());

            out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(pref.getOutputArchive())));
            out.setLevel(Deflater.BEST_SPEED);

            long start = System.currentTimeMillis();
            merge(in, out);
            long end = System.currentTimeMillis();
            workingState.setWorkTime((end - start) / 1000);

        } finally {

            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

    /**
     * ????Java ???
     * API ???????????? ZIP
     * ??????
     *
     * @param  in  
     * @param  out ZIP 
     * @throws MergeDocException ??????
     * @throws SAXException SAX ????
     * @throws IOException ????
     */
    private void merge(ArchiveInputStream in, ZipOutputStream out)
            throws MergeDocException, SAXException, IOException {
        Merger merger = new Merger(pref.getDocDirectory());
        merger.setDocEncoding(pref.getDocEncoding());

        ArchiveInputStream.Entry inEntry = null;
        while ((inEntry = in.getNextEntry()) != null) {

            if (workingState.isCanceled()) {
                return;
            }
            String entryName = inEntry.getName();
            out.putNextEntry(new ZipEntry(entryName));
            workingState.changeWorkingText(entryName);

            //debug ?
            //if (!entryName.equals("java/lang/String.java")) continue;
            //if (!entryName.endsWith("/SuppressWarnings.java")) continue;
            //if (!entryName.endsWith("/System.java")) continue;

            if (entryName.endsWith(".java") && !entryName.endsWith("/package-info.java")) {

                // Java ??
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                copyStream(in, baos);
                String source = baos.toString(pref.getInputEncoding());
                source = FastStringUtils.optimizeLineSeparator(source);
                source = FastStringUtils.untabify(source);

                // Java  API ?
                Pattern classPat = PatternCache.getPattern(".*/(.*)\\.java");
                Matcher classMat = classPat.matcher(entryName);
                if (classMat.find()) {
                    String result = merger.merge(source, classMat.group(1));
                    String className = merger.getMergedClassName();
                    if (className != null) {
                        result = doFilter(className, result);
                    }
                    byte[] resultBuf = result.getBytes(pref.getOutputEncoding());
                    out.write(resultBuf);
                } else {
                    copyStream(in, out);
                }
            } else {
                // Java ??
                copyStream(in, out);
            }
        }
    }

    /**
     * ????
     * @param in 
     * @param out 
     * @throws IOException ????
     */
    private void copyStream(ArchiveInputStream in, OutputStream out) throws IOException {
        for (int size = 0; (size = in.read(byteBuffer)) > 0;) {
            out.write(byteBuffer, 0, size);
        }
    }

    /**
     * XML ??????????
     * @param className ??
     * @param source Java 
     * @return ??
     * @throws MergeDocException ??????
     * @throws SAXException SAX ????
     * @throws IOException ????
     */
    private String doFilter(String className, String source) throws MergeDocException, SAXException, IOException {
        // ???
        String path = FastStringUtils.replaceAll(className, "\\.", "/") + ".xml";
        ConfigManager config = ConfigManager.getInstance();
        File entryXML = config.getFile(path);
        if (entryXML.exists()) {
            SAXParser saxParser = config.getSAXPerser();
            ReplaceHandler handler = new ReplaceHandler(source);
            saxParser.parse(entryXML, handler);
            source = handler.getResult();
        }

        // ????
        for (ReplaceEntry entry : pref.getGlobalEntries()) {
            source = entry.replace(source);
        }

        return source;
    }

    /**
     * ???????
     * @return ???
     * @throws ExecutionException ?????
     * @throws InterruptedException ????????
     */
    public int entrySize() throws InterruptedException, ExecutionException {
        return entrySizeFuture.get();
    }

    /**
     * ?????
     * @param changeListener ??
     */
    public void setChangeListener(ChangeListener changeListener) {
        workingState.setChangeListener(changeListener);
    }

    /**
     * ?????
     * @return ?
     */
    public WorkingState getWorkingState() {
        return workingState;
    }
}