001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.catalina.ha.context;
018:
019: import org.apache.catalina.core.StandardContext;
020: import org.apache.catalina.LifecycleException;
021: import org.apache.catalina.ha.CatalinaCluster;
022: import org.apache.catalina.tribes.tipis.ReplicatedMap;
023: import org.apache.catalina.tribes.Channel;
024: import org.apache.catalina.Loader;
025: import org.apache.catalina.core.ApplicationContext;
026: import org.apache.catalina.Globals;
027: import javax.servlet.ServletContext;
028: import java.util.AbstractMap;
029: import org.apache.catalina.tribes.tipis.AbstractReplicatedMap;
030: import java.util.ArrayList;
031: import java.util.Iterator;
032: import javax.servlet.ServletContextAttributeListener;
033: import javax.servlet.ServletContextAttributeEvent;
034: import org.apache.catalina.LifecycleEvent;
035: import org.apache.catalina.LifecycleListener;
036: import java.util.Enumeration;
037: import java.util.concurrent.ConcurrentHashMap;
038: import org.apache.catalina.util.Enumerator;
039:
040: /**
041: * @author Filip Hanik
042: * @version 1.0
043: */
044: public class ReplicatedContext extends StandardContext implements
045: LifecycleListener {
046: private int mapSendOptions = Channel.SEND_OPTIONS_DEFAULT;
047: public static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
048: .getLog(ReplicatedContext.class);
049: protected boolean startComplete = false;
050: protected static long DEFAULT_REPL_TIMEOUT = 15000;//15 seconds
051:
052: public void lifecycleEvent(LifecycleEvent event) {
053: if (event.getType() == AFTER_START_EVENT)
054: startComplete = true;
055: }
056:
057: public synchronized void start() throws LifecycleException {
058: if (this .started)
059: return;
060: super .addLifecycleListener(this );
061: try {
062: CatalinaCluster catclust = (CatalinaCluster) this
063: .getCluster();
064: if (this .context == null)
065: this .context = new ReplApplContext(this .getBasePath(),
066: this );
067: if (catclust != null) {
068: ReplicatedMap map = new ReplicatedMap(this , catclust
069: .getChannel(), DEFAULT_REPL_TIMEOUT, getName(),
070: getClassLoaders());
071: map.setChannelSendOptions(mapSendOptions);
072: ((ReplApplContext) this .context).setAttributeMap(map);
073: if (getAltDDName() != null)
074: context.setAttribute(Globals.ALT_DD_ATTR,
075: getAltDDName());
076: }
077: super .start();
078: } catch (Exception x) {
079: log.error("Unable to start ReplicatedContext", x);
080: throw new LifecycleException(
081: "Failed to start ReplicatedContext", x);
082: }
083: }
084:
085: public synchronized void stop() throws LifecycleException {
086: ReplicatedMap map = (ReplicatedMap) ((ReplApplContext) this .context)
087: .getAttributeMap();
088: if (map != null) {
089: map.breakdown();
090: }
091: if (!this .started)
092: return;
093: try {
094: super .lifecycle.removeLifecycleListener(this );
095: } catch (Exception x) {
096: log.error("Unable to stop ReplicatedContext", x);
097: throw new LifecycleException(
098: "Failed to stop ReplicatedContext", x);
099: } finally {
100: this .startComplete = false;
101: super .stop();
102: }
103:
104: }
105:
106: public void setMapSendOptions(int mapSendOptions) {
107: this .mapSendOptions = mapSendOptions;
108: }
109:
110: public int getMapSendOptions() {
111: return mapSendOptions;
112: }
113:
114: public ClassLoader[] getClassLoaders() {
115: Loader loader = null;
116: ClassLoader classLoader = null;
117: loader = this .getLoader();
118: if (loader != null)
119: classLoader = loader.getClassLoader();
120: if (classLoader == null)
121: classLoader = Thread.currentThread()
122: .getContextClassLoader();
123: if (classLoader == Thread.currentThread()
124: .getContextClassLoader()) {
125: return new ClassLoader[] { classLoader };
126: } else {
127: return new ClassLoader[] { classLoader,
128: Thread.currentThread().getContextClassLoader() };
129: }
130: }
131:
132: public ServletContext getServletContext() {
133: if (context == null) {
134: context = new ReplApplContext(getBasePath(), this );
135: if (getAltDDName() != null)
136: context.setAttribute(Globals.ALT_DD_ATTR,
137: getAltDDName());
138: }
139:
140: return ((ReplApplContext) context).getFacade();
141:
142: }
143:
144: protected static class ReplApplContext extends ApplicationContext {
145: protected ConcurrentHashMap tomcatAttributes = new ConcurrentHashMap();
146:
147: public ReplApplContext(String basePath,
148: ReplicatedContext context) {
149: super (basePath, context);
150: }
151:
152: protected ReplicatedContext getParent() {
153: return (ReplicatedContext) getContext();
154: }
155:
156: protected ServletContext getFacade() {
157: return super .getFacade();
158: }
159:
160: public AbstractMap getAttributeMap() {
161: return (AbstractMap) this .attributes;
162: }
163:
164: public void setAttributeMap(AbstractMap map) {
165: this .attributes = map;
166: }
167:
168: public void removeAttribute(String name) {
169: tomcatAttributes.remove(name);
170: //do nothing
171: super .removeAttribute(name);
172: }
173:
174: public void setAttribute(String name, Object value) {
175: if ((!getParent().startComplete)
176: || "org.apache.jasper.runtime.JspApplicationContextImpl"
177: .equals(name)) {
178: tomcatAttributes.put(name, value);
179: } else
180: super .setAttribute(name, value);
181: }
182:
183: public Object getAttribute(String name) {
184: if (tomcatAttributes.containsKey(name))
185: return tomcatAttributes.get(name);
186: else
187: return super .getAttribute(name);
188: }
189:
190: public Enumeration getAttributeNames() {
191: return new MultiEnumeration(new Enumeration[] {
192: super .getAttributeNames(),
193: new Enumerator(tomcatAttributes.keySet(), true) });
194: }
195:
196: }
197:
198: protected static class MultiEnumeration implements Enumeration {
199: Enumeration[] e = null;
200:
201: public MultiEnumeration(Enumeration[] lists) {
202: e = lists;
203: }
204:
205: public boolean hasMoreElements() {
206: for (int i = 0; i < e.length; i++) {
207: if (e[i].hasMoreElements())
208: return true;
209: }
210: return false;
211: }
212:
213: public Object nextElement() {
214: for (int i = 0; i < e.length; i++) {
215: if (e[i].hasMoreElements())
216: return e[i].nextElement();
217: }
218: return null;
219:
220: }
221: }
222:
223: }
|