Merge branch 'omaha_14.4.1' of ssh://www.awips2omaha.com:29418/AWIPS2_baseline into master_14.4.1

Former-commit-id: 1dc1cede71ab27d3339f396369827a6a89a8ad80
This commit is contained in:
Fay.Liang 2015-03-05 10:33:36 -05:00
commit c5257a52c6
31 changed files with 1450 additions and 1754 deletions

Binary file not shown.

View file

@ -37,7 +37,6 @@ import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
@ -69,6 +68,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
* Mar 05, 2014 2632 mpduff Changed task set to map of user->task.
* Mar 27, 2014 2632 mpduff Sorted users in combo box, changed how Add action works.
* Jun 12, 2014 3269 mpduff Changed to use the unsaved values upon open.
* Feb 25, 2015 4154 mapeters Added null check in constructor, removed editFlag field.
*
* </pre>
*
@ -82,10 +82,10 @@ public class AddNotifierDlg extends CaveSWTDialog {
private final String[] userIds;
/** Map of buttons to Notifiers */
private final Map<Button, Notifier> buttonMap = new HashMap<Button, Notifier>();
private final Map<Button, Notifier> buttonMap = new HashMap<>();
/** Set of NotifierTask objects */
private Map<String, NotifierTask> taskMap = new HashMap<String, NotifierTask>();
private Map<String, NotifierTask> taskMap;
/** The user select Combo box */
private Combo userCbo;
@ -102,28 +102,28 @@ public class AddNotifierDlg extends CaveSWTDialog {
/** Close callback */
private final ICloseCallback callback;
/** Flag for dialog mode, edit or new */
private boolean editFlag;
/**
* Constructor.
*
* @param parent
* @param userIds
* @param editFlag
* Flag for dialog mode (edit or new)
* @param taskMap
* @param callback
*/
public AddNotifierDlg(Shell parent, String[] userIds, boolean editFlag, Map<String, NotifierTask> taskMap,
ICloseCallback callback) {
public AddNotifierDlg(Shell parent, String[] userIds, boolean editFlag,
Map<String, NotifierTask> taskMap, ICloseCallback callback) {
super(parent, SWT.DIALOG_TRIM, CAVE.DO_NOT_BLOCK);
if (editFlag) {
setText("Edit Notifier");
setText("Edit Notifier");
} else {
setText("Add Notifier");
setText("Add Notifier");
}
this.userIds = userIds;
this.callback = callback;
this.editFlag = editFlag;
this.taskMap = taskMap;
this.taskMap = taskMap == null ? new HashMap<String, NotifierTask>()
: taskMap;
}
public AddNotifierDlg(Shell parent, String[] userIds) {
@ -319,7 +319,7 @@ public class AddNotifierDlg extends CaveSWTDialog {
GridData btnData = new GridData(75, SWT.DEFAULT);
Button okBtn = new Button(comp, SWT.PUSH);
okBtn.setText("OK");
okBtn.setText("OK");
okBtn.setLayoutData(btnData);
okBtn.addSelectionListener(new SelectionAdapter() {
@Override

View file

@ -1,42 +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.viz.gfe.dialogs.formatterlauncher;
/**
* Interface for storing/transmitting a product.
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 18 APR 2008 ### lvenable Initial creation
*
* </pre>
*
* @author lvenable
* @version 1.0
*
*/
public interface IStoreTransmitProduct {
/**
* Store/Transmit method call.
*/
void storeTransmitProduct();
}

View file

@ -1,225 +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.viz.gfe.dialogs.formatterlauncher;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.gfe.core.DataManager;
/**
* Thread used for counting down Storing/Transmitting products.
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 18 APR 2008 ### lvenable Initial creation
* 20 AUG 2010 4687 cjeanbap &quot;null&quot; showed up in
* countdown message.
*
* </pre>
*
* @author lvenable
* @version 1.0
*
*/
public class StoreTransmitCountdownThread extends Thread {
/**
* Parent display.
*/
private Display display;
/**
* Progress bar to be updated.
*/
private ProgressBar progressBar;
/**
* Flag indicating if the thread is done running.
*/
private boolean isDone = false;
/**
* Flag indicating if the thread has been canceled.
*/
private boolean isCancelled = false;
/**
* Count down label.
*/
private Label countdownLbl;
/**
* Count down string.
*/
private String countdownStr;
/**
* Counter.
*/
private int counter = 5;
/**
* Store/Transmit callback.
*/
private IStoreTransmitProduct storeCB;
/**
* Count down prefix string.
*/
private String countdownPrefix;
/**
* Constructor.
*
* @param display
* Parent display.
* @param progressBar
* Progress bar.
* @param countdownLbl
* Count down label.
* @param countdownStr
* Count down string.
* @param cb
* Callback interface.
* @param isStore
* True to display store, false to display transmit.
*/
public StoreTransmitCountdownThread(Display display,
ProgressBar progressBar, Label countdownLbl, String countdownStr,
IStoreTransmitProduct cb, boolean isStore) {
this.display = display;
this.progressBar = progressBar;
this.countdownLbl = countdownLbl;
this.countdownStr = countdownStr;
this.storeCB = cb;
countdownPrefix = new String();
CAVEMode opMode = DataManager.getCurrentInstance().getOpMode();
if (!opMode.equals(CAVEMode.OPERATIONAL)) {
countdownPrefix = "Simulated ";
}
if (isStore == true) {
countdownPrefix += "Store in ";
} else {
countdownPrefix += "Transmit in ";
}
}
/**
* Thread's run method.
*/
@Override
public void run() {
isDone = false;
countdownLabelStart();
for (int i = 0; i < 6; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (isCancelled == false) {
display.asyncExec(new Runnable() {
public void run() {
if (progressBar.isDisposed()) {
return;
}
// Increment the progress bar
progressBar.setSelection(progressBar.getSelection() + 1);
countdownLbl.setText(countdownPrefix + counter
+ " seconds...");
--counter;
}
});
} else {
break;
}
}
if (isCancelled == false) {
countdownLabelFinished();
}
isDone = true;
storeCB.storeTransmitProduct();
}
/**
* Check if the thread is done running.
*
* @return True if the thread is done running, false if it is still running.
*/
public boolean isDone() {
return isDone;
}
/**
* Cancel the running thread.
*/
public void cancelThread() {
isCancelled = true;
}
/**
* Check if the thread has been canceled.
*
* @return True if the thread was canceled, false otherwise.
*/
public boolean threadCancelled() {
return isCancelled;
}
/**
* Set the count down label to have a red background and white text while
* the Store/Transmit is in count down mode.
*/
private void countdownLabelStart() {
display.asyncExec(new Runnable() {
public void run() {
countdownLbl.setBackground(display
.getSystemColor(SWT.COLOR_RED));
countdownLbl.setForeground(display
.getSystemColor(SWT.COLOR_WHITE));
}
});
}
/**
* Set the count down label back to its original state.
*/
private void countdownLabelFinished() {
display.asyncExec(new Runnable() {
public void run() {
countdownLbl.setText(countdownStr);
countdownLbl.setBackground(display
.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
countdownLbl.setForeground(display
.getSystemColor(SWT.COLOR_BLACK));
}
});
}
}

View file

@ -26,6 +26,8 @@ import java.util.Map;
import java.util.TimeZone;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
@ -33,7 +35,6 @@ import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
@ -50,7 +51,7 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.auth.UserController;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
@ -85,6 +86,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Jan 06, 2014 2649 dgilling Make ETN assignment process optional.
* Feb 17, 2014 2774 dgilling Merge changes from 14.1 baseline to 14.2.
* Nov 14, 2014 4953 randerso Cleaned up practice product requests
* Feb 26, 2015 4126 randerso Ensure transmit/store is properly cancelled if dialog is closed
* Code cleanup
*
* </pre>
*
@ -92,22 +95,23 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* @version 1.0
*
*/
public class StoreTransmitDlg extends CaveSWTDialog implements
IStoreTransmitProduct {
public class StoreTransmitDlg extends CaveSWTDialog {
private static final int COUNT_DOWN_SECONDS = 5;
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(StoreTransmitDlg.class);
private static int SEQ_NUMBER = 0;
/**
* PRoduct ID text control.
* Product ID text control.
*/
private Text productIdTF;
private Text productIdText;
/**
* Count down progress label.
*/
private Label progressLbl;
private Label progressLabel;
/**
* Count down text string.
@ -117,13 +121,7 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
/**
* Count down progress bar.
*/
private ProgressBar progBar;
/**
* Thread used to count down the store/transmit. A separate thread is needed
* so updates can be made to the display with user interruption.
*/
private StoreTransmitCountdownThread countdownThread;
private ProgressBar progressBar;
/**
* Label image that will display the Store/Transmit image.
@ -150,6 +148,10 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
private final boolean updateVtec;
private String countdownFormat;
private boolean isCancelled;
/**
* @param parent
* Parent shell.
@ -177,33 +179,28 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
this.productText = editor.getProductText();
this.pid = pid;
this.updateVtec = updateVtec;
CAVEMode opMode = CAVEMode.getMode();
String title = null;
if (isStoreDialog) {
countdownFormat = "Store in %s seconds...";
countdownText = "Store Countdown";
title = "Store in AWIPS TextDB";
} else {
countdownFormat = "Transmit in %s seconds...";
countdownText = "Transmit Countdown";
title = "Transmit to AWIPS *WAN*";
}
if (!opMode.equals(CAVEMode.OPERATIONAL)) {
countdownFormat = "Simulated " + countdownFormat;
countdownText = "Simulated " + countdownText;
title += " (" + opMode.name() + " MODE)";
}
setText(title);
}
@Override
protected void initializeComponents(Shell shell) {
String title = null;
CAVEMode opMode = CAVEMode.getMode();
if (opMode.equals(CAVEMode.OPERATIONAL)) {
if (isStoreDialog == true) {
title = "Store in AWIPS TextDB";
countdownText = "Store Countdown";
} else {
title = "Transmit to AWIPS *WAN*";
countdownText = "Transmit Countdown";
}
} else {
if (isStoreDialog == true) {
title = "Store in AWIPS TextDB";
countdownText = "Simulated Store Countdown";
} else {
title = "Store Transmit to AWIPS *WAN*";
countdownText = "Simulated Transmit Countdown";
}
title += " (" + opMode.name() + " MODE)";
}
shell.setText(title);
// Create the main layout for the shell.
GridLayout mainLayout = new GridLayout(1, false);
@ -214,19 +211,26 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
// Initialize all of the controls and layouts
initializeComponents();
shell.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
doCancel();
}
});
}
@Override
protected void preOpened() {
super.preOpened();
productIdTF.insert(pid);
productIdText.insert(pid);
}
/**
* Initialize the controls on the display.
*/
private void initializeComponents() {
if (isStoreDialog == true) {
if (isStoreDialog) {
labelImg = parentEditor.getImageRegistry().get("yieldsign");
} else {
labelImg = parentEditor.getImageRegistry().get("stopsign");
@ -234,11 +238,6 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
createMainControls();
createBottomButtons();
Display display = shell.getParent().getDisplay();
countdownThread = new StoreTransmitCountdownThread(display, progBar,
progressLbl, countdownText, this, isStoreDialog);
}
/**
@ -258,19 +257,19 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
productIdLbl.setText("AWIPS Product ID:");
GridData gd = new GridData(200, SWT.DEFAULT);
productIdTF = new Text(leftComp, SWT.BORDER);
productIdTF.setLayoutData(gd);
productIdText = new Text(leftComp, SWT.BORDER);
productIdText.setLayoutData(gd);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
progressLbl = new Label(leftComp, SWT.CENTER);
progressLbl.setText(countdownText);
progressLbl.setLayoutData(gd);
progressLabel = new Label(leftComp, SWT.CENTER);
progressLabel.setText(countdownText);
progressLabel.setLayoutData(gd);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
progBar = new ProgressBar(leftComp, SWT.SMOOTH);
progBar.setMinimum(0);
progBar.setMaximum(5);
progBar.setLayoutData(gd);
progressBar = new ProgressBar(leftComp, SWT.SMOOTH);
progressBar.setMinimum(0);
progressBar.setMaximum(COUNT_DOWN_SECONDS);
progressBar.setLayoutData(gd);
// -------------------------------------
// Create the right side image control
@ -300,30 +299,35 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
buttons.setLayout(new GridLayout(2, true));
gd = new GridData(150, SWT.DEFAULT);
final Button actionBtn = new Button(buttons, SWT.PUSH);
final Button actionButton = new Button(buttons, SWT.PUSH);
CAVEMode opMode = CAVEMode.getMode();
if (opMode.equals(CAVEMode.OPERATIONAL)) {
if (isStoreDialog == true) {
actionBtn.setText("Store");
if (isStoreDialog) {
actionButton.setText("Store");
} else {
actionBtn.setText("Transmit");
actionButton.setText("Transmit");
}
} else if (isStoreDialog == true) {
actionBtn.setText("Simulated Store");
} else if (isStoreDialog) {
actionButton.setText("Simulated Store");
} else {
actionBtn.setText("Simulated Transmit");
actionButton.setText("Simulated Transmit");
}
actionBtn.setLayoutData(gd);
actionBtn.addSelectionListener(new SelectionAdapter() {
actionButton.setLayoutData(gd);
actionButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
// Disable the store button.
actionBtn.setEnabled(false);
actionButton.setEnabled(false);
progressLabel.setText(String.format(countdownFormat,
COUNT_DOWN_SECONDS));
progressLabel.setBackground(progressLabel.getDisplay()
.getSystemColor(SWT.COLOR_RED));
progressLabel.setForeground(progressLabel.getDisplay()
.getSystemColor(SWT.COLOR_WHITE));
// Start the countdown thread.
countdownThread.start();
countDown();
}
});
@ -334,19 +338,6 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
cancelBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
if (countdownThread != null) {
if (countdownThread.isDone() == false) {
countdownThread.cancelThread();
progressLbl.setText(countdownText);
Display display = shell.getParent().getDisplay();
progressLbl.setBackground(display
.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
progressLbl.setForeground(display
.getSystemColor(SWT.COLOR_BLACK));
}
}
setReturnValue(null);
close();
}
});
@ -355,11 +346,9 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
/**
* Method to store or transmit the product.
*/
@Override
public void storeTransmitProduct() {
// Store/Transmit the product...
if (!countdownThread.threadCancelled()) {
if (!this.isCancelled) {
try {
if (updateVtec) {
// With GFE VTEC products, it's possible to have multiple
@ -433,113 +422,105 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
etnCache);
}
VizApp.runSync(new Runnable() {
@Override
public void run() {
String pid = productIdTF.getText();
if (parentEditor.isTestVTEC()) {
if (isStoreDialog) {
parentEditor.devStore(pid.substring(3));
} else {
parentEditor.devStore(pid.substring(4));
transmitProduct(true);
}
} else {
if (isStoreDialog) {
TextDBUtil.storeProduct(pid, productText,
parentEditor.isTestVTEC());
} else {
transmitProduct(false);
}
}
String pid = productIdText.getText();
if (parentEditor.isTestVTEC()) {
if (isStoreDialog) {
parentEditor.devStore(pid.substring(3));
} else {
parentEditor.devStore(pid.substring(4));
transmitProduct(true);
}
});
} else {
if (isStoreDialog) {
TextDBUtil.storeProduct(pid, productText,
parentEditor.isTestVTEC());
} else {
transmitProduct(false);
}
}
} catch (VizException e) {
statusHandler.handle(Priority.CRITICAL,
"Error preparing product for transmission.", e);
VizApp.runAsync(new Runnable() {
@Override
public void run() {
sendTransmissionStatus(ConfigData.productStateEnum.Failed);
StoreTransmitDlg.this.parentEditor.revive();
}
});
sendTransmissionStatus(ConfigData.productStateEnum.Failed);
StoreTransmitDlg.this.parentEditor.revive();
}
}
// The asyncExec call is used to dispose of the shell since it is
// called outside the GUI thread (count down thread).
VizApp.runAsync(new Runnable() {
@Override
public void run() {
close();
}
});
close();
}
private Integer getNextEtn(VtecObject vtec) throws VizException {
GetNextEtnResponse serverResponse = GFEVtecUtil.getNextEtn(
vtec.getOffice(), vtec.getPhensig(), true, true);
if (!serverResponse.isOkay()) {
final VtecObject vtecToFix = vtec;
final boolean[] exitLoopContainer = { false };
final Exception[] exceptionContainer = { null };
final GetNextEtnResponse[] responseContainer = { serverResponse };
boolean exitLoop = false;
Exception exception = null;
do {
getDisplay().syncExec(new Runnable() {
@Override
public void run() {
GetNextEtnResponse serverResponse = responseContainer[0];
ETNConfirmationDialog dlg = new ETNConfirmationDialog(
getShell(), serverResponse);
if (dlg.open() == ETNConfirmationDialog.OK) {
int etn = dlg.getProposedEtn();
statusHandler.info(String.format(
"User confirmed ETN for %s: %04d",
serverResponse.getPhensig(), etn));
try {
GetNextEtnResponse followupResp = GFEVtecUtil
.getNextEtn(vtecToFix.getOffice(),
vtecToFix.getPhensig(), true,
true, true, etn);
responseContainer[0] = followupResp;
} catch (VizException e) {
exceptionContainer[0] = e;
exitLoopContainer[0] = true;
}
} else {
statusHandler.info(
"User declined to fix ETN for %s",
serverResponse.getPhensig());
exitLoopContainer[0] = true;
}
ETNConfirmationDialog dlg = new ETNConfirmationDialog(
getShell(), serverResponse);
if (dlg.open() == ETNConfirmationDialog.OK) {
int etn = dlg.getProposedEtn();
statusHandler.info(String.format(
"User confirmed ETN for %s: %04d",
serverResponse.getPhensig(), etn));
try {
GetNextEtnResponse followupResp = GFEVtecUtil
.getNextEtn(vtec.getOffice(),
vtec.getPhensig(), true, true, true,
etn);
serverResponse = followupResp;
} catch (VizException e) {
exception = e;
exitLoop = true;
}
});
} while (!responseContainer[0].isOkay() && !exitLoopContainer[0]);
} else {
statusHandler.info("User declined to fix ETN for %s",
serverResponse.getPhensig());
exitLoop = true;
}
} while (!serverResponse.isOkay() && !exitLoop);
if (!responseContainer[0].isOkay()) {
if (!serverResponse.isOkay()) {
String msg = "Unable to set ETN for phensig "
+ responseContainer[0].getPhensig() + "\nStatus: "
+ responseContainer[0].toString();
Exception e = exceptionContainer[0];
+ serverResponse.getPhensig() + "\nStatus: "
+ serverResponse.toString();
Exception e = exception;
if (e == null) {
throw new VizException(msg);
} else {
throw new VizException(msg, e);
}
} else {
serverResponse = responseContainer[0];
}
}
return serverResponse.getNextEtn();
}
private void countDown() {
getShell().getDisplay().timerExec(1000, new Runnable() {
@Override
public void run() {
bumpCounter();
}
});
}
private void bumpCounter() {
if (!progressBar.isDisposed()) {
// Increment the progress bar
int count = progressBar.getSelection() + 1;
if (count < COUNT_DOWN_SECONDS) {
progressBar.setSelection(count);
progressLabel.setText(String.format(countdownFormat,
(COUNT_DOWN_SECONDS - count)));
countDown();
} else {
storeTransmitProduct();
}
}
}
/**
* Method to transmit the product.
*
@ -566,13 +547,13 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
OfficialUserProduct oup = new OfficialUserProduct();
// make sure the awipsWanPil is exactly 10 characters space-padded
// long
String awipsWanPil = String.format("%-10s", productIdTF.getText()
String awipsWanPil = String.format("%-10s", productIdText.getText()
.trim());
oup.setAwipsWanPil(awipsWanPil);
oup.setProductText(productText);
String tempName = awipsWanPil + "-" + SEQ_NUMBER + "-"
+ (System.currentTimeMillis() / 1000);
+ (System.currentTimeMillis() / TimeUtil.MILLIS_PER_SECOND);
oup.setFilename(tempName);
String type = parentEditor.getProductType();
@ -590,8 +571,8 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
try {
Object response = ThriftClient.sendRequest(req);
// TODO need a response on the other one? it's going
// async....
// TODO need a response on the other one?
// it's going async....
if (response instanceof OUPResponse) {
OUPResponse resp = (OUPResponse) response;
Priority p = null;
@ -646,8 +627,13 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
}
private void sendTransmissionStatus(ConfigData.productStateEnum status) {
if (isStoreDialog == false) {
if (!isStoreDialog) {
transmissionCB.setTransmissionState(status);
}
}
private void doCancel() {
this.isCancelled = true;
storeTransmitProduct();
}
}

View file

@ -51,7 +51,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 20, 2014 3353 rferrel Initial creation
*
* Feb 26, 2015 3353 rjpeter Make modal optional.
* </pre>
*
* @author rferrel
@ -71,9 +71,10 @@ public class GenerateGeoDataSetDialog extends CaveSWTDialog {
* @param parentShell
* @param site
* @param gmd
* @param modal
*/
protected GenerateGeoDataSetDialog(Shell parentShell, String site,
GeospatialMetadata gmd) {
GeospatialMetadata gmd, boolean modal) {
/*
* This needs to be a blocking dialog. The return value is used to
* placed an entry in WarngenLayer's siteMap. Several layers of calls in
@ -84,7 +85,8 @@ public class GenerateGeoDataSetDialog extends CaveSWTDialog {
* way of being informed when the siteMap is updated. Also synchronize
* on siteMap become more complicated.
*/
super(parentShell, SWT.PRIMARY_MODAL | SWT.BORDER, CAVE.NONE);
super(parentShell, (modal ? SWT.PRIMARY_MODAL : 0) | SWT.BORDER,
CAVE.NONE);
this.site = site;
this.gmd = gmd;
}

View file

@ -121,18 +121,18 @@ import com.vividsolutions.jts.geom.Polygon;
* Apr 27, 2011 #9250 bkowal getStyle and getName are now used to
* get the style and name associated with
* a FontData object.
* Apr 16, 2012 #14515 Qinglu Lin Added return at the beginning of changeTemplate()
* Apr 16, 2012 #14515 Qinglu Lin Added return at the beginning of changeTemplate()
* if the newly selected product is same as current one.
* Jul 10, 2012 #15099 Qinglu Lin Add updatePolygon() and apply it in xxxSelected methods.
* Jul 10, 2012 #15099 Qinglu Lin Add updatePolygon() and apply it in xxxSelected methods.
* Jul 26, 2012 #15227 Qinglu Lin Added removeDuplicateVertices(), removeOverlaidSegments(),
* adjustLatLon(), etc.
* Sep 05, 2012 DR 15261 D. Friedman Prevent additional counties from being selected for EXPs
* Sep 27, 2012 #1196 rferrel Refactored to use non-blocking dialogs
* Oct 03, 2012 DR 15426 Qinglu Lin Unlock WarnGen GUI for COR, implemented in corSelected();
* but lock immediate cause, implemented in individual template.
* Nov 02, 2012 DR 15455 Qinglu Lin Added warngenLayer.setWarningAction() in resetPressed()
* Nov 02, 2012 DR 15455 Qinglu Lin Added warngenLayer.setWarningAction() in resetPressed()
* and in updateListSelected().
* Dec 20, 2012 DR 15537 Qinglu Lin Changed the assigned value to trackEditable from false
* Dec 20, 2012 DR 15537 Qinglu Lin Changed the assigned value to trackEditable from false
* to true in boxSelected().
* Jan 24, 2013 DR 15723 Qinglu Lin Invoked WarngenLayer's initRemovedGids().
* Feb 7, 2013 DR 15799 Qinglu Lin Added setPolygonLocked(false) to conSelected(), newSelected(); added
@ -158,6 +158,7 @@ import com.vividsolutions.jts.geom.Polygon;
* May 09, 2014 DR16694 m.gamazaychikov Fixed disabled duration menu after creating text for a COR SVS.
* Jul 01, 2014 DR 17450 D. Friedman Use list of templates from backup site.
* Jul 21, 2014 3419 jsanchez Created a hidden button to make recreating polygons easier.
* Feb 26, 2015 3353 rjpeter Fixed NPE on clear.
* </pre>
*
* @author chammack
@ -172,7 +173,7 @@ public class WarngenDialog extends CaveSWTDialog implements
* This flag allows a hidden button to appear to help recreating warning
* polygons that had issues in the feed.
*/
private boolean debug = false;
private final boolean debug = false;
private static final int BULLET_WIDTH = 390;
@ -181,7 +182,7 @@ public class WarngenDialog extends CaveSWTDialog implements
private static final int FONT_HEIGHT = 9;
private class TemplateRunnerInitJob extends Job {
private String site;
private final String site;
public TemplateRunnerInitJob() {
super("Template Runner Initialization");
@ -1132,16 +1133,18 @@ public class WarngenDialog extends CaveSWTDialog implements
if ((followupData != null)
&& (WarningAction.valueOf(followupData.getAct()) == WarningAction.NEW)) {
if (!redrawFromWarned())
if (!redrawFromWarned()) {
return;
}
}
if (((followupData == null) || ((WarningAction.valueOf(followupData
.getAct()) == WarningAction.CON) && warngenLayer
.conWarnAreaChanged(followupData)))
&& !polygonLocked && !trackLocked) {
if (!redrawFromWarned())
if (!redrawFromWarned()) {
return;
}
}
// Need to check again because redraw may have failed.
@ -1313,7 +1316,8 @@ public class WarngenDialog extends CaveSWTDialog implements
warngenLayer.resetState();
warngenLayer.getStormTrackState().duration = ((DurationData) durationList
.getData(durationList.getItem(durationList.getSelectionIndex()))).minutes;
durationList.setEnabled(warngenLayer.getConfiguration().isEnableDuration());
durationList.setEnabled(warngenLayer.getConfiguration()
.isEnableDuration());
if (lineOfStorms.getSelection()) {
selectLineOfStorms();
} else {
@ -1587,7 +1591,9 @@ public class WarngenDialog extends CaveSWTDialog implements
warngenLayer.setOldWarningPolygon(null);
warngenLayer.resetInitialFrame();
warngenLayer.setTemplateName(templateName);
warngenLayer.state.followupData = null;
if (warngenLayer.state != null) {
warngenLayer.state.followupData = null;
}
warngenLayer.getStormTrackState().endTime = null;
damBreakInstruct = null;
extEndTime = null;

View file

@ -154,24 +154,24 @@ import com.vividsolutions.jts.io.WKTReader;
* 02/01/2012 DR 14491 D. Friedman Load/unload only the maps not already loaded
* 02/28/2012 DR 13596 Qinglu Lin Call GisUtil.restoreAlaskaLon() in figurePoint().
* 03/19/2012 DR 14690 Qinglu Lin While newHatchedArea==null, handle the polygon differently
* for initial warning and followup (CON); and
* for initial warning and followup (CON); and
* convert ratio to percentage while doing comparison.
* 10/29/2012 DR 15479 Qinglu Lin Added code to call removeDuplicateCoordinate()
* 10/29/2012 DR 15479 Qinglu Lin Added code to call removeDuplicateCoordinate()
* in redrawBoxFromHatched().
* 11/02/2012 DR 15455 Qinglu Lin Added setWarningAction(), called redrawBoxFromTrack() while
* warningAction is neither null nor WarningAction.NEW, removed
* some code from redrawBoxFromHatched().
* warningAction is neither null nor WarningAction.NEW, removed
* some code from redrawBoxFromHatched().
* 11/15/2012 DR 15430 D. Friedman Use correct county/zone in createGeometryForWatches.
* 11/29/2012 DR 15571 Qinglu Lin Called compuateCurrentStormCenter() in getStormLocations();
* For CON, CAN, and COR, calculate Coordinate array, cc, specifically in
* For CON, CAN, and COR, calculate Coordinate array, cc, specifically in
* getStormLocations().
* 12/10/2012 DR 15571 Qinglu Lin Change warningAction's initialization from null to WarningAction.NEW, and add code
* in getStormLocations() for handling case when warningAction equals WarningAction.NEW;
* 12/13/2012 DR 15559 Qinglu Lin Added code to call WarngenUIState's adjustPolygon().
* 12/17/2012 DR 15571 Qinglu Lin For hydro products,futurePoints is null. Resolved an issue caused by trying to get
* 12/17/2012 DR 15571 Qinglu Lin For hydro products,futurePoints is null. Resolved an issue caused by trying to get
* Coordinate[] from futurePoints.
* 12/18/2012 DR 15571 Qinglu Lin Resolved coordinate issue in TML line caused by clicking Restart button.
* 01/24/2013 DR 15723 Qinglu Lin Added initRemovedGids() and updated updateWarnedAreas() to prevent the removed
* 01/24/2013 DR 15723 Qinglu Lin Added initRemovedGids() and updated updateWarnedAreas() to prevent the removed
* counties from being re-hatched.
* 03/06/2013 DR 15831 D. Friedman Use area inclusion filter in followups.
* 03/28/2013 DR 15973 Qinglu Lin Added adjustVertex() and applied it invalid polygon.
@ -207,12 +207,12 @@ import com.vividsolutions.jts.io.WKTReader;
* 12/17/2013 DR 16567 Qinglu Lin Added findLargestGeometry() and findLargestQuadrant(), and updated
* populateStrings() and paintText().
* 01/09/2014 DR 16974 D. Friedman Improve followup redraw-from-hatched-area polygons.
* 02/07/2014 DR16090 m.gamazaychikov Added GeomMetaDataUpdateNotificationObserver class to get notification
* 02/07/2014 DR16090 m.gamazaychikov Added GeomMetaDataUpdateNotificationObserver class to get notification
* when geometry file get updated to re-read them in.
* 02/19/2014 2819 randerso Removed unnecessary .clone() call
* 03/17/2014 DR 16309 Qinglu Lin Updated getWarningAreaFromPolygon(); changed searchCountyGeospatialDataAccessor) to
* 03/17/2014 DR 16309 Qinglu Lin Updated getWarningAreaFromPolygon(); changed searchCountyGeospatialDataAccessor) to
* searchGeospatialDataAccessor() and updated it; changed getCountyGeospatialDataAcessor()
* to getGeospatialDataAcessor(); changed getAllCountyUgcs() to getAllUgcs(); changed
* to getGeospatialDataAcessor(); changed getAllCountyUgcs() to getAllUgcs(); changed
* getUgcsForWatches() to getUgcsForCountyWatches().
* 04/15/2014 DR 17247 D. Friedman Rework error handling in AreaHatcher.
* 04/23/2014 DR 16356 Qinglu Lin Updated initializeState() and added reset().
@ -221,7 +221,7 @@ import com.vividsolutions.jts.io.WKTReader;
* 06/23/2014 DR16322 m.gamazaychikov Fix Warngen unloading previously loaded maps.
* 07/01/2014 DR 17450 D. Friedman Use list of templates from backup site.
* 07/24/2014 3429 mapeters Updated deprecated drawLine() calls.
* 07/28/2014 DR 17475 Qinglu Lin Updated populateStrings() and findLargestQuadrant(), removed findLargestGeometry(),
* 07/28/2014 DR 17475 Qinglu Lin Updated populateStrings() and findLargestQuadrant(), removed findLargestGeometry(),
* added createAreaAndCentroidMaps() and movePopulatePt(), updated paintText() to center W.
* 08/01/2014 3471 mapeters Updated deprecated createShadedShape() calls.
* 08/20/2014 3353 rferrel Generating Geo Spatial data set no longer on the UI thread.
@ -233,6 +233,7 @@ import com.vividsolutions.jts.io.WKTReader;
* 09/17/2014 ASM #15465 Qinglu Lin get backupOfficeShort and backupOfficeLoc from backup WFO config.xml, and pop up AlertViz if
* any of them is missing.
* 11/03/2014 3353 rferrel Ignore GeoSpatialData notification when this is the instance layer will do an update.
* 02/25/2014 3353 rjpeter Fix synchronized use case, updated to not create dialog before init is finished.
* </pre>
*
* @author mschenke
@ -285,9 +286,13 @@ public class WarngenLayer extends AbstractStormTrackResource {
public GeospatialDataAccessor(GeospatialDataList geoData,
AreaSourceConfiguration areaConfig) {
if ((geoData == null) || (areaConfig == null)) {
if (geoData == null) {
throw new IllegalArgumentException(
"GeospatialDataAccessor must not be null");
"GeospatialDataAccessor must have geospatial data, geoData is null.");
}
if (areaConfig == null) {
throw new IllegalArgumentException(
"GeospatialDataAccessor must have area source configuration, areaConfig is null.");
}
this.geoData = geoData;
this.areaConfig = areaConfig;
@ -385,7 +390,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
private class CustomMaps extends Job {
private Set<String> customMaps = new HashSet<String>();
private final Set<String> customMaps = new HashSet<>();
private Set<String> mapsToLoad;
@ -479,7 +484,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
this.warningArea = this.warningPolygon = null;
}
if (warningArea != null && warningPolygon != null) {
if ((warningArea != null) && (warningPolygon != null)) {
Polygon inputWarningPolygon = warningPolygon;
Polygon outputHatchedArea = null;
Geometry outputHatchedWarningArea = null;
@ -518,7 +523,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
adjustPolygon_counter += 1;
}
int counter = 0;
if (!outputHatchedArea.isValid() && counter < 2) {
if (!outputHatchedArea.isValid() && (counter < 2)) {
System.out
.println("calling adjustVertex & alterVertexes: loop #"
+ counter);
@ -541,7 +546,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
int inner_counter = 0;
System.out.println("");
while (!outputHatchedArea.isValid()
&& inner_counter < 5) {
&& (inner_counter < 5)) {
System.out
.println(" Calling alterVertexes #"
+ inner_counter);
@ -670,14 +675,11 @@ public class WarngenLayer extends AbstractStormTrackResource {
Object payload = message.getMessagePayload();
if (payload instanceof GenerateGeospatialDataResult) {
GenerateGeospatialDataResult result = (GenerateGeospatialDataResult) payload;
synchronized (warngenLayer.ignoreNotifications) {
synchronized (siteMap) {
String curKey = result.getArea() + "."
+ result.getSite();
if (warngenLayer.ignoreNotifications
.contains(curKey)) {
warngenLayer.ignoreNotifications.remove(curKey);
} else {
if (warngenLayer.ignoreNotifications.remove(curKey) == false) {
siteMap.remove(curKey);
initWarngen = true;
}
@ -1288,20 +1290,24 @@ public class WarngenLayer extends AbstractStormTrackResource {
if (dataSet != null) {
updateGeoData(gData, dataSet, gmd, currKey, tq0);
} else {
// This makes sure dialog exists and is open
createDialog();
/*
* Add to list prior to opening the genDialog. That
* way if the notfication arrives prior to or after
* closing the genDialog the notfication will be
* ignored.
*/
synchronized (ignoreNotifications) {
ignoreNotifications.add(currKey);
ignoreNotifications.add(currKey);
GenerateGeoDataSetDialog genDialog = null;
if (dialog != null && dialog.isDisposed() == false) {
genDialog = new GenerateGeoDataSetDialog(
dialog.getShell(), site, gmd, true);
} else {
genDialog = new GenerateGeoDataSetDialog(
PlatformUI.getWorkbench()
.getActiveWorkbenchWindow()
.getShell(), site, gmd, false);
}
GenerateGeoDataSetDialog genDialog = new GenerateGeoDataSetDialog(
dialog.getShell(), site, gmd);
// Assume this is a blocking dialog.
genDialog.open();
@ -1513,7 +1519,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
"Unable to load local WarnGen configuration.", e);
}
}
if (dc != null && dialogConfig != null) {
if ((dc != null) && (dialogConfig != null)) {
dialogConfig.setDefaultTemplate(dc.getDefaultTemplate());
dialogConfig.setMainWarngenProducts(dc.getMainWarngenProducts());
dialogConfig.setOtherWarngenProducts(dc.getOtherWarngenProducts());
@ -1523,12 +1529,12 @@ public class WarngenLayer extends AbstractStormTrackResource {
boolean shortTag = false;
boolean locTag = false;
String infoType = null;
if (backupOfficeShort == null
|| backupOfficeShort.trim().length() == 0) {
if ((backupOfficeShort == null)
|| (backupOfficeShort.trim().isEmpty())) {
shortTag = true;
}
if (backupOfficeLoc == null
|| backupOfficeLoc.trim().length() == 0) {
if ((backupOfficeLoc == null)
|| (backupOfficeLoc.trim().isEmpty())) {
locTag = true;
}
if (shortTag && locTag) {
@ -1654,8 +1660,9 @@ public class WarngenLayer extends AbstractStormTrackResource {
throws Exception {
Set<String> ugcs = new HashSet<String>();
GeospatialDataAccessor gda = getGeospatialDataAcessor(type);
for (String fips : gda.getAllFipsInArea(gda.buildArea(polygon)))
for (String fips : gda.getAllFipsInArea(gda.buildArea(polygon))) {
ugcs.add(FipsUtil.getUgcFromFips(fips));
}
return ugcs;
}
@ -1682,13 +1689,14 @@ public class WarngenLayer extends AbstractStormTrackResource {
* changed again? A ticket should be opened for this to be resolved.
*/
String templateName;
if (type == GeoFeatureType.COUNTY)
if (type == GeoFeatureType.COUNTY) {
templateName = "tornadoWarning";
else if (type == GeoFeatureType.MARINE)
} else if (type == GeoFeatureType.MARINE) {
templateName = "specialMarineWarning";
else
} else {
throw new IllegalArgumentException(
"Unsupported geo feature type " + type);
}
WarngenConfiguration config = WarngenConfiguration.loadConfig(
templateName, getLocalizedSite(), null);
loadGeodataForConfiguration(config);
@ -3369,7 +3377,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
}
areaM = warningAreaM.getArea();
geomIndex = i;
while (i + 1 < geomNum) {
while ((i + 1) < geomNum) {
warningAreaN = warningArea.getGeometryN(i + 1);
prefixN = GeometryUtil.getPrefix(warningAreaN.getUserData());
if (prefixN.equals(prefixM)) {
@ -3404,7 +3412,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
warningAreaM = warningArea.getGeometryN(iter.next().intValue());
prefixM = GeometryUtil.getPrefix(warningAreaM.getUserData());
area = warningAreaM.getArea();
if (area < minArea || area / geomArea.get(prefixM) < threshold) {
if ((area < minArea)
|| ((area / geomArea.get(prefixM)) < threshold)) {
// Hatched area inside a county is small, move W toward to
// default centroid
centroid = movePopulatePt(gf, warningAreaM,
@ -3423,7 +3432,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
geomN = gd.getGeometry();
CountyUserData cud = (CountyUserData) geomN.getUserData();
prefixN = cud.gid;
if (prefixN.length() > 0 && prefixM.length() > 0
if ((prefixN.length() > 0) && (prefixM.length() > 0)
&& !prefixN.equals(prefixM)) {
if (GeometryUtil.contains(geomN, populatePtGeom)) {
// W is inside a county. Use default centroid of a
@ -3436,7 +3445,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
}
loop = 1;
while (GeometryUtil.contains(geomN, populatePtGeom)
&& loop < maxLoop) {
&& (loop < maxLoop)) {
// W is still inside a county, move W to the largest
// quadrant
warningAreaM = findLargestQuadrant(gf, warningAreaM);
@ -3460,8 +3469,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
Point point, double weight) {
Point centroid = geom.getCentroid();
Coordinate coord = new Coordinate();
coord.x = centroid.getX() * weight + point.getX() * (1.0 - weight);
coord.y = centroid.getY() * weight + point.getY() * (1.0 - weight);
coord.x = (centroid.getX() * weight) + (point.getX() * (1.0 - weight));
coord.y = (centroid.getY() * weight) + (point.getY() * (1.0 - weight));
return gf.createPoint(new Coordinate(coord.x, coord.y));
}
@ -3767,9 +3776,9 @@ public class WarngenLayer extends AbstractStormTrackResource {
;
}
}
if (null != intersections[index] && intersections[index].isValid())
if ((null != intersections[index]) && intersections[index].isValid()) {
return intersections[index];
else {
} else {
return geom;
}
}

View file

@ -4,128 +4,150 @@
<property file="${basedir}/edex/common.properties" />
<property file="${basedir}/edex/developer.properties" />
<condition property="wa.enabled">
<not><equals arg1="${wa.to.deploy}" arg2="" /></not>
<not>
<equals arg1="${wa.to.deploy}" arg2="" />
</not>
</condition>
<dirname property="antfile.dir" file="${ant.file}" />
<echo message="ANT FILE DIR:${antfile.dir}"/>
<echo message="ANT FILE DIR:${antfile.dir}" />
<dirname property="base.dir" file="${antfile.dir}" />
<echo message="BASE DIR:${base.dir}"/>
<basename property="base.name" file="${base.dir}"/>
<echo message="BASE NAME:${base.name}"/>
<echo message="BASE DIR:${base.dir}" />
<basename property="base.name" file="${base.dir}" />
<echo message="BASE NAME:${base.name}" />
<if>
<equals arg1="${base.name}" arg2="edexOsgi" />
<then>
<!-- we are in the distributed development environment -->
<echo message="BUILDING: in distributed development environment"/>
<echo message="BUILDING: in distributed development environment" />
<dirname property="awips.baseline.directory" file="${base.dir}" />
<dirname property="git.directory" file="${awips.baseline.directory}" />
<echo message="GIT.DIRECTORY:${git.directory}"/>
<var name="repository.directories"
value="${awips.baseline.directory}" />
<echo message="GIT.DIRECTORY:${git.directory}" />
<var name="repository.directories" value="${awips.baseline.directory}" />
<for list="${core.repositories}" param="repo.directory">
<sequential>
<var name="repository.directories"
value="${repository.directories},${git.directory}${file.separator}@{repo.directory}" />
<var name="repository.directories" value="${repository.directories},${git.directory}${file.separator}@{repo.directory}" />
</sequential>
</for>
<property name="tab" value=" "/>
<echo level="info" message=" "/>
<echo level="info" message="Deploy checks the following directories for source:"/>
<echo level="info" message=" "/>
<for list="${repository.directories}" param="repository.directory">
<sequential>
<echo level="info" message="${tab}@{repository.directory}" />
<if>
<not>
<available file="@{repository.directory}" type="dir" />
</not>
<then>
<echo level="error" message="${tab}@{repository.directory} does not exist!"/>
<property name="missingDir"
value="true" />
</then>
</if>
</sequential>
</for>
<if>
<isset property="missingDir" />
<then>
<echo level="error" message=" "/>
<echo level="error" message="Edit core.repositories=${core.repositories} in common.properties, rename source directories or create a symlink!"/>
<echo level="error" message=" "/>
<fail message="Unable to locate source directories."/>
</then>
</if>
<echo level="info" message=" "/>
<echo message="${optional.repositories}"/>
<for list="${optional.repositories}" param="repo.directory">
<sequential>
<if>
<isset property="optional.directories" />
<then>
<var name="optional.directories" value="${optional.directories},${git.directory}${file.separator}@{repo.directory}" />
</then>
<else>
<var name="optional.directories" value="${git.directory}${file.separator}@{repo.directory}" />
</else>
</if>
</sequential>
</for>
<property name="tab" value=" " />
<echo level="info" message=" " />
<echo level="info" message="Deploy checks the following directories for source:" />
<echo level="info" message=" " />
<for list="${repository.directories}" param="repository.directory">
<sequential>
<echo level="info" message="${tab}@{repository.directory}" />
<if>
<not>
<available file="@{repository.directory}" type="dir" />
</not>
<then>
<echo level="error" message="${tab}@{repository.directory} does not exist!" />
<property name="missingDir" value="true" />
</then>
</if>
</sequential>
</for>
<if>
<isset property="missingDir" />
<then>
<echo level="error" message=" " />
<echo level="error" message="Edit core.repositories=${core.repositories} in common.properties, rename source directories or create a symlink!" />
<echo level="error" message=" " />
<fail message="Unable to locate source directories." />
</then>
</if>
<echo level="info" message=" " />
</then>
<else>
<!-- all of the projects are in the workspace or one single directory -->
<echo message="BUILDING: in workspace or flattened directory structure"/>
<var name="awips.baseline.directory"
value="${base.dir}" />
<var name="repository.directories"
value="${base.dir}" />
<echo message="BUILDING: in workspace or flattened directory structure" />
<var name="awips.baseline.directory" value="${base.dir}" />
<var name="repository.directories" value="${base.dir}" />
</else>
</if>
<echo message="AWIPS.BASELINE.DIRECTORY:${awips.baseline.directory}"/>
<echo message="REPOSITORY.DIRECTORIES:${repository.directories}"/>
<echo message="AWIPS.BASELINE.DIRECTORY:${awips.baseline.directory}" />
<echo message="REPOSITORY.DIRECTORIES:${repository.directories}" />
<!-- construct the list of "basedirectories" -->
<propertyselector property="baseline.variables"
delimiter="${path.separator}"
match="dir.([0-9][0-9])"
select="\1"
casesensitive="true" />
<var name="basedirectories"
value="${awips.baseline.directory}" />
<for list="${baseline.variables}" param="index"
delimiter="${path.separator}">
<sequential>
<propertycopy property="variable.name"
override="true"
from="dir.@{index}" />
<for list="${repository.directories}" param="repo.directory">
<sequential>
<var name="base.directory"
value="@{repo.directory}/${variable.name}" />
<if>
<available file="${base.directory}" type="dir" />
<then>
<echo message="BASE.DIRECTORY:${base.directory}"/>
<var name="basedirectories"
value="${base.directory};${basedirectories}" />
</then>
</if>
</sequential>
</for>
<!-- Loop through the WA directories, if they exist. -->
<if>
<isset property="wa.enabled" />
<then>
<for list="${wa.to.deploy}" param="wa"
delimiter="${path.separator}">
<sequential>
<var name="wa.base.directory"
value="@{wa}/${variable.name}" />
<if>
<available file="${wa.base.directory}"
type="dir" />
<then>
<var name="basedirectories"
value="${wa.base.directory};${basedirectories}" />
</then>
</if>
</sequential>
</for>
</then>
</if>
</sequential>
</for>
<propertyselector property="baseline.variables" delimiter="${path.separator}" match="dir.([0-9][0-9])" select="\1" casesensitive="true" />
<var name="basedirectories" value="${awips.baseline.directory}" />
<for list="${baseline.variables}" param="index" delimiter="${path.separator}">
<sequential>
<propertycopy property="variable.name" override="true" from="dir.@{index}" />
<for list="${repository.directories}" param="repo.directory">
<sequential>
<var name="base.directory" value="@{repo.directory}/${variable.name}" />
<if>
<available file="${base.directory}" type="dir" />
<then>
<echo message="BASE.DIRECTORY:${base.directory}" />
<var name="basedirectories" value="${base.directory};${basedirectories}" />
</then>
</if>
</sequential>
</for>
<for list="${optional.directories}" param="repo.directory">
<sequential>
<var name="optional.directory" value="@{repo.directory}/${variable.name}" />
<if>
<available file="${optional.directory}" type="dir" />
<then>
<echo message="OPTIONAL.DIRECTORY:${optional.directory}" />
<if>
<isset property="optionaldirectories"/>
<then>
<var name="optionaldirectories" value="${optional.directory};${optionaldirectories}" />
</then>
<else>
<var name="optionaldirectories" value="${optional.directory}" />
</else>
</if>
</then>
</if>
</sequential>
</for>
<!-- Loop through the WA directories, if they exist. -->
<if>
<isset property="wa.enabled" />
<then>
<for list="${wa.to.deploy}" param="wa" delimiter="${path.separator}">
<sequential>
<var name="wa.base.directory" value="@{wa}/${variable.name}" />
<if>
<available file="${wa.base.directory}" type="dir" />
<then>
<var name="basedirectories" value="${wa.base.directory};${basedirectories}" />
</then>
</if>
</sequential>
</for>
</then>
</if>
</sequential>
</for>
</target>
</project>

View file

@ -49,7 +49,7 @@
<sequential>
<var name="plugin.path" value="" />
<!-- first we need to find the plugin -->
<for list="${basedirectories}" param="directory"
<for list="@{plugin.directories}" param="directory"
delimiter=";">
<sequential>
<if>

View file

@ -3,15 +3,15 @@
<import file="${basedir}/deploy-common/deploy-init.xml" />
<import file="${basedir}/deploy-common/deploy-setup.xml" />
<import file="${basedir}/deploy-common/plugin-methods.xml" />
<!-- public static final -->
<path id="ant.classpath">
<fileset dir="${basedir}/lib/ant">
<include name="*.jar" />
</fileset>
</path>
<path id="ant.classpath">
<fileset dir="${basedir}/lib/ant">
<include name="*.jar" />
</fileset>
</path>
<property name="esb.directory" value="${basedir}/esb" />
<target name="main" depends="init, setup">
<!-- deploy esb {optionally: data, web} -->
<ant antfile="${basedir}/deploy-common/deploy-esb.xml" />
@ -33,40 +33,35 @@
Find the feature associated with
Work Assignments.
-->
<var name="feature.to.find"
value="${wa.edex.feature}" />
<var name="feature.to.find" value="${wa.edex.feature}" />
</then>
<else>
<!--
Find the standard AWIPS II
Baseline feature.
-->
<var name="feature.to.find"
value="${edex.feature}" />
<var name="feature.to.find" value="${edex.feature}" />
</else>
</if>
<var name="feature" value="" />
<!--
find the feature file: we may deploy multiple features
if multiple Work Assignment directories have been
specified.
-->
<for list="${basedirectories}" param="directory"
delimiter=";">
<sequential>
<if>
<available file="@{directory}/${feature.to.find}" />
<then>
<var name="feature"
value="@{directory}/${feature.to.find}" />
<deploy.feature
feature="${feature}" />
</then>
</if>
</sequential>
</for>
<for list="${basedirectories}" param="directory" delimiter=";">
<sequential>
<if>
<available file="@{directory}/${feature.to.find}" />
<then>
<var name="feature" value="@{directory}/${feature.to.find}" />
<deploy.feature feature="${feature}" />
</then>
</if>
</sequential>
</for>
<!-- optionally: deploy raytheon python -->
<if>
<equals arg1="${deploy.python}" arg2="true" />
@ -91,36 +86,30 @@
<if>
<isset property="wa.enabled" />
<then>
<for list="${wa.to.deploy}" param="wa"
delimiter="${path.separator}">
<for list="${wa.to.deploy}" param="wa" delimiter="${path.separator}">
<sequential>
<basename property="wa.name" file="@{wa}" />
<if>
<available file="@{wa}/edex/deploy-${wa.name}/wa-deploy.xml"
type="file" />
<available file="@{wa}/edex/deploy-${wa.name}/wa-deploy.xml" type="file" />
<then>
<ant
antfile="@{wa}/edex/deploy-${wa.name}/wa-deploy.xml"
inheritall="true" inheritrefs="true"
useNativeBasedir="true" />
<ant antfile="@{wa}/edex/deploy-${wa.name}/wa-deploy.xml" inheritall="true" inheritrefs="true" useNativeBasedir="true" />
</then>
</if>
</sequential>
</for>
</then>
</then>
</if>
<tstamp>
<format property="TIMESTAMP_COMPLETE" pattern="d-MMM-yyyy h:mm:ss a"
locale="en,US" />
</tstamp>
<echo message="Deploy Complete: ${TIMESTAMP_COMPLETE}" />
<tstamp>
<format property="TIMESTAMP_COMPLETE" pattern="d-MMM-yyyy h:mm:ss a" locale="en,US" />
</tstamp>
<echo message="Deploy Complete: ${TIMESTAMP_COMPLETE}" />
</target>
<!-- public -->
<!-- Targets specific to the developer deployment. -->
<macrodef name="deploy.feature">
<attribute name="feature" />
<sequential>
<!-- prepare to run includegen -->
<var name="includes.directory" value="${basedir}/tmp/includes" />
@ -128,151 +117,136 @@
<available file="${includes.directory}" type="dir" />
<then>
<delete verbose="true" includeemptydirs="true">
<fileset dir="${includes.directory}"
includes="*/**" />
<fileset dir="${includes.directory}" includes="*/**" />
</delete>
</then>
</if>
<mkdir dir="${includes.directory}" />
<!-- run includegen -->
<echo message="Generating deployment list for feature: ${feature}" />
<echo message="Generating deployment list for feature: ${feature}" />
<!--
TODO: need to update the includegen ant task to recognize
plugin architecture restrictions. Plugins that should only
be deployed for a 64-bit system should not be deployed for
a 32-bit system, etc.
-->
<includegen providerfilter="${includegen.filter}"
basedirectories="${basedirectories}"
featurefile="${feature}"
cotsout="${includes.directory}/cots.includes"
plugsout="${includes.directory}/plugins.includes"
coreout="${includes.directory}/core.includes" />
<var name="destination.directory"
value="${edex.root.directory}/lib/plugins" />
<echo message="${feature}" />
<echo message="${includes.directory}/cots.includes" />
<echo message="${includes.directory}/core.includes" />
<includegen providerfilter="${includegen.filter}" basedirectories="${basedirectories}" optionaldirectories="${optionaldirectories}" featurefile="${feature}" cotsout="${includes.directory}/cots.includes" plugsout="${includes.directory}/plugins.includes" coreout="${includes.directory}/core.includes" />
<var name="destination.directory" value="${edex.root.directory}/lib/plugins" />
<mkdir dir="${destination.directory}" />
<processPlugins
includes.file="${includes.directory}/plugins.includes"
plugin.type="plugins"
plugin.directories="${basedirectories}"
destination.directory="${destination.directory}" />
<processPlugins
includes.file="${includes.directory}/core.includes"
plugin.type="core"
plugin.directories="${basedirectories}"
destination.directory="${destination.directory}" />
<var name="destination.directory"
value="${edex.root.directory}/lib/dependencies" />
<if>
<isset property="optionaldirectories" />
<then>
<var name="allDir" value="${basedirectories};${optionaldirectories}" />
<processPlugins includes.file="${includes.directory}/plugins.includes" plugin.type="plugins" plugin.directories="${allDir}" destination.directory="${destination.directory}" />
<processPlugins includes.file="${includes.directory}/core.includes" plugin.type="core" plugin.directories="${allDir}" destination.directory="${destination.directory}" />
</then>
<else>
<processPlugins includes.file="${includes.directory}/plugins.includes" plugin.type="plugins" plugin.directories="${basedirectories}" destination.directory="${destination.directory}" />
<processPlugins includes.file="${includes.directory}/core.includes" plugin.type="core" plugin.directories="${basedirectories}" destination.directory="${destination.directory}" />
</else>
</if>
<var name="destination.directory" value="${edex.root.directory}/lib/dependencies" />
<mkdir dir="${destination.directory}" />
<processPlugins
includes.file="${includes.directory}/cots.includes"
plugin.type="cots"
plugin.directories="${basedirectories}"
destination.directory="${destination.directory}" />
<if>
<isset property="optionaldirectories" />
<then>
<var name="allDir" value="${basedirectories};${optionaldirectories}" />
<processPlugins includes.file="${includes.directory}/cots.includes" plugin.type="cots" plugin.directories="${allDir}" destination.directory="${destination.directory}" />
</then>
<else>
<processPlugins includes.file="${includes.directory}/cots.includes" plugin.type="cots" plugin.directories="${basedirectories}" destination.directory="${destination.directory}" />
</else>
</if>
<!-- cleanup the temporary directories -->
<if>
<available file="${basedir}/tmp"
type="dir" />
<available file="${basedir}/tmp" type="dir" />
<then>
<delete includeemptydirs="true">
<fileset dir="${basedir}"
includes="tmp/**" />
<fileset dir="${basedir}" includes="tmp/**" />
</delete>
</then>
</if>
</sequential>
</macrodef>
<target name="deploy.python">
<property name="site-package.directory"
value="${python.root.directory}/lib/${python.version.dir}/site-packages" />
<property name="site-package.directory" value="${python.root.directory}/lib/${python.version.dir}/site-packages" />
<echo message="Deploying the Raytheon python site-packages." />
<deploy.python.site-package
site.package="ufpy" />
<deploy.python.site-package
site.package="dynamicserialize" />
<deploy.python.site-package
site.package="pypies" />
<deploy.python.site-package site.package="ufpy" />
<deploy.python.site-package site.package="dynamicserialize" />
<deploy.python.site-package site.package="pypies" />
</target>
<target name="deploy.localization">
<for list="${localization.sites}" param="site"
delimiter="${path.separator}">
<sequential>
<echo message="Deploying localization for site: @{site}" />
<for list="${localization.sites}" param="site" delimiter="${path.separator}">
<sequential>
<echo message="Deploying localization for site: @{site}" />
<!-- determine which directory the localization
project should be in. -->
<var name="localization.path" value="" />
<var name="localization.path" value="" />
<if>
<available file="${awips.baseline.directory}/localization.@{site}"
type="dir" />
<available file="${awips.baseline.directory}/localization.@{site}" type="dir" />
<then>
<var name="localization.path"
value="${awips.baseline.directory}/localization.@{site}" />
<var name="localization.path" value="${awips.baseline.directory}/localization.@{site}" />
</then>
<else>
<var name="localization.path"
value="${awips.baseline.directory}/${localization.directory}/localization.@{site}" />
<var name="localization.path" value="${awips.baseline.directory}/${localization.directory}/localization.@{site}" />
</else>
</if>
<!-- copy the localization files. -->
<copy todir="${edex.root.directory}/data/utility"
overwrite="true">
<fileset dir="${localization.path}/utility"
includes="*/**" />
</copy>
</sequential>
</for>
<!-- copy the localization files. -->
<copy todir="${edex.root.directory}/data/utility" overwrite="true">
<fileset dir="${localization.path}/utility" includes="*/**" />
</copy>
</sequential>
</for>
</target>
<!-- private -->
<macrodef name="deploy.python.site-package">
<attribute name="site.package" />
<sequential>
<echo message="Deploying @{site.package} ..." />
<if>
<available file="${site-package.directory}/@{site.package}"
type="dir" />
<available file="${site-package.directory}/@{site.package}" type="dir" />
<then>
<delete dir="${site-package.directory}/@{site.package}"
includeemptydirs="true">
<fileset dir="${site-package.directory}"
includes="@{site.package}/**" />
<delete dir="${site-package.directory}/@{site.package}" includeemptydirs="true">
<fileset dir="${site-package.directory}" includes="@{site.package}/**" />
</delete>
</then>
</if>
<if>
<equals arg1="@{site.package}" arg2="pypies" />
<then>
<!-- custom rule for pypies due to alternate directory layout -->
<copy todir="${site-package.directory}">
<fileset dir="${awips.baseline.directory}/pythonPackages/pypies"
includes="@{site.package}/**" />
<fileset dir="${awips.baseline.directory}/pythonPackages/pypies" includes="@{site.package}/**" />
</copy>
</then>
<else>
<copy todir="${site-package.directory}">
<fileset dir="${awips.baseline.directory}/pythonPackages"
includes="@{site.package}/**" />
<fileset dir="${awips.baseline.directory}/pythonPackages" includes="@{site.package}/**" />
</copy>
</else>
</if>
</sequential>
</macrodef>
<!-- static -->
<taskdef name="includegen"
classname="com.raytheon.uf.anttasks.includesgen.GenerateIncludesFromFeature"
classpathref="ant.classpath" />
<taskdef resource="net/sf/antcontrib/antlib.xml"
classpath="${basedir}/lib/ant/ant-contrib-1.0b3.jar" />
<taskdef name="includegen" classname="com.raytheon.uf.anttasks.includesgen.GenerateIncludesFromFeature" classpathref="ant.classpath" />
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${basedir}/lib/ant/ant-contrib-1.0b3.jar" />
</project>

View file

@ -1,14 +1,19 @@
edex.root.directory=/awips2/edex
architecture=x86_64
includegen.filter=raytheon|noaa\.nws|noaa\.gsd|gov\.nasa\.msfc|edu\.wisc\.ssec\.cimss
includegen.filter=raytheon|noaa\.nws|gov.nasa.msfc|noaa\.gsd|edu\.wisc\.ssec\.cimss
# AWIPSII core repositories required for build
core.repo=ufcore
core-foss.repo=ufcore-foss
awips2-foss.repo=AWIPS2_foss
awips2-ncep.repo=AWIPS2_NCEP
awips2-cimss.repo=AWIPS2_CIMSS
awips2-gsd.repo=AWIPS2_GSD
core.repositories=${core.repo},${core-foss.repo},${awips2-foss.repo}
optional.repositories=${awips2-ncep.repo},${awips2-cimss.repo},${awips2-gsd.repo}
# Note: currently, there is a limit of 99 plugin directories.
dir.01=cave

View file

@ -140,8 +140,4 @@
id="gov.nasa.msfc.sport.edex.sportlma.feature"
version="0.0.0"/>
<includes
id="edu.wisc.ssec.cimss.edex.convectprob.feature"
version="0.0.0"/>
</feature>

View file

@ -27,10 +27,6 @@
<constructor-arg ref="gfeDbPluginProperties"/>
</bean>
<bean id="gfeSiteActivation" class="com.raytheon.edex.plugin.gfe.config.GFESiteActivation" factory-method="getInstance"
depends-on="commonTimeRegistered, gfeDbRegistered, levelFactoryInitialized">
</bean>
<bean id="ifpServer" class="com.raytheon.edex.plugin.gfe.server.IFPServer.Wrapper"/>
<camelContext id="gfe-common-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">

View file

@ -3,6 +3,11 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="gfeSiteActivation" class="com.raytheon.edex.plugin.gfe.config.GFESiteActivation"
depends-on="commonTimeRegistered, gfeDbRegistered, levelFactoryInitialized">
<constructor-arg ref="fetchATSrv" />
</bean>
<bean id="gfeSitesActiveRequest" factory-bean="siteAwareRegistry" factory-method="register">
<constructor-arg ref="gfeSiteActivation"/>
</bean>
@ -583,4 +588,23 @@
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredGfeIscRoutes"/>
</bean>
<!-- Active Table Sharing Definitions -->
<bean id="fetchATSrv" class="com.raytheon.edex.plugin.gfe.isc.FetchActiveTableSrv" />
<bean factory-bean="contextManager" factory-method="registerContextStateProcessor">
<constructor-arg ref="activeTableSharingRoutes"/>
<constructor-arg ref="fetchATSrv"/>
</bean>
<camelContext id="activeTableSharingRoutes" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<route id="activateFetchATSrv">
<from uri="timer://activateActiveTableSharing?repeatCount=1"/>
<bean ref="fetchATSrv" method="activateService"/>
</route>
</camelContext>
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="activeTableSharingRoutes"/>
</bean>
</beans>

View file

@ -6,6 +6,9 @@
<constructor-arg value="smartInit" />
<constructor-arg value="smartInit.*" />
</bean>
<bean id="gfeSiteActivation" class="com.raytheon.edex.plugin.gfe.config.GFESiteActivation"
depends-on="commonTimeRegistered, gfeDbRegistered, levelFactoryInitialized" />
<bean id="smartInitQueue" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitQueue" factory-method="createQueue"/>

View file

@ -35,6 +35,7 @@ import jep.JepException;
import com.google.common.util.concurrent.MoreExecutors;
import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException;
import com.raytheon.edex.plugin.gfe.exception.GfeMissingConfigurationException;
import com.raytheon.edex.plugin.gfe.isc.FetchActiveTableSrv;
import com.raytheon.edex.plugin.gfe.isc.IRTManager;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.edex.site.SiteUtil;
@ -92,6 +93,7 @@ import com.raytheon.uf.edex.site.notify.SendSiteActivationNotifications;
* Sent activation failure message to alertViz
* Oct 07, 2014 #3684 randerso Restructured IFPServer start up
* Dec 10, 2014 #4953 randerso Added requestTCVFiles call at site activation
* Feb 25, 2015 #4128 dgilling Simplify activation of active table sharing.
*
* </pre>
*
@ -109,25 +111,33 @@ public class GFESiteActivation implements ISiteActivationListener {
private static final int LOCK_TASK_TIMEOUT = 180000;
private static GFESiteActivation instance = new GFESiteActivation();
private boolean intialized;
private boolean intialized = false;
private final ExecutorService postActivationTaskExecutor;
private final ExecutorService postActivationTaskExecutor = MoreExecutors
.getExitingExecutorService((ThreadPoolExecutor) Executors
.newCachedThreadPool());
private final FetchActiveTableSrv fetchAtSrv;
/**
* @return the singleton instance
* Default constructor. Builds a GFESiteActivation instance with no
* associated {@code FetchActiveTableSrv} instance.
*/
public static GFESiteActivation getInstance() {
return instance;
public GFESiteActivation() {
this(null);
}
/**
* private constructor for singleton class
* Builds a GFESiteActivation instance with an associated
* {@code FetchActiveTableSrv} instance. Should only be used on request JVM.
*
* @param fetchAtSrv
* {@code FetchActiveTableSrv} instance
*/
private GFESiteActivation() {
public GFESiteActivation(final FetchActiveTableSrv fetchAtSrv) {
this.intialized = false;
this.postActivationTaskExecutor = MoreExecutors
.getExitingExecutorService((ThreadPoolExecutor) Executors
.newCachedThreadPool());
this.fetchAtSrv = fetchAtSrv;
}
@Override
@ -322,7 +332,6 @@ public class GFESiteActivation implements ISiteActivationListener {
// Doesn't need to be cluster locked
statusHandler.info("Checking ISC configuration...");
boolean isIscActivated = false;
if (config.requestISC()) {
String host = InetAddress.getLocalHost().getCanonicalHostName();
String gfeHost = config.getServerHost();
@ -337,14 +346,27 @@ public class GFESiteActivation implements ISiteActivationListener {
statusHandler.info("Enabling ISC...");
try {
IRTManager.getInstance().enableISC(siteID, config);
isIscActivated = true;
// wait until EDEX is up and running to request TCV files
final IFPServerConfig configRef = config;
if (configRef.tableFetchTime() > 0) {
Runnable activateTableSharing = new Runnable() {
@Override
public void run() {
EDEXUtil.waitForRunning();
fetchAtSrv.activateSite(siteID, configRef);
}
};
postActivationTaskExecutor.submit(activateTableSharing);
}
Runnable requestTCV = new Runnable() {
@Override
public void run() {
// wait until EDEX is up and running to request TCV
// files
EDEXUtil.waitForRunning();
requestTCVFiles(siteID, configRef);
@ -367,45 +389,6 @@ public class GFESiteActivation implements ISiteActivationListener {
statusHandler.info("ISC is not enabled.");
}
// doesn't need to be cluster locked
final IFPServerConfig configRef = config;
if ((config.tableFetchTime() > 0) && isIscActivated) {
Runnable activateFetchAT = new Runnable() {
@Override
public void run() {
EDEXUtil.waitForRunning();
Map<String, Object> fetchATConfig = new HashMap<String, Object>();
fetchATConfig.put("siteId", configRef.getSiteID().get(0));
fetchATConfig.put("interval", configRef.tableFetchTime());
fetchATConfig.put("ancf", configRef
.iscRoutingTableAddress().get("ANCF"));
fetchATConfig.put("bncf", configRef
.iscRoutingTableAddress().get("BNCF"));
fetchATConfig.put("serverHost", configRef.getServerHost());
fetchATConfig.put("port", configRef.getRpcPort());
fetchATConfig.put("protocolV",
configRef.getProtocolVersion());
fetchATConfig.put("mhsid", configRef.getMhsid());
fetchATConfig.put("transmitScript",
configRef.transmitScript());
try {
EDEXUtil.getMessageProducer().sendAsyncUri(
"jms-generic:queue:gfeSiteActivated",
fetchATConfig);
} catch (EdexException e) {
statusHandler.handle(Priority.PROBLEM,
"Could not activate active table sharing for site: "
+ siteID, e);
}
}
};
postActivationTaskExecutor.submit(activateFetchAT);
}
statusHandler.info("Adding " + siteID + " to active sites list.");
IFPServerConfigManager.addActiveSite(siteID);
statusHandler.info(siteID + " successfully activated");

View file

@ -0,0 +1,335 @@
/**
* 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.isc;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
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.RunProcess;
import com.raytheon.uf.edex.core.IContextStateProcessor;
/**
* Service that fetches neighboring sites' active table entries that are
* relevant to this site using requestAT.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 28, 2013 dgilling Initial creation
* Feb 20, 2014 #2824 randerso Changed log level of message when activating FetchAT
* Registered with SiteAwareRegistry so we can stop
* fetching when site is deactivated.
* Feb 26, 2015 #4128 dgilling Moved to edex.gfe plugin, rewritten as
* IContextStateProcessor.
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public final class FetchActiveTableSrv implements IContextStateProcessor {
private static final class FetchATJobConfig {
private final String siteId;
private final long interval;
private final String ancfAddress;
private final String bncfAddress;
private final String serverHost;
private final String port;
private final String protocolV;
private final String mhsId;
private final String transmitScript;
public FetchATJobConfig(final String siteId,
final IFPServerConfig gfeConfig) {
this.siteId = siteId;
this.interval = gfeConfig.tableFetchTime();
this.ancfAddress = gfeConfig.iscRoutingTableAddress().get("ANCF");
this.bncfAddress = gfeConfig.iscRoutingTableAddress().get("BNCF");
this.serverHost = gfeConfig.getServerHost();
this.port = Long.toString(gfeConfig.getRpcPort());
this.protocolV = Long.toString(gfeConfig.getProtocolVersion());
this.mhsId = gfeConfig.getMhsid();
this.transmitScript = gfeConfig.transmitScript();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("FetchATJobConfig [siteId=");
builder.append(siteId);
builder.append(", interval=");
builder.append(interval);
builder.append(", ancfAddress=");
builder.append(ancfAddress);
builder.append(", bncfAddress=");
builder.append(bncfAddress);
builder.append(", serverHost=");
builder.append(serverHost);
builder.append(", port=");
builder.append(port);
builder.append(", protocolV=");
builder.append(protocolV);
builder.append(", mhsId=");
builder.append(mhsId);
builder.append(", transmitScript=");
builder.append(transmitScript);
builder.append("]");
return builder.toString();
}
public String getSiteId() {
return siteId;
}
public long getInterval() {
return interval;
}
public String getAncfAddress() {
return ancfAddress;
}
public String getBncfAddress() {
return bncfAddress;
}
public String getServerHost() {
return serverHost;
}
public String getPort() {
return port;
}
public String getProtocolV() {
return protocolV;
}
public String getMhsId() {
return mhsId;
}
public String getTransmitScript() {
return transmitScript;
}
}
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(FetchActiveTableSrv.class);
private final ConcurrentMap<String, ScheduledFuture<?>> siteJobInstanceMap;
private ScheduledExecutorService jobExecutor;
private volatile boolean activeServiceInstance;
/**
* Default constructor.
*/
public FetchActiveTableSrv() {
this.activeServiceInstance = false;
this.siteJobInstanceMap = new ConcurrentHashMap<String, ScheduledFuture<?>>();
}
/**
* Dummy trigger method for the timer in the camel context this bean
* monitors. Ensures this bean properly fails over between cluster members
* as needed.
*/
public void activateService() {
activeServiceInstance = true;
}
/**
* Removes a site's active table sharing job from the job pool.
*
* @param siteID
* Site identifier for the site's job to stop.
*/
public void deactivateSite(final String siteID) {
ScheduledFuture<?> siteJob = siteJobInstanceMap.remove(siteID);
if (siteJob != null) {
statusHandler.info("Deactivating FetchAT for " + siteID);
siteJob.cancel(false);
}
}
/**
* Adds a site's active table sharing job to the job pool.
*
* @param siteID
* Site identifier for the site's job to add to job pool.
* @param gfeConfig
* {@code IFPServerConfig} for the site.
*/
public void activateSite(final String siteID,
final IFPServerConfig gfeConfig) {
if (activeServiceInstance && (!siteJobInstanceMap.containsKey(siteID))) {
FetchATJobConfig jobConfig = new FetchATJobConfig(siteID, gfeConfig);
statusHandler.info("Activating FetchAT for " + siteID);
statusHandler.debug("Site: " + siteID + " config: " + jobConfig);
Runnable job = constructJob(jobConfig);
try {
ScheduledFuture<?> jobInstance = jobExecutor
.scheduleWithFixedDelay(job, 10,
jobConfig.getInterval(), TimeUnit.SECONDS);
siteJobInstanceMap.put(siteID, jobInstance);
} catch (RejectedExecutionException e) {
statusHandler.handle(Priority.PROBLEM,
"Unable to submit fetchAT job for execution:", e);
siteJobInstanceMap.remove(siteID);
}
}
}
private Runnable constructJob(final FetchATJobConfig jobConfig) {
Runnable job = new Runnable() {
@Override
public void run() {
statusHandler.info("Starting requestAT process for site: "
+ jobConfig.getSiteId());
/*
* requestAT -H ourHost -P ourPort -L ourServerProto -M mhsid -S
* ourSite -t irtWebAddr -x transmitScript
*/
List<String> args = new ArrayList<String>(17);
args.add("requestAT");
args.add("-H");
args.add(jobConfig.getServerHost());
args.add("-P");
args.add(jobConfig.getPort());
args.add("-L");
args.add(jobConfig.getProtocolV());
args.add("-M");
args.add(jobConfig.getMhsId());
args.add("-S");
args.add(jobConfig.getSiteId());
args.add("-a");
args.add(jobConfig.getAncfAddress());
args.add("-b");
args.add(jobConfig.getBncfAddress());
args.add("-x");
args.add(jobConfig.getTransmitScript());
try {
/*
* We'll wait for requestAT to finish execution so that we
* can't accidentally overlap running instances if the user
* configures the run interval too low.
*/
ProcessBuilder command = new ProcessBuilder(args);
RunProcess proc = RunProcess.getRunProcess();
proc.setProcess(command.start());
proc.waitFor();
} catch (Throwable t) {
statusHandler.error(
"Unhandled exception thrown during requestAT: ", t);
}
}
};
return job;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.core.IContextStateProcessor#preStart()
*/
@Override
public void preStart() {
statusHandler.info("Initializing FetchATSrv...");
activeServiceInstance = true;
jobExecutor = Executors.newScheduledThreadPool(1);
for (IFPServer ifpServer : IFPServer.getActiveServers()) {
IFPServerConfig config = ifpServer.getConfig();
if ((config.requestISC()) && (config.tableFetchTime() > 0)) {
activateSite(ifpServer.getSiteId(), config);
}
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.core.IContextStateProcessor#postStart()
*/
@Override
public void postStart() {
// no op
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.core.IContextStateProcessor#preStop()
*/
@Override
public void preStop() {
statusHandler.info("Shutting down FetchATSrv...");
activeServiceInstance = false;
jobExecutor.shutdown();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.core.IContextStateProcessor#postStop()
*/
@Override
public void postStop() {
jobExecutor = null;
siteJobInstanceMap.clear();
}
}

View file

@ -29,7 +29,6 @@ import java.util.Map;
import jep.JepException;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager;
import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException;
@ -59,6 +58,8 @@ import com.raytheon.uf.edex.core.EdexTimerBasedThread;
* ------------ ---------- ----------- --------------------------
* Oct 20, 2011 dgilling Initial creation
* May 19, 2014 2726 rjpeter Integrate IscSendJob for graceful shutdown.
* Feb 26, 2015 4128 dgilling Switch to IFPServer.getActiveSites().
*
* </pre>
*
* @author dgilling
@ -128,8 +129,7 @@ public class SendIscSrv extends EdexTimerBasedThread {
String xmlDest = request.getXmlDest();
String siteId = id.getDbId().getSiteId();
if (!GFESiteActivation.getInstance().getActiveSites()
.contains(siteId)) {
if (!IFPServer.getActiveSites().contains(siteId)) {
statusHandler.warn("Attempted to send " + id
+ " for deactivated site " + siteId + ".");
return;

View file

@ -25,7 +25,7 @@ import java.util.Map;
import jep.JepException;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
@ -45,6 +45,7 @@ import com.raytheon.uf.common.python.PythonScript;
* ------------ ---------- ----------- --------------------------
* Jul 26, 2011 bphillip Initial creation
* Sep 05, 2013 #2307 dgilling Use better PythonScript constructor.
* Feb 26, 2015 #4128 dgilling Switch to IFPServer.getActiveSites().
*
* </pre>
*
@ -62,7 +63,7 @@ public class LogPurger {
public void purge() throws JepException {
for (String siteID : GFESiteActivation.getInstance().getActiveSites()) {
for (String siteID : IFPServer.getActiveSites()) {
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext cx = pathMgr.getContext(
LocalizationType.EDEX_STATIC, LocalizationLevel.BASE);

View file

@ -23,8 +23,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.uf.common.dataplugin.gfe.request.GetSiteTimeZoneInfoRequest;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
@ -39,6 +39,7 @@ import com.raytheon.uf.common.serialization.comm.IRequestHandler;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 19, 2011 dgilling Initial creation
* Feb 26, 2015 #4128 dgilling Switch to IFPServer.getActiveSites().
*
* </pre>
*
@ -61,7 +62,7 @@ public class GetSiteTimeZoneInfoRequestHandler implements
GetSiteTimeZoneInfoRequest request) throws Exception {
ServerResponse<Map<String, String>> sr = new ServerResponse<Map<String, String>>();
Set<String> sites = GFESiteActivation.getInstance().getActiveSites();
Set<String> sites = IFPServer.getActiveSites();
Map<String, String> siteWithTimeZone = new HashMap<String, String>();
for (String site : sites) {
// getTimeZones() seems to only ever return a 1 sized List

View file

@ -78,23 +78,4 @@
<constructor-arg value="com.raytheon.uf.common.activetable.request.UnlockAndSetNextEtnRequest"/>
<constructor-arg ref="setAndUnlockEtnHandler"/>
</bean>
<bean id="fetchATSrv" class="com.raytheon.uf.edex.activetable.vtecsharing.FetchActiveTableSrv"/>
<camelContext id="activeTableSharingRoutes" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<route id="activeSiteForFetchATSrv">
<from uri="jms-generic:queue:gfeSiteActivated"/>
<doTry>
<bean ref="fetchATSrv" method="addSite"/>
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:fetchATSrv?level=ERROR"/>
</doCatch>
</doTry>
</route>
</camelContext>
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="activeTableSharingRoutes"/>
</bean>
</beans>

View file

@ -1,208 +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.edex.activetable.vtecsharing;
import java.util.Map;
/**
* Configuration information for a given site's vtec active table fetching.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 28, 2013 dgilling Initial creation
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public class FetchATJobConfig {
private String siteId;
private long interval;
private String ancfAddress;
private String bncfAddress;
private String serverHost;
private String port;
private String protocolV;
private String mhsId;
private String transmitScript;
public FetchATJobConfig(Map<String, Object> configMap) {
siteId = configMap.get("siteId").toString();
interval = ((Number) configMap.get("interval")).longValue();
ancfAddress = configMap.get("ancf").toString();
bncfAddress = configMap.get("bncf").toString();
serverHost = configMap.get("serverHost").toString();
port = configMap.get("port").toString();
protocolV = configMap.get("protocolV").toString();
mhsId = configMap.get("mhsid").toString();
transmitScript = configMap.get("transmitScript").toString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
FetchATJobConfig other = (FetchATJobConfig) obj;
if (ancfAddress == null) {
if (other.ancfAddress != null) {
return false;
}
} else if (!ancfAddress.equals(other.ancfAddress)) {
return false;
}
if (bncfAddress == null) {
if (other.bncfAddress != null) {
return false;
}
} else if (!bncfAddress.equals(other.bncfAddress)) {
return false;
}
if (interval != other.interval) {
return false;
}
if (mhsId == null) {
if (other.mhsId != null) {
return false;
}
} else if (!mhsId.equals(other.mhsId)) {
return false;
}
if (port == null) {
if (other.port != null) {
return false;
}
} else if (!port.equals(other.port)) {
return false;
}
if (protocolV == null) {
if (other.protocolV != null) {
return false;
}
} else if (!protocolV.equals(other.protocolV)) {
return false;
}
if (serverHost == null) {
if (other.serverHost != null) {
return false;
}
} else if (!serverHost.equals(other.serverHost)) {
return false;
}
if (siteId == null) {
if (other.siteId != null) {
return false;
}
} else if (!siteId.equals(other.siteId)) {
return false;
}
if (transmitScript == null) {
if (other.transmitScript != null) {
return false;
}
} else if (!transmitScript.equals(other.transmitScript)) {
return false;
}
return true;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("FetchATJobConfig [siteId=");
builder.append(siteId);
builder.append(", interval=");
builder.append(interval);
builder.append(", ancfAddress=");
builder.append(ancfAddress);
builder.append(", bncfAddress=");
builder.append(bncfAddress);
builder.append(", serverHost=");
builder.append(serverHost);
builder.append(", port=");
builder.append(port);
builder.append(", protocolV=");
builder.append(protocolV);
builder.append(", mhsId=");
builder.append(mhsId);
builder.append(", transmitScript=");
builder.append(transmitScript);
builder.append("]");
return builder.toString();
}
public String getSiteId() {
return siteId;
}
public long getInterval() {
return interval;
}
public String getAncfAddress() {
return ancfAddress;
}
public String getBncfAddress() {
return bncfAddress;
}
public String getServerHost() {
return serverHost;
}
public String getPort() {
return port;
}
public String getProtocolV() {
return protocolV;
}
public String getMhsId() {
return mhsId;
}
public String getTransmitScript() {
return transmitScript;
}
}

View file

@ -1,218 +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.edex.activetable.vtecsharing;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import com.google.common.util.concurrent.MoreExecutors;
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.registry.RegistryException;
import com.raytheon.uf.edex.site.ISiteActivationListener;
import com.raytheon.uf.edex.site.SiteAwareRegistry;
/**
* Service that fetches neighboring sites' active table entries that are
* relevant to this site using requestAT.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 28, 2013 dgilling Initial creation
* Feb 20, 2014 #2824 randerso Changed log level of message when activating FetchAT
* Registered with SiteAwareRegistry so we can stop
* fetching when site is deactivated.
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public class FetchActiveTableSrv implements ISiteActivationListener {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(FetchActiveTableSrv.class);
private final Map<String, FetchATJobConfig> siteConfigMap;
private final Map<String, ScheduledFuture<?>> siteJobInstanceMap;
private final ScheduledExecutorService jobExecutor;
public FetchActiveTableSrv() {
siteConfigMap = new ConcurrentHashMap<String, FetchATJobConfig>();
siteJobInstanceMap = new ConcurrentHashMap<String, ScheduledFuture<?>>();
jobExecutor = MoreExecutors
.getExitingScheduledExecutorService((ScheduledThreadPoolExecutor) Executors
.newScheduledThreadPool(1));
try {
SiteAwareRegistry.getInstance().register(this);
} catch (RegistryException e) {
statusHandler.handle(Priority.PROBLEM,
"Error registering with SiteAwareRegistry", e);
}
}
public void addSite(Map<String, Object> configData) {
FetchATJobConfig config = new FetchATJobConfig(configData);
final String site = config.getSiteId();
statusHandler.info("Activating FetchAT for " + site);
statusHandler.debug("Site: " + site + " config: " + config);
if ((siteConfigMap.containsKey(site))
&& siteConfigMap.get(site).equals(config)) {
return;
}
Runnable job = new Runnable() {
@Override
public void run() {
statusHandler.info("Starting requestAT process for site: "
+ site);
// requestAT -H ourHost -P ourPort -L ourServerProto -M mhsid
// -S ourSite -t irtWebAddr -x transmitScript
FetchATJobConfig jobConfig = siteConfigMap.get(site);
List<String> args = new ArrayList<String>(17);
args.add("requestAT");
args.add("-H");
args.add(jobConfig.getServerHost());
args.add("-P");
args.add(jobConfig.getPort());
args.add("-L");
args.add(jobConfig.getProtocolV());
args.add("-M");
args.add(jobConfig.getMhsId());
args.add("-S");
args.add(jobConfig.getSiteId());
args.add("-a");
args.add(jobConfig.getAncfAddress());
args.add("-b");
args.add(jobConfig.getBncfAddress());
args.add("-x");
args.add(jobConfig.getTransmitScript());
// String msg = Joiner.on(' ').join(args);
// statusHandler.debug("Running command: " + msg);
try {
ProcessBuilder command = new ProcessBuilder(args);
command.start();
} catch (IOException e) {
statusHandler.handle(Priority.PROBLEM,
"Error executing requestAT: ", e);
}
}
};
try {
siteConfigMap.put(site, config);
ScheduledFuture<?> jobInstance = jobExecutor.scheduleAtFixedRate(
job, 10, config.getInterval(), TimeUnit.SECONDS);
siteJobInstanceMap.put(site, jobInstance);
} catch (RejectedExecutionException e) {
statusHandler.handle(Priority.PROBLEM,
"Unable to submit fetchAT job for execution:", e);
siteConfigMap.remove(site);
siteJobInstanceMap.remove(site);
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.site.ISiteActivationListener#deactivateSite(java
* .lang.String)
*/
@Override
public void deactivateSite(String siteID) throws Exception {
ScheduledFuture<?> siteJob = siteJobInstanceMap.remove(siteID);
if (siteJob != null) {
statusHandler.info("Deactivating FetchAT for " + siteID);
siteJob.cancel(false);
}
siteConfigMap.remove(siteID);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.site.ISiteActivationListener#activateSite(java.lang
* .String)
*/
@Override
public void activateSite(String siteID) throws Exception {
return;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.site.ISiteActivationListener#getActiveSites()
*/
@Override
public Set<String> getActiveSites() {
return Collections.emptySet();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.site.ISiteActivationListener#validateConfig(java
* .lang.String)
*/
@Override
public String validateConfig(String siteID) {
return "";
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.site.ISiteActivationListener#registered()
*/
@Override
public void registered() {
return;
}
}

View file

@ -84,12 +84,6 @@
version="0.0.0"
unpack="false"/>
<plugin
id="gov.nasa.gsfc.fits"
download-size="0"
install-size="0"
version="0.0.0"/>
<plugin
id="ucar.nc2.bufrsplitter"
download-size="0"

View file

@ -7,3 +7,4 @@ Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: org.apache.ant;bundle-version="1.7.1",
com.raytheon.uf.featureexplorer;bundle-version="1.0.0"
Import-Package: com.raytheon.uf.featureexplorer

View file

@ -1,11 +1,13 @@
package com.raytheon.uf.anttasks.includesgen;
import java.io.File;
import java.io.FileFilter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
@ -28,6 +30,7 @@ import com.raytheon.uf.featureexplorer.FeatureExplorer;
* 28Jan2009 1930 MW Fegan Added provider and plugin filtering.
* Feb 4, 2013 #1577 bkowal Remove component-deploy.xml suffixes for
* core and plugins; remove jar wildcard for cots
* Feb 25, 2015 #3299 garmendariz Process a list of included features
* </pre>
*
* @author bclement
@ -36,319 +39,367 @@ import com.raytheon.uf.featureexplorer.FeatureExplorer;
public class GenerateIncludesFromFeature extends Task {
protected String baseDirectories;
protected String baseDirectories;
protected File baseDirectory;
protected File baseDirectory;
protected File featureFile;
protected File featureFile;
protected File cotsOut;
protected File cotsOut;
protected File plugsOut;
protected File plugsOut;
protected File coreOut;
protected File coreOut;
protected File allOut;
protected File allOut;
/* attributes for filtering */
private static final String PATTERN = "^.*(%s).*$";
protected String optionalDirectories;
protected String provider = "raytheon";
/* attributes for filtering */
private static final String PATTERN = "^.*(%s).*$";
private Pattern providerPattern = Pattern.compile(String.format(PATTERN,
provider));
protected String provider = "raytheon";
protected String plugin = "plugin";
private Pattern providerPattern = Pattern.compile(String.format(PATTERN,
provider));
private Pattern pluginPattern = Pattern.compile(String.format(PATTERN,
plugin));
protected String plugin = "plugin";
/**
* @return the baseDirectories
*/
public String getBaseDirectories() {
return baseDirectories;
}
private Pattern pluginPattern = Pattern.compile(String.format(PATTERN,
plugin));
/**
* @param baseDirectories
* the baseDirectories to set
*/
public void setBaseDirectories(String baseDirectories) {
this.baseDirectories = baseDirectories;
}
/**
* @return the baseDirectories
*/
public String getBaseDirectories() {
return baseDirectories;
}
/**
* Sets the component provider filter. This is a pipe (|) separated string
* of names that identify a component as a non-COTS component. The default
* provider filter is <em>raytheon</em>.
*/
public void setProviderFilter(String filter) {
this.provider = filter;
this.providerPattern = Pattern.compile(String.format("^.*(%s).*$",
filter));
}
/**
* @param baseDirectories
* the baseDirectories to set
*/
public void setBaseDirectories(String baseDirectories) {
this.baseDirectories = baseDirectories;
}
/**
* Sets the plug-in identifier filter. This is a pipe (|) separated string
* of names that identify a component as an EDEX plug-in. The default
* plug-in filter is <em>plugin</em>.
*/
public void setPluginFilter(String filter) {
this.plugin = filter;
this.pluginPattern = Pattern.compile(String
.format("^.*(%s).*$", filter));
}
/**
* @return the optionalDirectories
*/
public String getOptionalDirectories() {
return optionalDirectories;
}
public void setAllOut(File f) {
this.allOut = f;
}
/**
* @param optionalDirectories
* the optionalDirectories to set
*/
public void setOptionalDirectories(String optionalDirectories) {
this.optionalDirectories = optionalDirectories;
}
public void setFeatureFile(File f) {
this.featureFile = f;
}
/**
* Sets the component provider filter. This is a pipe (|) separated string
* of names that identify a component as a non-COTS component. The default
* provider filter is <em>raytheon</em>.
*/
public void setProviderFilter(String filter) {
this.provider = filter;
this.providerPattern = Pattern.compile(String.format("^.*(%s).*$",
filter));
}
public void setCotsOut(File f) {
this.cotsOut = f;
}
/**
* Sets the plug-in identifier filter. This is a pipe (|) separated string
* of names that identify a component as an EDEX plug-in. The default
* plug-in filter is <em>plugin</em>.
*/
public void setPluginFilter(String filter) {
this.plugin = filter;
this.pluginPattern = Pattern.compile(String
.format("^.*(%s).*$", filter));
}
public void setPlugsOut(File f) {
this.plugsOut = f;
}
public void setAllOut(File f) {
this.allOut = f;
}
public void setCoreOut(File f) {
this.coreOut = f;
}
public void setFeatureFile(File f) {
this.featureFile = f;
}
public void setBaseDirectory(File aDir) {
this.baseDirectory = aDir;
}
public void setCotsOut(File f) {
this.cotsOut = f;
}
/**
* Main class called from ant. Tests to see if at least 1 includes file is
* to be generated. Only generates includes that have been specified from
* ant script. Throws BuildException if any error occurs, this halts the ant
* build and displays the error.
*
*/
public void execute() throws BuildException {
public void setPlugsOut(File f) {
this.plugsOut = f;
}
log("provider filter=" + this.providerPattern.toString());
log("plugin filter=" + this.pluginPattern.toString());
public void setCoreOut(File f) {
this.coreOut = f;
}
ArrayList<File> components = getComponents();
if (cotsOut == null && plugsOut == null && coreOut == null
&& allOut == null)
throw new BuildException(
"Must supply destination for at least one includes file");
if (featureFile == null)
throw new BuildException("Must supply a feature.xml file");
if (cotsOut != null)
generateCots(components);
if (plugsOut != null)
generatePlugs(components);
if (coreOut != null)
generateCore(components);
if (allOut != null)
generateAll(components);
}
public void setBaseDirectory(File aDir) {
this.baseDirectory = aDir;
}
/**
* Generates an includes file for all components in the feature. The
* directories in comps will be added to the includes file with a recursive
* reg ex. This means that the director and all of its sub directories and
* files will be included.
*
* @param comps
*/
protected void generateAll(ArrayList<File> comps) {
log("Generating ALL list in " + this.allOut.getPath());
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(allOut));
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
out.println("## Feature includes file generated on "
+ format.format(new Date()));
/**
* Main class called from ant. Tests to see if at least 1 includes file is
* to be generated. Only generates includes that have been specified from
* ant script. Throws BuildException if any error occurs, this halts the ant
* build and displays the error.
*
*/
public void execute() throws BuildException {
for (File f : comps) {
out.println(f.getName() + "/**");
}
log(String.format("Identified %d ALL list entries", comps.size()));
} catch (IOException e) {
throw new BuildException(e);
} finally {
if (out != null) {
out.close();
}
}
log("provider filter=" + this.providerPattern.toString());
log("plugin filter=" + this.pluginPattern.toString());
}
ArrayList<File> components = getComponents();
if (cotsOut == null && plugsOut == null && coreOut == null
&& allOut == null)
throw new BuildException(
"Must supply destination for at least one includes file");
if (featureFile == null)
throw new BuildException("Must supply a feature.xml file");
if (cotsOut != null)
generateCots(components);
if (plugsOut != null)
generatePlugs(components);
if (coreOut != null)
generateCore(components);
if (allOut != null)
generateAll(components);
}
/**
* Populates a list of project directories with one directory for each
* component stated in feature. This list is built based on manifest ids and
* version compared to what is stated in the feature. These can differ
* drastically from the name of project.
*
* @return a populated list of directories based off feature
* @throws BuildException
* if there are any problems accessing feature or finding
* required components from feature.
*/
protected ArrayList<File> getComponents() throws BuildException {
/**
* Generates an includes file for all components in the feature. The
* directories in comps will be added to the includes file with a recursive
* reg ex. This means that the director and all of its sub directories and
* files will be included.
*
* @param comps
*/
protected void generateAll(ArrayList<File> comps) {
log("Generating ALL list in " + this.allOut.getPath());
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(allOut));
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
out.println("## Feature includes file generated on "
+ format.format(new Date()));
ArrayList<File> rval = null;
for (File f : comps) {
out.println(f.getName() + "/**");
}
log(String.format("Identified %d ALL list entries", comps.size()));
} catch (IOException e) {
throw new BuildException(e);
} finally {
if (out != null) {
out.close();
}
}
FeatureExplorer fe = null;
}
// list of directories overrides single directory
if (baseDirectories != null) {
String[] fileNames = baseDirectories.split(";");
ArrayList<File> files = new ArrayList<File>(fileNames.length);
for (String fName : fileNames) {
File file = new File(fName);
files.add(file);
}
fe = new FeatureExplorer(new WorkspaceFeatureSearch(files),
new WorkspacePluginSearch(files));
} else if (baseDirectory != null) {
fe = new FeatureExplorer(baseDirectory, new WorkspaceFeatureSearch(
baseDirectory), new WorkspacePluginSearch(baseDirectory));
} else {
throw new BuildException(
"Did not have a baseDirectory or baseDirectories");
}
/**
* Populates a list of project directories with one directory for each
* component stated in feature. This list is built based on manifest ids and
* version compared to what is stated in the feature. These can differ
* drastically from the name of project.
*
* @return a populated list of directories based off feature
* @throws BuildException
* if there are any problems accessing feature or finding
* required components from feature.
*/
protected ArrayList<File> getComponents() throws BuildException {
try {
rval = fe.getPlugins(featureFile);
} catch (FeatureException e) {
throw new BuildException(e);
}
if (rval.isEmpty()) {
throw new BuildException("Unable to access file " + featureFile);
}
ArrayList<File> rval = null;
return rval;
}
FeatureExplorer fe = null;
/**
* Generates an includes file for all components (comps) having a project
* directory name that does not match the {@link #setProviderFilter(String)
* provider filter}. The project's manifest will be searched for a list of
* jars to specify in the includes file. If the list is not present in the
* manifest, the default is to include all *.jar files in the includes file.
*
* @param comps
* The full list of feature specified components
* @throws BuildException
* if any IOException occurs
*/
protected void generateCots(ArrayList<File> comps) throws BuildException {
log("Generating COTS list in " + this.cotsOut.getPath());
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(cotsOut));
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
out.println("## Cots includes file generated on "
+ format.format(new Date()));
int count = 0;
for (File f : comps) {
Matcher m = providerPattern.matcher(f.getName());
if (!m.matches()) {
out.println(f.getName());
count++;
}
}
log(String.format("Identified %d COTS list entries", count));
} catch (IOException e) {
throw new BuildException(e);
} finally {
if (out != null) {
out.close();
}
}
}
ArrayList<File> files = null;
/**
* Generates an includes file for all components (comps) having a project
* directory name that matches both the {@link #setProviderFilter(String)
* provider filter} and the {@link #setPluginFilter(String) plug-in filter}.
*
* @param comps
* The full list of feature specified components
* @throws BuildException
* if any IOException occurs
*/
protected void generatePlugs(ArrayList<File> comps) throws BuildException {
log("Generating PLUGS list in " + this.plugsOut.getPath());
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(plugsOut));
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
out.println("## Plug-in includes file generated on "
+ format.format(new Date()));
int count = 0;
for (File f : comps) {
Matcher prm = providerPattern.matcher(f.getName());
Matcher plm = pluginPattern.matcher(f.getName());
if (prm.matches() && plm.matches()) {
out.println(f.getName());
count++;
}
}
log(String.format("Identified %d PLUGS list entries", count));
} catch (IOException e) {
throw new BuildException(e);
} finally {
if (out != null) {
out.close();
}
}
}
File[] incFiles = null;
/**
* Generates an includes file for all components (comps) having a project
* directory name that matches the {@link #setProviderFilter(String)
* provider filter} and does not match the {@link #setPluginFilter(String)
* plug-in filter}.
*
* @param comps
* The full list of feature specified components
* @throws BuildException
* if any IOException occurs
*/
protected void generateCore(ArrayList<File> comps) throws BuildException {
log("Generating CORE list in " + this.coreOut.getPath());
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(coreOut));
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
out.println("## Core includes file generated on "
+ format.format(new Date()));
int count = 0;
for (File f : comps) {
Matcher prm = providerPattern.matcher(f.getName());
Matcher plm = pluginPattern.matcher(f.getName());
if (prm.matches() && !plm.matches()) {
out.println(f.getName());
count++;
}
}
log(String.format("Identified %d CORE list entries", count));
} catch (IOException e) {
throw new BuildException(e);
} finally {
if (out != null) {
out.close();
}
}
}
ArrayList<File> includes = null;
// list of directories overrides single directory
if (baseDirectories != null) {
String[] fileNames = baseDirectories.split(";");
files = new ArrayList<File>(fileNames.length);
for (String fName : fileNames) {
File file = new File(fName);
files.add(file);
}
if (optionalDirectories != null) {
fileNames = optionalDirectories.split(";");
includes = new ArrayList<File>();
for (String fName : fileNames) {
File file = new File(fName);
files.add(file);
// iterate through each optional dir to find edex features
final Pattern p = Pattern.compile(".*edex.*feature");
incFiles = file.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return p.matcher(file.getName()).matches();
}
});
if (incFiles != null) {
includes.addAll(Arrays.asList(incFiles));
}
}
}
fe = new FeatureExplorer(new WorkspaceFeatureSearch(files),
new WorkspacePluginSearch(files));
} else if (baseDirectory != null) {
fe = new FeatureExplorer(baseDirectory, new WorkspaceFeatureSearch(
baseDirectory), new WorkspacePluginSearch(baseDirectory));
} else {
throw new BuildException(
"Did not have a baseDirectory or baseDirectories");
}
try {
rval = fe.getPlugins(featureFile, includes);
} catch (FeatureException e) {
throw new BuildException(e);
}
if (rval.isEmpty()) {
throw new BuildException("Unable to access file " + featureFile);
}
return rval;
}
/**
* Generates an includes file for all components (comps) having a project
* directory name that does not match the {@link #setProviderFilter(String)
* provider filter}. The project's manifest will be searched for a list of
* jars to specify in the includes file. If the list is not present in the
* manifest, the default is to include all *.jar files in the includes file.
*
* @param comps
* The full list of feature specified components
* @throws BuildException
* if any IOException occurs
*/
protected void generateCots(ArrayList<File> comps) throws BuildException {
log("Generating COTS list in " + this.cotsOut.getPath());
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(cotsOut));
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
out.println("## Cots includes file generated on "
+ format.format(new Date()));
int count = 0;
for (File f : comps) {
Matcher m = providerPattern.matcher(f.getName());
if (!m.matches()) {
out.println(f.getName());
count++;
}
}
log(String.format("Identified %d COTS list entries", count));
} catch (IOException e) {
throw new BuildException(e);
} finally {
if (out != null) {
out.close();
}
}
}
/**
* Generates an includes file for all components (comps) having a project
* directory name that matches both the {@link #setProviderFilter(String)
* provider filter} and the {@link #setPluginFilter(String) plug-in filter}.
*
* @param comps
* The full list of feature specified components
* @throws BuildException
* if any IOException occurs
*/
protected void generatePlugs(ArrayList<File> comps) throws BuildException {
log("Generating PLUGS list in " + this.plugsOut.getPath());
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(plugsOut));
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
out.println("## Plug-in includes file generated on "
+ format.format(new Date()));
int count = 0;
for (File f : comps) {
Matcher prm = providerPattern.matcher(f.getName());
Matcher plm = pluginPattern.matcher(f.getName());
if (prm.matches() && plm.matches()) {
out.println(f.getName());
count++;
}
}
log(String.format("Identified %d PLUGS list entries", count));
} catch (IOException e) {
throw new BuildException(e);
} finally {
if (out != null) {
out.close();
}
}
}
/**
* Generates an includes file for all components (comps) having a project
* directory name that matches the {@link #setProviderFilter(String)
* provider filter} and does not match the {@link #setPluginFilter(String)
* plug-in filter}.
*
* @param comps
* The full list of feature specified components
* @throws BuildException
* if any IOException occurs
*/
protected void generateCore(ArrayList<File> comps) throws BuildException {
log("Generating CORE list in " + this.coreOut.getPath());
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(coreOut));
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
out.println("## Core includes file generated on "
+ format.format(new Date()));
int count = 0;
for (File f : comps) {
Matcher prm = providerPattern.matcher(f.getName());
Matcher plm = pluginPattern.matcher(f.getName());
if (prm.matches() && !plm.matches()) {
out.println(f.getName());
count++;
}
}
log(String.format("Identified %d CORE list entries", count));
} catch (IOException e) {
throw new BuildException(e);
} finally {
if (out != null) {
out.close();
}
}
}
}

View file

@ -6,6 +6,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
@ -36,253 +37,271 @@ import com.raytheon.uf.featureexplorer.search.IPluginSearch;
* Oct 10, 2008 SP#15 bclement Added static functions for reading manifests
* Feb 4, 2013 #1577 bkowal Verify that a plugin has not been included in more than one feature.
* May 22, 2013 #1927 bkowal Fix improper String comparison
* Feb 25, 2015 #3299 garmendariz Process a list of included features
* </pre>
*
* @author dglazesk
* @version 1.0
*/
public class FeatureExplorer {
/**
* This holds the feature searching object for the class.
*/
protected IFeatureSearch featureSearch;
/**
* This holds the feature searching object for the class.
*/
protected IFeatureSearch featureSearch;
/**
* This holds the plugin searching object for the class.
*/
protected IPluginSearch pluginSearch;
/**
* This holds the plugin searching object for the class.
*/
protected IPluginSearch pluginSearch;
/**
* This holds the feature file object should the user choose to set it.
*/
protected File feature = null;
/**
* This holds the feature file object should the user choose to set it.
*/
protected File feature = null;
private Map<String, File> pluginLookupMap = new HashMap<String, File>();
private Map<String, File> pluginLookupMap = new HashMap<String, File>();
/**
* This constructor allows a user to setup what the feature for this
* instance is. This allows the user to use getPlugins(), though the other
* methods are still available.
*
* @param aFeature
* File object for the feature for this instance
* @param aFeatureSearch
* The object that can search for features
* @param aPluginSearh
* The object that can search for plugins
*/
public FeatureExplorer(File aFeature, IFeatureSearch aFeatureSearch,
IPluginSearch aPluginSearh) {
featureSearch = aFeatureSearch;
pluginSearch = aPluginSearh;
feature = aFeature;
}
/**
* This constructor allows a user to setup what the feature for this
* instance is. This allows the user to use getPlugins(), though the other
* methods are still available.
*
* @param aFeature
* File object for the feature for this instance
* @param aFeatureSearch
* The object that can search for features
* @param aPluginSearh
* The object that can search for plugins
*/
public FeatureExplorer(File aFeature, IFeatureSearch aFeatureSearch,
IPluginSearch aPluginSearh) {
featureSearch = aFeatureSearch;
pluginSearch = aPluginSearh;
feature = aFeature;
}
/**
* This constructor sets up the classes that will be used for searching for
* plugins and features. It is expected that a user will use
* getPlugins(File) or getPlugins(String) later when getting the plugins.
*
* @param aFeatureSearch
* The object that can search for features
* @param aPluginSearh
* The object that can search for plugins
*/
public FeatureExplorer(IFeatureSearch aFeatureSearch,
IPluginSearch aPluginSearh) {
featureSearch = aFeatureSearch;
pluginSearch = aPluginSearh;
}
/**
* This constructor sets up the classes that will be used for searching for
* plugins and features. It is expected that a user will use
* getPlugins(File) or getPlugins(String) later when getting the plugins.
*
* @param aFeatureSearch
* The object that can search for features
* @param aPluginSearh
* The object that can search for plugins
*/
public FeatureExplorer(IFeatureSearch aFeatureSearch,
IPluginSearch aPluginSearh) {
featureSearch = aFeatureSearch;
pluginSearch = aPluginSearh;
}
/**
* This is a convenience method for when the feature file object is set in a
* constructor.
*
* @return The list of files in the feature for this instance
* @throws FeatureException
*/
public ArrayList<File> getPlugins() throws FeatureException {
return getPlugins(feature);
}
/**
* This is a convenience method for when the feature file object is set in a
* constructor.
*
* @return The list of files in the feature for this instance
* @throws FeatureException
*/
public ArrayList<File> getPlugins() throws FeatureException {
return getPlugins(feature, null);
}
/**
* This is just a convenience method for getting plugins from a feature.
* This is equivalent to doing getPlugins(new File(aPath)).
*
* @param aPath
* Path to the feature.xml file to be scanned
* @return The list of file objects for all of the plugins in the feature
* @throws FeatureException
*/
public ArrayList<File> getPlugins(String aPath) throws FeatureException {
File feat = new File(aPath);
return getPlugins(feat);
}
/**
* This is just a convenience method for getting plugins from a feature.
* This is equivalent to doing getPlugins(new File(aPath)).
*
* @param aPath
* Path to the feature.xml file to be scanned
* @return The list of file objects for all of the plugins in the feature
* @throws FeatureException
*/
public ArrayList<File> getPlugins(String aPath, ArrayList<File> incList)
throws FeatureException {
File feat = new File(aPath);
return getPlugins(feat, incList);
}
/**
* This function attempts to find all of the plugins associated with the
* feature. This includes recursing into any included features and grabbing
* their plugins.
*
* @param aFeature
* The file object for the feature to be scanned
* @return The list of file objects for the located plugins
* @throws FeatureException
*/
public ArrayList<File> getPlugins(File aFeature) throws FeatureException {
ArrayList<File> rval = new ArrayList<File>();
/**
* This function attempts to find all of the plugins associated with the
* feature. This includes recursing into any included features and grabbing
* their plugins.
*
* @param aFeature
* The file object for the feature to be scanned
* @param incList
* @return The list of file objects for the located plugins
* @throws FeatureException
*/
public ArrayList<File> getPlugins(File aFeature, ArrayList<File> incList)
throws FeatureException {
ArrayList<File> rval = new ArrayList<File>();
HashMap<String, File> plugins = getFeaturePlugins(aFeature);
rval = new ArrayList<File>(plugins.values());
HashMap<String, File> plugins = getFeaturePlugins(aFeature, incList);
rval = new ArrayList<File>(plugins.values());
return rval;
}
return rval;
}
/**
* This finds all of the plugins listed in a feature and maps their ids to
* their file system locations as file objects. This is the function that
* does the brunt of the work in locating the plugins.
*
* @param aFile
* The feature file that is being scanned
* @return A hash map that links the plugin id to its file system location
* @throws FeatureException
* If there are any problems with JAXB, a feature cannot be
* found, or a plugin cannot be found
*/
protected HashMap<String, File> getFeaturePlugins(File aFile)
throws FeatureException {
HashMap<String, File> rval = new HashMap<String, File>();
if (aFile == null || !aFile.exists() || !aFile.canRead())
return rval;
/**
* This finds all of the plugins listed in a feature and maps their ids to
* their file system locations as file objects. This is the function that
* does the brunt of the work in locating the plugins.
*
* @param aFile
* The feature file that is being scanned
* @param incList
* @return A hash map that links the plugin id to its file system location
* @throws FeatureException
* If there are any problems with JAXB, a feature cannot be
* found, or a plugin cannot be found
*/
protected HashMap<String, File> getFeaturePlugins(File aFile,
ArrayList<File> incList) throws FeatureException {
HashMap<String, File> rval = new HashMap<String, File>();
if (aFile == null || !aFile.exists() || !aFile.canRead())
return rval;
Feature feat = null;
try {
JAXBContext jc = JAXBContext.newInstance(Feature.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
feat = (Feature) unmarshaller.unmarshal(aFile);
} catch (Exception e) {
throw new FeatureException("Unable to unmarshal file " + aFile, e);
}
Feature feat = null;
try {
JAXBContext jc = JAXBContext.newInstance(Feature.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
feat = (Feature) unmarshaller.unmarshal(aFile);
} catch (Exception e) {
throw new FeatureException("Unable to unmarshal file " + aFile, e);
}
for (Includes include : feat.getIncludes()) {
// go through all of the included features and try to find them
List<File> features = featureSearch.findFeature(include.getId(),
include.getVersion());
try {
// get all of the plugin id to file objects and add them
rval.putAll(getFeaturePlugins(features.get(0)));
} catch (IndexOutOfBoundsException e) {
if (!include.getOptional()) {
// this means we received an empty list, no feature found
throw new FeatureException("Could not find feature "
+ include.getId() + " with version greater than "
+ include.getVersion());
}
}
}
// if additional includes are passed in, add them for processing
if (incList != null && feat != null) {
List<Includes> featList = feat.getIncludes();
for (Plugin plugin : feat.getPlugins()) {
// go through all of the mentioned plugins
List<File> plugs = pluginSearch.findPlugin(plugin.getId(),
plugin.getVersion());
try {
if (this.pluginLookupMap.containsKey(plugin.getId())
&& !this.pluginLookupMap.get(plugin.getId()).equals(aFile)) {
StringBuilder stringBuilder = new StringBuilder("Plugin ");
stringBuilder.append(plugin.getId());
stringBuilder.append(" is in Feature ");
stringBuilder.append(this.generateFeatureFileName(
aFile.getParent(), aFile.getName()));
stringBuilder.append(" and Feature ");
stringBuilder
.append(this.generateFeatureFileName(
this.pluginLookupMap.get(plugin.getId())
.getParent(), this.pluginLookupMap
.get(plugin.getId()).getName()));
stringBuilder.append("!");
throw new FeatureException(stringBuilder.toString());
}
for (Iterator<File> iterator = incList.iterator(); iterator
.hasNext();) {
File incFile = (File) iterator.next();
featList.add(new Includes(incFile.getName(), "0.0.0", false));
}
// add the plugin id and its file object to the map
rval.put(plugin.getId(), plugs.get(0));
this.pluginLookupMap.put(plugin.getId(), aFile);
} catch (IndexOutOfBoundsException e) {
// this means we received an empty list, no plugin found
throw new FeatureException("Could not find plugin "
+ plugin.getId() + " with version greater than "
+ plugin.getVersion());
}
}
}
return rval;
}
for (Includes include : feat.getIncludes()) {
// go through all of the included features and try to find them
List<File> features = featureSearch.findFeature(include.getId(),
include.getVersion());
try {
// get all of the plugin id to file objects and add them
rval.putAll(getFeaturePlugins(features.get(0), null));
} catch (IndexOutOfBoundsException e) {
if (!include.getOptional()) {
// this means we received an empty list, no feature found
throw new FeatureException("Could not find feature "
+ include.getId() + " with version greater than "
+ include.getVersion());
}
}
}
private String generateFeatureFileName(String parentPath, String fileName) {
String[] pathElements = parentPath.split(File.separator);
return pathElements[pathElements.length - 1] + File.separator
+ fileName;
}
for (Plugin plugin : feat.getPlugins()) {
// go through all of the mentioned plugins
List<File> plugs = pluginSearch.findPlugin(plugin.getId(),
plugin.getVersion());
try {
if (this.pluginLookupMap.containsKey(plugin.getId())
&& !this.pluginLookupMap.get(plugin.getId()).equals(
aFile)) {
StringBuilder stringBuilder = new StringBuilder("Plugin ");
stringBuilder.append(plugin.getId());
stringBuilder.append(" is in Feature ");
stringBuilder.append(this.generateFeatureFileName(
aFile.getParent(), aFile.getName()));
stringBuilder.append(" and Feature ");
stringBuilder
.append(this.generateFeatureFileName(
this.pluginLookupMap.get(plugin.getId())
.getParent(), this.pluginLookupMap
.get(plugin.getId()).getName()));
stringBuilder.append("!");
throw new FeatureException(stringBuilder.toString());
}
/**
* Searches a project's manifest for a specific attribute. The returned list
* will contain all values for the attribute or empty if not found.
*
* @param projectRoot
* @param attrib
* @return a list of a values for the attribute or an empty list if not
* found
* @throws IOException
*/
public static List<String> readManifest(File projectRoot, String attrib)
throws IOException {
File maniFile = new File(projectRoot, "/META-INF/MANIFEST.MF");
Manifest m = null;
List<String> rval = new ArrayList<String>();
// add the plugin id and its file object to the map
rval.put(plugin.getId(), plugs.get(0));
this.pluginLookupMap.put(plugin.getId(), aFile);
} catch (IndexOutOfBoundsException e) {
// this means we received an empty list, no plugin found
throw new FeatureException("Could not find plugin "
+ plugin.getId() + " with version greater than "
+ plugin.getVersion());
}
}
try {
m = new Manifest();
// we only care if the manifest actually exists
InputStream is = new FileInputStream(maniFile);
m.read(is);
is.close();
return rval;
}
} catch (IOException e) {
throw new IOException(
"IO Error while reading manifest for project: "
+ projectRoot.getName());
}
private String generateFeatureFileName(String parentPath, String fileName) {
String[] pathElements = parentPath.split(File.separator);
return pathElements[pathElements.length - 1] + File.separator
+ fileName;
}
// if we get this far, m shouldn't be null
if (m != null) {
Attributes attribs = m.getMainAttributes();
String deploys = attribs.getValue(attrib);
/**
* Searches a project's manifest for a specific attribute. The returned list
* will contain all values for the attribute or empty if not found.
*
* @param projectRoot
* @param attrib
* @return a list of a values for the attribute or an empty list if not
* found
* @throws IOException
*/
public static List<String> readManifest(File projectRoot, String attrib)
throws IOException {
File maniFile = new File(projectRoot, "/META-INF/MANIFEST.MF");
Manifest m = null;
List<String> rval = new ArrayList<String>();
// manifests that do not have a deploy entry will return a wildcard
if (deploys != null) {
for (String s : deploys.split(",")) {
rval.add(s.trim());
}
}
}
return rval;
}
try {
m = new Manifest();
// we only care if the manifest actually exists
InputStream is = new FileInputStream(maniFile);
m.read(is);
is.close();
/**
* Reads the manifest for the project and returns all values for the
* "Edex-Deploy" attribute. If the attribute could not be found, default to
* returning a wildcard for all jars.
*
* @param projectRoot
* @return a list of jar names or a wildcard for all jars if attribute not
* found
* @throws IOException
*/
public static List<String> getJars(File projectRoot) throws IOException {
List<String> rval = readManifest(projectRoot, "Edex-Deploy");
if (rval.isEmpty()) {
rval.add("*.jar");
}
return rval;
}
} catch (IOException e) {
throw new IOException(
"IO Error while reading manifest for project: "
+ projectRoot.getName());
}
// if we get this far, m shouldn't be null
if (m != null) {
Attributes attribs = m.getMainAttributes();
String deploys = attribs.getValue(attrib);
// manifests that do not have a deploy entry will return a wildcard
if (deploys != null) {
for (String s : deploys.split(",")) {
rval.add(s.trim());
}
}
}
return rval;
}
/**
* Reads the manifest for the project and returns all values for the
* "Edex-Deploy" attribute. If the attribute could not be found, default to
* returning a wildcard for all jars.
*
* @param projectRoot
* @return a list of jar names or a wildcard for all jars if attribute not
* found
* @throws IOException
*/
public static List<String> getJars(File projectRoot) throws IOException {
List<String> rval = readManifest(projectRoot, "Edex-Deploy");
if (rval.isEmpty()) {
rval.add("*.jar");
}
return rval;
}
}