/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2012 psiinon@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.zaproxy.zap.extension.autoupdate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.parosproxy.paros.Constant;
import org.zaproxy.zap.control.AddOn;
import org.zaproxy.zap.control.AddOn.AddOnRunRequirements;
import org.zaproxy.zap.control.AddOnCollection;
import org.zaproxy.zap.extension.autoupdate.AddOnWrapper.Status;
public class InstalledAddOnsTableModel extends AddOnsTableModel {
private static final long serialVersionUID = 1L;
private static final String[] COLUMN_NAMES = {
"", // Column for warning of running issues (e.g. incorrect Java version, missing dependency...)
Constant.messages.getString("cfu.table.header.name"),
Constant.messages.getString("cfu.table.header.desc"),
Constant.messages.getString("cfu.table.header.update"),
""};
private static final int COLUMN_COUNT = COLUMN_NAMES.length;
private AddOnCollection availableAddOns;
public InstalledAddOnsTableModel(AddOnCollection installedAddOns) {
super(installedAddOns, 3);
for (AddOn addOn : installedAddOns.getAddOns()) {
addAddOnWrapper(addOn, null);
}
}
public void setAvailableAddOns(AddOnCollection availableAddOns) {
this.availableAddOns = availableAddOns;
}
@Override
public int getColumnCount() {
return COLUMN_COUNT;
}
@Override
public String getColumnName(int col) {
return COLUMN_NAMES[col];
}
@Override
public int getRowCount() {
return getAddOnWrappers().size();
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0 || columnIndex == 4) {
return Boolean.class;
}
return String.class;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
AddOnWrapper aow = getAddOnWrapper(rowIndex);
switch (columnIndex) {
case COLUMN_ADD_ON_WRAPPER:
return aow;
case 0:
return Boolean.valueOf(aow.hasRunningIssues());
case 1:
return aow.getAddOn().getName();
case 2:
return aow.getAddOn().getDescription();
case 3:
int progress = aow.getProgress();
if (aow.isFailed()) {
return Constant.messages.getString("cfu.table.label.failed");
} else if (AddOn.InstallationStatus.UNINSTALLATION_FAILED == aow.getInstallationStatus()
|| AddOn.InstallationStatus.SOFT_UNINSTALLATION_FAILED == aow.getInstallationStatus()) {
return Constant.messages.getString("cfu.table.label.restartRequired");
} else if (progress > 0) {
return progress + "%";
} else if (AddOnWrapper.Status.newVersion == aow.getStatus()) {
return Constant.messages.getString("cfu.table.label.update");
} else {
return "";
}
case 4:
return getAddOnWrapper(rowIndex).isEnabled();
}
return null;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex != 4) {
return;
}
AddOnWrapper addOnWrapper = getAddOnWrapper(rowIndex);
if (AddOn.InstallationStatus.UNINSTALLATION_FAILED == addOnWrapper.getInstallationStatus()
|| AddOn.InstallationStatus.SOFT_UNINSTALLATION_FAILED == addOnWrapper.getInstallationStatus()) {
return;
}
if (aValue instanceof Boolean) {
if (addOnWrapper.getInstallationStatus() != AddOn.InstallationStatus.DOWNLOADING) {
addOnWrapper.setEnabled(((Boolean) aValue).booleanValue());
this.fireTableCellUpdated(rowIndex, columnIndex);
}
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex != 4) {
return false;
}
AddOnWrapper addOnWrapper = getAddOnWrapper(rowIndex);
if (AddOn.InstallationStatus.UNINSTALLATION_FAILED == addOnWrapper.getInstallationStatus()
|| AddOn.InstallationStatus.SOFT_UNINSTALLATION_FAILED == addOnWrapper.getInstallationStatus()) {
return false;
}
if (addOnWrapper.getInstallationStatus() != AddOn.InstallationStatus.DOWNLOADING) {
// Its the 'enabled' checkbox, and no download is in progress
return true;
}
return false;
}
public boolean canUpdateSelected() {
boolean enable = false;
for (AddOnWrapper addon : getAddOnWrappers()) {
if (addon.isEnabled()) {
if (Status.newVersion == addon.getStatus()) {
enable = true;
} else {
return false;
}
}
}
return enable;
}
public boolean canUninstallSelected() {
boolean enable = false;
for (AddOnWrapper addon : getAddOnWrappers()) {
if (addon.isEnabled()) {
return true;
}
}
return enable;
}
public void addOrRefreshAddOn(AddOn addOn) {
for (int idx = 0; idx < getAddOnWrappers().size(); idx++) {
AddOnWrapper aow = getAddOnWrappers().get(idx);
if (addOn.isSameAddOn(getAddOnForDownload(aow))) {
aow.setAddOn(addOn);
fireTableRowsUpdated(idx, idx);
refreshEntries();
return;
}
}
addAddOnWrapper(addOn, null);
}
@Override
protected boolean refreshEntry(AddOnWrapper aow, int row) {
boolean changed = super.refreshEntry(aow, row);
if (aow.getAddOnUpdate() != null) {
changed |= refreshUpdateIssues(aow);
}
return changed;
}
@Override
protected AddOnWrapper createAddOnWrapper(AddOn addOn, Status status) {
AddOnWrapper aow = super.createAddOnWrapper(addOn, status);
if (availableAddOns != null) {
AddOn possibleUpdate = availableAddOns.getAddOn(addOn.getId());
if (possibleUpdate != null && possibleUpdate.isUpdateTo(aow.getAddOn())) {
aow.setAddOnUpdate(possibleUpdate);
refreshUpdateIssues(aow);
}
}
return aow;
}
private boolean refreshUpdateIssues(AddOnWrapper aow) {
AddOnRunRequirements reqs = aow.getAddOnUpdate().calculateRunRequirements(availableAddOns.getAddOns());
String issues = getAddOnRunningIssues(reqs);
aow.setUpdateIssues(issues, !reqs.hasExtensionsWithRunningIssues());
return !issues.isEmpty();
}
public Set<AddOn> getSelectedUpdates() {
Set<AddOn> selectedAddOns = new HashSet<>();
for (AddOnWrapper aow : getAddOnWrappers()) {
if (aow.isEnabled() && aow.getAddOnUpdate() != null) {
selectedAddOns.add(aow.getAddOnUpdate());
}
}
return selectedAddOns;
}
public Set<AddOn> getAllUpdates() {
Set<AddOn> selectedAddOns = new HashSet<>();
for (AddOnWrapper aow : getAddOnWrappers()) {
if (aow.getAddOnUpdate() != null) {
selectedAddOns.add(aow.getAddOnUpdate());
}
}
return selectedAddOns;
}
@Override
protected AddOn getAddOnForDownload(AddOnWrapper aow) {
if (aow.getAddOnUpdate() == null) {
return aow.getAddOn();
}
return aow.getAddOnUpdate();
}
public List<AddOn> updateEntries() {
if (availableAddOns == null) {
return Collections.emptyList();
}
List<AddOn> addOnsNotInstalled = new ArrayList<>(availableAddOns.getAddOns());
for (int i = 0; i < getAddOnWrappers().size(); i++) {
boolean fireRowUpdate = false;
boolean fireCellUpdate = false;
AddOnWrapper aow = getAddOnWrappers().get(i);
removeAddOn(addOnsNotInstalled, aow.getAddOn().getId());
AddOn addOn = availableAddOns.getAddOn(aow.getAddOn().getId());
if (addOn != null && addOn.isUpdateTo(aow.getAddOn())) {
aow.setAddOnUpdate(addOn);
refreshUpdateIssues(aow);
fireRowUpdate = true;
} else {
aow.setStatus(null);
fireCellUpdate = true;
}
if (aow.hasRunningIssues()) {
fireRowUpdate = refreshRunningIssues(aow, i);
}
if (fireRowUpdate) {
fireTableRowsUpdated(i, i);
} else if (fireCellUpdate) {
fireTableCellUpdated(i, 3);
}
}
return addOnsNotInstalled;
}
public static void removeAddOn(List<AddOn> addOns, String id) {
for (Iterator<AddOn> it = addOns.iterator(); it.hasNext();) {
AddOn addOn = it.next();
if (addOn.getId().equals(id)) {
it.remove();
return;
}
}
}
@Override
protected void restoreInstallationStatusFailedDownload(AddOnWrapper aow) {
aow.setInstallationStatus(AddOn.InstallationStatus.INSTALLED);
}
@Override
protected AddOn getMissingAddOn(String addOnId) {
AddOn addOn = super.getMissingAddOn(addOnId);
if (addOn != null) {
return addOn;
}
if (availableAddOns != null) {
return availableAddOns.getAddOn(addOnId);
}
return null;
}
}