Package org.apache.ace.client.repository.impl

Source Code of org.apache.ace.client.repository.impl.RepositoryAdminImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.ace.client.repository.impl;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.ace.client.repository.ObjectRepository;
import org.apache.ace.client.repository.PreCommitMember;
import org.apache.ace.client.repository.RepositoryAdmin;
import org.apache.ace.client.repository.RepositoryAdminLoginContext;
import org.apache.ace.client.repository.RepositoryObject;
import org.apache.ace.client.repository.RepositoryObject.WorkingState;
import org.apache.ace.client.repository.SessionFactory;
import org.apache.ace.client.repository.helper.ArtifactHelper;
import org.apache.ace.client.repository.impl.RepositoryAdminLoginContextImpl.RepositorySetDescriptor;
import org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
import org.apache.ace.client.repository.object.ArtifactObject;
import org.apache.ace.client.repository.object.DeploymentVersionObject;
import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
import org.apache.ace.client.repository.object.DistributionObject;
import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
import org.apache.ace.client.repository.object.FeatureObject;
import org.apache.ace.client.repository.object.TargetObject;
import org.apache.ace.client.repository.repository.Artifact2FeatureAssociationRepository;
import org.apache.ace.client.repository.repository.ArtifactRepository;
import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
import org.apache.ace.client.repository.repository.Distribution2TargetAssociationRepository;
import org.apache.ace.client.repository.repository.DistributionRepository;
import org.apache.ace.client.repository.repository.Feature2DistributionAssociationRepository;
import org.apache.ace.client.repository.repository.FeatureRepository;
import org.apache.ace.client.repository.repository.RepositoryConfiguration;
import org.apache.ace.client.repository.repository.TargetRepository;
import org.apache.ace.connectionfactory.ConnectionFactory;
import org.apache.ace.repository.Repository;
import org.apache.ace.repository.ext.BackupRepository;
import org.apache.ace.repository.ext.CachedRepository;
import org.apache.ace.repository.ext.impl.CachedRepositoryImpl;
import org.apache.ace.repository.ext.impl.FilebasedBackupRepository;
import org.apache.ace.repository.ext.impl.RemoteRepository;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.osgi.service.log.LogService;
import org.osgi.service.prefs.Preferences;
import org.osgi.service.prefs.PreferencesService;
import org.osgi.service.useradmin.User;

/**
* An implementation of RepositoryAdmin, responsible for managing <code>ObjectRepositoryImpl</code> descendants.<br>
* The actual repository managing is delegated to <code>RepositorySet</code>s, while the logic for binding these sets
* together is located in this class. Set actual <code>RepositorySet</code>s to be used are defined in
* <code>login(...)</code>.<br>
*/
public class RepositoryAdminImpl implements RepositoryAdmin {
    private final static String PREFS_LOCAL_FILE_ROOT = "ClientRepositoryAdmin";
    private final static String PREFS_LOCAL_FILE_LOCATION = "FileLocation";
    private final static String PREFS_LOCAL_FILE_CURRENT = "current";
    private final static String PREFS_LOCAL_FILE_BACKUP = "backup";
   
    private static final String KEY_CAUSE = "cause";
    private static final String CAUSE_COMMIT = "commit";
    private static final String CAUSE_REVERT = "revert";
    private static final String CAUSE_CHECKOUT = "checkout";

    /**
     * Maps from interface classes of the ObjectRepositories to their implementations.
     */
    private Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> m_repositories;

    private final String m_sessionID;
    private final Properties m_sessionProps;
    private final RepositoryConfiguration m_repositoryConfig;
    private final ChangeNotifier m_changeNotifier;
    private final Object m_lock = new Object();

    // Injected by dependency manager
    private volatile DependencyManager m_dm;
    private volatile BundleContext m_context;
    private volatile PreferencesService m_preferences;
    private volatile LogService m_log;

    private User m_user;
    private RepositorySet[] m_repositorySets;
    private List<PreCommitMember> m_preCommitMembers;

    private List<Component[]> m_services;
    private ArtifactRepositoryImpl m_artifactRepositoryImpl;
    private FeatureRepositoryImpl m_featureRepositoryImpl;
    private Artifact2FeatureAssociationRepositoryImpl m_artifact2FeatureAssociationRepositoryImpl;
    private DistributionRepositoryImpl m_distributionRepositoryImpl;
    private Feature2DistributionAssociationRepositoryImpl m_feature2DistributionAssociationRepositoryImpl;
    private TargetRepositoryImpl m_targetRepositoryImpl;
    private Distribution2TargetAssociationRepositoryImpl m_distribution2TargetAssociationRepositoryImpl;
    private DeploymentVersionRepositoryImpl m_deploymentVersionRepositoryImpl;
    private ChangeNotifierManager m_changeNotifierManager;

    public RepositoryAdminImpl(String sessionID, RepositoryConfiguration repoConfig) {
        m_sessionID = sessionID;
        m_repositoryConfig = repoConfig;
        m_preCommitMembers = new ArrayList<PreCommitMember>();
        m_sessionProps = new Properties();
        m_sessionProps.put(SessionFactory.SERVICE_SID, sessionID);
        m_changeNotifierManager = new ChangeNotifierManager();
        m_changeNotifier = m_changeNotifierManager.getConfiguredNotifier(RepositoryAdmin.PRIVATE_TOPIC_ROOT, RepositoryAdmin.PUBLIC_TOPIC_ROOT, RepositoryAdmin.TOPIC_ENTITY_ROOT, m_sessionID);
    }

    public Properties getSessionProps() {
        return m_sessionProps;
    }

    /**
     * Returns a list of instances that make up this composition. Instances are used to inject dependencies into.
     *
     * @return list of instances
     */
    public Object[] getInstances() {
        return new Object[] { this, m_changeNotifierManager };
    }

    public void start() {
        synchronized (m_lock) {
            initialize(publishRepositories());
        }
    }

    public void stop() {
        pullRepositories();
        synchronized (m_lock) {
            if (loggedIn()) {
                try {
                    logout(true);
                }
                catch (IOException ioe) {
                    m_log.log(LogService.LOG_ERROR, "Failed to log out of the repositories.", ioe);
                }
            }
        }
    }

    void initialize(Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> repositories) {
        m_repositories = repositories;
    }

    private ChangeNotifier createChangeNotifier(String topic) {
        return m_changeNotifierManager.getConfiguredNotifier(topic, m_sessionID);
    }

    @SuppressWarnings("unchecked")
    private Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> publishRepositories() {
        // create the repository objects, if this is the first time this method is called. In case a repository
        // implementation needs some form of (runtime) configuration, adapt the RepositoryConfiguration object and pass
        // this object to the repository...
        if (m_artifactRepositoryImpl == null) {
            m_artifactRepositoryImpl = new ArtifactRepositoryImpl(createChangeNotifier(ArtifactObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
            m_featureRepositoryImpl = new FeatureRepositoryImpl(createChangeNotifier(FeatureObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
            m_distributionRepositoryImpl = new DistributionRepositoryImpl(createChangeNotifier(DistributionObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
            m_targetRepositoryImpl = new TargetRepositoryImpl(createChangeNotifier(TargetObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
            //
            m_deploymentVersionRepositoryImpl = new DeploymentVersionRepositoryImpl(createChangeNotifier(DeploymentVersionObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
            //
            m_artifact2FeatureAssociationRepositoryImpl = new Artifact2FeatureAssociationRepositoryImpl(m_artifactRepositoryImpl, m_featureRepositoryImpl, createChangeNotifier(Artifact2FeatureAssociation.TOPIC_ENTITY_ROOT), m_repositoryConfig);
            m_feature2DistributionAssociationRepositoryImpl = new Feature2DistributionAssociationRepositoryImpl(m_featureRepositoryImpl, m_distributionRepositoryImpl, createChangeNotifier(Feature2DistributionAssociation.TOPIC_ENTITY_ROOT), m_repositoryConfig);
            m_distribution2TargetAssociationRepositoryImpl = new Distribution2TargetAssociationRepositoryImpl(m_distributionRepositoryImpl, m_targetRepositoryImpl, createChangeNotifier(Distribution2TargetAssociation.TOPIC_ENTITY_ROOT), m_repositoryConfig);
        }

        // first, register the artifact repository manually; it needs some special care.
        Component artifactRepoService = m_dm.createComponent()
            .setInterface(ArtifactRepository.class.getName(), m_sessionProps)
            .setImplementation(m_artifactRepositoryImpl)
            .add(m_dm.createServiceDependency().setService(ConnectionFactory.class).setRequired(true))
            .add(m_dm.createServiceDependency().setService(LogService.class).setRequired(false))
            .add(m_dm.createServiceDependency().setService(ArtifactHelper.class).setRequired(false).setAutoConfig(false).setCallbacks(this, "addArtifactHelper", "removeArtifactHelper"));

        Dictionary topic = new Hashtable();
        topic.put(EventConstants.EVENT_FILTER, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")");
        topic.put(EventConstants.EVENT_TOPIC, new String[] {});

        Component artifactHandlerService = m_dm.createComponent()
            .setInterface(EventHandler.class.getName(), topic)
            .setImplementation(m_artifactRepositoryImpl);

        m_dm.add(artifactRepoService);
        m_dm.add(artifactHandlerService);

        m_services = new ArrayList<Component[]>();
        m_services.add(new Component[] { artifactRepoService, artifactHandlerService });

        // register all repositories are services. Keep the service objects around, we need them to pull the services
        // later.
        m_services.add(registerRepository(Artifact2FeatureAssociationRepository.class, m_artifact2FeatureAssociationRepositoryImpl, new String[] { createPrivateObjectTopic(ArtifactObject.TOPIC_ENTITY_ROOT),
            createPrivateObjectTopic(FeatureObject.TOPIC_ENTITY_ROOT) }));
        m_services.add(registerRepository(FeatureRepository.class, m_featureRepositoryImpl, new String[] {}));
        m_services.add(registerRepository(Feature2DistributionAssociationRepository.class, m_feature2DistributionAssociationRepositoryImpl, new String[] { createPrivateObjectTopic(FeatureObject.TOPIC_ENTITY_ROOT),
            createPrivateObjectTopic(DistributionObject.TOPIC_ENTITY_ROOT) }));
        m_services.add(registerRepository(DistributionRepository.class, m_distributionRepositoryImpl, new String[] {}));
        m_services.add(registerRepository(Distribution2TargetAssociationRepository.class, m_distribution2TargetAssociationRepositoryImpl, new String[] { createPrivateObjectTopic(DistributionObject.TOPIC_ENTITY_ROOT),
            createPrivateObjectTopic(TargetObject.TOPIC_ENTITY_ROOT) }));
        m_services.add(registerRepository(TargetRepository.class, m_targetRepositoryImpl, new String[] {}));
        m_services.add(registerRepository(DeploymentVersionRepository.class, m_deploymentVersionRepositoryImpl, new String[] {}));

        // prepare the results.
        Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> result = new HashMap<Class<? extends ObjectRepository>, ObjectRepositoryImpl>();

        result.put(ArtifactRepository.class, m_artifactRepositoryImpl);
        result.put(Artifact2FeatureAssociationRepository.class, m_artifact2FeatureAssociationRepositoryImpl);
        result.put(FeatureRepository.class, m_featureRepositoryImpl);
        result.put(Feature2DistributionAssociationRepository.class, m_feature2DistributionAssociationRepositoryImpl);
        result.put(DistributionRepository.class, m_distributionRepositoryImpl);
        result.put(Distribution2TargetAssociationRepository.class, m_distribution2TargetAssociationRepositoryImpl);
        result.put(TargetRepository.class, m_targetRepositoryImpl);
        result.put(DeploymentVersionRepository.class, m_deploymentVersionRepositoryImpl);

        return result;
    }

    /**
     * Pulls all repository services; is used to make sure the repositories go away before the RepositoryAdmin does.
     */
    private void pullRepositories() {
        for (Component[] services : m_services) {
            for (Component service : services) {
                m_dm.remove(service);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private <T extends RepositoryObject> Component[] registerRepository(Class<? extends ObjectRepository<T>> iface, ObjectRepositoryImpl<?, T> implementation, String[] topics) {
        Component repositoryService = m_dm.createComponent()
            .setInterface(iface.getName(), m_sessionProps)
            .setImplementation(implementation)
            .add(m_dm.createServiceDependency().setService(LogService.class).setRequired(false));
        Dictionary topic = new Hashtable();
        topic.put(EventConstants.EVENT_TOPIC, topics);
        topic.put(EventConstants.EVENT_FILTER, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")");
        Component handlerService = m_dm.createComponent()
            .setInterface(EventHandler.class.getName(), topic)
            .setImplementation(implementation);

        m_dm.add(repositoryService);
        m_dm.add(handlerService);
        return new Component[] { repositoryService, handlerService };
    }

    /**
     * Helper method for use in publishRepositories
     */
    private static String createPrivateObjectTopic(String entityRoot) {
        return RepositoryObject.PRIVATE_TOPIC_ROOT + entityRoot + RepositoryObject.TOPIC_ALL_SUFFIX;
    }

    public void checkout() throws IOException {
        synchronized (m_lock) {
            ensureLogin();
            m_changeNotifier.notifyChanged(TOPIC_HOLDUNTILREFRESH_SUFFIX, null);
            for (PreCommitMember member : m_preCommitMembers) {
                member.reset();
            }
            for (RepositorySet set : m_repositorySets) {
                set.checkout();
            }

            Properties props = new Properties();
            props.put(KEY_CAUSE, CAUSE_CHECKOUT);
            m_changeNotifier.notifyChanged(TOPIC_REFRESH_SUFFIX, props);
        }
    }

    public void commit() throws IOException {
        synchronized (m_lock) {
            ensureLogin();
            for (PreCommitMember member : m_preCommitMembers) {
                member.preCommit();
            }
            for (RepositorySet set : m_repositorySets) {
                set.commit();
            }

            Properties props = new Properties();
            props.put(KEY_CAUSE, CAUSE_COMMIT);
            m_changeNotifier.notifyChanged(TOPIC_REFRESH_SUFFIX, props);
        }
    }

    public void flush() throws IOException {
        synchronized (m_lock) {
            ensureLogin();
            for (RepositorySet set : m_repositorySets) {
                set.writeLocal();
                set.savePreferences();
            }
            m_changeNotifier.notifyChanged(TOPIC_FLUSHED_SUFFIX, null);
        }
    }

    public void revert() throws IOException {
        synchronized (m_lock) {
            ensureLogin();
            m_changeNotifier.notifyChanged(TOPIC_HOLDUNTILREFRESH_SUFFIX, null);
            for (PreCommitMember member : m_preCommitMembers) {
                member.reset();
            }
            for (RepositorySet set : m_repositorySets) {
                set.revert();
            }
           
            Properties props = new Properties();
            props.put(KEY_CAUSE, CAUSE_REVERT);
            m_changeNotifier.notifyChanged(TOPIC_REFRESH_SUFFIX, props);
        }
    }

    public boolean isCurrent() throws IOException {
        synchronized (m_lock) {
            ensureLogin();
            boolean result = true;
            for (RepositorySet set : m_repositorySets) {
                result &= (set.isCurrent() || !set.writeAccess());
            }
            return result;
        }
    }

    public boolean isModified() {
        synchronized (m_lock) {
            ensureLogin();
            for (PreCommitMember member : m_preCommitMembers) {
                if (member.hasChanges()) {
                    return true;
                }
            }
            for (RepositorySet set : m_repositorySets) {
                if (set.isModified()) {
                    return true;
                }
            }
            return false;
        }
    }

    public RepositoryAdminLoginContext createLoginContext(User user) {
        if (user == null) {
            throw new IllegalArgumentException("User may not be null.");
        }
        return new RepositoryAdminLoginContextImpl(user, m_sessionID);
    }

    public void login(RepositoryAdminLoginContext context) throws IOException {
        if (!(context instanceof RepositoryAdminLoginContextImpl)) {
            throw new IllegalArgumentException("Only the RepositoryAdminLoginContext returned by createLoginContext can be used.");
        }

        RepositoryAdminLoginContextImpl impl = ((RepositoryAdminLoginContextImpl) context);
        RepositorySet[] repositorySets = getRepositorySets(impl);

        synchronized (m_lock) {
            login(impl.getUser(), repositorySets);
        }
    }

    /**
     * Helper method for login; also allows injection of custom RepositorySet objects for testing purposes.
     *
     * @throws IOException
     */
    private void login(User user, RepositorySet[] sets) throws IOException {
        synchronized (m_lock) {
            if (m_user != null) {
                throw new IllegalStateException("Another user is logged in.");
            }
            m_user = user;
            m_repositorySets = sets;
            m_changeNotifier.notifyChanged(TOPIC_HOLDUNTILREFRESH_SUFFIX, null);
            for (RepositorySet set : m_repositorySets) {
                set.readLocal();
                set.loadPreferences();
            }
        }
        m_changeNotifier.notifyChanged(TOPIC_LOGIN_SUFFIX, null);
    }

    public void logout(boolean force) throws IOException {
        IOException exception = null;
        synchronized (m_lock) {
            ensureLogin();

            try {
                flush();
            }
            catch (IOException e) {
                if (!force) {
                    throw e;
                }
                else {
                    exception = e;
                }
            }

            for (RepositorySet set : m_repositorySets) {
                set.clearRepositories();
                set.unregisterHandler();
                // set.deleteLocal();
            }

            unloadRepositorySet(m_user);

            m_user = null;
            // m_repositorySets = new RepositorySet[0];
        }
        m_changeNotifier.notifyChanged(TOPIC_LOGOUT_SUFFIX, null);

        if (exception != null) {
            throw exception;
        }
    }

    public void deleteLocal() {
        synchronized (m_lock) {
            if (m_user != null && m_repositorySets != null) {
                for (RepositorySet set : m_repositorySets) {
                    set.deleteLocal();
                }
            }
        }
    }

    private boolean loggedIn() {
        return m_user != null;
    }

    /**
     * Helper method to make sure a user is logged in.
     *
     * @throws IllegalStateException
     */
    private void ensureLogin() throws IllegalStateException {
        if (!loggedIn()) {
            throw new IllegalStateException("This operation requires a user to be logged in.");
        }
    }

    /**
     * Helper method, creates RepositorySets based on the Login context.
     */
    private RepositorySet[] getRepositorySets(RepositoryAdminLoginContextImpl context) throws IOException {
        List<RepositorySetDescriptor> descriptors = context.getDescriptors();

        // First, some sanity checks on the list of descriptors.
        for (RepositorySetDescriptor rsd : descriptors) {
            for (Class c : rsd.m_objectRepositories) {
                // Do we have an impl for each repository class?
                if (!m_repositories.containsKey(c)) {
                    throw new IllegalArgumentException(rsd.toString() + " references repository class " + c.getName() + " for which no implementation is available.");
                }
            }
        }

        RepositorySet[] result = new RepositorySet[descriptors.size()];

        /*
         * Create the lists of repositories and topics, and create and register the sets with these.
         */
        for (int i = 0; i < result.length; i++) {
            RepositorySetDescriptor rsd = descriptors.get(i);

            ObjectRepositoryImpl[] impls = new ObjectRepositoryImpl[rsd.m_objectRepositories.length];
            String[] topics = new String[rsd.m_objectRepositories.length];
            for (int j = 0; j < impls.length; j++) {
                impls[j] = m_repositories.get(rsd.m_objectRepositories[j]);
                topics[j] = impls[j].getTopicAll(false);
            }

            result[i] = loadRepositorySet(context.getUser(), rsd, impls);
            result[i].registerHandler(m_context, m_sessionID, topics);
        }

        return result;
    }

    /**
     * Helper method for login.
     */
    private Preferences getRepositoryPrefs(Preferences userPrefs, URL location, String customer, String name) {
        // Note: we can only use the getAuthority part of the URL for indexing, because the full URL will contain
        // in the protocol part.
        Preferences repoPref = userPrefs.node(location.getAuthority() + location.getPath());
        Preferences customerPref = repoPref.node(customer);
        return customerPref.node(name);
    }

    /**
     * Helper method for login.
     *
     * @throws IOException
     */
    private File getFileFromPreferences(Preferences repositoryPrefs, String type) throws IOException {
        String sessionLocation = PREFS_LOCAL_FILE_LOCATION + m_sessionID;
        String directory = repositoryPrefs.get(sessionLocation, "");

        if (directory == "") {
            File directoryFile = null;
            try {
                File bundleDataDir = m_context.getDataFile(PREFS_LOCAL_FILE_ROOT);
                if (!bundleDataDir.isDirectory()) {
                    if (!bundleDataDir.mkdir()) {
                        throw new IOException("Error creating the local repository root directory.");
                    }
                }
                directoryFile = File.createTempFile("repo", "", bundleDataDir);
                if (!directoryFile.delete()) {
                    throw new IOException("Cannot delete temporary file: " + directoryFile.getName());
                }
            }
            catch (IOException e) {
                // We cannot create or delete the temp file? Then something is seriously wrong, so rethrow.
                throw e;
            }
            repositoryPrefs.put(sessionLocation, directoryFile.getName());
            return new File(directoryFile + "-" + type);
        }
        else {
            // Get the given file from that location.
            return m_context.getDataFile(PREFS_LOCAL_FILE_ROOT + "/" + directory + "-" + type);
        }
    }

    /**
     * Helper method for login.
     *
     * @throws IOException
     */
    private BackupRepository getBackupFromPreferences(Preferences repositoryPrefs) throws IOException {
        File current = getFileFromPreferences(repositoryPrefs, PREFS_LOCAL_FILE_CURRENT);
        File backup = getFileFromPreferences(repositoryPrefs, PREFS_LOCAL_FILE_BACKUP);
        return new FilebasedBackupRepository(current, backup);
    }

    /**
     * Helper method for login.
     *
     * @throws IOException
     */
    private CachedRepository getCachedRepositoryFromPreferences(Repository repository, Preferences repositoryPrefs) throws IOException {
        long mostRecentVersion = repositoryPrefs.getLong("version", CachedRepositoryImpl.UNCOMMITTED_VERSION);
        return new CachedRepositoryImpl(repository, getBackupFromPreferences(repositoryPrefs), mostRecentVersion);
    }

    /**
     * Helper method for login, which loads a set of repositories.
     *
     * @param user
     *            A <code>User</code> object
     * @param rsd
     *            A RepositorySetDescriptor, defining the set to be created.
     * @param repos
     *            An array of <code>ObjectRepositoryImpl</code> which this set should manage. Each
     * @return The newly created repository set.
     * @throws IOException
     */
    public RepositorySet loadRepositorySet(User user, RepositorySetDescriptor rsd, ObjectRepositoryImpl[] repos) throws IOException {
        Repository repo = new RemoteRepository(rsd.m_location, rsd.m_customer, rsd.m_name);

        // Expose the repository itself as component so its dependencies get managed...
        m_dm.add(m_dm.createComponent()
            .setImplementation(repo)
            .add(m_dm.createServiceDependency()
                .setService(ConnectionFactory.class)
                .setRequired(true)));

        Preferences prefs = m_preferences.getUserPreferences(user.getName());
        prefs = prefs.node(m_sessionID);
        Preferences repoPrefs = getRepositoryPrefs(prefs, rsd.m_location, rsd.m_customer, rsd.m_name);

        return new RepositorySet(m_changeNotifier, m_log, user, repoPrefs, repos, getCachedRepositoryFromPreferences(repo, repoPrefs), rsd.m_name, rsd.m_writeAccess);
    }

    private void unloadRepositorySet(User user) {
        Preferences prefs = m_preferences.getUserPreferences(user.getName());
        prefs.remove(m_sessionID);
    }

    public int getNumberWithWorkingState(Class<? extends RepositoryObject> clazz, WorkingState state) {
        int result = 0;
        synchronized (m_lock) {
            for (RepositorySet set : m_repositorySets) {
                result += set.getNumberWithWorkingState(clazz, state);
            }
        }
        return result;
    }

    public WorkingState getWorkingState(RepositoryObject object) {
        WorkingState result = null;
        synchronized (m_lock) {
            for (RepositorySet set : m_repositorySets) {
                result = set.getWorkingState(object);
                if (result != null) {
                    break;
                }
            }
        }
        return (result == null) ? WorkingState.Unchanged : result;
    }

    public void addArtifactHelper(ServiceReference ref, ArtifactHelper helper) {
        String mimetype = (String) ref.getProperty(ArtifactHelper.KEY_MIMETYPE);
        m_artifactRepositoryImpl.addHelper(mimetype, helper);
    }

    public synchronized void removeArtifactHelper(ServiceReference ref, ArtifactHelper helper) {
        String mimetype = (String) ref.getProperty(ArtifactHelper.KEY_MIMETYPE);
        m_artifactRepositoryImpl.removeHelper(mimetype, helper);
    }

    void addPreCommitMember(PreCommitMember member) {
        synchronized (m_lock) {
            m_preCommitMembers.add(member);
        }
    }
}
TOP

Related Classes of org.apache.ace.client.repository.impl.RepositoryAdminImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.