/******************************************************************************* * Copyright (c) 2005, 2009 committers of openArchitectureWare and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * committers of openArchitectureWare - initial API and implementation *******************************************************************************/ package org.eclipse.xpand2.output; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.internal.xpand2.ast.Statement; public class FileHandleImpl implements FileHandle, InsertionPointSupport { private final Log log = LogFactory.getLog(getClass()); private List<CharSequence> buffers = new ArrayList<CharSequence>(); private Map<Statement, CharSequence> namedBuffers = new HashMap<Statement, CharSequence>(); private CharSequence currentNamedBuffer = null; private CharSequence currentUnnamedBuffer; private File targetFile = null; private Outlet outlet = null; public FileHandleImpl(final Outlet outlet, final File f) { this.outlet = outlet; targetFile = f.getAbsoluteFile(); buffers.add(new StringBuilder(4096)); currentUnnamedBuffer = buffers.get(0); } public Outlet getOutlet() { return outlet; } public CharSequence getBuffer() { if (!namedBuffers.isEmpty()) { return currentNamedBuffer!=null ? currentNamedBuffer : currentUnnamedBuffer; } else { if (buffers.size()>1) { // no insertion point used anymore, but multiple buffers available // => compact to one buffer again StringBuilder compacted = new StringBuilder(); for (CharSequence cs : buffers) { compacted.append(cs); } buffers.clear(); buffers.add(compacted); currentUnnamedBuffer = compacted; } return buffers.get(0); } } public void setBuffer(final CharSequence newBuffer) { if (currentNamedBuffer != null) { int idx = buffers.indexOf(currentNamedBuffer); while (idx>=0) { buffers.add(idx, newBuffer); buffers.remove(idx+1); idx = buffers.indexOf(currentNamedBuffer); } for (Statement key : namedBuffers.keySet()) { if (namedBuffers.get(key)==currentNamedBuffer) { namedBuffers.put(key, newBuffer); } } currentNamedBuffer = newBuffer; } else { int idx = buffers.indexOf(currentUnnamedBuffer); buffers.add(idx, newBuffer); buffers.remove(idx+1); currentUnnamedBuffer = newBuffer; } } @SuppressWarnings("deprecation") public File getTargetFile() { return targetFile; } public String getAbsolutePath() { return getTargetFile().getAbsolutePath(); } public boolean isAppend() { return outlet.isAppend(); } public boolean isOverwrite() { return outlet.isOverwrite(); } public String getFileEncoding() { return outlet.getFileEncoding(); } public void writeAndClose() { try { if (!isOverwrite() && targetFile.exists()) { if (log.isDebugEnabled()) { log.debug("Skipping file : " + targetFile.getAbsolutePath() + " cause it exists already"); } return; } if (log.isDebugEnabled()) { log.debug("Opening file : " + targetFile.getAbsolutePath()); } // create all parent directories final File parentDir = targetFile.getParentFile(); if (!parentDir.exists()) { parentDir.mkdirs(); if (!parentDir.isDirectory()) { throw new RuntimeException("Failed to create parent directories of file " + targetFile.getAbsolutePath()); } } outlet.beforeWriteAndClose(this); if (outlet.shouldWrite(this)) { FileOutputStream out = null; try { out = new FileOutputStream(targetFile, isAppend()); out.write(getBytes()); } finally { if (out != null) { try { out.close(); outlet.afterClose(this); } catch (final IOException e) { throw new RuntimeException(e); } } } } } catch (final IOException e) { throw new RuntimeException(e); } } public byte[] getBytes() { CharSequence buffer = null; if (buffers.size()==1) { buffer = buffers.get(0); } else { StringBuilder tmp = new StringBuilder(); for (CharSequence cs : buffers) { tmp.append(cs); } buffer = tmp; } if (getFileEncoding() != null) { try { return buffer.toString().getBytes(getFileEncoding()); } catch (final UnsupportedEncodingException e) { log.error(e.getMessage(), e); } } return buffer.toString().getBytes(); } public void activateInsertionPoint(Statement stmt) { CharSequence buffer = namedBuffers.get(stmt); if (buffer == null) { throw new IllegalStateException ("Unknown insertion point "+stmt+"."); } currentNamedBuffer = buffer; } public void deactivateInsertionPoint(Statement stmt) { if (currentNamedBuffer == null) { throw new IllegalStateException ("Insertion point for "+stmt+" was not activated."); } CharSequence buffer = namedBuffers.get(stmt); if (buffer == null) { throw new IllegalStateException ("Unknown insertion point "+stmt+"."); } if (buffer != currentNamedBuffer) { throw new IllegalStateException ("Insertion point "+stmt+" is not the active one!"); } namedBuffers.remove(stmt); currentNamedBuffer = null; } public void registerInsertionPoint(Statement stmt) { CharSequence namedBuffer = namedBuffers.get(stmt); if (namedBuffer == null) { namedBuffer = new StringBuilder(); namedBuffers.put(stmt, namedBuffer); } buffers.add(namedBuffer); currentUnnamedBuffer = new StringBuilder(); buffers.add(currentUnnamedBuffer); } }