/*******************************************************************************
* Copyright (c) 2011 GigaSpaces Technologies Ltd. All rights reserved
*
* 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.cloudifysource.dsl.internal;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.cloudifysource.domain.Application;
import org.cloudifysource.domain.Service;
import org.cloudifysource.domain.cloud.Cloud;
import org.cloudifysource.dsl.internal.packaging.PackagingException;
import org.cloudifysource.dsl.internal.packaging.ZipUtils;
import org.codehaus.groovy.control.CompilationFailedException;
/****************
* Utility methods for commonly used DSL parsers.
*
* @author barakme
* @since 2.0
*
*/
public final class ServiceReader {
private static final int BUFFER_SIZE = 1024;
/*******
* name of property injected into DSL context containing the path to the DSL file.
*/
public static final String DSL_FILE_PATH_PROPERTY_NAME = "dslFilePath";
/*****
* Private Constructor to prevent instantiation.
*
*/
private ServiceReader() {
}
/**
*
* @param projectZipFile
* .
* @return The project file.
* @throws IOException .
*/
public static File extractProjectFile(final File projectZipFile)
throws IOException {
return extractProjectFileToDir(projectZipFile, "gs_usm_", null);
}
/**
*
* @param zipFile
* The file to unzip.
* @param projectDirName
* The name of the project directory.
* @param parentDir
* The directory in which the projectDir is to be created,
* or null if the default temporary-file directory is to be used.
* @return .
* @throws IOException if failed to create or delete the extract to directory
* or if failed to unzip the zipFile.
*/
public static File extractProjectFileToDir(final File zipFile, final String projectDirName,
final File parentDir) throws IOException {
File destFolder = null;
destFolder = File.createTempFile(projectDirName, "", parentDir);
FileUtils.forceDelete(destFolder);
FileUtils.forceMkdir(destFolder);
ZipUtils.unzip(zipFile, destFolder);
return destFolder;
}
/**
*
* @param serviceDirOrFile
* .
* @param maxJarSizePermitted
* .
* @throws PackagingException .
*/
public static void validateFolderSize(final File serviceDirOrFile, final long maxJarSizePermitted)
throws PackagingException {
File folder = serviceDirOrFile;
if (folder.isFile()) {
folder = folder.getParentFile();
}
final long folderSize = FileUtils.sizeOfDirectory(folder);
if (folderSize == 0) {
throw new PackagingException("folder " + folder.getAbsolutePath() + " is empty");
}
final long maxJarSize = maxJarSizePermitted;
if (folderSize > maxJarSize || folderSize == 0) {
throw new PackagingException("folder " + folder.getAbsolutePath() + "size is: "
+ FileUtils.byteCountToDisplaySize(folderSize) + ", it must be smaller than: "
+ FileUtils.byteCountToDisplaySize(maxJarSize));
}
}
/**
*
* @param dslFile
* dslFile
* @return the service
* @throws PackagingException
* PackagingException
*/
public static Service getServiceFromFile(final File dslFile)
throws PackagingException {
try {
return ServiceReader.getServiceFromFile(dslFile,
// new File(System.getProperty("user.dir"))).getService();
dslFile.getParentFile()).getService();
} catch (final CompilationFailedException e) {
throw new PackagingException("The file " + dslFile + " could not be compiled: " + e.getMessage(), e);
} catch (final Exception e) {
throw new PackagingException("Failed to read service from file " + dslFile + ": " + e.getMessage(), e);
}
}
/****************
* Reads a service object from a groovy DSL file placed in the given directory. The file name must be of the format
* *-service.groovy, and there must be exactly one file in the directory with a name that matches this format.
*
* @param dir
* the directory to scan for the DSL file.
* @return the service .
* @throws DSLException .
*/
public static DSLServiceCompilationResult getServiceFromDirectory(final File dir)
throws DSLException {
return ServiceReader.getServiceFromFile(null, dir, null, true, null /* overrides file */);
}
/****************
* Reads a service object from a groovy DSL file placed in the given directory. The file name must be of the format
* *-service.groovy, and there must be exactly one file in the directory with a name that matches this format.
*
* @param dir
* the directory to scan for the DSL file.
* @param overridesFile .
* @return the service .
* @throws DSLException .
*/
public static DSLServiceCompilationResult getServiceFromDirectory(final File dir, final File overridesFile)
throws DSLException {
return ServiceReader.getServiceFromFile(null, dir, null, true, overridesFile);
}
/**
* Reads a service object from the given groovy DSL file (dslFile) or placed in the given directory. The file name
* must be of the format *-service.groovy, and there must be exactly one file in the directory with a name that
* matches this format.
*
* @param dslFile
* the groovy dsl file (*-service.groovy)
* @param workDir
* the directory to scan for the DSL file.
* @return the service
* @throws DSLException
* DSLException
*/
public static DSLServiceCompilationResult getServiceFromFile(
final File dslFile, final File workDir) throws DSLException {
return ServiceReader.getServiceFromFile(dslFile, workDir,
null, true, null /* overrides file */);
}
/**
* Reads a service object from a groovy DSL file placed in the given directory. The file name must be of the format
* *-service.groovy, and there must be exactly one file in the directory with a name that matches this format.
*
* @param workDir
* the directory to scan for the DSL file.
* @param applicationProperties
* application's properties to override service's properties.
* @return the service.
* @throws DSLException
* DSLException
*/
public static DSLServiceCompilationResult getApplicationServiceFromDirectory(
final File workDir, final Map<String, Object> applicationProperties)
throws DSLException {
final DSLReader dslReader = new DSLReader();
dslReader.setRunningInGSC(true);
dslReader.setWorkDir(workDir);
dslReader.setDslFileNameSuffix(DSLUtils.SERVICE_DSL_FILE_NAME_SUFFIX);
dslReader.setOverridesFile(null);
dslReader.setApplicationProperties(applicationProperties);
final Service service = dslReader.readDslEntity(Service.class);
return new DSLServiceCompilationResult(service, dslReader.getContext(), null);
}
/**
*
* @param dslFile
* .
* @param workDir
* .
* @param admin
* .
* @param clusterInfo
* .
* @param propertiesFileName
* .
* @param isRunningInGSC
* .
* @param overridesFile
* .
* @return DSLServiceCompilationResult.
* @throws DSLException .
*/
public static DSLServiceCompilationResult getServiceFromFile(final File dslFile, final File workDir,
final String propertiesFileName, final boolean isRunningInGSC, final File overridesFile)
throws DSLException {
final DSLReader dslReader = new DSLReader();
dslReader.setPropertiesFileName(propertiesFileName);
dslReader.setRunningInGSC(isRunningInGSC);
dslReader.setDslFile(dslFile);
dslReader.setWorkDir(workDir);
dslReader.setDslFileNameSuffix(DSLUtils.SERVICE_DSL_FILE_NAME_SUFFIX);
dslReader.setOverridesFile(overridesFile);
final Service service = dslReader.readDslEntity(Service.class);
return new DSLServiceCompilationResult(
service,
dslReader.getContext(),
null /* cloud */,
dslFile,
dslReader.getPropertiesFile(),
dslReader.getOverridesFile());
}
/**
*
* @param inputFile
* .
* @return The service.
* @throws IOException .
* @throws DSLException .
*/
public static Service readServiceFromZip(final File inputFile)
throws IOException, DSLException {
final File projectFolder = extractProjectFile(inputFile);
try {
return ServiceReader.getServiceFromDirectory(projectFolder).getService();
} finally {
FileUtils.forceDelete(projectFolder);
}
}
/**
*
* @param dslFileOrDir
* .
* @return The service.
* @throws PackagingException .
* @throws DSLException .
*/
public static Service readService(final File dslFileOrDir)
throws PackagingException, DSLException {
if (dslFileOrDir.isFile()) {
return getServiceFromFile(dslFileOrDir);
} else if (dslFileOrDir.isDirectory()) {
return getServiceFromFile(null, dslFileOrDir, null, true, null).getService();
} else {
throw new IllegalArgumentException(dslFileOrDir + " is neither a file nor a directory");
}
}
/**
*
* @param dslFile
* .
* @param workDir
* .
* @param admin
* .
* @param clusterInfo
* .
* @param propertiesFileName
* .
* @param isRunningInGSC
* .
* @param overridesFile
* .
* @return the read service.
* @throws DSLException .
*/
public static Service readService(final File dslFile, final File workDir,
final String propertiesFileName, final boolean isRunningInGSC, final File overridesFile) throws DSLException {
return getServiceFromFile(dslFile, workDir, propertiesFileName
, isRunningInGSC, overridesFile).getService();
}
/**
*
* @param inputFile
* The application file.
* @return The application.
* @throws IOException
* IOException.
* @throws DSLException
* DSLException.
*/
public static DSLApplicationCompilationResult getApplicationFromFile(
final File inputFile) throws IOException, DSLException {
return getApplicationFromFile(inputFile, null);
}
/**
*
* @param inputFile
* The application file.
* @param overridesFile
* application overrides file.
* @return The application.
* @throws IOException
* IOException.
* @throws DSLException
* DSLException.
*/
public static DSLApplicationCompilationResult getApplicationFromFile(
final File inputFile, final File overridesFile)
throws IOException, DSLException {
File actualApplicationDslFile = inputFile;
if (inputFile.isFile()) {
if (inputFile.getName().endsWith(".zip") || inputFile.getName().endsWith(".jar")) {
// Unzip application zip file to temp folder
final File tempFolder = ServiceReader.unzipFile(inputFile, "application");
actualApplicationDslFile =
DSLReader.findDefaultDSLFile(DSLUtils.APPLICATION_DSL_FILE_NAME_SUFFIX, tempFolder);
}
} else {
actualApplicationDslFile =
DSLReader.findDefaultDSLFile(DSLUtils.APPLICATION_DSL_FILE_NAME_SUFFIX, inputFile);
}
final DSLReader dslReader = new DSLReader();
File workDir = actualApplicationDslFile.getParentFile();
dslReader.setDslFile(actualApplicationDslFile);
dslReader.setWorkDir(workDir);
dslReader.setCreateServiceContext(false);
dslReader.addProperty(DSLUtils.APPLICATION_DIR, workDir.getAbsolutePath());
dslReader.setOverridesFile(overridesFile);
final Application application = dslReader.readDslEntity(Application.class);
return new DSLApplicationCompilationResult(application, actualApplicationDslFile.getParentFile(),
actualApplicationDslFile, dslReader.getPropertiesFile(), dslReader.getOverridesFile());
}
/**
*
* @param inputFile
* to unzip.
* @param directorySuffix
* the suffix of the target directory.
* @return The unzipped file.
* @throws IOException .
*/
public static File unzipFile(final File inputFile, final String directorySuffix)
throws IOException {
final File baseDir = ServiceReader.createTempDir(directorySuffix);
ZipUtils.unzip(inputFile, baseDir);
return baseDir;
}
/**
*
* @param in
* .
* @param out
* .
* @throws IOException .
*/
public static void copyInputStream(final InputStream in, final OutputStream out)
throws IOException {
final byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = in.read(buffer)) >= 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
}
/**
*
* @param suffix
* suffix for temp file name.
* @return A temporary directory.
* @throws IOException .
*/
public static File createTempDir(final String suffix)
throws IOException {
final File tempFile = File.createTempFile("GS_tmp_dir", "." + suffix);
final String path = tempFile.getAbsolutePath();
tempFile.delete();
tempFile.mkdirs();
return new File(path);
}
private static Cloud readCloud(final String dslContents, final File dslFile)
throws DSLException {
final DSLReader dslReader = new DSLReader();
dslReader.setCreateServiceContext(false);
dslReader.setDslContents(dslContents);
dslReader.setDslFile(dslFile);
if (dslFile != null) {
dslReader.setWorkDir(dslFile.getParentFile());
}
return dslReader.readDslEntity(Cloud.class);
}
/**
*
* @param dslFile
* .
* @return The cloud.
* @throws IOException .
* @throws DSLException .
*/
public static Cloud readCloud(final File dslFile)
throws IOException,
DSLException {
if (!dslFile.exists()) {
throw new FileNotFoundException(dslFile.getAbsolutePath());
}
final String dslContents = FileUtils.readFileToString(dslFile);
final Cloud cloud = readCloud(dslContents, dslFile);
return cloud;
}
/**
*
* @param cloudConfigDirectory
* .
* @return The cloud.
* @throws DSLException .
*/
public static Cloud readCloudFromDirectory(final File cloudConfigDirectory)
throws DSLException {
return readCloudFromDirectory(cloudConfigDirectory.getAbsolutePath(), null);
}
/**
*
* @param cloudConfigDirectory
* .
* @return The cloud.
* @throws DSLException .
*/
public static Cloud readCloudFromDirectory(final String cloudConfigDirectory)
throws DSLException {
return readCloudFromDirectory(cloudConfigDirectory, null);
}
/**
*
* @param cloudConfigDirectory
* .
* @param overridesScript
* - a String containing the overrides properties. (not a file path)
* @return The cloud.
* @throws DSLException .
*/
public static Cloud readCloudFromDirectory(final String cloudConfigDirectory, final String overridesScript)
throws DSLException {
final DSLReader reader = new DSLReader();
reader.setDslFileNameSuffix(DSLUtils.CLOUD_DSL_FILE_NAME_SUFFIX);
reader.setWorkDir(new File(cloudConfigDirectory));
reader.setCreateServiceContext(false);
reader.setOverridesScript(overridesScript);
final Cloud cloud = reader.readDslEntity(Cloud.class);
return cloud;
}
}