remoteoperator.java
来自「Rapla是一个灵活的多用户资源管理系统。它提供的一些功能有:日历GUI」· Java 代码 · 共 639 行 · 第 1/2 页
JAVA
639 行
/*--------------------------------------------------------------------------*
| Copyright (C) 2006 Christopher Kohlhaas |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by the |
| Free Software Foundation. A copy of the license has been included with |
| these distribution in the COPYING file, if not go to www.fsf.org |
| |
| As a special exception, you are granted the permissions to link this |
| program with every library, which license fulfills the Open Source |
| Definition as published by the Open Source Initiative (OSI). |
*--------------------------------------------------------------------------*/
package org.rapla.storage.dbrm;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import org.apache.avalon.framework.configuration.Configuration;
import org.rapla.components.util.Command;
import org.rapla.components.util.CommandQueue;
import org.rapla.components.util.SerializableDateTimeFormat;
import org.rapla.entities.EntityNotFoundException;
import org.rapla.entities.RaplaType;
import org.rapla.entities.User;
import org.rapla.entities.storage.EntityResolver;
import org.rapla.entities.storage.RefEntity;
import org.rapla.entities.storage.internal.SimpleEntity;
import org.rapla.entities.storage.internal.SimpleIdentifier;
import org.rapla.framework.Container;
import org.rapla.framework.RaplaContext;
import org.rapla.framework.RaplaException;
import org.rapla.plugin.RaplaExtensionPoints;
import org.rapla.server.RemoteMethod;
import org.rapla.server.RemoteServiceCaller;
import org.rapla.server.RemoteStorage;
import org.rapla.server.RestartServer;
import org.rapla.server.internal.RemoteStorageImpl;
import org.rapla.server.internal.SessionExpiredException;
import org.rapla.storage.IOContext;
import org.rapla.storage.LocalCache;
import org.rapla.storage.RaplaSecurityException;
import org.rapla.storage.UpdateEvent;
import org.rapla.storage.UpdateResult;
import org.rapla.storage.impl.AbstractCachableOperator;
import org.rapla.storage.impl.EntityStore;
import org.rapla.storage.xml.RaplaInput;
import org.rapla.storage.xml.RaplaMainReader;
/** This operator can be used to modify and access data over the
* network. It needs an server-process providing the StorageService
* (usually this is the default rapla-server).
* <p>Sample configuration:
<pre>
<remote-storage id="web">
</remote-storate>
</pre>
* The messaging-client value contains the id of a
* messaging-client-component which handles the
* communication with the server.
* The RemoteOperator provides also the Service {@link RemoteServiceCaller}
* @see org.rapla.server.RemoteStorageCallback
* @see org.rapla.components.rpc.MessagingClient
*/
public class RemoteOperator
extends
AbstractCachableOperator
implements
RemoteServiceCaller
,RestartServer
{
ServerStub serv = new ServerStub();
String username;
String password;
protected CommandQueue notifyQueue;
private boolean bSessionActive = false;
Connector connector;
private boolean bReservationsFetched;
private Date firstCachedDate = null;
private Date lastCachedDate = null;
private boolean isRestarting;
public RemoteOperator(RaplaContext context, Configuration config) throws RaplaException {
super( context );
Container raplaMainContainer = ((Container)context.lookup( Container.ROLE));
raplaMainContainer.addContainerProvidedComponent( RaplaExtensionPoints.SERVLET_PAGE_EXTENSION, RaplaStorePage.class.getName(), "store", null);
((Container)context.lookup( Container.ROLE)).addContainerProvidedComponentInstance(RestartServer.ROLE, this);
((Container)context.lookup( Container.ROLE)).addContainerProvidedComponentInstance(RemoteServiceCaller.ROLE, this);
connector = new HTTPConnector(context,config);
}
public void connect() throws RaplaException {
throw new RaplaException("RemoteOperator doesn't support anonymous connect");
}
public void connect(String username,char[] password) throws RaplaException {
this.username = username;
this.password = new String(password);
if (isConnected())
return;
getLogger().info("Connecting to server and starting login..");
doConnect();
try {
String clientVersion= i18n.getString("rapla.version") ;
serv.checkServerVersion( clientVersion);
serv.login(this.username,this.password);
bSessionActive = true;
updateToday();
getLogger().info("login successfull");
} catch (RaplaException ex){
disconnect();
throw ex;
}
loadData();
notifyQueue = org.rapla.components.util.CommandQueue.createCommandQueue();
}
public void saveData() throws RaplaException {
throw new RaplaException("RemoteOperator doesn't support storing complete cache, yet!");
}
/** implementation specific. Should be private */
public void serverHangup() {
getLogger().warn("Server hangup");
if (!isRestarting) {
getLogger().error(getI18n().format("error.connection_closed",getConnectionName()));
}
isRestarting = false;
new Thread() {
public void run() {
fireStorageDisconnected();
}
}.start();
}
public String getConnectionName() {
return connector.getInfo();
}
private void doConnect() throws RaplaException {
boolean bFailed = true;
try {
connector.start();
bFailed = false;
} catch (Exception e) {
throw new RaplaException(i18n.format("error.connect",getConnectionName()),e);
} finally {
if (bFailed)
disconnect();
}
}
public boolean isConnected() {
// return connector.hasSession();//messagingClient != null && messagingClient.isRunning();
return bSessionActive;
}
public boolean supportsActiveMonitoring() {
return true;
}
public void refresh() throws RaplaException {
serv.refresh();
}
public void restartServer() throws RaplaException {
isRestarting = true;
serv.restartServer();
fireStorageDisconnected();
}
/** disconnect from the server */
public void disconnect() throws RaplaException {
getLogger().info("Disconnecting from server");
try {
bSessionActive = false;
if ( notifyQueue != null)
{
notifyQueue.dequeueAll(); // Execute all update Commands.
}
firstCachedDate = null;
lastCachedDate = null;
bReservationsFetched = false;
connector.stop();
cache.clearAll();
} catch (Exception e) {
throw new RaplaException("Could not disconnect", e);
}
fireStorageDisconnected();
}
private void addToCache(List list, boolean useCache) throws RaplaException {
EntityResolver entityResolver = createEntityResolver( list, useCache ? cache : null );
synchronized (cache) {
resolveEntities( list.iterator(), entityResolver );
for( Iterator it = list.iterator();it.hasNext();) {
SimpleEntity entity = (SimpleEntity) it.next();
cache.put(entity);
}
}
}
private void loadData() throws RaplaException {
checkConnected();
cache.clearAll();
getLogger().debug("Getting Data..");
// recontextualize Entities
addToCache(serv.getResources(), false );
getLogger().debug("Data flushed");
}
protected void checkConnected() throws RaplaException {
if ( !bSessionActive ) {
if (username == null) {
throw new RaplaException("Need to login first!");
} else {
throw new RaplaException(i18n.format("error.connection_closed", getConnectionName()));
}
}
}
protected long getCurrentTime() throws RaplaException {
if ( bSessionActive )
return serv.getServerTime();
else
return super.getCurrentTime();
}
public void dispatch(UpdateEvent evt) throws RaplaException {
checkConnected();
// Create closure
UpdateEvent closure = createClosure(evt );
check( closure );
// Store on server
if (getLogger().isDebugEnabled()) {
Iterator it =closure.getStoreObjects().iterator();
while (it.hasNext()) {
RefEntity entity = (RefEntity)it.next();
getLogger().debug("dispatching store for: " + entity);
}
it =closure.getRemoveObjects().iterator();
while (it.hasNext()) {
RefEntity entity = (RefEntity)it.next();
getLogger().debug("dispatching remove for: " + entity);
}
}
serv.dispatch( closure );
// Store in cache
UpdateResult result = update( closure, true );
fireStorageUpdated(result);
}
public Object createIdentifier(RaplaType raplaType) throws RaplaException {
return serv.createIdentifier(raplaType);
}
/** we must override this method because we can't store the passwords on the client*/
public void authenticate(String username,String password) throws RaplaException {
serv.authenticate(username,password);
}
public boolean canChangePassword() {
try {
return serv.canChangePassword();
} catch (RaplaException ex) {
return false;
}
}
public void changePassword(User user,char[] oldPassword,char[] newPassword) throws RaplaException {
try {
serv.changePassword(user.getUsername(),oldPassword,newPassword);
} catch (RaplaSecurityException ex) {
throw new RaplaSecurityException(i18n.getString("error.wrong_password"));
}
}
private void updateReservations(User user,Date start,Date end) throws RaplaException {
if ( !bReservationsFetched ) {
bReservationsFetched = true;
firstCachedDate = start;
lastCachedDate = end;
addToCache(serv.getReservations(firstCachedDate, lastCachedDate), true );
return;
}
if ( firstCachedDate != null) {
if (start == null || start.before(firstCachedDate)) {
addToCache(serv.getReservations( start, firstCachedDate), true );
firstCachedDate = start;
}
}
if ( lastCachedDate != null) {
if (end == null || end.after(lastCachedDate)) {
addToCache(serv.getReservations( lastCachedDate, end), true );
lastCachedDate = end;
}
}
}
public RefEntity resolveId(Object id) throws EntityNotFoundException {
try {
return super.resolveId(id);
} catch (EntityNotFoundException ex) {
try {
List resolved = serv.getEntityRecursive( id );
addToCache(resolved, true );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?