/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * 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.constellation.configuration; import java.io.File; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.naming.RefAddr; import javax.naming.Reference; import org.apache.sis.util.logging.Logging; /** * Temporary copy of static methods from the WebService class (in module * web-base), in order to retrieve the configuration directory of Constellation. * <p/> * TODO: this implementation should probably been handled by the server * registry, so move it there. * * @author Cédric Briançon (Geomatys) * @author Guilhem Legal (Geomatys) * @version $Id$ */ public final class ConfigDirectory { private static class Config { public Config(Builder builder) { this.home = builder.home; this.data = builder.data; this.dataIntegrated = builder.dataIntegrated; this.dataIndex = builder.dataIndex; this.dataUserUploads = builder.dataUserUploads; this.dataMetadata = builder.dataMetadata; this.dataStyle = builder.dataStyle; this.dataAdmin = builder.dataAdmin; this.dataServices = builder.dataServices; this.testing = builder.testing; } private static class Builder { private Path home; private Path data; private Path dataIntegrated; private Path dataIndex; private Path dataMetadata; private Path dataStyle; private Path dataAdmin; public Path dataServices; private String homeLocation; private String dataLocation; private Path dataUserUploads; private boolean testing; public Builder() { this.homeLocation = Application.getProperty(AppProperty.CSTL_HOME, System.getProperty("user.home") + "/.constellation"); this.dataLocation = Application.getProperty(AppProperty.CSTL_DATA, homeLocation + "/data"); } Config build() { this.home = initFolder(homeLocation); this.data = initFolder(dataLocation); this.dataIntegrated = initDataSubFolder("integrated"); this.dataIndex = initDataSubFolder("index"); this.dataUserUploads = initDataSubFolder("user", "uploads"); this.dataMetadata = initDataSubFolder("metadata"); this.dataStyle = initDataSubFolder("styles"); this.dataAdmin = initDataSubFolder("admin"); this.dataServices = initDataSubFolder("services"); return new Config(this); } private Path initFolder(String absLocation) { return ConfigDirectory.initFolder(Paths.get(absLocation)); } private Path initDataSubFolder(String sub, String... subs) { Path paths = Paths.get(sub, subs); return ConfigDirectory.initFolder(data.resolve(paths)); } public Builder forTest(String filename) { this.homeLocation = filename; this.dataLocation = filename + "/data"; this.testing = true; return this; } } final Path home; final Path data; final Path dataIntegrated; final Path dataIndex; final Path dataUserUploads; final Path dataMetadata; final Path dataStyle; final Path dataAdmin; final boolean testing; final Path dataServices; } /** * The default debugging logger. */ private static final Logger LOGGER = Logging.getLogger("org.constellation.provider.configuration"); private static Config config; /** * Specifies if the process is running on a Glassfish application server. */ private static Boolean runningOnGlassfish = null; private ConfigDirectory() { } static Path initFolder(Path path) { if (Files.notExists(path)) { try { Files.createDirectories(path); LOGGER.info(path.toString() + " created."); } catch (IOException e) { throw new ConfigurationRuntimeException("Could not create: " + path.toString(), e); } } return path; } public static File getUserHomeDirectory() { final String home = System.getProperty("user.home"); return new File(home); } /** * Give a data directory {@link java.io.File} defined on * constellation.properties or by default on .constellation-data from user * home directory * * @return data directory as {@link java.io.File} */ public static File getDataDirectory() { return config.data.toFile(); } public static Path getDataPath() { return config.data; } /** * Give a integrated data directory {@link java.io.File} defined on * constellation.properties or by default on .constellation-data/integrated/ * from user home directory * * @return providers directory as {@link java.io.File} */ public static File getDataIntegratedDirectory() { return config.dataIntegrated.toFile(); } /** * Give a index data directory {@link java.io.File} defined on * constellation.properties or by default on .constellation-data/index/ from * user home directory * * @return providers directory as {@link java.io.File} */ public static File getDataIndexDirectory() { return config.dataIndex.toFile(); } /** * Give a integrated data directory {@link java.io.File} defined on * constellation.properties or by default on .constellation-data/integrated/ * from user home directory for given provider. * * @return providers directory as {@link java.io.File} */ public static File getDataIntegratedDirectory(String providerId) { final File rootFolder = getDataIntegratedDirectory(); final File f = new File(rootFolder, providerId); f.mkdirs(); return f; } /** * remove upload directory for the sessionId {@link java.io.File} by default * on .constellation-data/upload/<sessionId> from user home directory * * @param sessionId */ public static void removeUploadDirectory(String sessionId) { Path sessionFolder = resolveUserUploads(sessionId); deleteDir(sessionFolder); } private static void deleteDir(Path sessionFolder) { if (Files.exists(sessionFolder)) { try { Files.walkFileTree(sessionFolder, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); return FileVisitResult.CONTINUE; } }); } catch (IOException e) { LOGGER.log(Level.WARNING, e.getMessage(), e); } LOGGER.info(sessionFolder.toString() + " deleted."); } } private static Path resolveUserUploads(String sessionId) { return config.dataUserUploads.resolve(sessionId); } private static Path resolveInstanceDirectory(String type, String id) { Path typeService = resolveInstanceServiceDirectoryByType(type); return initFolder(typeService.resolve(id)); } private static Path resolveInstanceServiceDirectoryByType(String type) { Path typeService = config.dataServices.resolve(type); ConfigDirectory.initFolder(typeService); return typeService; } public static Path getUploadDirectory() { return config.dataUserUploads; } /** * Give a upload directory {@link java.io.File} defined on * constellation.properties or by default on * .constellation-data/upload/<sessionId> from user home directory * * @param sessionId * * @return providers directory as {@link java.io.File} */ public static File getUploadDirectory(String sessionId) { return resolveUserUploads(sessionId).toFile(); } /** * Give Metadata directory {@link java.io.File} defined on * constellation.properties or by default on .constellation-data/metadata * from user home directory * * @return metadata directory as {@link java.io.File} */ public static File getMetadataDirectory() { return config.dataMetadata.toFile(); } /** * Give styles directory {@link java.io.File} defined on * constellation.properties or by default on .constellation-data/metadata * from user home directory * * @return styles directory as {@link java.io.File} */ public static File getStyleDirectory() { return config.dataStyle.toFile(); } /** * Give temporary styles directory. * * @return temporary styles directory as {@link java.io.File} */ public static File getStyleTempDirectory() { final File constellationStyleFolder = new File(getDataDirectory(), "style_temp"); if (constellationStyleFolder.mkdirs()) { LOGGER.log(Level.INFO, "style folder created"); } return constellationStyleFolder; } /** * Return a folder named 'admin' at the root in the configuration directory. */ public static File getAdminConfigDirectory() { return config.dataAdmin.toFile(); } /** * Get the value for a property defined in the JNDI context chosen. * * @param propGroup * If you use Glassfish, you have to specify the name of the * resource that owns the property you wish to get. Otherwise you * should specify {@code null} * @param propName * The name of the property to get. * @return The property value defines in the context, or {@code null} if no * property of this name is defined in the resource given in * parameter. * @throws NamingException * if an error occurs while initializing the context, or if an * empty value for propGroup has been passed while using a * Glassfish application server. */ public static String getPropertyValue(final String propGroup, final String propName) throws NamingException { final InitialContext ctx = new InitialContext(); if (runningOnGlassfish == null) { runningOnGlassfish = (System.getProperty("domain.name") != null) ? true : false; } if (runningOnGlassfish) { if (propGroup == null) { throw new NamingException("The coverage property group is not specified."); } final Reference props = (Reference) getContextProperty(propGroup, ctx); if (props == null) { throw new NamingException("The coverage property group specified does not exist."); } final RefAddr permissionAddr = (RefAddr) props.get(propName); if (permissionAddr != null) { return (String) permissionAddr.getContent(); } return null; } else { final javax.naming.Context envContext = (javax.naming.Context) ctx.lookup("java:/comp/env"); return (String) getContextProperty(propName, envContext); } } /** * Returns the context value for the key specified, or {@code null} if not * found in this context. * * @param key * The key to search in the context. * @param context * The context which to consider. */ private static Object getContextProperty(final String key, final javax.naming.Context context) { Object value = null; try { value = context.lookup(key); } catch (NamingException n) { // Do nothing, the key is not found in the context and the value is // still null. } return value; } public static File getConfigDirectory() { return config.home.toFile(); } public static File setupTestEnvironement(String filename) { config = new Config.Builder().forTest("target/" + filename).build(); return config.home.toFile(); } public static void shutdownTestEnvironement(String string) { if (config.testing) { deleteDir(config.home); } } public static void init() { if (config == null) { config = new Config.Builder().build(); } } /** * * @return service URL found in configuration or null * @deprecated use {@link Application#getProperty(AppProperty#CSTL_SERVICE_URL)} instead */ @Deprecated public static String getServiceURL() { return Application.getProperty(AppProperty.CSTL_SERVICE_URL, null); } public static File getInstanceDirectory(String type, String id) { return resolveInstanceDirectory(type, id).toFile(); } public static Collection<? extends File> getInstanceDirectories(String typeService) { Path instancesDirectory = resolveInstanceServiceDirectoryByType(typeService); return Arrays.asList(instancesDirectory.toFile().listFiles()); } public static Path getDataUploads() { return config.dataUserUploads; } }