Java tutorial
/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed 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.pentaho.di.resource; import java.util.HashMap; import java.util.Map; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; import org.pentaho.di.core.variables.VariableSpace; public class SimpleResourceNaming implements ResourceNamingInterface { private final Map<String, String> namedResources = new HashMap<String, String>(); /** * The fileSystemPrefix would be appropriate for something like: * * zip://somefile.zip! or somefilesystem://export/folder/ */ private String fileSystemPrefix; private boolean useOriginalPathInTargetName; private Map<String, String> directoryMap; private int parameterNr; public SimpleResourceNaming() { super(); directoryMap = new HashMap<String, String>(); parameterNr = 0; } public SimpleResourceNaming(String fileSystemPrefix) { super(); this.fileSystemPrefix = fileSystemPrefix; } public String nameResource(FileObject fileObject, VariableSpace space, boolean includeFileName) throws FileSystemException { if (includeFileName) { return handleDataFile(fileObject.getName().getBaseName(), fileObject.getParent().getURL().toString(), ""); } else { return handleDataFile("", fileObject.getURL().toString(), ""); } } public String nameResource(String prefix, String originalFilePath, String extension, FileNamingType namingType) { switch (namingType) { case DATA_FILE: return handleDataFile(prefix, originalFilePath, extension); case SHELL_SCRIPT: return handleScript(prefix, originalFilePath, extension); case TRANSFORMATION: case JOB: return handleTransformationOrJob(prefix, originalFilePath, extension); default: throw new AssertionError("Unknown file naming type: " + namingType); } } private String handleTransformationOrJob(String prefix, String originalFilePath, String extension) { // // End result could look like any of the following: // // Inputs: // Prefix : Marc Sample Transformation // Original Path: D:\japps\pentaho\kettle\samples // Extension : .ktr // // Output Example 1 (no file system prefix, no path used) // Marc_Sample_Transformation.ktr // Output Example 2 (file system prefix: ${KETTLE_FILE_BASE}!, no path used) // ${KETTLE_FILE_BASE}!Marc_Sample_Transformation.ktr // Output Example 3 (file system prefix: ${KETTLE_FILE_BASE}!, path is used) // ${KETTLE_FILE_BASE}!japps/pentaho/kettle/samples/Marc_Sample_Transformation.ktr // // assert prefix != null; assert extension != null; String lookup = (originalFilePath != null ? originalFilePath : "") + "/" + prefix + "." + extension; String rtn = namedResources.get(lookup); if (rtn == null) { // Never generated a name for this... Generate a new file name String fixedPath = null; if (useOriginalPathInTargetName) { fixedPath = fixPath(originalFilePath); } rtn = (fileSystemPrefix != null ? fileSystemPrefix : "") + (fixedPath != null ? fixedPath + (fixedPath.endsWith("/") ? "" : "/") : "") + fixFileName(prefix, extension); String ext = (extension.charAt(0) == '.' ? extension : "." + extension); String uniqueId = this.getFileNameUniqueIdentifier(rtn, extension); rtn += (uniqueId != null ? "_" + uniqueId : ""); rtn += ext; namedResources.put(lookup, rtn); // Keep track of already generated object names... } return rtn; } private String handleScript(String prefix, String originalFilePath, String extension) { // TODO Auto-generated method stub return null; } /** * We have a data file and we need to create a reference to this (relative/absolute) path name. The cleanest way to do * this is by calculating the absolute filename. Then we put the path to the file in a parameter that we remember. * * FILE_LOCATION_01, FILE_LOCATION_02, etc. * * We keep a unique list of parameters this way. * * @param prefix * the name of the file (foo.csv) * @param originalFilePath * directory in which the file lives (file://path/to/foo/bar/) * @param extension * ignored (null) * @return the new filename including the created parameter... */ private String handleDataFile(String prefix, String originalFilePath, String extension) { // See if we find the path in the directory map that we have... // String parameter = directoryMap.get(originalFilePath); if (parameter == null) { parameter = createNewParameterName(originalFilePath); // Add it to the map... // directoryMap.put(originalFilePath, parameter); } return "${" + parameter + "}/" + prefix; } /** * Create a parameter name from an path TODO: actually use the original path * * @param originalFilePath * @return the new parameter name */ private String createNewParameterName(String originalFilePath) { parameterNr++; return "DATA_PATH_" + parameterNr; } protected String getFileNameUniqueIdentifier(String filename, String extension) { // // This implementation assumes that the file name will be sufficiently // unique. // return null; } protected String fixPath(String originalPathName) { // This should convert all of the following into foo\bar or foo/bar // D:\foo\bar // /foo/bar // \\server\share\foo\bar // String rtn = originalPathName.substring(getPrefixLength(originalPathName)); // Now, rtn has either either foo/bar or foo\bar. So, convert the \ to / // and return. return rtn.replace('\\', '/'); } private int getPrefixLength(String fileName) { if (fileName.charAt(1) == ':') { // Handle D:\foo\bar\ return 3; } else if (fileName.charAt(0) == '\\' && fileName.charAt(1) == '\\') { // Handle \\server\sharename\foo\bar int start = 0; int slashesFound = 0; for (int i = 2; i < fileName.length(); i++) { if (fileName.charAt(i) == '\\') { slashesFound++; } if (slashesFound == 2) { start = i + 1; break; } } return start; } else if (fileName.charAt(0) == '/') { // handle /foo/bar return 1; } return 0; } /** * This method turns a friendly name which could contain all manner of invalid characters for a file name into one * that's more conducive to being a file name. * * @param name * The name to fix up. * @param extension * the requested extension to see if we don't end up with 2 extensions (export of XML to XML) * @return */ protected String fixFileName(String name, String extension) { int length = name.length(); if (name.endsWith("." + extension)) { length -= 1 + extension.length(); } else if (name.endsWith(extension)) { length -= extension.length(); } StringBuffer buff = new StringBuffer(length); char ch; for (int i = 0; i < length; i++) { ch = name.charAt(i); if (ch == ' ') { buff.append(ch); } else { if ((ch <= '/') || (ch >= ':' && ch <= '?') || (ch >= '[' && ch <= '`') || (ch >= '{' && ch <= '~')) { buff.append('_'); } else { buff.append(ch); } } } return buff.toString(); } public String getFileSystemPrefix() { return this.fileSystemPrefix; } public void setFileSystemPrefix(String value) { this.fileSystemPrefix = value; } public boolean getUseOriginalPathInTargetName() { return this.useOriginalPathInTargetName; } public void setUseOriginalPathInTargetName(boolean value) { this.useOriginalPathInTargetName = value; } /** * @return the directoryMap */ public Map<String, String> getDirectoryMap() { return directoryMap; } /** * @param directoryMap * the directoryMap to set */ public void setDirectoryMap(Map<String, String> directoryMap) { this.directoryMap = directoryMap; } }