/*
* RED5 Open Source Flash Server - http://code.google.com/p/red5/
*
* Copyright 2006-2012 by respective authors (see below). 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.red5.server;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.red5.io.object.Deserializer;
import org.red5.io.object.Input;
import org.red5.io.object.Output;
import org.red5.io.object.Serializer;
import org.red5.server.api.IAttributeStore;
import org.red5.server.api.persistence.IPersistable;
import org.red5.server.api.persistence.IPersistenceStore;
/**
* Persistable attributes store. Server-side SharedObjects feature based on this class.
*/
public class PersistableAttributeStore extends AttributeStore implements IPersistable {
/**
* Persistence flag
*/
protected boolean persistent = true;
/**
* Attribute store name
*/
protected String name;
/**
* Attribute store type
*/
protected String type;
/**
* Attribute store path (on local hard drive)
*/
protected String path;
/**
* Last modified Timestamp
*/
protected long lastModified = -1;
/**
* Store object that deals with save/load routines
*/
protected IPersistenceStore store;
/**
* Creates persistable attribute store
*
* @param type Attribute store type
* @param name Attribute store name
* @param path Attribute store path
* @param persistent Whether store is persistent or not
*/
public PersistableAttributeStore(String type, String name, String path, boolean persistent) {
super();
this.type = type;
this.name = name;
this.path = path;
this.persistent = persistent;
}
/**
* Set last modified flag to current system time
*/
protected void modified() {
lastModified = System.currentTimeMillis();
if (store != null) {
store.save(this);
}
}
/**
* Check whether object is persistent or not
*
* @return true if object is persistent, false otherwise
*/
public boolean isPersistent() {
return persistent;
}
/**
* Set for persistence
* @param persistent Persistence flag value
*/
public void setPersistent(boolean persistent) {
this.persistent = persistent;
}
/**
* Returns last modification time as timestamp
* @return Timestamp of last attribute modification
*/
public long getLastModified() {
return lastModified;
}
/**
* Return store name
* @return Store name
*/
public String getName() {
return name;
}
/**
* Setter for name
* @param name Name
*/
public void setName(String name) {
this.name = name;
}
/**
* Ruturn scope path
* @return Path
*/
public String getPath() {
return path;
}
/**
* Setter for scope path
* @param path Path
*/
public void setPath(String path) {
this.path = path;
}
/**
* Return scope type
* @return Scope type
*/
public String getType() {
return type;
}
/**
* Serializes byte buffer output, storing them to attributes
*
* @param output Output object
* @throws IOException if error
*/
public void serialize(Output output) throws IOException {
Serializer serializer = new Serializer();
Map<String, Object> persistentAttributes = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : getAttributes().entrySet()) {
final String name = entry.getKey();
if (name.startsWith(IPersistable.TRANSIENT_PREFIX)) {
continue;
}
persistentAttributes.put(name, entry.getValue());
}
serializer.serialize(output, persistentAttributes);
}
/**
* Deserializes data from input to attributes
*
* @param input Input object
* @throws IOException I/O exception
*/
public void deserialize(Input input) throws IOException {
Deserializer deserializer = new Deserializer();
setAttributes(deserializer.<Map<String, Object>> deserialize(input, Map.class));
}
/**
* Load data from another persistent store
*
* @param store Persistent store
*/
public void setStore(IPersistenceStore store) {
if (this.store != null) {
this.store.notifyClose();
}
this.store = store;
if (store != null) {
store.load(this);
}
}
/**
* Return persistent store
* @return Persistence store
*/
public IPersistenceStore getStore() {
return store;
}
/** {@inheritDoc} */
@Override
public Object getAttribute(String name, Object defaultValue) {
if (name == null) {
return null;
}
if (defaultValue == null) {
throw new NullPointerException("the default value may not be null");
}
Object result = attributes.putIfAbsent(name, defaultValue);
if (result == null) {
// The default value has been set
modified();
result = defaultValue;
}
return result;
}
/**
* Set attribute by name and return success as boolean
*
* @param name Attribute name
* @param value Attribute value
* @return true if attribute was set, false otherwise
*/
@Override
public boolean setAttribute(String name, Object value) {
boolean result = super.setAttribute(name, value);
if (result && name != null && !name.startsWith(IPersistable.TRANSIENT_PREFIX)) {
modified();
}
return result;
}
/**
* Set attributes from Map
*
* @param values Attributes as Map
*/
@Override
public void setAttributes(Map<String, Object> values) {
super.setAttributes(values);
modified();
}
/**
* Bulk set of attributes from another attributes store
*
* @param values Attributes store
*/
@Override
public void setAttributes(IAttributeStore values) {
super.setAttributes(values);
modified();
}
/**
* Removes attribute
* @param name Attribute name
* @return true if attribute was removed, false otherwise
*/
@Override
public boolean removeAttribute(String name) {
boolean result = super.removeAttribute(name);
if (result && name != null && !name.startsWith(IPersistable.TRANSIENT_PREFIX)) {
modified();
}
return result;
}
/**
* Removes all attributes and sets modified flag
*/
@Override
public void removeAttributes() {
super.removeAttributes();
modified();
}
}