/** Returns the rest status code associated with this exception. */ public RestStatus status() { Throwable cause = unwrapCause(); if (cause == this) { return RestStatus.INTERNAL_SERVER_ERROR; } else { return ExceptionsHelper.status(cause); } }
@Override public String toString() { StringBuilder builder = new StringBuilder(); if (headers.containsKey(INDEX_HEADER_KEY)) { builder.append(getIndex()); if (headers.containsKey(SHARD_HEADER_KEY)) { builder.append('[').append(getShardId()).append(']'); } builder.append(' '); } return builder.append(ExceptionsHelper.detailedMessage(this).trim()).toString(); }
/** * Statis toXContent helper method that also renders non {@link * org.elasticsearch.ElasticsearchException} instances as XContent. */ public static void toXContent(XContentBuilder builder, Params params, Throwable ex) throws IOException { ex = ExceptionsHelper.unwrapCause(ex); if (ex instanceof ElasticsearchException) { ((ElasticsearchException) ex).toXContent(builder, params); } else { builder.field("type", getExceptionName(ex)); builder.field("reason", ex.getMessage()); if (ex.getCause() != null) { builder.field("caused_by"); builder.startObject(); toXContent(builder, params, ex.getCause()); builder.endObject(); } if (params.paramAsBoolean( REST_EXCEPTION_SKIP_STACK_TRACE, REST_EXCEPTION_SKIP_STACK_TRACE_DEFAULT) == false) { builder.field("stack_trace", ExceptionsHelper.stackTrace(ex)); } } }
/** * Returns the root cause of this exception or multiple if different shards caused different * exceptions. If the given exception is not an instance of {@link * org.elasticsearch.ElasticsearchException} an empty array is returned. */ public static ElasticsearchException[] guessRootCauses(Throwable t) { Throwable ex = ExceptionsHelper.unwrapCause(t); if (ex instanceof ElasticsearchException) { return ((ElasticsearchException) ex).guessRootCauses(); } return new ElasticsearchException[] { new ElasticsearchException(t.getMessage(), t) { @Override protected String getExceptionName() { return getExceptionName(getCause()); } } }; }
@Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { Throwable ex = ExceptionsHelper.unwrapCause(this); if (ex != this) { toXContent(builder, params, this); } else { builder.field("type", getExceptionName()); builder.field("reason", getMessage()); for (String key : headers.keySet()) { if (key.startsWith("es.")) { List<String> values = headers.get(key); xContentHeader(builder, key.substring("es.".length()), values); } } innerToXContent(builder, params); renderHeader(builder, params); if (params.paramAsBoolean( REST_EXCEPTION_SKIP_STACK_TRACE, REST_EXCEPTION_SKIP_STACK_TRACE_DEFAULT) == false) { builder.field("stack_trace", ExceptionsHelper.stackTrace(this)); } } return builder; }
private void extract(PluginHandle pluginHandle, Terminal terminal, Path pluginFile) throws IOException { // unzip plugin to a staging temp dir, named for the plugin Path tmp = Files.createTempDirectory(environment.tmpFile(), null); Path root = tmp.resolve(pluginHandle.name); unzipPlugin(pluginFile, root); // find the actual root (in case its unzipped with extra directory wrapping) root = findPluginRoot(root); // read and validate the plugin descriptor PluginInfo info = PluginInfo.readFromProperties(root); terminal.println(VERBOSE, "%s", info); // update name in handle based on 'name' property found in descriptor file pluginHandle = new PluginHandle(info.getName(), pluginHandle.version, pluginHandle.user); final Path extractLocation = pluginHandle.extractedDir(environment); if (Files.exists(extractLocation)) { throw new IOException( "plugin directory " + extractLocation.toAbsolutePath() + " already exists. To update the plugin, uninstall it first using 'remove " + pluginHandle.name + "' command"); } // check for jar hell before any copying if (info.isJvm()) { jarHellCheck(root, info.isIsolated()); } // install plugin FileSystemUtils.copyDirectoryRecursively(root, extractLocation); terminal.println("Installed %s into %s", pluginHandle.name, extractLocation.toAbsolutePath()); // cleanup tryToDeletePath(terminal, tmp, pluginFile); // take care of bin/ by moving and applying permissions if needed Path sourcePluginBinDirectory = extractLocation.resolve("bin"); Path destPluginBinDirectory = pluginHandle.binDir(environment); boolean needToCopyBinDirectory = Files.exists(sourcePluginBinDirectory); if (needToCopyBinDirectory) { if (Files.exists(destPluginBinDirectory) && !Files.isDirectory(destPluginBinDirectory)) { tryToDeletePath(terminal, extractLocation); throw new IOException( "plugin bin directory " + destPluginBinDirectory + " is not a directory"); } try { copyBinDirectory( sourcePluginBinDirectory, destPluginBinDirectory, pluginHandle.name, terminal); } catch (IOException e) { // rollback and remove potentially before installed leftovers terminal.printError( "Error copying bin directory [%s] to [%s], cleaning up, reason: %s", sourcePluginBinDirectory, destPluginBinDirectory, ExceptionsHelper.detailedMessage(e)); tryToDeletePath(terminal, extractLocation, pluginHandle.binDir(environment)); throw e; } } Path sourceConfigDirectory = extractLocation.resolve("config"); Path destConfigDirectory = pluginHandle.configDir(environment); boolean needToCopyConfigDirectory = Files.exists(sourceConfigDirectory); if (needToCopyConfigDirectory) { if (Files.exists(destConfigDirectory) && !Files.isDirectory(destConfigDirectory)) { tryToDeletePath(terminal, extractLocation, destPluginBinDirectory); throw new IOException( "plugin config directory " + destConfigDirectory + " is not a directory"); } try { terminal.println( VERBOSE, "Found config, moving to %s", destConfigDirectory.toAbsolutePath()); moveFilesWithoutOverwriting(sourceConfigDirectory, destConfigDirectory, ".new"); if (Environment.getFileStore(destConfigDirectory) .supportsFileAttributeView(PosixFileAttributeView.class)) { // We copy owner, group and permissions from the parent ES_CONFIG directory, assuming they // were properly set depending // on how es was installed in the first place: can be root:elasticsearch (750) if es was // installed from rpm/deb packages // or most likely elasticsearch:elasticsearch if installed from tar/zip. As for // permissions we don't rely on umask. final PosixFileAttributes parentDirAttributes = Files.getFileAttributeView( destConfigDirectory.getParent(), PosixFileAttributeView.class) .readAttributes(); // for files though, we make sure not to copy execute permissions from the parent dir and // leave them untouched final Set<PosixFilePermission> baseFilePermissions = new HashSet<>(); for (PosixFilePermission posixFilePermission : parentDirAttributes.permissions()) { switch (posixFilePermission) { case OWNER_EXECUTE: case GROUP_EXECUTE: case OTHERS_EXECUTE: break; default: baseFilePermissions.add(posixFilePermission); } } Files.walkFileTree( destConfigDirectory, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (attrs.isRegularFile()) { Set<PosixFilePermission> newFilePermissions = new HashSet<>(baseFilePermissions); Set<PosixFilePermission> currentFilePermissions = Files.getPosixFilePermissions(file); for (PosixFilePermission posixFilePermission : currentFilePermissions) { switch (posixFilePermission) { case OWNER_EXECUTE: case GROUP_EXECUTE: case OTHERS_EXECUTE: newFilePermissions.add(posixFilePermission); } } setPosixFileAttributes( file, parentDirAttributes.owner(), parentDirAttributes.group(), newFilePermissions); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { setPosixFileAttributes( dir, parentDirAttributes.owner(), parentDirAttributes.group(), parentDirAttributes.permissions()); return FileVisitResult.CONTINUE; } }); } else { terminal.println( VERBOSE, "Skipping posix permissions - filestore doesn't support posix permission"); } terminal.println( VERBOSE, "Installed %s into %s", pluginHandle.name, destConfigDirectory.toAbsolutePath()); } catch (IOException e) { terminal.printError( "Error copying config directory [%s] to [%s], cleaning up, reason: %s", sourceConfigDirectory, destConfigDirectory, ExceptionsHelper.detailedMessage(e)); tryToDeletePath(terminal, extractLocation, destPluginBinDirectory, destConfigDirectory); throw e; } } }
private Path download(PluginHandle pluginHandle, Terminal terminal) throws IOException { Path pluginFile = pluginHandle.newDistroFile(environment); HttpDownloadHelper downloadHelper = new HttpDownloadHelper(); boolean downloaded = false; boolean verified = false; HttpDownloadHelper.DownloadProgress progress; if (outputMode == OutputMode.SILENT) { progress = new HttpDownloadHelper.NullProgress(); } else { progress = new HttpDownloadHelper.VerboseProgress(terminal.writer()); } // first, try directly from the URL provided if (url != null) { URL pluginUrl = url; boolean isSecureProcotol = "https".equalsIgnoreCase(pluginUrl.getProtocol()); boolean isAuthInfoSet = !Strings.isNullOrEmpty(pluginUrl.getUserInfo()); if (isAuthInfoSet && !isSecureProcotol) { throw new IOException("Basic auth is only supported for HTTPS!"); } terminal.println("Trying %s ...", pluginUrl.toExternalForm()); try { downloadHelper.download(pluginUrl, pluginFile, progress, this.timeout); downloaded = true; terminal.println("Verifying %s checksums if available ...", pluginUrl.toExternalForm()); Tuple<URL, Path> sha1Info = pluginHandle.newChecksumUrlAndFile(environment, pluginUrl, "sha1"); verified = downloadHelper.downloadAndVerifyChecksum( sha1Info.v1(), pluginFile, sha1Info.v2(), progress, this.timeout, HttpDownloadHelper.SHA1_CHECKSUM); Tuple<URL, Path> md5Info = pluginHandle.newChecksumUrlAndFile(environment, pluginUrl, "md5"); verified = verified || downloadHelper.downloadAndVerifyChecksum( md5Info.v1(), pluginFile, md5Info.v2(), progress, this.timeout, HttpDownloadHelper.MD5_CHECKSUM); } catch (ElasticsearchTimeoutException | ElasticsearchCorruptionException e) { throw e; } catch (Exception e) { // ignore terminal.println("Failed: %s", ExceptionsHelper.detailedMessage(e)); } } else { if (PluginHandle.isOfficialPlugin( pluginHandle.name, pluginHandle.user, pluginHandle.version)) { checkForOfficialPlugins(pluginHandle.name); } } if (!downloaded && url == null) { // We try all possible locations for (URL url : pluginHandle.urls()) { terminal.println("Trying %s ...", url.toExternalForm()); try { downloadHelper.download(url, pluginFile, progress, this.timeout); downloaded = true; terminal.println("Verifying %s checksums if available ...", url.toExternalForm()); Tuple<URL, Path> sha1Info = pluginHandle.newChecksumUrlAndFile(environment, url, "sha1"); verified = downloadHelper.downloadAndVerifyChecksum( sha1Info.v1(), pluginFile, sha1Info.v2(), progress, this.timeout, HttpDownloadHelper.SHA1_CHECKSUM); Tuple<URL, Path> md5Info = pluginHandle.newChecksumUrlAndFile(environment, url, "md5"); verified = verified || downloadHelper.downloadAndVerifyChecksum( md5Info.v1(), pluginFile, md5Info.v2(), progress, this.timeout, HttpDownloadHelper.MD5_CHECKSUM); break; } catch (ElasticsearchTimeoutException | ElasticsearchCorruptionException e) { throw e; } catch (Exception e) { terminal.println(VERBOSE, "Failed: %s", ExceptionsHelper.detailedMessage(e)); } } } if (!downloaded) { // try to cleanup what we downloaded IOUtils.deleteFilesIgnoringExceptions(pluginFile); throw new IOException( "failed to download out of all possible locations..., use --verbose to get detailed information"); } if (verified == false) { terminal.println( "NOTE: Unable to verify checksum for downloaded plugin (unable to find .sha1 or .md5 file to verify)"); } return pluginFile; }
/** * Unwraps the actual cause from the exception for cases when the exception is a {@link * ElasticsearchWrapperException}. * * @see ExceptionsHelper#unwrapCause(Throwable) */ public Throwable unwrapCause() { return ExceptionsHelper.unwrapCause(this); }