Package org.cloudfoundry.ide.eclipse.server.ui.internal.console.file

Source Code of org.cloudfoundry.ide.eclipse.server.ui.internal.console.file.FileConsoleStream

/*******************************************************************************
* Copyright (c) 2013, 2014 Pivotal Software, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License,
* Version 2.0 (the "License�); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*  Contributors:
*     Pivotal Software, Inc. - initial API and implementation
********************************************************************************/
package org.cloudfoundry.ide.eclipse.server.ui.internal.console.file;

import java.util.List;

import org.cloudfoundry.client.lib.CloudFoundryException;
import org.cloudfoundry.ide.eclipse.server.core.internal.CloudErrorUtil;
import org.cloudfoundry.ide.eclipse.server.core.internal.CloudFoundryPlugin;
import org.cloudfoundry.ide.eclipse.server.core.internal.CloudFoundryServer;
import org.cloudfoundry.ide.eclipse.server.ui.internal.Messages;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;

/**
* Streams file content to the Cloud Foundry console. It continues to check for
* new content indefinitely, until the Cloud Foundry manager decided to
* terminate any further streaming (e.g., application is deleted or stopped, or
* enough errors have been encountered)
*/
public class FileConsoleStream extends CloudFoundryConsoleStream {

  protected int tailingOffset = 0;

  private final String path;

  private static final int MAX_COUNT = 40;

  private int attemptsRemaining;

  private static final IContentType FILE_CONTENT_TYPE = new FileStreamContentType();

  /**
   *
   * @param path relative path of content resource, relative to the
   * application in the remove server
   * @param swtColour valid constants would be something like SWT.COLOR_RED.
   * Use -1 to use default console colour.
   * @param server must not be null. Server where contents should be fetched.
   * @param appName must not be null
   * @param instanceIndex must be valid and greater than -1.
   */
  public FileConsoleStream(String path, int swtColour, CloudFoundryServer server, String appName, int instanceIndex) {
    super(server, swtColour, appName, instanceIndex);
    this.path = path;
    attemptsRemaining = getMaximumErrorCount();
  }

  /**
   *
   * @return true if still active, stream open and is able to stream content.
   * False otherwise
   */
  public synchronized boolean isActive() {
    return attemptsRemaining > 0 && super.isActive();
  }

  /**
   *
   * @return basic chaining API.
   */
  public synchronized List<ICloudFoundryConsoleStream> getNextContent() {
    return null;
  }

  protected String getFilePath() {
    return path;
  }

  protected int getMaximumErrorCount() {
    return MAX_COUNT;
  }

  protected String getContent(IProgressMonitor monitor) throws CoreException {

    if (!isActive()) {
      return null;
    }

    try {
      String content = getContentFromFile(monitor);

      // Note that if no error was thrown, reset the error count. The
      // stream should only terminate if N number of errors are met in
      // a row.
      attemptsRemaining = getMaximumErrorCount();
      return content;
    }
    catch (CoreException ce) {
      CloudFoundryException cfe = ce.getCause() instanceof CloudFoundryException ? (CloudFoundryException) ce
          .getCause() : null;

      // Do not log error if is is due to range not satisfied, or file is
      // not
      // found for instance
      if (cfe != null
          && (CloudErrorUtil.isRequestedFileRangeNotSatisfiable(cfe) || CloudErrorUtil
              .isFileNotFoundForInstance(cfe))) {
        // These types of errors are "valid" meaning they don't indicate
        // a problem. Return null to let the caller know that there is
        // no further content at the moment, but to keep the stream
        // alive.
        return null;
      }

      return handleErrorCount(ce);
    }
  }

  /**
   * Get content from the file from the client starting from the current
   * offset.
   * @param monitor
   * @return content from the file starting from the current offset. It may be
   * null if there is no more content available.
   * @throws CoreException if client or server error occurred while fetching
   * content for the file.
   */
  protected String getContentFromFile(IProgressMonitor monitor) throws CoreException {
    try {
      String content = server.getBehaviour().getFile(appName, instanceIndex, path, tailingOffset, monitor);
      if (content != null) {
        tailingOffset += content.length();
      }
      return content;
    }
    catch (CloudFoundryException cfex) {
      throw new CoreException(CloudFoundryPlugin.getErrorStatus(cfex));
    }
  }

  /**
   * Handling error has two options:
   *
   * <p/>
   *
   * 1. Retry on error. If a message should be displayed due to the error,
   * that message is returned to be streamed to the console.
   *
   * <p/>
   *
   * 2. Maximum errors reached. Exception is thrown if there is a message
   * associated with the last error that needs to be displayed to the user.
   * Otherwise, the stream deactives itself after maximum errors are reached.
   * <p/>
   *
   * If the error is encountered when the stream is no longer active, nothing
   * happens and null is returned.
   *
   * @return a message to be streamed to the console based on the current.
   * error. Or null if no message should be streamed.
   */
  protected String handleErrorCount(CoreException ce) throws CoreException {

    if (!isActive()) {
      return null;
    }

    if (isFatalError(ce)) {
      // NOTE: closing within the stream appears to throw exceptions. To
      // "deactivate" the stream, set
      // attempts to zero instead
      // close();
      attemptsRemaining = 0;
      throw ce;
    }

    // If error count maximum has been reached, display the error and close
    // stream
    String message = null;
    if (adjustErrorCount()) {
      message = reachedMaximumErrors(ce);
      if (message != null) {
        throw new CoreException(CloudFoundryPlugin.getErrorStatus(message, ce));
      }
    }

    // Otherwise see if there is a message on retry that should be sent to
    // the console
    if (message == null) {
      message = getMessageOnRetry(ce, attemptsRemaining);
    }

    return message;
  }

  /**
   * Return a message based on the current number of consecutive attempts made
   * to fetch streaming content from the file due to errors. If the message is
   * not meant to be an error, return it, and it will be displayed in the same
   * format as the file content. </p> If the message should be displayed as an
   * error to the user, throw a {@link CoreException}. This will not stop the
   * streaming process, but simply allow the content manager to handle the
   * error (e.g. display in std error console output).
   * @param ce error that will result in a further attempt to stream content
   * from the file.
   * @param attemptsRemaining how many consecutive attempts still remain
   * before any further streaming attempts are stopped.
   * @return optional message related to the attempt and associated error, or
   * null.
   * @throws CoreException if the error requires the content manager to handle
   * the error. Otherwise return a message or null.
   */
  protected String getMessageOnRetry(CoreException ce, int attemptsRemaining) throws CoreException {
    return null;
  }

  /**
   * Gets invoked when maximum errors have been reached. Return an error
   * message that gets displayed in the console.
   * @param ce
   * @return error message that gets displayed in the console when maximum
   * errors are reached. return Null if nothing should be displayed if maximum
   * errors are reached @
   */
  protected String reachedMaximumErrors(CoreException ce) {
    return Messages.FileConsoleStream_ERROR_REACH_MAX;
  }

  /**
   *
   * @param ce
   * @return true if error is fatal and streaming should stop. False otherwise
   */
  protected boolean isFatalError(CoreException ce) {
    return false;
  }

  /**
   *
   * @return true if maximum number of errors reached. False otherwise
   */
  protected boolean adjustErrorCount() {
    if (attemptsRemaining > 0) {
      attemptsRemaining--;
    }
    return attemptsRemaining == 0;
  }

  public IContentType getContentType() {
    return FILE_CONTENT_TYPE;
  }
}
TOP

Related Classes of org.cloudfoundry.ide.eclipse.server.ui.internal.console.file.FileConsoleStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.