Java tutorial
/* * 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; } }