/* * Copyright (C) 2012 The Android Open Source Project * * 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 com.motorolamobility.studio.android.db.devices.model; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.osgi.util.NLS; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; import com.motorola.studio.android.adt.DDMSFacade; import com.motorola.studio.android.common.log.StudioLogger; import com.motorolamobility.studio.android.db.core.CanRefreshStatus; import com.motorolamobility.studio.android.db.core.DbCoreActivator; import com.motorolamobility.studio.android.db.core.event.DatabaseModelEvent.EVENT_TYPE; import com.motorolamobility.studio.android.db.core.event.DatabaseModelEventManager; import com.motorolamobility.studio.android.db.core.ui.AbstractTreeNode; import com.motorolamobility.studio.android.db.core.ui.IDbMapperNode; import com.motorolamobility.studio.android.db.core.ui.IDbNode; import com.motorolamobility.studio.android.db.core.ui.ISaveStateTreeNode; import com.motorolamobility.studio.android.db.core.ui.ITreeNode; import com.motorolamobility.studio.android.db.core.ui.view.SaveStateManager; import com.motorolamobility.studio.android.db.devices.DbDevicesPlugin; import com.motorolamobility.studio.android.db.devices.i18n.DbDevicesNLS; /** * This node represents a external storage node, sd card on devices that have it. */ public class ExtStorageNode extends AbstractTreeNode implements IDbDeviceMapperNode, ISaveStateTreeNode { private static final String MEMENTO_EXTERNAL_STORAGE = "ExternalStorageMapping"; //$NON-NLS-1$ private static final String MEMENTO_KEY_PREFIX = "MappedPath_"; //$NON-NLS-1$ private static final String ID_SUFFIX = "_EXT_STOR"; //$NON-NLS-1$ private static final String ICON_PATH = "icons/obj16/card.png"; //$NON-NLS-1$ private String serialNumber; private Set<IPath> dbNodes; private static final Map<String, Set<IPath>> dbNodesMap = new HashMap<String, Set<IPath>>(); public ExtStorageNode(DeviceNode parent) { super(parent); setId(serialNumber + ID_SUFFIX); //$NON-NLS-1$ serialNumber = parent.getSerialNumber(); setName(DbDevicesNLS.ExtStorageNode_Node_Name); ImageDescriptor icon = DbDevicesPlugin.imageDescriptorFromPlugin(DbDevicesPlugin.PLUGIN_ID, ICON_PATH); setIcon(icon); Set<IPath> dbNodes = new HashSet<IPath>(getDbNodes(serialNumber)); for (IPath path : dbNodes) { map(path); } } /* (non-Javadoc) * @see com.motorolamobility.studio.android.db.core.ui.AbstractTreeNode#canRefresh() */ @Override public IStatus canRefresh() { IStatus status = null; boolean hasConnectedDb = false; //Search for connected dbs for (ITreeNode treeNode : getChildren()) { if (treeNode instanceof DeviceDbNode) { DeviceDbNode dbNode = (DeviceDbNode) treeNode; hasConnectedDb = dbNode.isConnected(); break; } } if (hasConnectedDb) { status = new CanRefreshStatus(CanRefreshStatus.ASK_USER, DbDevicesPlugin.PLUGIN_ID, DbDevicesNLS.ExternalStorageNode_ConnectedDbs_Refresh_Message); } return status != null ? status : Status.OK_STATUS; } /* (non-Javadoc) * @see com.motorolamobility.studio.android.db.core.ui.AbstractTreeNode#refresh() */ @Override public void refresh() { List<ITreeNode> children = getChildren(); for (ITreeNode child : children) { DeviceDbNode dbNode = (DeviceDbNode) child; if (!dbNode.remoteFileExists()) { dbNode.clear(); dbNode.setNodeStatus(new Status(IStatus.ERROR, DbDevicesPlugin.PLUGIN_ID, DbDevicesNLS.ExtStorageNode_RemoteFile_Not_Exist)); } else { dbNode.disconnect(); } } } /* (non-Javadoc) * @see com.motorolamobility.studio.android.db.core.ui.AbstractTreeNode#isLeaf() */ @Override public boolean isLeaf() { return getChildren().isEmpty(); } /* (non-Javadoc) * @see com.motorolamobility.studio.android.db.core.ui.IDbMapperNode#map() */ public IStatus map(IPath remoteDbPath) { DeviceDbNode deviceDbNode = new DeviceDbNode(remoteDbPath, serialNumber, this); putChild(deviceDbNode); dbNodes.add(remoteDbPath); DatabaseModelEventManager.getInstance().fireEvent(deviceDbNode, EVENT_TYPE.SELECT); saveState(SaveStateManager.getInstance().getPrefNode()); return Status.OK_STATUS; } /* (non-Javadoc) * @see org.eclipse.ui.IActionFilter#testAttribute(java.lang.Object, java.lang.String, java.lang.String) */ @Override public boolean testAttribute(Object target, String name, String value) { boolean canUnmap = false; if (name.equals(IDbMapperNode.UNMAP_ACTIONFILTER_NAME) && value.equals(IDbMapperNode.UNMAP_ACTIONFILTER_VALUE)) { if (!getChildren().isEmpty()) { canUnmap = true; } } else { super.testAttribute(target, name, value); } return canUnmap; } /* (non-Javadoc) * @see com.motorolamobility.studio.android.db.core.ui.IDbMapperNode#unmap(com.motorolamobility.studio.android.db.core.ui.ITreeNode) */ public IStatus unmap(ITreeNode treeNode) { IStatus status = Status.OK_STATUS; if (treeNode instanceof IDbNode) { IDbNode dbNode = (IDbNode) treeNode; if (dbNode.isConnected()) { status = dbNode.disconnect(); } if (status.isOK()) { removeChild(dbNode); dbNodes.remove(((DeviceDbNode) treeNode).getRemoteDbPath()); } else { status = new Status(IStatus.ERROR, DbCoreActivator.PLUGIN_ID, NLS.bind( DbDevicesNLS.ExtStorageNode_Disconnect_Failed, dbNode.getName(), status.getMessage())); } } saveState(SaveStateManager.getInstance().getPrefNode()); return status != null ? status : Status.OK_STATUS; } /* (non-Javadoc) * @see com.motorolamobility.studio.android.db.core.ui.IDbMapperNode#unmap(java.util.List) */ public IStatus unmap(List<ITreeNode> dbNodeList) { MultiStatus status = new MultiStatus(DbDevicesPlugin.PLUGIN_ID, IStatus.OK, "", null); //$NON-NLS-1$ for (ITreeNode dbNode : dbNodeList) { status.add(unmap(dbNode)); } saveState(SaveStateManager.getInstance().getPrefNode()); return status != null ? status : Status.OK_STATUS; } private Set<IPath> getDbNodes(String serialNumber_) { dbNodes = dbNodesMap.get(serialNumber_); if (dbNodes == null) { dbNodes = new HashSet<IPath>(); dbNodesMap.put(serialNumber_, dbNodes); } return dbNodes; } /* * (non-Javadoc) * @see com.motorolamobility.studio.android.db.core.ui.ISaveStateTreeNode#saveState(org.eclipse.core.runtime.preferences.IEclipsePreferences) */ public void saveState(IEclipsePreferences preferences) { Preferences node = preferences.node(MEMENTO_EXTERNAL_STORAGE); Preferences serialNode = node.node(DDMSFacade.getNameBySerialNumber(serialNumber)); int i = 1; List<ITreeNode> children = getChildren(); for (ITreeNode child : children) { DeviceDbNode dbNode = (DeviceDbNode) child; serialNode.put(MEMENTO_KEY_PREFIX + i, dbNode.getRemoteDbPath().toString()); i++; } try { preferences.flush(); } catch (BackingStoreException e) { StudioLogger.error("Could not contact backing store: ", e.getMessage()); //$NON-NLS-1$ } } /* * (non-Javadoc) * @see com.motorolamobility.studio.android.db.core.ui.ISaveStateTreeNode#restoreState(org.eclipse.core.runtime.preferences.IEclipsePreferences) */ public void restoreState(IEclipsePreferences preferences) { if (serialNumber == null) { serialNumber = ((DeviceNode) getParent()).getSerialNumber(); } boolean firstTime = !dbNodesMap.containsKey(serialNumber); Set<IPath> dbNodes = getDbNodes(serialNumber); if (firstTime) { try { if (preferences.nodeExists(MEMENTO_EXTERNAL_STORAGE)) { Preferences node = preferences.node(MEMENTO_EXTERNAL_STORAGE); String deviceName = DDMSFacade.getNameBySerialNumber(serialNumber); if (node.nodeExists(deviceName)) { Preferences deviceNode = node.node(deviceName); String[] attributeKeys = deviceNode.keys(); if (attributeKeys.length > 0) { for (String key : attributeKeys) { if (key.startsWith(MEMENTO_KEY_PREFIX)) //$NON-NLS-1$ { String mappedPath = deviceNode.get(key, null); if (mappedPath != null) { dbNodes.add(new Path(mappedPath)); } } } } } } } catch (BackingStoreException e) { StudioLogger.error("Could not contact backing store: ", e.getMessage()); //$NON-NLS-1$ } } } }