001 /*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005 *
006 * The contents of this file are subject to the terms of either the GNU
007 * General Public License Version 2 only ("GPL") or the Common
008 * Development and Distribution License("CDDL") (collectively, the
009 * "License"). You may not use this file except in compliance with the
010 * License. You can obtain a copy of the License at
011 * http://www.netbeans.org/cddl-gplv2.html
012 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013 * specific language governing permissions and limitations under the
014 * License. When distributing the software, include this License Header
015 * Notice in each file and include the License file at
016 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017 * particular file as subject to the "Classpath" exception as provided
018 * by Sun in the GPL Version 2 section of the License file that
019 * accompanied this code. If applicable, add the following below the
020 * License Header, with the fields enclosed by brackets [] replaced by
021 * your own identifying information:
022 * "Portions Copyrighted [year] [name of copyright owner]"
023 *
024 * If you wish your version of this file to be governed by only the CDDL
025 * or only the GPL Version 2, indicate your decision by adding
026 * "[Contributor] elects to include this software in this distribution
027 * under the [CDDL or GPL Version 2] license." If you do not indicate a
028 * single choice of license, a recipient has the option to distribute
029 * your version of this file under either the CDDL, the GPL Version 2 or
030 * to extend the choice of license to its licensees as provided above.
031 * However, if you add GPL Version 2 code and therefore, elected the GPL
032 * Version 2 license, then the option applies only if the new code is
033 * made subject to such option by the copyright holder.
034 *
035 * Contributor(s):
036 *
037 * Portions Copyrighted 2007 Sun Microsystems, Inc.
038 */
039
040 package org.netbeans.modules.j2ee.deployment.impl.bridge;
041
042 import java.util.HashMap;
043 import java.util.HashSet;
044 import java.util.Iterator;
045 import java.util.Map;
046 import java.util.Set;
047 import java.util.logging.Level;
048 import java.util.logging.Logger;
049 import org.netbeans.modules.j2ee.deployment.impl.Server;
050 import org.netbeans.modules.j2ee.deployment.impl.ServerRegistry;
051 import org.openide.util.Lookup.Template;
052 import org.openide.util.WeakListeners;
053 import org.openide.util.lookup.AbstractLookup;
054 import org.openide.util.lookup.InstanceContent;
055
056 /**
057 *
058 * @author Petr Hejl
059 */
060 public abstract class AbstractServerLookup<T> extends AbstractLookup
061 implements ServerRegistry.PluginListener {
062
063 private static final Logger LOGGER = Logger
064 .getLogger(AbstractServerLookup.class.getName());
065
066 private final InstanceContent content;
067
068 /** <i>GuardedBy("this")</i> */
069 private final Map<Server, T> serversMap = new HashMap<Server, T>();
070
071 /** <i>GuardedBy("this")</i> */
072 private boolean initialized;
073
074 protected AbstractServerLookup(InstanceContent content) {
075 super (content);
076 this .content = content;
077 }
078
079 public final void serverAdded(Server server) {
080 stateChanged();
081 }
082
083 public final void serverRemoved(Server server) {
084 stateChanged();
085 }
086
087 /**
088 * May return null.
089 * @param server
090 * @return
091 */
092 protected abstract T createBridgingInstance(Server server);
093
094 /**
095 *
096 * @param instance can be null
097 */
098 protected abstract void afterAddition(T instance);
099
100 /**
101 *
102 * @param instance can be null
103 */
104 protected abstract void beforeFinish(T instance);
105
106 /**
107 *
108 * @param server
109 * @param instance can be null
110 */
111 protected abstract void finishBridgingInstance(Server server,
112 T instance);
113
114 @Override
115 protected final void beforeLookup(Template<?> template) {
116 init();
117 super .beforeLookup(template);
118 }
119
120 private void init() {
121 synchronized (this ) {
122 if (!initialized) {
123 final ServerRegistry registry = ServerRegistry
124 .getInstance();
125 registry.addPluginListener(WeakListeners.create(
126 ServerRegistry.PluginListener.class, this ,
127 registry));
128
129 LOGGER.log(Level.FINE, "Registered bridging listener"); // NOI18N
130
131 initialized = true;
132 } else {
133 return;
134 }
135 }
136
137 stateChanged();
138 }
139
140 private void stateChanged() {
141 LOGGER.log(Level.FINE, "Updating the lookup content"); // NOI18N
142 Set servers = new HashSet(ServerRegistry.getInstance()
143 .getServers());
144 synchronized (this ) {
145 for (Iterator<Map.Entry<Server, T>> it = serversMap
146 .entrySet().iterator(); it.hasNext();) {
147 Map.Entry<Server, T> entry = it.next();
148 Server server = entry.getKey();
149 if (!servers.contains(server)) {
150 beforeFinish(entry.getValue());
151 content.remove(serversMap.get(server));
152 it.remove();
153
154 finishBridgingInstance(server, entry.getValue());
155 } else {
156 servers.remove(server);
157 }
158 }
159
160 for (Iterator it = servers.iterator(); it.hasNext();) {
161 Server server = (Server) it.next();
162 T instance = createBridgingInstance(server);
163 if (instance != null) {
164 content.add(instance);
165 serversMap.put(server, instance);
166 afterAddition(instance);
167 }
168 }
169 }
170 LOGGER.log(Level.FINE, "Lookup content updated"); // NOI18N
171 }
172 }
|