package org.ovirt.engine.ui.uicommonweb.models.storage; import java.util.HashMap; import java.util.Map; import org.ovirt.engine.core.common.businessentities.storage.VolumeFormat; import org.ovirt.engine.ui.uicommonweb.models.EntityModel; import org.ovirt.engine.ui.uicompat.ConstantsManager; import org.ovirt.engine.ui.uicompat.EventArgs; import org.ovirt.engine.ui.uicompat.UIConstants; import com.google.gwt.dom.client.Element; public class ImageInfoModel extends EntityModel<String> { private static final UIConstants constants = ConstantsManager.getInstance().getConstants(); private VolumeFormat format; private int actualSize; private int virtualSize; private QemuCompat qcowCompat; private Boolean backingFile; private Boolean fileLoaded = false; public VolumeFormat getFormat() { return format; } public void setFormat(VolumeFormat format) { this.format = format; } public int getActualSize() { return actualSize; } public void setActualSize(int actualSize) { this.actualSize = actualSize; } public int getVirtualSize() { return virtualSize; } public void setVirtualSize(int virtualSize) { this.virtualSize = virtualSize; } public QemuCompat getQcowCompat() { return qcowCompat; } public void setQcowCompat(QemuCompat qcowCompat) { this.qcowCompat = qcowCompat; } public Boolean isBackingFile() { return backingFile; } public void setBackingFile(Boolean backingFile) { this.backingFile = backingFile; } public Boolean getFileLoaded() { return fileLoaded; } public void setFileLoaded(Boolean fileLoaded) { this.fileLoaded = fileLoaded; } public native void initialize(Element imageFileUploadElement) /*-{ var self = this; imageFileUploadElement.addEventListener('change', onChange); function onChange() { self.@org.ovirt.engine.ui.uicommonweb.models.storage.ImageInfoModel::clearModel()(); // See http://git.qemu.org/?p=qemu.git;a=blob;f=docs/specs/qcow2.txt var file = imageFileUploadElement.files[0]; var reader = new FileReader(); reader.onload = function(e) { var header = reader.result; if (header.byteLength == 0) { // can't open the file return; } var headerStr = readString(header.slice(0, 4)); var info = {}; info.format = headerStr == "QFI\xfb" ? "COW" : "RAW"; info.actualSize = toGB(file.size); info.virtualSize = 0; info.backingFile = false; info.fileLoaded = true; if (info.format == "COW") { var version = readUint32(header.slice(4, 8)); info.qcowCompat = version == 2 ? "0.10" : version == 3 ? "1.1" : ""; var backingFileOffset = readUint64(header.slice(8, 16)); info.backingFile = backingFileOffset != 0; info.virtualSize = toGB(readUint64(header.slice(24, 32))); } self.@org.ovirt.engine.ui.uicommonweb.models.storage.ImageInfoModel::updateModel(*) ( info.format, info.actualSize, info.virtualSize, info.qcowCompat, info.backingFile, info.fileLoaded); }; var blob = file.slice(0, 32); reader.readAsArrayBuffer(blob); }; function readString(buf) { // Reading from array buffer, assuming big endian return String.fromCharCode.apply(null, new Uint8Array(buf)); }; function readUint32(buf) { return new DataView(buf).getUint32(0); }; function readUint64(buf) { var dv = new DataView(buf); var high = dv.getUint32(0); var low = dv.getUint32(4); // There is no way to represent uint64, but double works. return high * 4294967296.0 + low; }; function toGB(size) { return Math.ceil(size / Math.pow(1024, 3)); }; }-*/; public void updateModel(String format, int actualSize, int virtualSize, String qcowCompat, boolean backingFile, boolean fileLoaded) { setFormat(VolumeFormat.valueOf(format)); setActualSize(actualSize); setVirtualSize(virtualSize); setQcowCompat(QemuCompat.forValue(qcowCompat)); setBackingFile(backingFile); setFileLoaded(fileLoaded); getEntityChangedEvent().raise(this, EventArgs.EMPTY); } public void clearModel() { setFormat(null); setActualSize(0); setVirtualSize(0); setQcowCompat(null); setBackingFile(null); setFileLoaded(false); setIsValid(true); getInvalidityReasons().clear(); getEntityChangedEvent().raise(this, EventArgs.EMPTY); } public boolean validate() { if (!fileLoaded) { getInvalidityReasons().add(constants.uploadImageCannotBeOpened()); return false; } if (backingFile) { getInvalidityReasons().add(constants.uploadImageBackingFileUnsupported()); return false; } return true; } public enum QemuCompat { V2("0.10"), //$NON-NLS-1$ V3("1.1"); //$NON-NLS-1$ private final String value; private static final Map<String, QemuCompat> mappings = new HashMap<>(); static { for (QemuCompat compat : values()) { mappings.put(compat.getValue(), compat); } } private QemuCompat(String value) { this.value = value; } public String getValue() { return value; } public static QemuCompat forValue(String value) { return mappings.get(value); } } }