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>
   &lt;remote-storage id="web">
   &lt;/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 + -
显示快捷键?