blob: 24046baabef4f3934d3a730889f5208c60caeb22 [file] [log] [blame]
package org.eclipse.scout.sdk.util.pde;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.pde.internal.core.iproduct.IConfigurationFileInfo;
import org.eclipse.pde.internal.core.product.WorkspaceProductModel;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.sdk.util.FormatPreservingProperties;
import org.eclipse.scout.sdk.util.log.ScoutStatus;
import org.eclipse.scout.sdk.util.resources.ResourceUtility;
@SuppressWarnings("restriction")
public final class LazyProductFileModel {
private final static Pattern FRAGMENT_PATTERN = Pattern.compile("^(\\sfragment\\=\\\")([^\\\"]*)(\\\")");
private final IFile m_productFile;
//lazily instantiated models
private volatile WorkspaceProductModel m_productModel;
private volatile IConfigurationFileInfo m_configFileInfo;
private volatile FormatPreservingProperties m_configFileProperties;
private volatile IFile m_configIniFile;
public LazyProductFileModel(IFile productFile) {
if (productFile == null) {
throw new IllegalArgumentException("null product file not allowed.");
}
if (!productFile.exists()) {
throw new IllegalArgumentException("invalid product file passed: '" + productFile.getFullPath().toString() + "'.");
}
m_productFile = productFile;
}
public synchronized WorkspaceProductModel getWorkspaceProductModel() throws CoreException {
if (m_productModel == null) {
WorkspaceProductModel tmp = new WorkspaceProductModel(m_productFile, true);
tmp.load();
tmp.setDirty(false);
m_productModel = tmp;
}
return m_productModel;
}
public synchronized IConfigurationFileInfo getConfigurationFileInfo() throws CoreException {
if (m_configFileInfo == null) {
m_configFileInfo = getWorkspaceProductModel().getProduct().getConfigurationFileInfo();
}
return m_configFileInfo;
}
/**
* gets the config.ini file specified in the product.
*
* @return the config.ini file or null if no file is specified for the running OS ({@link Platform#getOS()}).
* @throws CoreException
*/
public synchronized IFile getConfigIniFile() throws CoreException {
if (m_configIniFile == null) {
String osPath = getConfigurationFileInfo().getPath(Platform.getOS());
if (StringUtility.hasText(osPath)) {
IFile configIniFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(osPath.trim()));
if (ResourceUtility.exists(configIniFile)) {
m_configIniFile = configIniFile;
}
else {
throw new CoreException(new ScoutStatus("could not find product configuration file: " + osPath));
}
}
}
return m_configIniFile;
}
public synchronized FormatPreservingProperties getConfigFileProperties() throws CoreException {
if (m_configFileProperties == null) {
FormatPreservingProperties tmp = new FormatPreservingProperties();
IFile configIni = getConfigIniFile();
if (configIni != null) {
tmp.load(configIni);
}
m_configFileProperties = tmp;
}
return m_configFileProperties;
}
public synchronized void save() throws CoreException {
if (m_productModel != null && m_productModel.isDirty()) {
saveProductModel();
}
if (m_configFileProperties != null && m_configFileProperties.isDirty()) {
saveConfigIni();
}
}
private void saveConfigIni() throws CoreException {
IFile configIni = getConfigIniFile();
if (configIni == null) {
return;
}
OutputStream stream = null;
try {
stream = new BufferedOutputStream(new FileOutputStream(configIni.getRawLocation().toFile()));
m_configFileProperties.store(stream);
}
catch (IOException e) {
throw new CoreException(new ScoutStatus("unable to save product configuration file: " + configIni.getRawLocation().toOSString(), e));
}
finally {
if (stream != null) {
try {
stream.close();
}
catch (IOException e) {
}
}
configIni.refreshLocal(IFile.DEPTH_ZERO, null);
}
}
/**
* TODO can be eliminated when <b>BUG 362398</b> is fixed (was fixed for Indigo SR1).<br>
* When the bug is fixed call m_model.save() directly instead of calling this method.
*
* @see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=362398">Bugzilla #362398</a>
*/
private void saveProductModel() throws CoreException {
// save product file into byte array not writing empty fragment parts (fragment="").
ByteArrayOutputStream out = new ByteArrayOutputStream(8192);
PrintWriter writer = new PrintWriter(out, false) {
@Override
public void print(String s) {
// overwrite writer.print(" fragment=\"true\""); //$NON-NLS-1$
Matcher matcher = FRAGMENT_PATTERN.matcher(s);
if (matcher.matches()) {
if (StringUtility.isNullOrEmpty(matcher.group(2))) {
return;
}
}
super.print(s);
}
};
m_productModel.save(writer);
writer.flush();
writer.close();
// get corrected contents from ByteArrayOutputStream and write it to the file.
IFile file = (IFile) m_productModel.getUnderlyingResource();
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
file.setContents(in, true, false, null);
file.refreshLocal(IFile.DEPTH_ONE, null);
// no need to close a ByteArrayInputStream
}
}