/******************************************************************************* * Copyright (c) 2002, 2008 Innoopract Informationssysteme GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation ******************************************************************************/ package org.eclipse.rwt.internal.service; import java.util.*; import org.eclipse.rwt.RWT; import org.eclipse.rwt.internal.util.ParamCheck; import org.eclipse.rwt.service.*; /** * This {@link ISettingStore} implementation "persists" all settings * in memory, for as long the application is running. * <p> * <b>This strategy results in an ever increasing memory * consuption over time</b>. We do <b>*not*</b> recommend using this * implementation in a production environment. */ public final class MemorySettingStore implements ISettingStore { private static final Map VALUES = new HashMap(); private static final Set LISTENERS = new HashSet(); private String id; /** * Create a {@link MemorySettingStore} instance and containing the * attributes persisted under the given <code>id</code>. * * @param id a non-null; non-empty; non-whitespace-only String * @throws NullPointerException if id is <code>null</null> * @throws IllegalArgumentException if id is empty or composed * entirely of whitespace */ public MemorySettingStore( final String id ) { ParamCheck.notNullOrEmpty( id, "id" ); this.id = id; } //////////////////////// // ISettingStore methods public String getId() { return id; } public synchronized void loadById( final String id ) { ParamCheck.notNullOrEmpty( id, "id" ); fakeRemoval(); this.id = id; loadAttributes(); } public synchronized String getAttribute( final String name ) { ParamCheck.notNull( name, "name" ); String key = id + name; return ( String )VALUES.get( key ); } public synchronized Enumeration getAttributeNames() { List result = new ArrayList(); Iterator iter = VALUES.keySet().iterator(); int nameBeginIndex = id.length(); while( iter.hasNext() ) { String key = ( String )iter.next(); if( key.startsWith( id ) ) { result.add( key.substring( nameBeginIndex ) ); } } final Iterator resultIterator = result.iterator(); return new Enumeration() { public boolean hasMoreElements() { return resultIterator.hasNext(); } public Object nextElement() { return resultIterator.next(); } }; } public synchronized void removeAttribute( final String name ) { ParamCheck.notNull( name, "name" ); String key = id + name; String oldValue = ( String )VALUES.remove( key ); if( oldValue != null ) { notifyListeners( name, oldValue, null ); } } public synchronized void setAttribute( final String name, final String value ) { ParamCheck.notNull( name, "name" ); if( value == null ) { removeAttribute( name ); } else { ParamCheck.notNull( value, "value" ); String key = id + name; String oldValue = ( String )VALUES.put( key, value ); if( !value.equals( oldValue ) ) { notifyListeners( name, oldValue, value ); } } } public synchronized void addSettingStoreListener( final SettingStoreListener listener ) { ParamCheck.notNull( listener, "listener" ); LISTENERS.add( listener ); } public synchronized void removeSettingStoreListener( final SettingStoreListener listener ) { ParamCheck.notNull( listener, "listener" ); LISTENERS.remove( listener ); } ////////////////// // helping methods private void fakeRemoval() { Enumeration attributes = getAttributeNames(); while( attributes.hasMoreElements() ) { String name = ( String )attributes.nextElement(); String key = id + name; String value = ( String )VALUES.get( key ); notifyListeners( name, value, null ); } } private synchronized void loadAttributes() { Enumeration attributes = getAttributeNames(); while( attributes.hasMoreElements() ) { String name = ( String )attributes.nextElement(); String key = id + name; String value = ( String )VALUES.get( key ); notifyListeners( name, null, value ); } } private void log( final String msg, final Throwable throwable ) { RWT.getRequest().getSession().getServletContext().log( msg, throwable ); } private synchronized void notifyListeners( final String attribute, final String oldValue, final String newValue ) { SettingStoreEvent event = new SettingStoreEvent( this, attribute, oldValue, newValue ); Iterator iter = LISTENERS.iterator(); while( iter.hasNext() ) { SettingStoreListener listener = ( SettingStoreListener )iter.next(); try { listener.settingChanged( event ); } catch( Exception exc ) { String msg = "Exception when invoking listener " + listener.getClass().getName(); log( msg, exc ); } catch( LinkageError le ) { String msg = "Linkage error when invoking listener " + listener.getClass().getName(); log( msg, le ); } } } }