Omaha #5605 Fix combinations file retrieval again

Change-Id: I491ee8426bb6a22d9cdabe925c906d1c86777cb8

Former-commit-id: cd5be4eec18a9dc9453e0da3af301b7f5394e11f
This commit is contained in:
Ron Anderson 2016-04-25 15:13:29 -05:00
parent 9e8c36cc91
commit 8212a8ebd0
7 changed files with 137 additions and 292 deletions

View file

@ -63,12 +63,14 @@ import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.CombinationsFileChangedNotification;
import com.raytheon.uf.common.localization.FileUpdatedMessage;
import com.raytheon.uf.common.localization.ILocalizationFileObserver;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.LocalizationUtil;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
@ -80,7 +82,6 @@ import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.gfe.Activator;
import com.raytheon.viz.gfe.core.DataManager;
import com.raytheon.viz.gfe.core.DataManagerUIFactory;
import com.raytheon.viz.gfe.core.internal.NotificationRouter.AbstractGFENotificationObserver;
import com.raytheon.viz.gfe.textformatter.CombinationsFileUtil;
import com.raytheon.viz.gfe.textformatter.TextProductManager;
import com.raytheon.viz.gfe.ui.zoneselector.ZoneSelector;
@ -112,6 +113,7 @@ import com.raytheon.viz.gfe.ui.zoneselector.ZoneSelector;
* FileUpdatedMessage so we can ignore our own changes
* Moved retrieval of combinations file to CombinationsFileUtil.init
* Oct 07, 2015 #4695 dgilling Move loading of combinations file off UI thread.
* Apr 25, 2016 #5605 randerso Switched back to writing combinations file using Localization
*
* </pre>
*
@ -208,7 +210,7 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
protected boolean mapRequired;
private List<RGB> colorMap = new ArrayList<RGB>();
private List<RGB> colorMap = new ArrayList<>();
private final String COLOR_MAP_FILE = FileUtil.join("gfe", "combinations",
"Combinations_ColorMap");
@ -229,15 +231,13 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
protected Object initialZoom = null;
private String currentComboFile = null;
private final LocalizationFile comboDir;
private final LocalizationFile combinationsFile;
private boolean includeAllZones = false;
private List<String> mapNames;
private AbstractGFENotificationObserver<CombinationsFileChangedNotification> comboChangeListener;
private ILocalizationFileObserver combinationsChangeListener;
private final ExecutorService asyncExecutor;
@ -289,41 +289,43 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
initPreferences();
init();
String combinationsName = textProductMgr
.getCombinationsFileName(productName);
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext baseCtx = pathMgr.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
comboDir = pathMgr.getLocalizationFile(baseCtx,
CombinationsFileUtil.COMBO_DIR_PATH);
combinationsFile = pathMgr.getLocalizationFile(baseCtx,
LocalizationUtil.join(
CombinationsFileUtil.COMBINATIONS_DIR_PATH,
combinationsName + ".py"));
this.comboChangeListener = new AbstractGFENotificationObserver<CombinationsFileChangedNotification>(
CombinationsFileChangedNotification.class) {
this.combinationsChangeListener = new ILocalizationFileObserver() {
@Override
public void notify(
CombinationsFileChangedNotification notificationMessage) {
comboFileChanged(notificationMessage);
}
public void fileUpdated(FileUpdatedMessage message) {
comboFileChanged(message);
}
};
this.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
ZoneCombinerComp.this.dataManager.getNotificationRouter()
.removeObserver(
ZoneCombinerComp.this.comboChangeListener);
combinationsFile
.removeFileUpdatedObserver(combinationsChangeListener);
ZoneCombinerComp.this.asyncExecutor.shutdown();
}
});
dataManager.getNotificationRouter().addObserver(
this.comboChangeListener);
combinationsFile
.addFileUpdatedObserver(this.combinationsChangeListener);
}
private List<String> getMapNames(String productName) {
Object obj = this.textProductMgr.getMapNameForCombinations(productName);
List<String> mapNames = new ArrayList<String>();
List<String> mapNames = new ArrayList<>();
if (obj instanceof String) {
String s = (String) obj;
if (!s.isEmpty()) {
@ -554,7 +556,7 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
if (zoneSelector != null) {
return zoneSelector.getZoneGroupings();
} else {
return new ArrayList<List<String>>();
return new ArrayList<>();
}
}
@ -717,7 +719,7 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
}
LocalizationFile[] lfs = CombinationsFileUtil.getSavedCombos();
List<String> names = new ArrayList<String>();
List<String> names = new ArrayList<>();
for (LocalizationFile lf : lfs) {
String id = CombinationsFileUtil.fileToId(lf);
String name = CombinationsFileUtil.fnToName(this.mapNames, id);
@ -943,8 +945,8 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
LocalizationContext localization = pm.getContext(
LocalizationType.CAVE_STATIC, level);
File localFile = pm.getFile(localization,
FileUtil.join(CombinationsFileUtil.COMBO_DIR_PATH, local));
File localFile = pm.getFile(localization, FileUtil.join(
CombinationsFileUtil.COMBINATIONS_DIR_PATH, local));
return localFile;
}
@ -960,7 +962,7 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
} catch (Exception e) {
statusHandler.handle(Priority.SIGNIFICANT,
"Error loading combo file", e);
comboDict = new HashMap<String, Integer>();
comboDict = new HashMap<>();
}
zoneSelector.updateCombos(comboDict);
}
@ -992,7 +994,7 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
return Collections.emptyMap();
}
Map<String, Integer> dict = new HashMap<String, Integer>();
Map<String, Integer> dict = new HashMap<>();
// reformat combinations into combo dictionary
int group = 1;
for (List<String> zonelist : combolist) {
@ -1002,8 +1004,6 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
group += 1;
}
currentComboFile = comboName;
return dict;
}
@ -1011,7 +1011,7 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
* load the color map file
*/
private List<RGB> getColorsFromFile() {
List<RGB> colors = new ArrayList<RGB>();
List<RGB> colors = new ArrayList<>();
IPathManager pm = PathManagerFactory.getPathManager();
File file = pm.getStaticFile(COLOR_MAP_FILE);
@ -1037,19 +1037,16 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
return colors;
}
private void comboFileChanged(CombinationsFileChangedNotification notif) {
String comboName = notif.getCombinationsFileName();
private void comboFileChanged(FileUpdatedMessage message) {
String comboName = LocalizationUtil.extractName(message.getFileName())
.replace(".py", "");
statusHandler
.info("Received CombinationsFileChangedNotification for combinations file: "
+ comboName);
// if it's the same file and not changed by me update the combos
if (comboName.equalsIgnoreCase(currentComboFile)
&& !VizApp.getWsId().equals(notif.getWhoChanged())) {
statusHandler
.info("Received CombinationsFileChangedNotification for combinations file: "
+ comboName);
Map<String, Integer> comboDict = loadCombinationsFile(comboName);
this.zoneSelector.updateCombos(comboDict);
applyButtonState(false);
}
Map<String, Integer> comboDict = loadCombinationsFile(comboName);
this.zoneSelector.updateCombos(comboDict);
applyButtonState(false);
}
@Override

View file

@ -22,6 +22,10 @@ package com.raytheon.viz.gfe.textformatter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -38,7 +42,6 @@ import jep.JepException;
import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException;
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
import com.raytheon.uf.common.dataplugin.gfe.request.SaveCombinationsFileRequest;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
@ -56,8 +59,7 @@ import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.viz.gfe.core.DataManagerUIFactory;
import com.raytheon.viz.gfe.core.internal.IFPClient;
import com.raytheon.uf.common.util.StringUtil;
import com.raytheon.viz.gfe.textformatter.CombinationsFileUtil.ComboData.Entry;
/**
@ -78,6 +80,7 @@ import com.raytheon.viz.gfe.textformatter.CombinationsFileUtil.ComboData.Entry;
* Sep 08, 2014 #3592 randerso Changed to use only list site level files as all
* combo files are saved to the site level
* Oct 07, 2015 #4695 dgilling Code cleanup to remove compile warnings.
* Apr 25, 2016 #5605 randerso Switched back to writing combinations file using Localization
*
* </pre>
*
@ -91,7 +94,8 @@ public class CombinationsFileUtil {
private static final int MAX_TRIES = 2;
public static String COMBO_DIR_PATH = FileUtil.join("gfe", "combinations");
public static String COMBINATIONS_DIR_PATH = FileUtil.join("gfe",
"combinations");
public static String SAVED_COMBO_DIR = FileUtil.join("gfe", "comboData");
@ -127,8 +131,7 @@ public class CombinationsFileUtil {
}
public ComboData(Map<String, Integer> comboDict) {
this.combos = new ArrayList<CombinationsFileUtil.ComboData.Entry>(
comboDict.size());
this.combos = new ArrayList<>(comboDict.size());
for (java.util.Map.Entry<String, Integer> entry : comboDict
.entrySet()) {
this.combos.add(new Entry(entry.getKey(), entry.getValue()));
@ -214,7 +217,7 @@ public class CombinationsFileUtil {
try (InputStream in = lf.openInputStream()) {
ComboData comboData = (ComboData) jaxb.unmarshalFromInputStream(in);
Map<String, Integer> comboDict = new HashMap<String, Integer>(
Map<String, Integer> comboDict = new HashMap<>(
comboData.combos.size());
for (Entry entry : comboData.combos) {
comboDict.put(entry.zone, entry.group);
@ -232,18 +235,18 @@ public class CombinationsFileUtil {
// retrieve combinations file if it's changed
LocalizationFile lf = pm.getStaticLocalizationFile(
LocalizationType.CAVE_STATIC,
FileUtil.join(COMBO_DIR_PATH, comboName + ".py"));
FileUtil.join(COMBINATIONS_DIR_PATH, comboName + ".py"));
File pyFile = null;
if (lf != null) {
try {
// get the local .py file
pyFile = lf.getFile(false);
// delete both the local .py and .pyo files to force retrieval
// delete both the local .py and .pyc files to force retrieval
// and regeneration
pyFile.delete();
File pyoFile = new File(pyFile.getPath() + "o");
pyoFile.delete();
File pycFile = new File(pyFile.getPath() + "c");
pycFile.delete();
// retrieve the .py file
pyFile = lf.getFile(true);
@ -265,7 +268,7 @@ public class CombinationsFileUtil {
.getPath(), "CombinationsInterface.py");
List<List<String>> combos = null;
HashMap<String, Object> map = new HashMap<String, Object>();
HashMap<String, Object> map = new HashMap<>();
map.put("comboName", comboName);
for (int retryCount = 0; retryCount < MAX_TRIES; retryCount++) {
try (PythonScript python = new PythonScript(scriptPath,
@ -279,8 +282,8 @@ public class CombinationsFileUtil {
// if successfully retrieved break out of the loop
break;
} catch (JepException e) {
// remove the .pyo file
new File(pyFile.getAbsolutePath() + "o").delete();
// remove the .pyc file
new File(pyFile.getAbsolutePath() + "c").delete();
// if not last try, log and try again
if (retryCount < (MAX_TRIES - 1)) {
@ -303,25 +306,53 @@ public class CombinationsFileUtil {
* Generates combinations files based on just running the formatter
*
* @param zoneGroupList
* @param filename
* @param comboName
* @throws Exception
* @throws IOException
*/
public static void generateAutoCombinationsFile(
List<List<String>> zoneGroupList, String filename) throws Exception {
IFPClient ifpc = DataManagerUIFactory.getCurrentInstance().getClient();
SaveCombinationsFileRequest req = new SaveCombinationsFileRequest();
req.setFileName(filename);
req.setCombos(zoneGroupList);
try {
statusHandler.info("Saving combinations file: " + filename);
ifpc.makeRequest(req);
statusHandler.info("Successfully saved combinations file: "
+ filename);
List<List<String>> zoneGroupList, String comboName)
throws Exception {
IPathManager pm = PathManagerFactory.getPathManager();
LocalizationContext localization = pm.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.SITE);
String fileName = FileUtil.join(COMBINATIONS_DIR_PATH, comboName)
+ ".py";
LocalizationFile lf = pm.getLocalizationFile(localization, fileName);
try (SaveableOutputStream stream = lf.openOutputStream();
Writer outWriter = new OutputStreamWriter(stream)) {
String zoneComments = "\n# Automatically generated combinations file\n# "
+ comboName + "\n\nCombinations = [\n";
outWriter.write(zoneComments);
NumberFormat df = new DecimalFormat("00");
for (int i = 0; i < zoneGroupList.size(); i++) {
StringBuilder nextLineToWrite = new StringBuilder();
List<String> modZGL = new ArrayList<>(zoneGroupList.get(i)
.size());
for (String zone : zoneGroupList.get(i)) {
modZGL.add("'" + zone + "'");
}
nextLineToWrite.append("\t([");
nextLineToWrite.append(StringUtil.join(modZGL, ','));
nextLineToWrite.append("], ");
nextLineToWrite.append("'Region");
nextLineToWrite.append(df.format(i + 1));
nextLineToWrite.append("' ),\n");
outWriter.write(nextLineToWrite.toString());
}
outWriter.write("]");
outWriter.close();
stream.save();
} catch (Exception e) {
statusHandler.error("Error saving combinations file: " + filename,
statusHandler.error("Error saving combinations file: " + fileName,
e);
throw e;
}
}
}

View file

@ -0,0 +1,37 @@
#!/awips2/python/bin/python
# Adds the gfe/combinations permission to user ALL for all site level userRoles.xml files
USER_ROLES_PATH = "/awips2/edex/data/utility/common_static/site/*/roles/userRoles.xml"
COMBINATIONS_PERMISSION = "com.raytheon.localization.site/cave_static/gfe/combinations"
import glob
import sys
import xml.etree.ElementTree as ET
def main():
for path in glob.iglob(USER_ROLES_PATH):
print "Updating", path
tree = ET.parse(path)
root = tree.getroot()
for user in root.iterfind("user"):
userId = user.attrib["userId"]
if userId == "ALL":
found = False
for userPermission in user.iterfind("userPermission"):
if userPermission.text == COMBINATIONS_PERMISSION:
found = True
break
if found:
print "userId", userId, "already has", COMBINATIONS_PERMISSION
else:
print "Adding", COMBINATIONS_PERMISSION, "to userId", userId
sub = ET.SubElement(user, "userPermission")
sub.text = COMBINATIONS_PERMISSION
# write out the updated file
tree.write(path)
break
if __name__ == '__main__':
main()

View file

@ -206,11 +206,6 @@
<constructor-arg value="com.raytheon.uf.common.dataplugin.gfe.request.ConfigureTextProductsRequest"/>
<constructor-arg ref="configureTextProductsHandler"/>
</bean>
<bean id="SaveCombinationsFileHandler" class="com.raytheon.edex.plugin.gfe.server.handler.SaveCombinationsFileHandler"/>
<bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.dataplugin.gfe.request.SaveCombinationsFileRequest"/>
<constructor-arg ref="SaveCombinationsFileHandler"/>
</bean>
<bean id="GetSelectTRHandler" class="com.raytheon.edex.plugin.gfe.server.handler.GetSelectTimeRangeHandler"/>
<bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.dataplugin.gfe.request.GetSelectTimeRangeRequest"/>

View file

@ -1,135 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.gfe.server.handler;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.dataplugin.gfe.request.SaveCombinationsFileRequest;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.CombinationsFileChangedNotification;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.common.util.StringUtil;
/**
* Request handler for <code>SaveCombinationsFileRequest</code>. Writes the
* specified zone combinations to the specified site's combinations file
* directory.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 16, 2011 dgilling Initial creation
* Dec 02, 2013 #2591 dgilling Only send notification after Writer is
* flushed/closed.
* Feb 05, 2014 #2591 Added CombinationFileChangedNotification
* Jul 21, 2014 2768 bclement removed FileUpdateMessage
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public class SaveCombinationsFileHandler implements
IRequestHandler<SaveCombinationsFileRequest> {
private static final String COMBO_FILE_DIR = FileUtil.join("gfe",
"combinations");
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest
* (com.raytheon.uf.common.serialization.comm.IServerRequest)
*/
@Override
public ServerResponse<Object> handleRequest(
SaveCombinationsFileRequest request) throws Exception {
String siteID = request.getSiteID();
IPathManager pm = PathManagerFactory.getPathManager();
LocalizationContext localization = pm.getContextForSite(
LocalizationType.CAVE_STATIC, siteID);
String comboName = request.getFileName();
String fileName = FileUtil.join(COMBO_FILE_DIR, comboName) + ".py";
LocalizationFile lf = pm.getLocalizationFile(localization, fileName);
Writer outWriter = null;
try {
outWriter = new BufferedWriter(new OutputStreamWriter(
lf.openOutputStream()));
String zoneComments = "\n# Automatically generated combinations file\n# "
+ comboName + "\n\nCombinations = [\n";
outWriter.write(zoneComments);
NumberFormat df = new DecimalFormat("00");
for (int i = 0; i < request.getCombos().size(); i++) {
StringBuilder nextLineToWrite = new StringBuilder();
List<String> modZGL = new ArrayList<String>(request.getCombos()
.get(i).size());
for (String zone : request.getCombos().get(i)) {
modZGL.add("'" + zone + "'");
}
nextLineToWrite.append("\t([");
nextLineToWrite.append(StringUtil.join(modZGL, ','));
nextLineToWrite.append("], ");
nextLineToWrite.append("'Region");
nextLineToWrite.append(df.format(i + 1));
nextLineToWrite.append("' ),\n");
outWriter.write(nextLineToWrite.toString());
}
outWriter.write("]");
} finally {
if (outWriter != null) {
outWriter.close();
}
}
lf.save();
/*
* placing the notification code here ensures we only send the
* notification on a successful file write operation. Otherwise we would
* have thrown an IOException and never gotten to this portion of the
* request handler.
*/
CombinationsFileChangedNotification notif = new CombinationsFileChangedNotification(
comboName, request.getWorkstationID(), siteID);
SendNotifications.send(notif);
return new ServerResponse<Object>();
}
}

View file

@ -1,83 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.gfe.request;
import java.util.List;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 16, 2011 dgilling Initial creation
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
@DynamicSerialize
public class SaveCombinationsFileRequest extends AbstractGfeRequest {
@DynamicSerializeElement
private String fileName;
@DynamicSerializeElement
private List<List<String>> combos;
/**
* @param fileName
* the fileName to set
*/
public void setFileName(String fileName) {
this.fileName = fileName;
}
/**
* @return the fileName
*/
public String getFileName() {
return fileName;
}
/**
* @param combos
* the combos to set
*/
public void setCombos(List<List<String>> combos) {
this.combos = combos;
}
/**
* @return the combos
*/
public List<List<String>> getCombos() {
return combos;
}
}

View file

@ -53,6 +53,9 @@
<permission id="com.raytheon.localization.site/cave_static/gfe/comboData">
</permission>
<permission id="com.raytheon.localization.site/cave_static/gfe/combinations">
</permission>
<permission id="com.raytheon.localization.site/cave_static/gfe/tcvAdvisories">
</permission>