001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.type.scope;
020
021import java.io.Serializable;
022
023import lucee.runtime.PageContext;
024import lucee.runtime.config.ConfigServer;
025import lucee.runtime.dump.DumpData;
026import lucee.runtime.dump.DumpProperties;
027import lucee.runtime.exp.ExpressionException;
028import lucee.runtime.exp.PageException;
029import lucee.runtime.op.Caster;
030import lucee.runtime.type.Collection;
031import lucee.runtime.type.Sizeable;
032import lucee.runtime.type.Struct;
033
034public final class ClusterWrap extends ScopeSupport implements Cluster,Sizeable {
035
036        private static final long serialVersionUID = -4952656252539755770L;
037        
038        private ClusterRemote core;
039        private int offset;
040        private ConfigServer configServer;
041
042        public ClusterWrap(ConfigServer cs,ClusterRemote core) {
043                this(cs,core,false);
044        }
045        
046        private ClusterWrap(ConfigServer configServer,ClusterRemote core,boolean duplicate) {
047                super(true, "cluster", Struct.TYPE_SYNC);
048                this.configServer=configServer;
049                if(duplicate) this.core=core.duplicate();
050                else this.core=core;
051                this.core.init(configServer,this);
052        }
053        
054        @Override
055        public void init(ConfigServer configServer) {
056                // for the custer wrap this method is not invoked, but it is part of the interface
057        }
058
059        @Override
060        public Object get(Key key) throws PageException {
061                return ((ClusterEntry)super.get(key)).getValue();
062        }
063
064        @Override
065        public Object get(Key key, Object defaultValue) {
066                Object res = super.get(key,defaultValue);
067                if(res instanceof ClusterEntry) return  ((ClusterEntry)res).getValue();
068                return res;
069        }
070        
071        @Override
072        public Object remove(Key key) throws PageException {
073                core.addEntry(new ClusterEntryImpl(key,null,offset));
074                return ((ClusterEntry)super.remove (key)).getValue();
075                
076        }
077
078        public Object removeEL(Key key) {
079                core.addEntry(new ClusterEntryImpl(key,null,offset));
080                ClusterEntry entry = (ClusterEntry) super.removeEL (key);
081                if(entry!=null) return entry.getValue();
082                return null;
083        }
084
085        @Override
086        public Object setEL(Key key, Object value) {
087                if(core.checkValue(value)) {
088                        ClusterEntry entry;
089                        core.addEntry(entry=new ClusterEntryImpl(key,(Serializable)value,offset));
090                        super.setEL (key, entry);
091                }
092                return value;
093        }
094
095        public void setEntry(ClusterEntry newEntry) {
096                ClusterEntry existingEntry=(ClusterEntry)super.get(newEntry.getKey(),null);
097                // add
098                if(existingEntry==null || existingEntry.getTime()<newEntry.getTime()) {
099                        if(newEntry.getValue()==null)removeEL (newEntry.getKey());
100                        else {
101                                core.addEntry(newEntry);
102                                super.setEL (newEntry.getKey(), newEntry);
103                        }
104                }
105        }
106        
107        @Override
108        public Object set(Key key, Object value) throws PageException {
109                if(!core.checkValue(value))
110                        throw new ExpressionException("object from type ["+Caster.toTypeName(value)+"] are not allowed in cluster scope" );
111                ClusterEntry entry;
112                core.addEntry(entry=new ClusterEntryImpl(key,(Serializable)value,offset));
113                super.setEL (key, entry);
114                return value;
115        }
116        
117        @Override
118        public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) {
119                return super.toDumpData(pageContext, maxlevel,dp);
120        }
121
122        @Override
123        public int getType() {
124                return SCOPE_CLUSTER;
125        } 
126
127        @Override
128        public String getTypeAsString() {
129                return "cluster";
130        }
131        
132        @Override
133        public Collection duplicate(boolean deepCopy) {
134                return new ClusterWrap(configServer,core,true);
135        }
136
137        @Override
138        public void broadcast() {
139                core.broadcastEntries();
140        }
141
142        @Override
143        public long sizeOf() {
144                return 0;
145        }
146}