blob: 358b588808f0816eaa3fbfe3aa5cf7872c6a55a3 [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.sling.settings.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is the basic implementation of the sling settings service.
*/
public class SlingSettingsServiceImpl
implements SlingSettingsService {
/** The logger */
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/** The sling instance id. */
private String slingId;
/** The sling home */
private String slingHome;
/** The sling home url */
private URL slingHomeUrl;
private Set<String> runModes;
/** The name of the data file holding the sling id. */
private static final String DATA_FILE = "sling.id.file";
/**
* Create the service and search the Sling home urls and
* get/create a sling id.
* Setup run modes
* @param context The bundle context
*/
public SlingSettingsServiceImpl(final BundleContext context) {
this.setupSlingHome(context);
this.setupSlingId(context);
this.setupRunModes(context);
}
/**
* Get sling home and sling home url
*/
private void setupSlingHome(final BundleContext context) {
this.slingHome = context.getProperty(SLING_HOME);
final String url = context.getProperty(SLING_HOME_URL);
if ( url != null ) {
try {
this.slingHomeUrl = new URL(url);
} catch (MalformedURLException e) {
logger.error("Sling home url is not a url: {}", url);
}
}
}
/**
* Get / create sling id
*/
private void setupSlingId(final BundleContext context) {
// try to read the id from the id file first
final File idFile = context.getDataFile(DATA_FILE);
if ( idFile == null ) {
// the osgi framework does not support storing something in the file system
throw new RuntimeException("Unable to read from bundle data file.");
}
this.slingId = this.readSlingId(idFile);
// no sling id yet or failure to read file: create an id and store
if (slingId == null) {
slingId = UUID.randomUUID().toString();
this.writeSlingId(idFile, this.slingId);
}
}
/**
* Set up run modes.
*/
private void setupRunModes(final BundleContext context) {
final String prop = context.getProperty(RUN_MODES_PROPERTY);
if (prop == null || prop.trim().length() == 0) {
this.runModes = Collections.emptySet();
} else {
final Set<String> modesSet = new HashSet<String>();
final String[] modes = prop.split(",");
for(int i=0; i < modes.length; i++) {
modesSet.add(modes[i].trim());
}
// make the set unmodifiable and synced
// we propably don't need a synced set as it is read only
this.runModes = Collections.synchronizedSet(Collections.unmodifiableSet(modesSet));
logger.info("Active run modes {}", this.runModes);
}
}
/**
* Read the id from a file.
*/
private String readSlingId(final File idFile) {
if (idFile.exists() && idFile.length() >= 36) {
FileInputStream fin = null;
try {
fin = new FileInputStream(idFile);
final byte[] rawBytes = new byte[36];
if (fin.read(rawBytes) == 36) {
final String rawString = new String(rawBytes, "ISO-8859-1");
// roundtrip to ensure correct format of UUID value
final String id = UUID.fromString(rawString).toString();
logger.debug("Got Sling ID {} from file {}", id, idFile);
return id;
}
} catch (Throwable t) {
logger.error("Failed reading UUID from id file " + idFile
+ ", creating new id", t);
} finally {
if (fin != null) {
try {
fin.close();
} catch (IOException ignore) {
}
}
}
}
return null;
}
/**
* Write the sling id file.
*/
private void writeSlingId(final File idFile, final String id) {
idFile.delete();
idFile.getParentFile().mkdirs();
FileOutputStream fout = null;
try {
fout = new FileOutputStream(idFile);
fout.write(slingId.getBytes("ISO-8859-1"));
fout.flush();
} catch (Throwable t) {
logger.error("Failed writing UUID to id file " + idFile, t);
} finally {
if (fout != null) {
try {
fout.close();
} catch (IOException ignore) {
}
}
}
}
/**
* @see org.apache.sling.settings.SlingSettingsService#getAbsolutePathWithinSlingHome(String)
*/
public String getAbsolutePathWithinSlingHome(final String relativePath) {
return new File(slingHome, relativePath).getAbsolutePath();
}
/**
* @see org.apache.sling.settings.SlingSettingsService#getSlingId()
*/
public String getSlingId() {
return this.slingId;
}
/**
* @see org.apache.sling.settings.SlingSettingsService#getSlingHome()
*/
public URL getSlingHome() {
return this.slingHomeUrl;
}
/**
* @see org.apache.sling.settings.SlingSettingsService#getSlingHomePath()
*/
public String getSlingHomePath() {
return this.slingHome;
}
/**
* @see org.apache.sling.settings.SlingSettingsService#getRunModes()
*/
public Set<String> getRunModes() {
return this.runModes;
}
}