blob: 01bffe836be829b02699e3b115a48a8fa94d1195 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Xored Software Inc 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
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.core.persistence;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.rcptt.core.workspace.Q7Utils;
import org.eclipse.rcptt.internal.core.RcpttPlugin;
import org.eclipse.rcptt.util.FileUtil;
import org.eclipse.rcptt.util.StreamUtil;
public abstract class BasePersistenceModel implements IPersistenceModel {
protected final Map<String, File> files = new HashMap<String, File>();
protected abstract void doExtractAll(InputStream contents)
throws IOException;
protected abstract void doExtractFile(String fName, InputStream contents)
throws IOException;
protected abstract void doReadIndex(InputStream contents);
protected abstract void doStoreTo(File file) throws FileNotFoundException,
IOException;
protected final Resource element;
protected final File root;
protected final IPath rootPath;
private boolean modified = false;
private byte[] internalContent = null;
private Set<String> extractions = new HashSet<String>();
private boolean disposed = false;
public boolean isContentEntryRequired() {
return true;
}
public boolean isAllowEmptyMetadataContent() {
return false;
}
public BasePersistenceModel(Resource element) {
this.element = element;
IPath nonExistent = null;
while (true) {
RcpttPlugin default1 = RcpttPlugin.getDefault();
assert default1 != null;
String uri = (element == null || element.getURI() == null) ? "_"
: element.getURI().toString();
nonExistent = default1
.getStateLocation()
.append("attachments")
.append(FileUtil.limitSize(FileUtil.getID(uri))
+ System.currentTimeMillis());
if (!nonExistent.toFile().exists()) {
break;
}
}
assert nonExistent != null;
rootPath = nonExistent;
this.root = rootPath.toFile();
// Make index
try {
readIndex();
} catch (CoreException e) {
RcpttPlugin.log(e);
}
}
public Resource getResource() {
return this.element;
}
public void setInternalContent(byte[] internalContent) {
this.internalContent = internalContent;
try {
readIndex();
} catch (CoreException e) {
RcpttPlugin.log(e);
}
}
private void initialize() {
assert !disposed;
root.mkdirs();
}
public boolean hasElements() {
return !files.isEmpty();
}
public String[] getNames() {
return files.keySet().toArray(new String[files.size()]);
}
private void readIndex() throws CoreException {
assert !disposed;
InputStream contents = getContentsStream();
if (contents == null) {
return;
}
try {
doReadIndex(contents);
} finally {
try {
contents.close();
} catch (IOException e) {
}
}
}
protected InputStream getContentsStream() {
InputStream input = null;
IFile file = element != null ? Q7Utils.getLocation(element) : null;
if (file != null && !file.exists()) {
return null;
}
if (internalContent != null) {
input = new ByteArrayInputStream(internalContent);
}
InputStream contents;
try {
if (input == null && file == null) {
return null;
}
if (input == null) {
input = file.getContents();
}
contents = new BufferedInputStream(input);
} catch (CoreException e) {
// Ignore file not found exception
if (e.getStatus().getCode() != 271) {
RcpttPlugin.log(e);
}
return null;
}
return contents;
}
protected File putFileItem(String name, IPath filePath) {
return files.put(name, filePath.toFile());
}
public void dispose() {
if (disposed)
return;
removeAll();
disposed = true;
}
public InputStream read(String name) {
assert !disposed;
File file = files.get(name);
if (file == null) {
return null;
}
waitUntilExtracted(name);
if (!file.exists()) {
extractFile(name);
waitUntilExtracted(name);
}
if (file.exists()) {
try {
return getInput(file);
} catch (FileNotFoundException e) {
RcpttPlugin.log(e);
}
}
return null;
}
private void waitUntilExtracted(String name) {
synchronized (extractions) {
while (extractions.contains(name)) {
try {
extractions.wait(100);
} catch (InterruptedException e) {
RcpttPlugin.log(e);
}
}
}
}
protected BufferedInputStream getInput(File file)
throws FileNotFoundException {
return new BufferedInputStream(new FileInputStream(file));
}
private void extractFile(String fName) {
initialize();
InputStream contents = null;
try {
synchronized (extractions) {
if (extractions.contains(fName)) {
return;
}
extractions.add(fName);
}
contents = getContentsStream();
if (contents == null) {
return;
}
doExtractFile(fName, contents);
} catch (Throwable e1) {
RcpttPlugin.log(e1);
} finally {
synchronized (extractions) {
extractions.remove(fName);
extractions.notifyAll();
}
try {
if (contents != null) {
contents.close();
}
} catch (IOException e) {
}
}
}
public void delete(String name) {
File file = files.get(name);
if (file != null && file.exists()) {
file.delete();
}
files.remove(name);
}
public boolean restore(String name) {
File file = files.get(name);
if (file != null && file.exists()) {
file.delete();
extractFile(name);
return file.exists();
}
return false;
}
public OutputStream store(String name) {
modified = true;
return internalStore(name);
}
protected OutputStream internalStore(String name) {
initialize();
IPath path = rootPath.append(new Path(name));
File file = path.toFile();
file.getParentFile().mkdirs();
files.put(name, file);
try {
return new BufferedOutputStream(new FileOutputStream(file));
} catch (FileNotFoundException e) {
RcpttPlugin.log(e);
return null;
}
}
public void extractAll() {
initialize();
InputStream contents = null;
try {
contents = getContentsStream();
if (contents == null) {
return;
}
doExtractAll(contents);
} catch (Throwable e1) {
RcpttPlugin.log(e1);
} finally {
try {
if (contents != null) {
contents.close();
}
} catch (IOException e) {
}
}
}
public File storeToTemporaty() {
initialize();
File file = rootPath.append(
".q7.content.temporary" + System.currentTimeMillis()).toFile();
try {
doStoreTo(file);
} catch (Exception e) {
RcpttPlugin.log(e);
}
return file;
}
public void removeAll() {
files.clear();
if (root != null) {
FileUtil.deleteFiles(root.listFiles());
root.delete();
}
}
/**
* Return true if some resources are copied. Copy all resources except
* PersistenceManager.CONTENT_ENTRY
*/
public boolean copyFrom(IPersistenceModel originalModel) {
removeAll();
String[] names = originalModel.getNames();
for (String name : names) {
InputStream inputStream = originalModel.read(name);
OutputStream outputStream = store(name);
try {
FileUtil.copy(inputStream, outputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
return names.length > 0;
}
public boolean isModified() {
return modified;
}
public void updateMetadata() {
}
public void updateAttributes() {
}
public void setUnmodified() {
modified = false;
}
public int size(String teslaContentEntry) {
InputStream stream = read(teslaContentEntry);
int result = 0;
if (stream != null) {
try {
byte[] buffer = new byte[4096];
int len = 0;
while ((len = stream.read(buffer)) > 0) {
result += len;
}
} catch (IOException e) {
result = 0;
} finally {
StreamUtil.closeSilently(stream);
}
}
return result;
}
public void rename(String oldName, String newName) {
InputStream read = read(oldName);
if (read != null) {
OutputStream store = store(newName);
try {
FileUtil.copy(read, store);
delete(oldName);
} catch (IOException e) {
RcpttPlugin.log(e);
}
}
}
}