/*
* Copyright 2013 NGDATA nv
* Copyright 2008 Outerthought bvba and Schaubroeck nv
*
* 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.lilyproject.runtime.source;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.jci.monitor.FilesystemAlterationListener;
import org.apache.commons.jci.monitor.FilesystemAlterationMonitor;
import org.lilyproject.runtime.LilyRTException;
import org.lilyproject.runtime.rapi.Mode;
import org.lilyproject.runtime.rapi.ModuleSource;
public abstract class AbstractDirectoryModuleSource implements ModuleSource {
private File dir;
private File resourceDir;
private File overrideResourceDir;
private File springDir;
private File classLoaderConfig;
private File classPathEntry;
private FilesystemAlterationMonitor fam;
/**
*
* @param overrideResourceDir a directory that overrides the files from the normal resourceDir,
* if they are newer. Optional, can be null.
*/
public AbstractDirectoryModuleSource(File dir, File resourceDir, File overrideResourceDir, File springDir,
File classLoaderConfig, File classPathEntry, FilesystemAlterationMonitor fam) throws IOException {
this.dir = dir;
this.resourceDir = resourceDir;
this.overrideResourceDir = overrideResourceDir;
this.springDir = springDir;
this.classLoaderConfig = classLoaderConfig;
this.classPathEntry = classPathEntry;
this.fam = fam;
}
private static final Pattern LEADING_SLASHES_PATTERN = Pattern.compile("^(/)*");
private static final FilenameFilter SPRING_FILE_FILTER = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".xml");
}
};
public List<SpringConfigEntry> getSpringConfigs(Mode mode) {
List<File> springFiles = new ArrayList<File>();
File[] commonFiles = springDir.listFiles(SPRING_FILE_FILTER);
if (commonFiles != null) {
springFiles.addAll(Arrays.asList(commonFiles));
}
File[] modeSpecificFiles = new File(springDir, mode.getName()).listFiles(SPRING_FILE_FILTER);
if (modeSpecificFiles != null) {
springFiles.addAll(Arrays.asList(modeSpecificFiles));
}
List<SpringConfigEntry> result = new ArrayList<SpringConfigEntry>();
for (final File file : springFiles) {
result.add(new SpringConfigEntry() {
public String getLocation() {
return file.getAbsolutePath();
}
public InputStream getStream() throws IOException {
return new FileInputStream(file);
}
});
}
return result;
}
public ModuleSource.Resource getResource(String path) {
// Paths should always be relative (this current code is not 'safe', only convenient in case of accidental start slashes)
path = LEADING_SLASHES_PATTERN.matcher(path).replaceFirst("");
File file = new File(resourceDir, path);
if (!file.exists()) {
return null;
}
FileResource fileResource = new FileResource(file);
if (overrideResourceDir != null) {
File overrideFile = new File(overrideResourceDir, path);
if (overrideFile.exists() && !overrideFile.isDirectory()
&& overrideFile.lastModified() > file.lastModified()) {
fileResource = new FileResource(overrideFile);
}
}
return fileResource;
}
public Resource getClasspathResource(String path) {
File file = new File(classPathEntry, path);
if (!file.exists()) {
return null;
} else {
return new FileResource(file);
}
}
public InputStream getClassLoaderConfig() throws IOException {
if (!classLoaderConfig.exists()) {
return null;
}
return new FileInputStream(classLoaderConfig);
}
public File getClassPathEntry() {
return classPathEntry;
}
public boolean supportsListening() {
return true;
}
public void addResourceListener(String path, FilesystemAlterationListener listener) {
File file = new File(resourceDir, path);
fam.addListener(file, listener);
}
public void removeResourceListener(FilesystemAlterationListener listener) {
fam.removeListener(listener);
}
public void dispose() throws Exception {
// Nothing to dispose
}
private class FileResource implements ModuleSource.Resource {
private File file;
private FileResource(File file) {
this.file = file;
}
public InputStream getInputStream() throws IOException {
return new FileInputStream(file);
}
public Collection<String> getChildren() {
return Arrays.asList(file.list());
}
public boolean isDirectory() {
return file.isDirectory();
}
public URL getURL() {
try {
return file.toURL();
} catch (MalformedURLException e) {
throw new LilyRTException("Error constructing file URL for file " + file.getAbsolutePath(), e);
}
}
public long lastModified() {
return file.lastModified();
}
}
}