PEPServiceManager.java 6.27 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
/**
 * Copyright (C) 2004-2008 Jive Software. 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.jivesoftware.openfire.pep;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.locks.Lock;

import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.pubsub.CollectionNode;
import org.jivesoftware.openfire.pubsub.Node;
import org.jivesoftware.openfire.pubsub.PubSubEngine;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.util.cache.Cache;
import org.jivesoftware.util.cache.CacheFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;

/**
 * Manages the creation, persistence and removal of {@link PEPService}
 * instances.
 * 
 * @author Guus der Kinderen, guus.der.kinderen@gmail.com
 * 
 */
public class PEPServiceManager {

	public static final Logger Log = LoggerFactory
			.getLogger(PEPServiceManager.class);

	private final static String GET_PEP_SERVICE = "SELECT DISTINCT serviceID FROM ofPubsubNode WHERE serviceID=?";

	/**
	 * Cache of PEP services. Table, Key: bare JID (String); Value: PEPService
	 */
	private final Cache<String, PEPService> pepServices = CacheFactory
55
			.createLocalCache("PEPServiceManager");
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

	private PubSubEngine pubSubEngine = null;

	/**
	 * Retrieves a PEP service -- attempting first from memory, then from the
	 * database.
	 * 
	 * @param jid
	 *            the bare JID of the user that owns the PEP service.
	 * @return the requested PEP service if found or null if not found.
	 */
	public PEPService getPEPService(String jid) {
		PEPService pepService = null;

		final Lock lock = CacheFactory.getLock(jid, pepServices);
		try {
			lock.lock();
			if (pepServices.containsKey(jid)) {
				// lookup in cache
				pepService = pepServices.get(jid);
			} else {
				// lookup in database.
				pepService = loadPEPServiceFromDB(jid);
				
				// always add to the cache, even if it doesn't exist. This will
				// prevent future database lookups.
				pepServices.put(jid, pepService);
			}
		} finally {
			lock.unlock();
		}

		return pepService;
	}

	public PEPService create(JID owner) {
		// Return an error if the packet is from an anonymous, unregistered user
		// or remote user
		if (!XMPPServer.getInstance().isLocal(owner)
				|| !UserManager.getInstance().isRegisteredUser(owner.getNode())) {
			throw new IllegalArgumentException(
					"Request must be initiated by a local, registered user, but is not: "
							+ owner);
		}

		PEPService pepService = null;
		final String bareJID = owner.toBareJID();
		final Lock lock = CacheFactory.getLock(owner, pepServices);
		try {
			lock.lock();

			pepService = pepServices.get(bareJID);
			if (pepService == null) {
				pepService = new PEPService(XMPPServer.getInstance(), bareJID);
				pepServices.put(bareJID, pepService);

				if (Log.isDebugEnabled()) {
					Log.debug("PEPService created for : " + bareJID);
				}
			}
		} finally {
			lock.unlock();
		}

		return pepService;
	}

	/**
	 * Loads a PEP service from the database, if it exists.
	 * 
	 * @param jid
	 *            the JID of the owner of the PEP service.
	 * @return the loaded PEP service, or null if not found.
	 */
	private PEPService loadPEPServiceFromDB(String jid) {
		PEPService pepService = null;

		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			con = DbConnectionManager.getConnection();
			// Get all PEP services
			pstmt = con.prepareStatement(GET_PEP_SERVICE);
			pstmt.setString(1, jid);
			rs = pstmt.executeQuery();
			// Restore old PEPServices
			while (rs.next()) {
				String serviceID = rs.getString(1);

				// Create a new PEPService
				pepService = new PEPService(XMPPServer.getInstance(), serviceID);
				pepServices.put(serviceID, pepService);
				pubSubEngine.start(pepService);

				if (Log.isDebugEnabled()) {
					Log.debug("PEP: Restored service for " + serviceID
							+ " from the database.");
				}
			}
		} catch (SQLException sqle) {
			Log.error(sqle.getMessage(), sqle);
		} finally {
			DbConnectionManager.closeConnection(rs, pstmt, con);
		}

		return pepService;
	}

	/**
	 * Deletes the {@link PEPService} belonging to the specified owner.
	 * 
	 * @param owner
	 *            The JID of the owner of the service to be deleted.
	 */
	public void remove(JID owner) {
		PEPService service = null;

		final Lock lock = CacheFactory.getLock(owner, pepServices);
		try {
			lock.lock();
			service = pepServices.remove(owner.toBareJID());
		} finally {
			lock.unlock();
		}

		if (service == null) {
			return;
		}

		// Delete the user's PEP nodes from memory and the database.
		CollectionNode rootNode = service.getRootCollectionNode();
		for (final Node node : service.getNodes()) {
			if (rootNode.isChildNode(node)) {
				node.delete();
			}
		}
		rootNode.delete();
	}

	public void start(PEPService pepService) {
		pubSubEngine.start(pepService);
	}

	public void start() {
		pubSubEngine = new PubSubEngine(XMPPServer.getInstance()
				.getPacketRouter());
	}

	public void stop() {

		for (PEPService service : pepServices.values()) {
			pubSubEngine.shutdown(service);
		}

		pubSubEngine = null;
	}

	public void process(PEPService service, IQ iq) {
		pubSubEngine.process(service, iq);
	}
	
	public boolean hasCachedService(JID owner) {
219
		return pepServices.get(owner.toBareJID()) != null;
220 221 222 223 224 225 226
	}
	
	// mimics Shutdown, without killing the timer.
	public void unload(PEPService service) {	
		pubSubEngine.shutdown(service);
	}
}