|
@@ -0,0 +1,251 @@
|
|
|
+/**
|
|
|
+ * Licensed to the Apache Software Foundation (ASF) under one
|
|
|
+ * or more contributor license agreements. See the NOTICE file
|
|
|
+ * distributed with this work for additional information
|
|
|
+ * regarding copyright ownership. The ASF licenses this file
|
|
|
+ * to you under 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
|
|
|
+ * <p>
|
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
+ * <p>
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+package org.apache.hadoop.ozone.web.ozShell;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.URI;
|
|
|
+import java.net.URISyntaxException;
|
|
|
+
|
|
|
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
|
|
+import org.apache.hadoop.ozone.client.OzoneClient;
|
|
|
+import org.apache.hadoop.ozone.client.OzoneClientException;
|
|
|
+import org.apache.hadoop.ozone.client.OzoneClientFactory;
|
|
|
+import org.apache.hadoop.ozone.client.rest.OzoneException;
|
|
|
+
|
|
|
+import static org.apache.hadoop.ozone.OzoneConsts.OZONE_HTTP_SCHEME;
|
|
|
+import static org.apache.hadoop.ozone.OzoneConsts.OZONE_RPC_SCHEME;
|
|
|
+import org.apache.http.client.utils.URIBuilder;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Address of an ozone object for ozone shell.
|
|
|
+ */
|
|
|
+public class OzoneAddress {
|
|
|
+
|
|
|
+ private static final String EMPTY_HOST = "___DEFAULT___";
|
|
|
+
|
|
|
+ private URI ozoneURI;
|
|
|
+
|
|
|
+ private String volumeName = "";
|
|
|
+
|
|
|
+ private String bucketName = "";
|
|
|
+
|
|
|
+ private String keyName = "";
|
|
|
+
|
|
|
+ public OzoneAddress() throws OzoneException {
|
|
|
+ this("o3:///");
|
|
|
+ }
|
|
|
+
|
|
|
+ public OzoneAddress(String address)
|
|
|
+ throws OzoneException {
|
|
|
+ if (address == null || address.equals("")) {
|
|
|
+ address = OZONE_RPC_SCHEME + ":///";
|
|
|
+ }
|
|
|
+ this.ozoneURI = parseURI(address);
|
|
|
+ String path = this.ozoneURI.getPath();
|
|
|
+
|
|
|
+ path = path.replaceAll("^/+", "");
|
|
|
+
|
|
|
+ int sep1 = path.indexOf('/');
|
|
|
+ int sep2 = path.indexOf('/', sep1 + 1);
|
|
|
+
|
|
|
+ if (sep1 == -1) {
|
|
|
+ volumeName = path;
|
|
|
+ } else {
|
|
|
+ //we have vol/bucket
|
|
|
+ volumeName = path.substring(0, sep1);
|
|
|
+ if (sep2 == -1) {
|
|
|
+ bucketName = path.substring(sep1 + 1);
|
|
|
+ } else {
|
|
|
+ //we have vol/bucket/key/.../...
|
|
|
+ bucketName = path.substring(sep1 + 1, sep2);
|
|
|
+ keyName = path.substring(sep2 + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public OzoneClient createClient(OzoneConfiguration conf)
|
|
|
+ throws IOException, OzoneClientException {
|
|
|
+ OzoneClient client;
|
|
|
+ String scheme = ozoneURI.getScheme();
|
|
|
+ if (ozoneURI.getScheme() == null || scheme.isEmpty()) {
|
|
|
+ scheme = OZONE_RPC_SCHEME;
|
|
|
+ }
|
|
|
+ if (scheme.equals(OZONE_HTTP_SCHEME)) {
|
|
|
+ if (ozoneURI.getHost() != null && !ozoneURI.getAuthority()
|
|
|
+ .equals(EMPTY_HOST)) {
|
|
|
+ if (ozoneURI.getPort() == -1) {
|
|
|
+ client = OzoneClientFactory.getRestClient(ozoneURI.getHost());
|
|
|
+ } else {
|
|
|
+ client = OzoneClientFactory
|
|
|
+ .getRestClient(ozoneURI.getHost(), ozoneURI.getPort(), conf);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ client = OzoneClientFactory.getRestClient(conf);
|
|
|
+ }
|
|
|
+ } else if (scheme.equals(OZONE_RPC_SCHEME)) {
|
|
|
+ if (ozoneURI.getHost() != null && !ozoneURI.getAuthority()
|
|
|
+ .equals(EMPTY_HOST)) {
|
|
|
+ if (ozoneURI.getPort() == -1) {
|
|
|
+ client = OzoneClientFactory.getRpcClient(ozoneURI.getHost());
|
|
|
+ } else {
|
|
|
+ client = OzoneClientFactory
|
|
|
+ .getRpcClient(ozoneURI.getHost(), ozoneURI.getPort(), conf);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ client = OzoneClientFactory.getRpcClient(conf);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Invalid URI, unknown protocol scheme: " + scheme);
|
|
|
+ }
|
|
|
+ return client;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * verifies user provided URI.
|
|
|
+ *
|
|
|
+ * @param uri - UriString
|
|
|
+ * @return URI
|
|
|
+ * @throws URISyntaxException
|
|
|
+ * @throws OzoneException
|
|
|
+ */
|
|
|
+ protected URI parseURI(String uri)
|
|
|
+ throws OzoneException {
|
|
|
+ if ((uri == null) || uri.isEmpty()) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Ozone URI is needed to execute this command.");
|
|
|
+ }
|
|
|
+ URIBuilder uriBuilder = new URIBuilder(stringToUri(uri));
|
|
|
+ if (uriBuilder.getPort() == 0) {
|
|
|
+ uriBuilder.setPort(Shell.DEFAULT_OZONE_PORT);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ return uriBuilder.build();
|
|
|
+ } catch (URISyntaxException e) {
|
|
|
+ throw new OzoneClientException("Invalid URI: " + ozoneURI, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Construct a URI from a String with unescaped special characters
|
|
|
+ * that have non-standard semantics. e.g. /, ?, #. A custom parsing
|
|
|
+ * is needed to prevent misbehavior.
|
|
|
+ *
|
|
|
+ * @param pathString The input path in string form
|
|
|
+ * @return URI
|
|
|
+ */
|
|
|
+ private static URI stringToUri(String pathString) {
|
|
|
+ // parse uri components
|
|
|
+ String scheme = null;
|
|
|
+ String authority = null;
|
|
|
+ int start = 0;
|
|
|
+
|
|
|
+ // parse uri scheme, if any
|
|
|
+ int colon = pathString.indexOf(':');
|
|
|
+ int slash = pathString.indexOf('/');
|
|
|
+ if (colon > 0 && (slash == colon + 1)) {
|
|
|
+ // has a non zero-length scheme
|
|
|
+ scheme = pathString.substring(0, colon);
|
|
|
+ start = colon + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // parse uri authority, if any
|
|
|
+ if (pathString.startsWith("//", start) &&
|
|
|
+ (pathString.length() - start > 2)) {
|
|
|
+ start += 2;
|
|
|
+ int nextSlash = pathString.indexOf('/', start);
|
|
|
+ int authEnd = nextSlash > 0 ? nextSlash : pathString.length();
|
|
|
+ authority = pathString.substring(start, authEnd);
|
|
|
+ start = authEnd;
|
|
|
+ }
|
|
|
+ // uri path is the rest of the string. ? or # are not interpreted,
|
|
|
+ // but any occurrence of them will be quoted by the URI ctor.
|
|
|
+ String path = pathString.substring(start, pathString.length());
|
|
|
+
|
|
|
+ if (authority == null || authority.equals("")) {
|
|
|
+ authority = EMPTY_HOST;
|
|
|
+ }
|
|
|
+ // Construct the URI
|
|
|
+ try {
|
|
|
+ return new URI(scheme, authority, path, null, null);
|
|
|
+ } catch (URISyntaxException e) {
|
|
|
+ throw new IllegalArgumentException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getVolumeName() {
|
|
|
+ return volumeName;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getBucketName() {
|
|
|
+ return bucketName;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getKeyName() {
|
|
|
+ return keyName;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ensureBucketAddress() throws OzoneClientException {
|
|
|
+ if (keyName.length() > 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Invalid bucket name. Delimiters (/) not allowed in bucket name");
|
|
|
+ } else if (volumeName.length() == 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Volume name is required.");
|
|
|
+ } else if (bucketName.length() == 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Bucket name is required.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ensureKeyAddress() throws OzoneClientException {
|
|
|
+ if (keyName.length() == 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Key name is missing.");
|
|
|
+ } else if (volumeName.length() == 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Volume name is missing");
|
|
|
+ } else if (bucketName.length() == 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Bucket name is missing");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ensureVolumeAddress() throws OzoneClientException {
|
|
|
+ if (keyName.length() != 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Invalid volume name. Delimiters (/) not allowed in volume name");
|
|
|
+ } else if (volumeName.length() == 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Volume name is required");
|
|
|
+ } else if (bucketName.length() != 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Invalid volume name. Delimiters (/) not allowed in volume name");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ensureRootAddress() throws OzoneClientException {
|
|
|
+ if (keyName.length() != 0 || bucketName.length() != 0
|
|
|
+ || volumeName.length() != 0) {
|
|
|
+ throw new OzoneClientException(
|
|
|
+ "Invalid URI. Volume/bucket/key elements should not been used");
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|