Java tutorial
/* * 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 * * 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. */ package org.apache.oozie.action.hadoop; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.attribute.PosixFilePermissions; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Objects; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.oozie.action.hadoop.GitOperations.GitOperationsException; import com.google.common.annotations.VisibleForTesting; public class GitMain extends LauncherMain { private static final String OOZIE_ACTION_CONF = "oozie.action.conf.xml"; private String nameNode; private String keyPath; private String destinationUri; private String gitUri; private String gitBranch; public static void main(final String[] args) throws Exception { run(GitMain.class, args); } @VisibleForTesting void setNameNode(final String nameNode) { this.nameNode = nameNode; } @Override protected void run(final String[] args) throws Exception { System.out.println("============================================="); System.out.println("Oozie Git Action Configuration"); System.out.println("============================================="); final Configuration actionConf = prepareActionConf(); parseActionConfiguration(actionConf); final File localKey = getLocalKeyFile(); final GitOperations gitRepo = new GitOperations(new URI(gitUri), gitBranch, localKey); try { gitRepo.cloneRepoToFS(new Path(destinationUri)); } catch (final IOException | GitOperationsException e) { System.err.println(e.getMessage()); throw e; } } @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "File created without user input") private Configuration prepareActionConf() { final Configuration actionConf = new Configuration(false); final String actionXml = System.getProperty(OOZIE_ACTION_CONF); if (actionXml == null) { throw new RuntimeException("Missing Java System Property [" + OOZIE_ACTION_CONF + "]"); } if (!new File(actionXml).exists()) { throw new RuntimeException("Action Configuration XML file [" + actionXml + "] does not exist"); } actionConf.addResource(new Path("file:///", actionXml)); return actionConf; } private File getLocalKeyFile() throws IOException, URISyntaxException { File localKey = null; if (keyPath != null) { localKey = getKeyFromFS(new Path(keyPath)); } return localKey; } /** * Gathers the Git authentication key from a FileSystem and copies it to a local * filesystem location * * @param location where the key is located (an HDFS URI) * @return the location to where the key was saved */ @VisibleForTesting @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "File created without user input") File getKeyFromFS(final Path location) throws IOException, URISyntaxException { final String keyCopyMsg = "Copied keys to local container!"; final Configuration conf = new Configuration(); final FileSystem fs = FileSystem.newInstance(new URI(nameNode), conf); final File key = createTempDir("git"); fs.copyToLocalFile(location, new Path("file:///" + key.getAbsolutePath() + "/privkey")); System.out.println(keyCopyMsg); return new File(key.getAbsolutePath() + "/privkey"); } /** * Create a local temporary directory * * @param prefix string to use as a prefix to the directory * @return file path of temp. directory (will be set to delete on exit) */ @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "File created without user input") static File createTempDir(final String prefix) throws IOException { final File tempDir = new File(Files .createTempDirectory(Paths.get("."), prefix + "_" + Long.toString(System.nanoTime()), PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------"))) .toString()); tempDir.deleteOnExit(); final String localMkdirMsg = "Local mkdir called creating temp. dir at: " + tempDir.getAbsolutePath(); System.out.println(localMkdirMsg); return tempDir; } /** * Validate a URI is well formed and has a scheme * * @param testUri URI string to test * @return URI from string * @throws OozieActionConfiguratorException if the <code>testUri</code> fails any validity checks */ private URI isValidUri(final String testUri) throws OozieActionConfiguratorException { final URI uri; try { uri = new URI(testUri); } catch (final URISyntaxException e) { throw new OozieActionConfiguratorException("Action Configuration does not have " + "a proper URI: " + testUri + " exception " + e.toString()); } if (uri.getScheme() == null) { throw new OozieActionConfiguratorException( "Action Configuration does not have " + "a proper URI " + testUri + " null scheme."); } return uri; } /** * Calls helper function to verify name not null and throw an exception if so. * Otherwise, returns actionConf value * @param name - actionConf value to return */ String checkAndGetTrimmed(final Configuration actionConf, String name) { Objects.requireNonNull(actionConf.getTrimmed(name), () -> String.format("Action Configuration does not have [%s] property", name)); return actionConf.getTrimmed(name); } /** * Parse action configuration and set configuration variables * * @param actionConf Oozie action configuration * @throws OozieActionConfiguratorException upon any required properties missing */ private void parseActionConfiguration(final Configuration actionConf) throws OozieActionConfiguratorException { nameNode = checkAndGetTrimmed(actionConf, GitActionExecutor.NAME_NODE); destinationUri = checkAndGetTrimmed(actionConf, GitActionExecutor.DESTINATION_URI); try { final FileSystem fs = FileSystem.get(isValidUri(destinationUri), actionConf); destinationUri = fs.makeQualified(new Path(destinationUri)).toString(); } catch (final IOException e) { throw new OozieActionConfiguratorException( "Action Configuration does not have " + "a valid filesystem for URI " + GitActionExecutor.DESTINATION_URI + "exception " + e.toString()); } gitUri = isValidUri(checkAndGetTrimmed(actionConf, GitActionExecutor.GIT_URI)).toString(); gitBranch = actionConf.get(GitActionExecutor.GIT_BRANCH); keyPath = actionConf.get(GitActionExecutor.KEY_PATH); } }