blob: cd518e33a64a7ec3cce7f38142b956525c5b9583 [file] [log] [blame]
/*
* 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.oodt.cas.pge.config;
//OODT static imports
import static org.apache.oodt.cas.pge.metadata.PgeTaskMetKeys.CONFIG_FILE_PATH;
import static org.apache.oodt.cas.pge.util.XmlHelper.fillIn;
import static org.apache.oodt.cas.pge.util.XmlHelper.getCustomMetadataElement;
import static org.apache.oodt.cas.pge.util.XmlHelper.getDir;
import static org.apache.oodt.cas.pge.util.XmlHelper.getDynamicConfigFiles;
import static org.apache.oodt.cas.pge.util.XmlHelper.getExeCmds;
import static org.apache.oodt.cas.pge.util.XmlHelper.getFileStaging;
import static org.apache.oodt.cas.pge.util.XmlHelper.getImports;
import static org.apache.oodt.cas.pge.util.XmlHelper.getMetadataElements;
import static org.apache.oodt.cas.pge.util.XmlHelper.getMetadataKey;
import static org.apache.oodt.cas.pge.util.XmlHelper.getMetadataKeyRef;
import static org.apache.oodt.cas.pge.util.XmlHelper.getMetadataValues;
import static org.apache.oodt.cas.pge.util.XmlHelper.getOuputDirs;
import static org.apache.oodt.cas.pge.util.XmlHelper.getOutput;
import static org.apache.oodt.cas.pge.util.XmlHelper.getRootElement;
import static org.apache.oodt.cas.pge.util.XmlHelper.getShellType;
import static org.apache.oodt.cas.pge.util.XmlHelper.getStageFilesMetKeys;
import static org.apache.oodt.cas.pge.util.XmlHelper.isForceStage;
import static org.apache.oodt.cas.pge.util.XmlHelper.isWorkflowMetKey;
//JDK imports
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.List;
//OODT imports
import org.apache.oodt.cas.metadata.Metadata;
import org.apache.oodt.cas.pge.metadata.PgeMetadata;
import org.apache.oodt.cas.pge.util.Pair;
import org.apache.oodt.cas.pge.util.XmlHelper;
//DOM imports
import org.w3c.dom.Element;
import com.google.common.collect.Lists;
/**
* An implementation of the {@link PgeConfigBuilder} that reads an XML file
* representation of the {@link PgeConfig}.
*
* @author bfoster (Brian Foster)
*/
public class XmlFilePgeConfigBuilder implements PgeConfigBuilder {
private final List<String> missingMetadataKeys;
public XmlFilePgeConfigBuilder() {
missingMetadataKeys = Lists.newArrayList();
}
@Override
public PgeConfig build(PgeMetadata pgeMetadata) throws IOException {
try {
missingMetadataKeys.clear();
PgeConfig pgeConfig = new PgeConfig();
String configFile = fillIn(pgeMetadata.getMetadata(CONFIG_FILE_PATH),
pgeMetadata.asMetadata());
if (configFile == null) {
throw new Exception("Must specify metadata field '"
+ CONFIG_FILE_PATH + "'");
}
pgeMetadata.replaceMetadata(loadConfigFile(configFile, pgeConfig,
pgeMetadata));
return pgeConfig;
} catch (Exception e) {
throw new IOException("Failed to build PgeConfig : " + e.getMessage(),
e);
}
}
private PgeMetadata loadConfigFile(String configFile, PgeConfig pgeConfig,
PgeMetadata parentPgeMetadata) throws Exception {
PgeMetadata pgeMetadata = new PgeMetadata(parentPgeMetadata);
Element root = getRootElement(configFile);
// Read in imports
List<Pair<String, String>> imports = getImports(root, pgeMetadata.asMetadata());
for (Pair<String, String> imp : imports) {
String namespace = imp.getFirst();
String file = imp.getSecond();
// If relative path, then make path relative to configFile.
if (!file.startsWith(File.separator)) {
file = new File(configFile).getParent() + File.separator + file;
}
// Add metadata generated from import.
if (namespace != null) {
pgeMetadata.replaceMetadata(
loadConfigFile(file, pgeConfig, parentPgeMetadata),
namespace);
} else {
pgeMetadata.replaceMetadata(loadConfigFile(file, pgeConfig,
parentPgeMetadata));
}
}
// load custom metadata
loadCustomMetadata(root, pgeMetadata);
Metadata metadata = pgeMetadata.asMetadata();
// load dynamic config file info
for (DynamicConfigFile dcf : getDynamicConfigFiles(root, metadata)) {
pgeConfig.addDynamicConfigFile(dcf);
}
// load file staging info.
loadFileStagingInfo(root, pgeConfig, pgeMetadata);
// load exe info
Element exeElem = XmlHelper.getExe(root);
if (exeElem != null) {
pgeConfig.setExeDir(getDir(exeElem, metadata));
pgeConfig.setShellType(getShellType(exeElem, metadata));
pgeConfig.setExeCmds(getExeCmds(exeElem, metadata));
}
// load output dirs
Element outputElem = getOutput(root);
if (outputElem != null) {
for (OutputDir outputDir : getOuputDirs(outputElem, metadata)) {
pgeConfig.addOuputDirAndExpressions(outputDir);
}
}
return pgeMetadata;
}
private void loadCustomMetadata(Element root, PgeMetadata pgeMetadata)
throws MalformedURLException, Exception {
// Check if there is a 'customMetadata' elem and load it.
Element customMetadataElem = getCustomMetadataElement(root);
if (customMetadataElem == null) {
return;
}
// Iterate through metadata elements.
for (Element metElem : getMetadataElements(customMetadataElem)) {
Metadata curMetadata = pgeMetadata.asMetadata();
// Load supported metadata element attributes.
String key = getMetadataKey(metElem, curMetadata);
List<String> values = getMetadataValues(metElem, curMetadata);
String keyRef = getMetadataKeyRef(metElem, curMetadata);
// Check that either val or key-ref is given.
if (!values.isEmpty() && keyRef != null) {
throw new Exception(
"Cannot specify both values and keyref for metadata key '"
+ key + "'");
// If val is given then set metadata with key and val.
} else if (!values.isEmpty()) {
pgeMetadata.replaceMetadata(key, values);
// Otherwise key-ref was given, so set the link.
} else {
pgeMetadata.linkKey(key, keyRef);
}
// Check if current key should be marked as workflow metadata.
if (isWorkflowMetKey(metElem, curMetadata)) {
pgeMetadata.markAsDynamicMetadataKey(key);
}
}
}
private void loadFileStagingInfo(Element root, PgeConfig pgeConfig,
PgeMetadata pgeMetadata) throws Exception {
Metadata metadata = pgeMetadata.asMetadata();
Element fileStagingElem = getFileStaging(root);
// Check if there is file staging info specified.
if (fileStagingElem != null) {
FileStagingInfo fileStagingInfo = new FileStagingInfo(getDir(
fileStagingElem, metadata), isForceStage(fileStagingElem,
metadata));
// Iterate through list of metadata keys which have list of files as
// their values which should be staged.
for (String metKey : getStageFilesMetKeys(fileStagingElem, metadata)) {
List<String> files = metadata.getAllMetadata(metKey);
fileStagingInfo.addFilePaths(files);
// Generate paths which the files will be staged to.
List<String> newPaths = Lists.newArrayList();
for (String file : files) {
File fileHandle = new File(file);
if (fileStagingInfo.isForceStaging() || !fileHandle.exists()) {
newPaths.add(fileStagingInfo.getStagingDir() + File.separator
+ fileHandle.getName());
} else {
newPaths.add(file);
}
}
// Update metadata key with what will be the new paths of the files.
pgeMetadata.replaceMetadata(metKey, newPaths);
}
// Add staging info to PgeConfig.
pgeConfig.setFileStagingInfo(fileStagingInfo);
}
}
}