IDEMPIERE-5034 NPE and other problems when a file is removed from store attachment filesystem (#971)
This commit is contained in:
parent
d0340e70d5
commit
0f31a07f43
|
@ -33,6 +33,7 @@ import javax.xml.transform.TransformerFactory;
|
||||||
import javax.xml.transform.dom.DOMSource;
|
import javax.xml.transform.dom.DOMSource;
|
||||||
import javax.xml.transform.stream.StreamResult;
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
import org.compiere.util.CLogger;
|
import org.compiere.util.CLogger;
|
||||||
import org.compiere.util.Util;
|
import org.compiere.util.Util;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
@ -52,6 +53,9 @@ public class AttachmentFileSystem implements IAttachmentStore {
|
||||||
|
|
||||||
private final CLogger log = CLogger.getCLogger(getClass());
|
private final CLogger log = CLogger.getCLogger(getClass());
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean save(MAttachment attach,MStorageProvider prov) {
|
public boolean save(MAttachment attach,MStorageProvider prov) {
|
||||||
String attachmentPathRoot = getAttachmentPathRoot(prov);
|
String attachmentPathRoot = getAttachmentPathRoot(prov);
|
||||||
|
@ -59,6 +63,13 @@ public class AttachmentFileSystem implements IAttachmentStore {
|
||||||
attach.setBinaryData(null);
|
attach.setBinaryData(null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get list of old entries
|
||||||
|
byte[] data = (byte[]) attach.get_ValueOld(MAttachment.COLUMNNAME_BinaryData);
|
||||||
|
NodeList xmlEntries = null;
|
||||||
|
if (data != null && data.length > 0)
|
||||||
|
xmlEntries = getEntriesFromXML(data);
|
||||||
|
|
||||||
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
try {
|
try {
|
||||||
final DocumentBuilder builder = factory.newDocumentBuilder();
|
final DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
|
@ -70,6 +81,31 @@ public class AttachmentFileSystem implements IAttachmentStore {
|
||||||
for (int i = 0; i < attach.m_items.size(); i++) {
|
for (int i = 0; i < attach.m_items.size(); i++) {
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(attach.m_items.get(i).toString());
|
if (log.isLoggable(Level.FINE)) log.fine(attach.m_items.get(i).toString());
|
||||||
File entryFile = attach.m_items.get(i).getFile();
|
File entryFile = attach.m_items.get(i).getFile();
|
||||||
|
if (entryFile == null) {
|
||||||
|
String itemName = attach.m_items.get(i).getName();
|
||||||
|
if (itemName.startsWith("~") && itemName.endsWith("~")) {
|
||||||
|
itemName = itemName.substring(1, itemName.length()-1);
|
||||||
|
if (xmlEntries != null) {
|
||||||
|
for (int x = 0; x < xmlEntries.getLength(); x++) {
|
||||||
|
final Node entryNode = xmlEntries.item(x);
|
||||||
|
final NamedNodeMap attributes = entryNode.getAttributes();
|
||||||
|
final Node fileNode = attributes.getNamedItem("file");
|
||||||
|
final Node nameNode = attributes.getNamedItem("name");
|
||||||
|
if (itemName.equals(nameNode.getNodeValue())) {
|
||||||
|
// file was not found but we preserve the old location just in case is temporary
|
||||||
|
final Element entry = document.createElement("entry");
|
||||||
|
entry.setAttribute("name", itemName);
|
||||||
|
entry.setAttribute("file", fileNode.getNodeValue());
|
||||||
|
root.appendChild(entry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new AdempiereException("Attachment file not found: " + itemName);
|
||||||
|
}
|
||||||
final String path = entryFile.getAbsolutePath();
|
final String path = entryFile.getAbsolutePath();
|
||||||
// if local file - copy to central attachment folder
|
// if local file - copy to central attachment folder
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(path + " - " + attachmentPathRoot);
|
if (log.isLoggable(Level.FINE)) log.fine(path + " - " + attachmentPathRoot);
|
||||||
|
@ -171,48 +207,59 @@ public class AttachmentFileSystem implements IAttachmentStore {
|
||||||
if (data.length == 0)
|
if (data.length == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
NodeList entries = getEntriesFromXML(data);
|
||||||
|
for (int i = 0; i < entries.getLength(); i++) {
|
||||||
|
final Node entryNode = entries.item(i);
|
||||||
|
final NamedNodeMap attributes = entryNode.getAttributes();
|
||||||
|
final Node fileNode = attributes.getNamedItem("file");
|
||||||
|
final Node nameNode = attributes.getNamedItem("name");
|
||||||
|
if(fileNode==null || nameNode==null){
|
||||||
|
log.severe("no filename for entry " + i);
|
||||||
|
attach.m_items = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine("name: " + nameNode.getNodeValue());
|
||||||
|
String filePath = fileNode.getNodeValue();
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine("filePath: " + filePath);
|
||||||
|
if(filePath!=null){
|
||||||
|
filePath = filePath.replaceFirst(attach.ATTACHMENT_FOLDER_PLACEHOLDER, attachmentPathRoot.replaceAll("\\\\","\\\\\\\\"));
|
||||||
|
//just to be shure...
|
||||||
|
String replaceSeparator = File.separator;
|
||||||
|
if(!replaceSeparator.equals("/")){
|
||||||
|
replaceSeparator = "\\\\";
|
||||||
|
}
|
||||||
|
filePath = filePath.replaceAll("/", replaceSeparator);
|
||||||
|
filePath = filePath.replaceAll("\\\\", replaceSeparator);
|
||||||
|
}
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine("filePath: " + filePath);
|
||||||
|
final File file = new File(filePath);
|
||||||
|
if (file.exists()) {
|
||||||
|
// file data read delayed
|
||||||
|
IAttachmentLazyDataSource ds = new AttachmentFileLazyDataSource(file);
|
||||||
|
final MAttachmentEntry entry = new MAttachmentEntry(file.getName(), attach.m_items.size() + 1, ds);
|
||||||
|
attach.m_items.add(entry);
|
||||||
|
} else {
|
||||||
|
log.severe("file not found: " + file.getAbsolutePath());
|
||||||
|
attach.m_items.add(new MAttachmentEntry("~" + file.getName() + "~", "".getBytes(), attach.m_items.size() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entries from the XML
|
||||||
|
* @param data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private NodeList getEntriesFromXML(byte[] data) {
|
||||||
|
NodeList entries = null;
|
||||||
try {
|
try {
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||||
final DocumentBuilder builder = factory.newDocumentBuilder();
|
final DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
final Document document = builder.parse(new ByteArrayInputStream(data));
|
final Document document = builder.parse(new ByteArrayInputStream(data));
|
||||||
final NodeList entries = document.getElementsByTagName("entry");
|
entries = document.getElementsByTagName("entry");
|
||||||
for (int i = 0; i < entries.getLength(); i++) {
|
|
||||||
final Node entryNode = entries.item(i);
|
|
||||||
final NamedNodeMap attributes = entryNode.getAttributes();
|
|
||||||
final Node fileNode = attributes.getNamedItem("file");
|
|
||||||
final Node nameNode = attributes.getNamedItem("name");
|
|
||||||
if(fileNode==null || nameNode==null){
|
|
||||||
log.severe("no filename for entry " + i);
|
|
||||||
attach.m_items = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("name: " + nameNode.getNodeValue());
|
|
||||||
String filePath = fileNode.getNodeValue();
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("filePath: " + filePath);
|
|
||||||
if(filePath!=null){
|
|
||||||
filePath = filePath.replaceFirst(attach.ATTACHMENT_FOLDER_PLACEHOLDER, attachmentPathRoot.replaceAll("\\\\","\\\\\\\\"));
|
|
||||||
//just to be shure...
|
|
||||||
String replaceSeparator = File.separator;
|
|
||||||
if(!replaceSeparator.equals("/")){
|
|
||||||
replaceSeparator = "\\\\";
|
|
||||||
}
|
|
||||||
filePath = filePath.replaceAll("/", replaceSeparator);
|
|
||||||
filePath = filePath.replaceAll("\\\\", replaceSeparator);
|
|
||||||
}
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("filePath: " + filePath);
|
|
||||||
final File file = new File(filePath);
|
|
||||||
if (file.exists()) {
|
|
||||||
// file data read delayed
|
|
||||||
IAttachmentLazyDataSource ds = new AttachmentFileLazyDataSource(file);
|
|
||||||
final MAttachmentEntry entry = new MAttachmentEntry(file.getName(), attach.m_items.size() + 1, ds);
|
|
||||||
attach.m_items.add(entry);
|
|
||||||
} else {
|
|
||||||
log.severe("file not found: " + file.getAbsolutePath());
|
|
||||||
attach.m_items.add(new MAttachmentEntry("~" + file.getName() + "~", "".getBytes(), attach.m_items.size() + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (SAXException sxe) {
|
} catch (SAXException sxe) {
|
||||||
// Error generated during parsing)
|
// Error generated during parsing)
|
||||||
Exception x = sxe;
|
Exception x = sxe;
|
||||||
|
@ -231,8 +278,7 @@ public class AttachmentFileSystem implements IAttachmentStore {
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
log.severe(ioe.getMessage());
|
log.severe(ioe.getMessage());
|
||||||
}
|
}
|
||||||
|
return entries;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -322,7 +322,12 @@ public class MAttachment extends X_AD_Attachment
|
||||||
if (m_items == null)
|
if (m_items == null)
|
||||||
loadLOBData();
|
loadLOBData();
|
||||||
for (int i = 0; i < m_items.size(); i++) {
|
for (int i = 0; i < m_items.size(); i++) {
|
||||||
if (m_items.get(i).getName().equals(item.getName()) ) {
|
String itemName = m_items.get(i).getName();
|
||||||
|
// Filesystem (and store other plugins can) mark not found files surrounding it with ~
|
||||||
|
// avoid duplicating the file in this case
|
||||||
|
if (itemName.startsWith("~") && itemName.endsWith("~"))
|
||||||
|
itemName = itemName.substring(1, itemName.length()-1);
|
||||||
|
if (itemName.equals(item.getName()) ) {
|
||||||
m_items.set(i, item);
|
m_items.set(i, item);
|
||||||
replaced = true;
|
replaced = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ public class WAttachment extends Window implements EventListener<Event>
|
||||||
private Button bDeleteAll = new Button();
|
private Button bDeleteAll = new Button();
|
||||||
private Button bLoad = new Button();
|
private Button bLoad = new Button();
|
||||||
private Button bCancel = ButtonFactory.createNamedButton(ConfirmPanel.A_CANCEL, false, true);
|
private Button bCancel = ButtonFactory.createNamedButton(ConfirmPanel.A_CANCEL, false, true);
|
||||||
|
private boolean bCancelClicked = false;
|
||||||
private Button bOk = ButtonFactory.createNamedButton(ConfirmPanel.A_OK, false, true);
|
private Button bOk = ButtonFactory.createNamedButton(ConfirmPanel.A_OK, false, true);
|
||||||
private Button bPreview = new Button();
|
private Button bPreview = new Button();
|
||||||
private Button bEmail = new Button();
|
private Button bEmail = new Button();
|
||||||
|
@ -613,7 +614,7 @@ public class WAttachment extends Window implements EventListener<Event>
|
||||||
}
|
}
|
||||||
clearPreview();
|
clearPreview();
|
||||||
autoPreview (cbContent.getSelectedIndex(), false);
|
autoPreview (cbContent.getSelectedIndex(), false);
|
||||||
} else if (e.getTarget() == bOk || DialogEvents.ON_WINDOW_CLOSE.equals(e.getName())) {
|
} else if (e.getTarget() == bOk || (!bCancelClicked && DialogEvents.ON_WINDOW_CLOSE.equals(e.getName()))) {
|
||||||
if (m_attachment != null) {
|
if (m_attachment != null) {
|
||||||
String newText = text.getText();
|
String newText = text.getText();
|
||||||
if (newText == null)
|
if (newText == null)
|
||||||
|
@ -640,6 +641,7 @@ public class WAttachment extends Window implements EventListener<Event>
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
} else if (e.getTarget() == bCancel) {
|
} else if (e.getTarget() == bCancel) {
|
||||||
|
bCancelClicked = true;
|
||||||
onCancel();
|
onCancel();
|
||||||
} else if (e.getTarget() == bDeleteAll) {
|
} else if (e.getTarget() == bDeleteAll) {
|
||||||
// Delete Attachment
|
// Delete Attachment
|
||||||
|
|
Loading…
Reference in New Issue