public void fire() throws IllegalActionException {
    super.fire();
    log.debug("\n\n\n--- fire");

    try {
      String ce = opendapCEParameter.getExpression();
      log.debug("Constraint Expression: " + ce);

      ce = createCEfromWiredPorts(ce);

      log.debug("Using CE: " + ce);

      DDS dds = dapConnection.getData(ce);
      // log.debug("fire(): dapConnection.getData(ce) returned DataDDS:");
      // dds.print(System.out);

      log.debug("Squeezing arrays.");
      squeezeArrays(dds);

      log.debug("Broadcasting DAP data arrays.");
      broadcastDapData(dds);

      // log.debug("fire(): After data broadcast:");
      // dds.print(System.out);

    } catch (Exception e) {
      log.error("fire() Failed: ", e);
    }
  }
  /**
   * Create the figure for this actor based on the user specified image file.
   *
   * @return The ImageFigure containing the image.
   * @exception IllegalActionException If the selected file does not exist.
   */
  protected ImageFigure _createFigure() throws IllegalActionException {
    URL url = fileOrURL.asURL();

    Image image = Toolkit.getDefaultToolkit().createImage(url);

    ImageFigure figure = new ImageFigure(image);

    return figure;
  }
  /**
   * Override the base class to open the model specified if the attribute is modelFileOrURL, or for
   * other parameters, to cache their values.
   *
   * @param attribute The attribute that changed.
   * @exception IllegalActionException If the change is not acceptable to this container (not thrown
   *     in this base class).
   */
  public void attributeChanged(Attribute attribute) throws IllegalActionException {
    if (attribute == modelFileOrURL) {
      // Open the file and read the MoML to create a model.
      URL url = modelFileOrURL.asURL();

      if (url != null) {
        // By specifying no workspace argument to the parser, we
        // are asking it to create a new workspace for the referenced
        // model. This is necessary because the execution of that
        // model will proceed through its own sequences, and it
        // will need to get write permission on the workspace.
        // Particularly if it is executing in a new thread, then
        // during the fire() method of this actor it would be
        // inappropriate to grant write access on the workspace
        // of this actor.
        MoMLParser parser = new MoMLParser();

        try {
          _model = parser.parse(null, url);
        } catch (Exception ex) {
          throw new IllegalActionException(this, ex, "Failed to read model.");
        }

        // Create a manager, if appropriate.
        if (_model instanceof CompositeActor) {
          _manager = new Manager(_model.workspace(), "Manager");
          ((CompositeActor) _model).setManager(_manager);

          if (_debugging) {
            _debug("** Created new manager.");
          }
        }
      } else {
        // URL is null... delete the current model.
        _model = null;
        _manager = null;
        _throwable = null;
      }
    } else if (attribute == maxOutputLength) {
      IntToken length = (IntToken) maxOutputLength.getToken();

      if (length.intValue() > 0) {
        _outputLength = length.intValue();
      } else {
        throw new IllegalActionException(this, "output array length is less than or equal 0?!");
      }
    } else {
      super.attributeChanged(attribute);
    }
  }
  /**
   * @param attribute The changed Attribute.
   * @throws ptolemy.kernel.util.IllegalActionException When bad things happen.
   */
  public void attributeChanged(ptolemy.kernel.util.Attribute attribute)
      throws ptolemy.kernel.util.IllegalActionException {

    log.debug("attributeChanged() start.");

    if (attribute == opendapURLParameter || attribute == opendapCEParameter) {

      String url = opendapURLParameter.getExpression();
      String ce = opendapCEParameter.getExpression();

      if (attribute == opendapURLParameter)
        log.debug("--- attributeChanged() url: " + url + " Current URL: " + opendapURL);
      if (attribute == opendapCEParameter)
        log.debug("--- attributeChanged()  ce: \"" + ce + "\" Current CE: \"" + opendapCE + "\"");

      boolean reload = false;
      if (!opendapURL.equals(url)) {
        opendapURL = url;

        // only reload if not empty.
        if (!url.equals("")) {
          reload = true;
        }
      }

      if (!opendapCE.equals(ce)) {
        opendapCE = ce;
        // *** I think this should test if url.equals(""). jhrg
        reload = true;
      }

      if (reload) {

        try {

          log.debug("OPeNDAP URL: " + opendapURL);
          dapConnection = new DConnect2(opendapURL);

          DDS dds = dapConnection.getDDS(opendapCE);

          log.debug("Got DDS.");
          // dds.print(System.out);

          log.debug("Squeezing arrays.");
          squeezeArrays(dds);

          // log.debug("Before ports configured.");
          // dds.print(System.out);

          log.debug("Configuring ports.");
          configureOutputPorts(dds);

          // log.debug("After ports configured.");
          // dds.print(System.out);

        } catch (Exception e) {
          e.printStackTrace();
          throw new IllegalActionException(
              "Problem accessing " + "OPeNDAP Data Source: " + e.getMessage());
        }
      }

    }
    // *** Remove the ODC option. jhrg
    else if (attribute == runODC) {
      BooleanToken token = (BooleanToken) runODC.getToken();
      if (token.booleanValue()) {
        // start ODC in separate thread
        ODCThread tr = new ODCThread();
        tr.start();
        runODC.setExpression("false");
      }
    }
  }