You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2012/04/23 14:15:06 UTC
svn commit: r1329199 [2/5] - in /ace/trunk: ./
ace-authenticationprocessor-basicauth/src/main/java/org/apache/ace/authenticationprocessor/basicauth/
ace-client-automation/src/main/java/org/apache/ace/client/automation/
ace-client-repository-api/src/mai...
Modified: ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java?rev=1329199&r1=1329198&r2=1329199&view=diff
==============================================================================
--- ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java (original)
+++ ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java Mon Apr 23 12:15:01 2012
@@ -33,26 +33,27 @@ import org.apache.ace.client.repository.
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.SessionFactory;
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.TargetObject;
-import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
-import org.apache.ace.client.repository.object.FeatureObject;
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.TargetRepository;
-import org.apache.ace.client.repository.repository.Feature2DistributionAssociationRepository;
-import org.apache.ace.client.repository.repository.FeatureRepository;
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.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;
@@ -78,28 +79,32 @@ import org.osgi.service.useradmin.User;
* 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";
+
/**
* Maps from interface classes of the ObjectRepositories to their implementations.
*/
@SuppressWarnings("unchecked")
private Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> m_repositories;
+ private final String m_sessionID;
+ private final Properties m_sessionProps;
private final ChangeNotifier m_changeNotifier;
- private volatile BundleContext m_context; /* Injected by dependency manager */
- private volatile PreferencesService m_preferences; /* Injected by dependency manager */
- private volatile LogService m_log; /* Injected by dependency manager */
-
private final Object m_lock = new Object();
- 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";
+ // Injected by dependency manager
+ private volatile DependencyManager m_manager;
+ private volatile BundleContext m_context;
+ private volatile PreferencesService m_preferences;
+ private volatile LogService m_log;
+
private User m_user;
private RepositorySet[] m_repositorySets;
- private volatile DependencyManager m_manager;
- List<Component[]> m_services;
+ private List<Component[]> m_services;
private ArtifactRepositoryImpl m_artifactRepositoryImpl;
private FeatureRepositoryImpl m_featureRepositoryImpl;
private Artifact2FeatureAssociationRepositoryImpl m_artifact2FeatureAssociationRepositoryImpl;
@@ -109,8 +114,7 @@ public class RepositoryAdminImpl impleme
private Distribution2TargetAssociationRepositoryImpl m_distribution2TargetAssociationRepositoryImpl;
private DeploymentVersionRepositoryImpl m_deploymentVersionRepositoryImpl;
private ChangeNotifierManager m_changeNotifierManager;
- private final String m_sessionID;
- private final Properties m_sessionProps;
+
public RepositoryAdminImpl(String sessionID) {
m_sessionID = sessionID;
@@ -135,11 +139,6 @@ public class RepositoryAdminImpl impleme
}
@SuppressWarnings("unchecked")
- void initialize(Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> repositories) {
- m_repositories = repositories;
- }
-
- @SuppressWarnings("unchecked")
public void start() {
synchronized (m_lock) {
initialize(publishRepositories());
@@ -161,6 +160,11 @@ public class RepositoryAdminImpl impleme
}
@SuppressWarnings("unchecked")
+ void initialize(Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> repositories) {
+ m_repositories = repositories;
+ }
+
+ @SuppressWarnings("unchecked")
private Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> publishRepositories() {
// create the repository objects, if this is the first time this method is called.
if (m_artifactRepositoryImpl == null) {
@@ -173,18 +177,23 @@ public class RepositoryAdminImpl impleme
m_distribution2TargetAssociationRepositoryImpl = new Distribution2TargetAssociationRepositoryImpl(m_distributionRepositoryImpl, m_targetRepositoryImpl, m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, Distribution2TargetAssociation.TOPIC_ENTITY_ROOT, m_sessionID));
m_deploymentVersionRepositoryImpl = new DeploymentVersionRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, DeploymentVersionObject.TOPIC_ENTITY_ROOT, m_sessionID));
}
+
// first, register the artifact repository manually; it needs some special care.
Component artifactRepoService = m_manager.createComponent()
.setInterface(ArtifactRepository.class.getName(), m_sessionProps)
.setImplementation(m_artifactRepositoryImpl)
+ .add(m_manager.createServiceDependency().setService(ConnectionFactory.class).setRequired(true))
.add(m_manager.createServiceDependency().setService(LogService.class).setRequired(false))
.add(m_manager.createServiceDependency().setService(ArtifactHelper.class).setRequired(false).setAutoConfig(false).setCallbacks(this, "addArtifactHelper", "removeArtifactHelper"));
+
Dictionary topic = new Hashtable();
- topic.put(EventConstants.EVENT_TOPIC, new String[] {});
topic.put(EventConstants.EVENT_FILTER, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")");
+ topic.put(EventConstants.EVENT_TOPIC, new String[] {});
+
Component artifactHandlerService = m_manager.createComponent()
.setInterface(EventHandler.class.getName(), topic)
.setImplementation(m_artifactRepositoryImpl);
+
m_manager.add(artifactRepoService);
m_manager.add(artifactHandlerService);
@@ -332,7 +341,7 @@ public class RepositoryAdminImpl impleme
synchronized(m_lock) {
// TODO I don't like this line, it should not be here...
- ((ArtifactRepositoryImpl) m_repositories.get(ArtifactRepository.class)).setObrBase(impl.getObrBase());
+ ((ArtifactRepository) m_repositories.get(ArtifactRepository.class)).setObrBase(impl.getObrBase());
login(impl.getUser(), repositorySets);
}
}
@@ -409,40 +418,34 @@ public class RepositoryAdminImpl impleme
*/
@SuppressWarnings("unchecked")
private RepositorySet[] getRepositorySets(RepositoryAdminLoginContextImpl context) throws IOException {
+ List<RepositorySetDescriptor> descriptors = context.getDescriptors();
+
// First, some sanity checks on the list of descriptors.
- for (RepositorySetDescriptor rsd : context.getDescriptors()) {
+ 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.");
}
- // Do other sets have a reference to this same class?
- for (RepositorySetDescriptor other : context.getDescriptors()) {
- if (other != rsd) {
- for (Class otherC : other.m_objectRepositories) {
- if (c.equals(otherC)) {
- throw new IllegalArgumentException(rsd.toString() + " references repository class " + c.getName() + ", but so does " + other.toString());
- }
- }
- }
- }
}
}
- RepositorySet[] result = new RepositorySet[context.getDescriptors().size()];
+ 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 = context.getDescriptors().get(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(true);
}
+
result[i] = loadRepositorySet(context.getUser(), rsd, impls);
result[i].registerHandler(m_context, m_sessionID, topics);
}
@@ -516,9 +519,9 @@ public class RepositoryAdminImpl impleme
* Helper method for login.
* @throws IOException
*/
- private CachedRepository getCachedRepositoryFromPreferences(User user, Repository repository, Preferences repositoryPrefs) throws IOException {
+ private CachedRepository getCachedRepositoryFromPreferences(Repository repository, Preferences repositoryPrefs) throws IOException {
long mostRecentVersion = repositoryPrefs.getLong("version", CachedRepositoryImpl.UNCOMMITTED_VERSION);
- return new CachedRepositoryImpl(user, repository, getBackupFromPreferences(repositoryPrefs), mostRecentVersion);
+ return new CachedRepositoryImpl(repository, getBackupFromPreferences(repositoryPrefs), mostRecentVersion);
}
/**
@@ -532,9 +535,18 @@ public class RepositoryAdminImpl impleme
@SuppressWarnings("unchecked")
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_manager.add(m_manager.createComponent()
+ .setImplementation(repo)
+ .add(m_manager.createServiceDependency()
+ .setService(ConnectionFactory.class)
+ .setRequired(true)));
+
Preferences prefs = m_preferences.getUserPreferences(user.getName());
Preferences repoPrefs = getRepositoryPrefs(prefs, rsd.m_location, rsd.m_customer, rsd.m_name);
- return new RepositorySet(m_changeNotifier, m_log, user, repoPrefs, repos, getCachedRepositoryFromPreferences(user, repo, repoPrefs), rsd.m_name, rsd.m_writeAccess);
+
+ return new RepositorySet(m_changeNotifier, m_log, user, repoPrefs, repos, getCachedRepositoryFromPreferences(repo, repoPrefs), rsd.m_name, rsd.m_writeAccess);
}
public int getNumberWithWorkingState(Class<? extends RepositoryObject> clazz, WorkingState state) {
Modified: ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java?rev=1329199&r1=1329198&r2=1329199&view=diff
==============================================================================
--- ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java (original)
+++ ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java Mon Apr 23 12:15:01 2012
@@ -20,6 +20,7 @@ package org.apache.ace.client.repository
import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.apache.ace.client.repository.ObjectRepository;
@@ -27,14 +28,15 @@ import org.apache.ace.client.repository.
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.TargetRepository;
-import org.apache.ace.client.repository.repository.Feature2DistributionAssociationRepository;
-import org.apache.ace.client.repository.repository.FeatureRepository;
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.TargetRepository;
import org.osgi.service.useradmin.User;
-class RepositoryAdminLoginContextImpl implements RepositoryAdminLoginContext {
+public class RepositoryAdminLoginContextImpl implements RepositoryAdminLoginContext {
+
private final String m_sessionid;
private final User m_user;
private final List<RepositorySetDescriptor> m_descriptors = new ArrayList<RepositorySetDescriptor>();
@@ -45,43 +47,60 @@ class RepositoryAdminLoginContextImpl im
m_sessionid = sessionid;
}
- @SuppressWarnings("unchecked")
- public RepositoryAdminLoginContext addRepositories(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess, Class<? extends ObjectRepository>... objectRepositories) {
- if ((repositoryLocation == null) || (repositoryCustomer == null) || (repositoryName == null)) {
- throw new IllegalArgumentException("No parameter should be null.");
- }
- if ((objectRepositories == null) || (objectRepositories.length == 0)) {
- throw new IllegalArgumentException("objectRepositories should not be null or empty.");
+ /**
+ * {@inheritDoc}
+ */
+ public RepositoryAdminLoginContext add(BaseRepositoryContext<?> repositoryContext) {
+ if (!(repositoryContext instanceof AbstractRepositoryContext)) {
+ throw new IllegalArgumentException("Invalid repository context!");
}
- m_descriptors.add(new RepositorySetDescriptor(repositoryLocation, repositoryCustomer, repositoryName, writeAccess, objectRepositories));
+
+ addDescriptor(((AbstractRepositoryContext<?>) repositoryContext).createDescriptor());
+
return this;
}
- @SuppressWarnings("unchecked")
- public RepositoryAdminLoginContext addShopRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess) {
- return addRepositories(repositoryLocation, repositoryCustomer, repositoryName, writeAccess,
- ArtifactRepository.class,
- FeatureRepository.class,
- Artifact2FeatureAssociationRepository.class,
- DistributionRepository.class,
- Feature2DistributionAssociationRepository.class);
- }
-
- @SuppressWarnings("unchecked")
- public RepositoryAdminLoginContext addTargetRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess) {
- return addRepositories(repositoryLocation, repositoryCustomer, repositoryName, writeAccess,
- TargetRepository.class,
- Distribution2TargetAssociationRepository.class);
- }
-
- @SuppressWarnings("unchecked")
- public RepositoryAdminLoginContext addDeploymentRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess) {
- return addRepositories(repositoryLocation, repositoryCustomer, repositoryName, writeAccess,
- DeploymentVersionRepository.class);
+ /**
+ * @param descriptor the descriptor to add, cannot be <code>null</code>.
+ */
+ public void addDescriptor(RepositorySetDescriptor descriptor) {
+ checkConsistency(descriptor);
+
+ synchronized (m_descriptors) {
+ m_descriptors.add(descriptor);
+ }
}
+ /**
+ * {@inheritDoc}
+ */
+ public ShopRepositoryContext createShopRepositoryContext() {
+ return new ShopRepositoryContextImpl();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TargetRepositoryContext createTargetRepositoryContext() {
+ return new TargetRepositoryContextImpl();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DeploymentRepositoryContext createDeploymentRepositoryContext() {
+ return new DeploymentRepositoryContextImpl();
+ }
+
+ /**
+ * @return a list with all repository set descriptors, never <code>null</code>.
+ */
public List<RepositorySetDescriptor> getDescriptors() {
- return m_descriptors;
+ List<RepositorySetDescriptor> result;
+ synchronized (m_descriptors) {
+ result = new ArrayList<RepositorySetDescriptor>(m_descriptors);
+ }
+ return result;
}
public RepositoryAdminLoginContext setObrBase(URL base) {
@@ -102,10 +121,36 @@ class RepositoryAdminLoginContextImpl im
}
/**
+ * Checks the consistency of the internal descriptors with the one given.
+ *
+ * @param descriptor the to-be-added repository set descriptor, cannot be <code>null</code>.
+ */
+ private void checkConsistency(RepositorySetDescriptor descriptor) {
+ List<Class<? extends ObjectRepository>> seenClasses = new ArrayList<Class<? extends ObjectRepository>>();
+ List<String> seenNames = new ArrayList<String>();
+
+ // Presumption: initially we start out without any duplication...
+ for (RepositorySetDescriptor rsd : getDescriptors()) {
+ seenClasses.addAll(Arrays.asList(rsd.m_objectRepositories));
+ seenNames.add(rsd.m_name);
+ }
+
+ if (seenNames.contains(descriptor.m_name)) {
+ throw new IllegalArgumentException("Duplicate repository name!");
+ }
+
+ for (Class<? extends ObjectRepository> clazz : descriptor.m_objectRepositories) {
+ if (seenClasses.contains(clazz)) {
+ throw new IllegalArgumentException("Duplicate object repository!");
+ }
+ }
+ }
+
+ /**
* Helper class to store all relevant information about a repository in a convenient location before
* we start using it.
*/
- static class RepositorySetDescriptor {
+ public static final class RepositorySetDescriptor {
public final URL m_location;
public final String m_customer;
public final String m_name;
@@ -114,7 +159,7 @@ class RepositoryAdminLoginContextImpl im
public final Class<? extends ObjectRepository>[] m_objectRepositories;
@SuppressWarnings("unchecked")
- RepositorySetDescriptor(URL location, String customer, String name, boolean writeAccess, Class<? extends ObjectRepository>... objectRepositories) {
+ public RepositorySetDescriptor(URL location, String customer, String name, boolean writeAccess, Class<? extends ObjectRepository>... objectRepositories) {
m_location = location;
m_customer = customer;
m_name = name;
@@ -127,4 +172,94 @@ class RepositoryAdminLoginContextImpl im
return "Repository location " + m_location.toString() + ", customer " + m_customer + ", name " + m_name;
}
}
+
+ static abstract class AbstractRepositoryContext<T extends BaseRepositoryContext<?>> implements BaseRepositoryContext<T>
+ {
+ private URL m_location;
+ private String m_name;
+ private String m_customer;
+ private boolean m_writeable;
+ private final Class<? extends ObjectRepository<?>>[] m_repositories;
+
+ public AbstractRepositoryContext(Class<? extends ObjectRepository<?>>... repositories) {
+ if (repositories == null || repositories.length == 0) {
+ throw new IllegalArgumentException("Need at least one object repository!");
+ }
+ m_repositories = repositories;
+ }
+
+ public T setCustomer(String customer) {
+ if (customer == null) {
+ throw new IllegalArgumentException("Customer cannot be null!");
+ }
+ m_customer = customer;
+ return getThis();
+ }
+
+ public T setLocation(URL location) {
+ if (location == null) {
+ throw new IllegalArgumentException("Location cannot be null!");
+ }
+ m_location = location;
+ return getThis();
+ }
+
+ public T setName(String name) {
+ if (name == null) {
+ throw new IllegalArgumentException("Name cannot be null!");
+ }
+ m_name = name;
+ return getThis();
+ }
+
+ public T setWriteable() {
+ m_writeable = true;
+ return getThis();
+ }
+
+ /**
+ * @return a new repository set descriptor, never <code>null</code>.
+ */
+ final RepositorySetDescriptor createDescriptor() {
+ return new RepositorySetDescriptor(m_location, m_customer, m_name, m_writeable, m_repositories);
+ }
+
+ abstract T getThis();
+ }
+
+ static final class ShopRepositoryContextImpl extends AbstractRepositoryContext<ShopRepositoryContext> implements ShopRepositoryContext {
+
+ public ShopRepositoryContextImpl() {
+ super(ArtifactRepository.class, FeatureRepository.class, Artifact2FeatureAssociationRepository.class, DistributionRepository.class, Feature2DistributionAssociationRepository.class);
+ }
+
+ @Override
+ ShopRepositoryContext getThis() {
+ return this;
+ }
+ }
+
+ static final class TargetRepositoryContextImpl extends AbstractRepositoryContext<TargetRepositoryContext> implements TargetRepositoryContext {
+
+ public TargetRepositoryContextImpl() {
+ super(TargetRepository.class, Distribution2TargetAssociationRepository.class);
+ }
+
+ @Override
+ TargetRepositoryContext getThis() {
+ return this;
+ }
+ }
+
+ static final class DeploymentRepositoryContextImpl extends AbstractRepositoryContext<DeploymentRepositoryContext> implements DeploymentRepositoryContext {
+
+ public DeploymentRepositoryContextImpl() {
+ super(DeploymentVersionRepository.class);
+ }
+
+ @Override
+ DeploymentRepositoryContext getThis() {
+ return this;
+ }
+ }
}
Modified: ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java?rev=1329199&r1=1329198&r2=1329199&view=diff
==============================================================================
--- ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java (original)
+++ ace/trunk/ace-client-repository-impl/src/main/java/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java Mon Apr 23 12:15:01 2012
@@ -74,8 +74,7 @@ public class StatefulTargetRepositoryImp
private LogService m_log; /* Injected by dependency manager */
private BundleHelper m_bundleHelper; /* Injected by dependency manager */
// TODO: Make the concurrencyLevel of this concurrent hashmap settable?
- private Map<String, StatefulTargetObjectImpl> m_repository =
- new ConcurrentHashMap<String, StatefulTargetObjectImpl>();
+ private Map<String, StatefulTargetObjectImpl> m_repository = new ConcurrentHashMap<String, StatefulTargetObjectImpl>();
private Map<String, StatefulTargetObjectImpl> m_index = new ConcurrentHashMap<String, StatefulTargetObjectImpl>();
private final String m_sessionID;
Modified: ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/CachedRepositoryImplTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/CachedRepositoryImplTest.java?rev=1329199&r1=1329198&r2=1329199&view=diff
==============================================================================
--- ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/CachedRepositoryImplTest.java (original)
+++ ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/CachedRepositoryImplTest.java Mon Apr 23 12:15:01 2012
@@ -43,7 +43,7 @@ public class CachedRepositoryImplTest {
m_repository.commit(new ByteArrayInputStream(testContent), 0);
BackupRepository m_backupRepository = new MockBackupRepository();
- CachedRepository m_cachedRepository = new CachedRepositoryImpl(null, m_repository, m_backupRepository, 0);
+ CachedRepository m_cachedRepository = new CachedRepositoryImpl(m_repository, m_backupRepository, 0);
InputStream input = m_cachedRepository.checkout(1);
byte[] inputBytes = AdminTestUtil.copy(input);
@@ -67,13 +67,13 @@ public class CachedRepositoryImplTest {
Repository m_repository = new MockRepository();
BackupRepository m_backupRepository = new MockBackupRepository();
- CachedRepository m_cachedRepository = new CachedRepositoryImpl(null, m_repository, m_backupRepository, 0);
+ CachedRepository m_cachedRepository = new CachedRepositoryImpl(m_repository, m_backupRepository, 0);
byte[] testContent = new byte[] {'i', 'n', 'i', 't', 'i', 'a', 'l'};
InputStream input = new ByteArrayInputStream(testContent);
m_cachedRepository.commit(input, 0);
- m_cachedRepository = new CachedRepositoryImpl(null, m_repository, m_backupRepository, 0);
+ m_cachedRepository = new CachedRepositoryImpl(m_repository, m_backupRepository, 0);
input = m_cachedRepository.checkout(1);
byte[] inputBytes = AdminTestUtil.copy(input);
assert AdminTestUtil.byteArraysEqual(inputBytes, testContent) : "We got something different than 'initial' from checkout: " + new String(inputBytes);
@@ -84,7 +84,7 @@ public class CachedRepositoryImplTest {
m_cachedRepository.commit();
- m_cachedRepository = new CachedRepositoryImpl(null, m_repository, m_backupRepository, 0);
+ m_cachedRepository = new CachedRepositoryImpl(m_repository, m_backupRepository, 0);
input = m_cachedRepository.checkout(2);
inputBytes = AdminTestUtil.copy(input);
assert AdminTestUtil.byteArraysEqual(inputBytes, newTestContent) : "We got something different than 'new' from checkout: " + new String(inputBytes);
@@ -100,13 +100,13 @@ public class CachedRepositoryImplTest {
Repository m_repository = new MockRepository();
BackupRepository m_backupRepository = new MockBackupRepository();
- CachedRepository m_cachedRepository = new CachedRepositoryImpl(null, m_repository, m_backupRepository, 0);
+ CachedRepository m_cachedRepository = new CachedRepositoryImpl(m_repository, m_backupRepository, 0);
byte[] testContent = new byte[] {'i', 'n', 'i', 't', 'i', 'a', 'l'};
InputStream input = new ByteArrayInputStream(testContent);
m_cachedRepository.commit(input, 0);
- m_cachedRepository = new CachedRepositoryImpl(null, m_repository, m_backupRepository, 0);
+ m_cachedRepository = new CachedRepositoryImpl(m_repository, m_backupRepository, 0);
input = m_cachedRepository.checkout(1);
byte[] newTestContent = new byte[] {'n', 'e', 'w'};
Added: ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImplTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImplTest.java?rev=1329199&view=auto
==============================================================================
--- ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImplTest.java (added)
+++ ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImplTest.java Mon Apr 23 12:15:01 2012
@@ -0,0 +1,82 @@
+/*
+ * 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.net.URL;
+
+import org.apache.ace.client.repository.impl.RepositoryAdminLoginContextImpl.RepositorySetDescriptor;
+import org.apache.ace.client.repository.repository.ArtifactRepository;
+import org.apache.ace.client.repository.repository.FeatureRepository;
+import org.apache.ace.test.constants.TestConstants;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.service.useradmin.User;
+
+/**
+ * Test cases for {@link RepositoryAdminLoginContextImpl}.
+ */
+public class RepositoryAdminLoginContextImplTest {
+
+ private static final String CUSTOMER = "apache";
+
+ private static final String NAME_SHOP = "shop";
+ private static final String NAME_DEPLOYMENT = "deployment";
+
+ private URL m_location;
+
+ @Before
+ public void setUp() throws Exception {
+ m_location = new URL("http://localhost:" + TestConstants.PORT);
+ }
+
+ /**
+ * Test method for {@link RepositoryAdminLoginContextImpl#addDescriptor(RepositorySetDescriptor)}.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddDuplicateObjectRepositoryFail() throws Exception {
+ RepositoryAdminLoginContextImpl context = new RepositoryAdminLoginContextImpl(Mockito.mock(User.class), "12345");
+
+ context.addDescriptor(new RepositorySetDescriptor(m_location, CUSTOMER, NAME_SHOP, true, FeatureRepository.class));
+ context.addDescriptor(new RepositorySetDescriptor(m_location, CUSTOMER, NAME_DEPLOYMENT, true, FeatureRepository.class));
+ }
+
+ /**
+ * Test method for {@link RepositoryAdminLoginContextImpl#addDescriptor(RepositorySetDescriptor)}.
+ */
+ @Test
+ public void testAddDisjointObjectRepositoriesOk() throws Exception {
+ RepositoryAdminLoginContextImpl context = new RepositoryAdminLoginContextImpl(Mockito.mock(User.class), "12345");
+
+ context.addDescriptor(new RepositorySetDescriptor(m_location, CUSTOMER, NAME_SHOP, true, ArtifactRepository.class));
+ context.addDescriptor(new RepositorySetDescriptor(m_location, CUSTOMER, NAME_DEPLOYMENT, true, FeatureRepository.class));
+ }
+
+ /**
+ * Test method for {@link RepositoryAdminLoginContextImpl#addDescriptor(RepositorySetDescriptor)}.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testDuplicateRepositoryNameFail() throws Exception {
+ RepositoryAdminLoginContextImpl context = new RepositoryAdminLoginContextImpl(Mockito.mock(User.class), "12345");
+
+ context.addDescriptor(new RepositorySetDescriptor(m_location, CUSTOMER, NAME_SHOP, true, ArtifactRepository.class));
+ context.addDescriptor(new RepositorySetDescriptor(m_location, CUSTOMER, NAME_SHOP, true, FeatureRepository.class));
+ }
+}
Propchange: ace/trunk/ace-client-repository-impl/src/test/java/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImplTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: ace/trunk/ace-client-rest/pom.xml
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-rest/pom.xml?rev=1329199&r1=1329198&r2=1329199&view=diff
==============================================================================
--- ace/trunk/ace-client-rest/pom.xml (original)
+++ ace/trunk/ace-client-rest/pom.xml Mon Apr 23 12:15:01 2012
@@ -60,6 +60,10 @@
</dependency>
<dependency>
<groupId>org.apache.ace</groupId>
+ <artifactId>org.apache.ace.connectionfactory</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ace</groupId>
<artifactId>org.apache.ace.client.repository.api</artifactId>
</dependency>
<dependency>
Modified: ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java?rev=1329199&r1=1329198&r2=1329199&view=diff
==============================================================================
--- ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java (original)
+++ ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java Mon Apr 23 12:15:01 2012
@@ -57,6 +57,8 @@ public class RESTClientServlet extends H
private static final String LATEST_FOLDER = "latest";
/** Name of the folder where working copies are kept. */
private static final String WORK_FOLDER = "work";
+ /** A boolean denoting whether or not authentication is enabled. */
+ private static final String KEY_USE_AUTHENTICATION = "authentication.enabled";
/** URL of the repository to talk to. */
private static final String KEY_REPOSITORY_URL = "repository.url";
/** URL of the OBR to talk to. */
@@ -69,7 +71,7 @@ public class RESTClientServlet extends H
private static final String KEY_DISTRIBUTION_REPOSITORY_NAME = "distribution.repository.name";
/** Name of the deployment repository. */
private static final String KEY_DEPLOYMENT_REPOSITORY_NAME = "deployment.repository.name";
- /** Name of the user to log in as. */
+ /** Name of the user to log in as, in case no actual authentication is used. */
private static final String KEY_USER_NAME = "user.name";
/** The action name for approving targets. */
private static final String ACTION_APPROVE = "approve";
@@ -88,6 +90,7 @@ public class RESTClientServlet extends H
private final Map<String, Component> m_workspaceComponents;
private final Gson m_gson;
+ private boolean m_useAuthentication;
private String m_repositoryURL;
private String m_obrURL;
private String m_customerName;
@@ -110,10 +113,17 @@ public class RESTClientServlet extends H
}
public void updated(Dictionary properties) throws ConfigurationException {
+ // First check whether all mandatory configuration keys are available...
+ String useAuth = getProperty(properties, KEY_USE_AUTHENTICATION);
+ if (useAuth == null || !("true".equalsIgnoreCase(useAuth) || "false".equalsIgnoreCase(useAuth))) {
+ throw new ConfigurationException(KEY_USE_AUTHENTICATION, "Missing or invalid value!");
+ }
+
// Note that configuration changes are only applied to new work areas, started after the
// configuration was changed. No attempt is done to "fix" existing work areas, although we
// might consider flushing/invalidating them.
synchronized (m_workspaces) {
+ m_useAuthentication = Boolean.valueOf(useAuth);
m_repositoryURL = getProperty(properties, KEY_REPOSITORY_URL, "http://localhost:8080/repository");
m_obrURL = getProperty(properties, KEY_OBR_URL, "http://localhost:8080/obr");
m_customerName = getProperty(properties, KEY_CUSTOMER_NAME, "apache");
@@ -176,13 +186,25 @@ public class RESTClientServlet extends H
* @return a property value, can be <code>null</code>.
*/
String getProperty(Dictionary properties, String key, String defaultValue) {
+ String value = getProperty(properties, key);
+ return (value == null) ? defaultValue : value;
+ }
+
+ /**
+ * Helper method to safely obtain a property value from the given dictionary.
+ *
+ * @param properties the dictionary to retrieve the value from, can be <code>null</code>;
+ * @param key the name of the property to retrieve, cannot be <code>null</code>.
+ * @return a property value, can be <code>null</code>.
+ */
+ String getProperty(Dictionary properties, String key) {
if (properties != null) {
Object value = properties.get(key);
if (value != null && value instanceof String) {
return (String) value;
}
}
- return defaultValue;
+ return null;
}
/**
@@ -391,7 +413,7 @@ public class RESTClientServlet extends H
synchronized (m_workspaces) {
sessionID = "rest-" + m_sessionID++;
- workspace = new Workspace(sessionID, m_repositoryURL, m_obrURL, m_customerName, m_storeRepositoryName, m_targetRepositoryName, m_deploymentRepositoryName, m_serverUser);
+ workspace = new Workspace(sessionID, m_repositoryURL, m_obrURL, m_customerName, m_storeRepositoryName, m_targetRepositoryName, m_deploymentRepositoryName, m_useAuthentication, m_serverUser);
m_workspaces.put(sessionID, workspace);
component = m_dm.createComponent().setImplementation(workspace);
Modified: ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java?rev=1329199&r1=1329198&r2=1329199&view=diff
==============================================================================
--- ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java (original)
+++ ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java Mon Apr 23 12:15:01 2012
@@ -19,6 +19,7 @@
package org.apache.ace.client.rest;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
@@ -32,6 +33,7 @@ import javax.servlet.http.HttpServletReq
import org.apache.ace.authentication.api.AuthenticationService;
import org.apache.ace.client.repository.ObjectRepository;
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.SessionFactory;
import org.apache.ace.client.repository.repository.Artifact2FeatureAssociationRepository;
@@ -57,14 +59,17 @@ public class Workspace {
static final String DISTRIBUTION = "distribution";
static final String DISTRIBUTION2TARGET = "distribution2target";
static final String TARGET = "target";
+
private final String m_sessionID;
- private final String m_repositoryURL;
- private final String m_obrURL;
+ private final URL m_repositoryURL;
+ private final URL m_obrURL;
private final String m_customerName;
private final String m_storeRepositoryName;
private final String m_distributionRepositoryName;
private final String m_deploymentRepositoryName;
private final String m_serverUser;
+ private final boolean m_useAuthentication;
+
private volatile AuthenticationService m_authenticationService;
private volatile DependencyManager m_manager;
private volatile RepositoryAdmin m_repositoryAdmin;
@@ -78,14 +83,15 @@ public class Workspace {
private volatile UserAdmin m_userAdmin;
private volatile LogService m_log;
- public Workspace(String sessionID, String repositoryURL, String obrURL, String customerName, String storeRepositoryName, String distributionRepositoryName, String deploymentRepositoryName, String serverUser) {
+ public Workspace(String sessionID, String repositoryURL, String obrURL, String customerName, String storeRepositoryName, String distributionRepositoryName, String deploymentRepositoryName, boolean useAuthentication, String serverUser) throws MalformedURLException {
m_sessionID = sessionID;
- m_repositoryURL = repositoryURL;
- m_obrURL = obrURL;
+ m_repositoryURL = new URL(repositoryURL);
+ m_obrURL = new URL(obrURL);
m_customerName = customerName;
m_storeRepositoryName = storeRepositoryName;
m_distributionRepositoryName = distributionRepositoryName;
m_deploymentRepositoryName = deploymentRepositoryName;
+ m_useAuthentication = useAuthentication;
m_serverUser = serverUser;
}
@@ -122,7 +128,7 @@ public class Workspace {
addSessionDependency(component, Artifact2FeatureAssociationRepository.class, true);
addSessionDependency(component, Feature2DistributionAssociationRepository.class, true);
addSessionDependency(component, Distribution2TargetAssociationRepository.class, true);
- addDependency(component, AuthenticationService.class, true);
+ addDependency(component, AuthenticationService.class, m_useAuthentication);
addDependency(component, UserAdmin.class, true);
addDependency(component, LogService.class, false);
}
@@ -135,23 +141,40 @@ public class Workspace {
public boolean login(HttpServletRequest request) {
try {
- User user = m_authenticationService.authenticate(request);
- if (user == null) {
- // No user obtained through request; try fallback scenario...
- // TODO this shouldn't be here, but otherwise we break all existing clients
+ final User user;
+ if (m_useAuthentication) {
+ // Use the authentication service to authenticate the given request...
+ user = m_authenticationService.authenticate(request);
+ } else {
+ // Use the "hardcoded" user to login with...
user = m_userAdmin.getUser("username", m_serverUser);
- if (user == null) {
- // Still no user obtained; no succesful login...
- return false;
- }
}
+
+ if (user == null) {
+ // No user obtained through request/fallback scenario; login failed...
+ return false;
+ }
+
+ RepositoryAdminLoginContext context = m_repositoryAdmin.createLoginContext(user);
+
+ context.setObrBase(m_obrURL)
+ .add(context.createShopRepositoryContext()
+ .setLocation(m_repositoryURL)
+ .setCustomer(m_customerName)
+ .setName(m_storeRepositoryName)
+ .setWriteable())
+ .add(context.createTargetRepositoryContext()
+ .setLocation(m_repositoryURL)
+ .setCustomer(m_customerName)
+ .setName(m_distributionRepositoryName)
+ .setWriteable())
+ .add(context.createDeploymentRepositoryContext()
+ .setLocation(m_repositoryURL)
+ .setCustomer(m_customerName)
+ .setName(m_deploymentRepositoryName)
+ .setWriteable());
- m_repositoryAdmin.login(m_repositoryAdmin.createLoginContext(user)
- .setObrBase(new URL(m_obrURL))
- .addShopRepository(new URL(m_repositoryURL), m_customerName, m_storeRepositoryName, true)
- .addTargetRepository(new URL(m_repositoryURL), m_customerName, m_distributionRepositoryName, true)
- .addDeploymentRepository(new URL(m_repositoryURL), m_customerName, m_deploymentRepositoryName, true)
- );
+ m_repositoryAdmin.login(context);
m_repositoryAdmin.checkout();
}
catch (IOException e) {
Modified: ace/trunk/ace-configurator-useradmin-task/src/main/java/org/apache/ace/configurator/useradmin/task/UpdateUserAdminTask.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-configurator-useradmin-task/src/main/java/org/apache/ace/configurator/useradmin/task/UpdateUserAdminTask.java?rev=1329199&r1=1329198&r2=1329199&view=diff
==============================================================================
--- ace/trunk/ace-configurator-useradmin-task/src/main/java/org/apache/ace/configurator/useradmin/task/UpdateUserAdminTask.java (original)
+++ ace/trunk/ace-configurator-useradmin-task/src/main/java/org/apache/ace/configurator/useradmin/task/UpdateUserAdminTask.java Mon Apr 23 12:15:01 2012
@@ -22,14 +22,17 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.util.Dictionary;
import java.util.Properties;
+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.resourceprocessor.useradmin.UserAdminConfigurator;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
import org.osgi.framework.BundleContext;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
@@ -56,13 +59,40 @@ public class UpdateUserAdminTask impleme
private static final String FILE_ROOT = "userrepositories";
private static final String VERSION = "version";
- private volatile UserAdminConfigurator m_configurator; /* Will be injected by dependency manager */
- private volatile LogService m_log; /* Will be injected by dependency manager */
- private volatile BundleContext m_context; /* Will be injected by dependency manager */
+ // Will by injected by Dependency Manager...
+ private volatile UserAdminConfigurator m_configurator;
+ private volatile LogService m_log;
+ private volatile BundleContext m_context;
private CachedRepository m_repo;
+ private BackupRepository m_backup;
+ private String m_repoFilter;
private File m_properties;
+
+ /**
+ * Called by Dependency Manager upon initialization of this component.
+ * <p>
+ * Due to the dependency on the configuration; the {@link #updated(Dictionary)} method is already called!
+ * </p>
+ *
+ * @param comp this component, cannot be <code>null</code>.
+ */
+ public void init(Component comp) {
+ final DependencyManager dm = comp.getDependencyManager();
+ // Add the required dependency to the remote repository...
+ comp.add(dm.createServiceDependency()
+ .setService(Repository.class, m_repoFilter)
+ .setCallbacks("addRepo", "removeRepo")
+ .setInstanceBound(true)
+ .setRequired(true)
+ );
+ }
+ /**
+ * Checks whether there are updates to the remote repository, and if so, updates the users' backend with its contents.
+ *
+ * @see java.lang.Runnable#run()
+ */
public void run() {
try {
if (!m_repo.isCurrent()) {
@@ -78,7 +108,12 @@ public class UpdateUserAdminTask impleme
}
}
- public void start() {
+ /**
+ * Called by Dependency Manager upon starting of this component.
+ *
+ * @param comp this component, cannot be <code>null</code>.
+ */
+ public void start(Component comp) {
try {
// Try to read the server data
m_configurator.setUsers(m_repo.checkout(true));
@@ -96,50 +131,8 @@ public class UpdateUserAdminTask impleme
}
}
- /**
- * Loads the most recent version from the given properties file.
- */
- private long loadVersion(File propertiesfile) {
- long result = CachedRepositoryImpl.UNCOMMITTED_VERSION;
- try {
- Properties props = new Properties();
- props.loadFromXML(new FileInputStream(propertiesfile));
- result = Long.parseLong((String) props.get(VERSION));
- }
- catch (IOException ioe) {
- // We have no data; no problem.
- }
- return result;
- }
-
- /**
- * Saves the most recent version to the given properties file.
- */
- private void saveVersion(File properties, Long version) {
- Properties props = new Properties();
- props.put(VERSION, version.toString());
- try {
- FileOutputStream fileOutputStream = new FileOutputStream(properties);
- props.storeToXML(fileOutputStream, null);
- }
- catch (IOException e) {
- m_log.log(LogService.LOG_ERROR, "UpdateUserAdminTask failed to save local version number.");
- }
- }
-
public void updated(Dictionary dict) throws ConfigurationException {
if (dict != null) {
- String locationString = (String) dict.get(KEY_REPOSITORY_LOCATION);
- if (locationString == null) {
- throw new ConfigurationException(KEY_REPOSITORY_LOCATION, "Property missing.");
- }
- URL location;
- try {
- location = new URL(locationString);
- }
- catch (MalformedURLException e) {
- throw new ConfigurationException(KEY_REPOSITORY_LOCATION, "Location " + locationString + " is not a valid URL.");
- }
String customer = (String) dict.get(KEY_REPOSITORY_CUSTOMER);
if (customer == null) {
throw new ConfigurationException(KEY_REPOSITORY_CUSTOMER, "Property missing.");
@@ -149,15 +142,36 @@ public class UpdateUserAdminTask impleme
throw new ConfigurationException(KEY_REPOSITORY_NAME, "Property missing.");
}
- String fileRoot = FILE_ROOT + File.separator + location.getAuthority().replace(':', '-') + location.getPath().replace('/', '\\') + File.separator + customer + File.separator + name + File.separator;
+ String fileRoot = FILE_ROOT + File.separator + customer + File.separator + name + File.separator;
+
File local = getFile(fileRoot + "local");
File backup = getFile(fileRoot + "backup");
+ m_backup = new FilebasedBackupRepository(local, backup);
+
m_properties = getFile(fileRoot + "properties");
-
- m_repo = new CachedRepositoryImpl(null, location, customer, name, local, backup, loadVersion(m_properties));
+
+ m_repoFilter = "(&(customer=" + customer + ")(name=" + name + "))";
}
}
+ /**
+ * Creates the cached repository when given a remote repository.
+ *
+ * @param remoteRepo the remote repository to add, cannot be <code>null</code>.
+ */
+ final void addRepo(Repository remoteRepo) {
+ m_repo = new CachedRepositoryImpl(remoteRepo, m_backup, loadVersion(m_properties));
+ }
+
+ /**
+ * Removes the cached repository when given a remote repository.
+ *
+ * @param remoteRepo the remote repository to remove, cannot be <code>null</code>.
+ */
+ final void removeRepo(Repository remoteRepo) {
+ m_repo = null;
+ }
+
private File getFile(String name) {
File result = m_context.getDataFile(name);
if (!result.exists()) {
@@ -174,4 +188,34 @@ public class UpdateUserAdminTask impleme
return result;
}
+ /**
+ * Loads the most recent version from the given properties file.
+ */
+ private long loadVersion(File propertiesfile) {
+ long result = CachedRepositoryImpl.UNCOMMITTED_VERSION;
+ try {
+ Properties props = new Properties();
+ props.loadFromXML(new FileInputStream(propertiesfile));
+ result = Long.parseLong((String) props.get(VERSION));
+ }
+ catch (IOException ioe) {
+ // We have no data; no problem.
+ }
+ return result;
+ }
+
+ /**
+ * Saves the most recent version to the given properties file.
+ */
+ private void saveVersion(File properties, Long version) {
+ Properties props = new Properties();
+ props.put(VERSION, version.toString());
+ try {
+ FileOutputStream fileOutputStream = new FileOutputStream(properties);
+ props.storeToXML(fileOutputStream, null);
+ }
+ catch (IOException e) {
+ m_log.log(LogService.LOG_ERROR, "UpdateUserAdminTask failed to save local version number.");
+ }
+ }
}
\ No newline at end of file
Propchange: ace/trunk/ace-connectionfactory/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Apr 23 12:15:01 2012
@@ -0,0 +1,14 @@
+.metadata
+.settings
+bin
+.classpath
+.project
+target
+*.ipr
+*.iws
+*.iml
+store
+test-output
+velocity.log
+
+
Added: ace/trunk/ace-connectionfactory/pom.xml
URL: http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/pom.xml?rev=1329199&view=auto
==============================================================================
--- ace/trunk/ace-connectionfactory/pom.xml (added)
+++ ace/trunk/ace-connectionfactory/pom.xml Mon Apr 23 12:15:01 2012
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.ace</groupId>
+ <artifactId>ace-pom</artifactId>
+ <version>0.8.1-SNAPSHOT</version>
+ <relativePath>../pom/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>org.apache.ace.connectionfactory</artifactId>
+
+ <name>Apache ACE :: Connection Factory</name>
+ <description>Provides a service for creating connections to remote resources.</description>
+ <packaging>bundle</packaging>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/ace/trunk/ace-connectionfactory</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/ace/trunk/ace-connectionfactory</developerConnection>
+ <url>http://svn.apache.org/repos/asf/ace/trunk/ace-connectionfactory</url>
+ </scm>
+
+ <properties>
+ <import.package>
+ org.apache.ace.connectionfactory;version=${project.version},
+ org.osgi.framework,
+ org.osgi.service.cm,
+ org.osgi.service.useradmin
+ </import.package>
+ <export.package>
+ org.apache.ace.connectionfactory;version=${project.version},
+ </export.package>
+ <private.package>
+ org.apache.ace.connectionfactory.impl,
+ org.apache.commons.codec,
+ org.apache.commons.codec.binary
+ </private.package>
+ <bundle.activator>org.apache.ace.connectionfactory.impl.Activator</bundle.activator>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ </dependencies>
+</project>
Propchange: ace/trunk/ace-connectionfactory/pom.xml
------------------------------------------------------------------------------
svn:eol-style = native
Added: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/ConnectionFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/ConnectionFactory.java?rev=1329199&view=auto
==============================================================================
--- ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/ConnectionFactory.java (added)
+++ ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/ConnectionFactory.java Mon Apr 23 12:15:01 2012
@@ -0,0 +1,53 @@
+/*
+ * 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.connectionfactory;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import org.osgi.service.useradmin.User;
+
+/**
+ * Provides a service to create {@link URLConnection}s. The connection factory will be responsible
+ * for supplying the necessary credentials to ensure the authentication of the connection succeeds.
+ */
+public interface ConnectionFactory {
+
+ /**
+ * Creates a new connection using the given URL, using the (optional) credentials.
+ *
+ * @param url the URL to connect to, cannot be <code>null</code>.
+ * @return a {@link URLConnection} instance, never <code>null</code>.
+ * @throws IllegalArgumentException in case the given URL was <code>null</code>;
+ * @throws IOException in case the creation of the connection failed.
+ */
+ URLConnection createConnection(URL url) throws IOException;
+
+ /**
+ * Creates a new connection using the given URL, using the (optional) credentials.
+ *
+ * @param url the URL to connect to, cannot be <code>null</code>;
+ * @param user the user to fetch the credentials from, cannot be <code>null</code>.
+ * @return a {@link URLConnection} instance, never <code>null</code>.
+ * @throws IllegalArgumentException in case the given URL was <code>null</code>, or when the supplied credentials are missing information;
+ * @throws IOException in case the creation of the connection failed.
+ */
+ URLConnection createConnection(URL url, User user) throws IOException;
+}
Propchange: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/ConnectionFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/Activator.java?rev=1329199&view=auto
==============================================================================
--- ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/Activator.java (added)
+++ ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/Activator.java Mon Apr 23 12:15:01 2012
@@ -0,0 +1,53 @@
+/*
+ * 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.connectionfactory.impl;
+
+import java.util.Properties;
+
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+/**
+ * Provides the bundle activator for the {@link ConnectionFactoryImpl} service.
+ */
+public class Activator implements BundleActivator {
+
+ /**
+ * {@inheritDoc}
+ */
+ public void start(BundleContext context) throws Exception {
+ Properties props = new Properties();
+ props.put(Constants.SERVICE_PID, ConnectionFactoryImpl.FACTORY_PID);
+ props.put("impl.type", "jdk");
+
+ context.registerService(new String[]{ ConnectionFactory.class.getName(), ManagedServiceFactory.class.getName() },
+ new ConnectionFactoryImpl(), props);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stop(BundleContext context) throws Exception {
+ // Nop
+ }
+}
Propchange: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/Activator.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java?rev=1329199&view=auto
==============================================================================
--- ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java (added)
+++ ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java Mon Apr 23 12:15:01 2012
@@ -0,0 +1,208 @@
+/*
+ * 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.connectionfactory.impl;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType;
+import org.apache.ace.connectionfactory.impl.UrlCredentialsFactory.MissingValueException;
+import org.apache.commons.codec.binary.Base64;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.useradmin.User;
+
+/**
+ * Provides a default implementation for {@link ConnectionFactory} based on the standard <code>java.net</code>
+ * implementation of {@link URLConnection}.
+ */
+public class ConnectionFactoryImpl implements ConnectionFactory, ManagedServiceFactory {
+
+ public static final String FACTORY_PID = "org.apache.ace.connectionfactory";
+
+ private static final String HTTP_HEADER_AUTHORIZATION = "Authorization";
+
+ private final Map<String /* config PID */, UrlCredentials> m_credentialMapping;
+
+ /**
+ * Creates a new {@link ConnectionFactoryImpl}.
+ */
+ public ConnectionFactoryImpl() {
+ m_credentialMapping = new HashMap<String, UrlCredentials>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public URLConnection createConnection(URL url) throws IOException {
+ if (url == null) {
+ throw new IllegalArgumentException("URL cannot be null!");
+ }
+
+ URLConnection conn = url.openConnection();
+
+ UrlCredentials creds = getCredentials(url);
+ if (creds != null) {
+ supplyCredentials(conn, creds);
+ }
+
+ return conn;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public URLConnection createConnection(URL url, User user) throws IOException {
+ if (url == null) {
+ throw new IllegalArgumentException("URL cannot be null!");
+ }
+ if (user == null) {
+ throw new IllegalArgumentException("User cannot be null!");
+ }
+
+ URLConnection conn = url.openConnection();
+
+ UrlCredentials creds = getCredentials(url);
+ if (creds != null) {
+ // TODO apply user!
+ supplyCredentials(conn, creds);
+ }
+
+ return conn;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void deleted(String pid) {
+ synchronized (m_credentialMapping) {
+ m_credentialMapping.remove(pid);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getName() {
+ return "HTTP Connection Factory";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void updated(String pid, Dictionary properties) throws ConfigurationException {
+ UrlCredentials creds;
+ synchronized (m_credentialMapping) {
+ creds = m_credentialMapping.get(pid);
+ }
+
+ if (creds == null) {
+ try {
+ creds = UrlCredentialsFactory.getCredentials(properties);
+
+ synchronized (m_credentialMapping) {
+ m_credentialMapping.put(pid, creds);
+ }
+ }
+ catch (MissingValueException e) {
+ throw new ConfigurationException(e.getProperty(), e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Returns the credentials to access the given URL.
+ *
+ * @param url the URL to find the credentials for, cannot be <code>null</code>.
+ * @return a {@link UrlCredentials} instance for the given URL, or <code>null</code>
+ * if none were found, or if none were necessary.
+ */
+ private UrlCredentials getCredentials(URL url) {
+ Collection<UrlCredentials> creds;
+ synchronized (m_credentialMapping) {
+ creds = new ArrayList<UrlCredentials>(m_credentialMapping.values());
+ }
+
+ for (UrlCredentials c : creds) {
+ if (c.matches(url)) {
+ return c;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the authorization header for HTTP Basic Authentication.
+ *
+ * @param creds the credentials to supply.
+ * @return a string that denotes the basic authentication header ("Basic " + encoded credentials), never <code>null</code>.
+ */
+ private String getBasicAuthCredentials(UrlCredentials creds) {
+ final Object[] values = creds.getCredentials();
+ if (values.length < 2) {
+ throw new IllegalArgumentException("Insufficient credentials passed! Expected 2 values, got " + values.length + " values.");
+ }
+
+ StringBuilder sb = new StringBuilder();
+ if (values[0] instanceof String) {
+ sb.append((String) values[0]);
+ }
+ else if (values[0] instanceof byte[]) {
+ sb.append(new String((byte[]) values[0]));
+ }
+ sb.append(':');
+ if (values[1] instanceof String) {
+ sb.append((String) values[1]);
+ }
+ else if (values[1] instanceof byte[]) {
+ sb.append(new String((byte[]) values[1]));
+ }
+
+ return "Basic " + Base64.encodeBase64String(sb.toString().getBytes());
+ }
+
+ /**
+ * Supplies the actual credentials to the given {@link URLConnection}.
+ *
+ * @param conn the connection to supply the credentials to, cannot be <code>null</code>;
+ * @param creds the credentials to supply, cannot be <code>null</code>.
+ * @throws IOException in case of I/O problems.
+ */
+ private void supplyCredentials(URLConnection conn, UrlCredentials creds) throws IOException {
+ final AuthType type = creds.getType();
+
+ if (AuthType.BASIC.equals(type)) {
+ if (conn instanceof HttpURLConnection) {
+ conn.setRequestProperty(HTTP_HEADER_AUTHORIZATION, getBasicAuthCredentials(creds));
+ }
+ }
+ else if (!AuthType.NONE.equals(type)) {
+ throw new IllegalArgumentException("Unknown authentication type: " + type);
+ }
+ }
+}
Propchange: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java?rev=1329199&view=auto
==============================================================================
--- ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java (added)
+++ ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java Mon Apr 23 12:15:01 2012
@@ -0,0 +1,131 @@
+/*
+ * 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.connectionfactory.impl;
+
+import java.net.URL;
+import java.util.Arrays;
+
+/**
+ * Small container for holding URL credentials.
+ */
+final class UrlCredentials {
+
+ static enum AuthType {
+ /** Indicates no authentication. */
+ NONE,
+ /** Indicates basic HTTP authentication. */
+ BASIC;
+ }
+
+ private final AuthType m_type;
+ private final URL m_baseURL;
+ private final Object[] m_credentials;
+
+ /**
+ * Creates a new, anonymous, {@link UrlCredentials} instance.
+ *
+ * @param baseURL the base URL for which to apply the credentials, cannot be <code>null</code>.
+ */
+ public UrlCredentials(URL baseURL) {
+ this(AuthType.NONE, baseURL);
+ }
+
+ /**
+ * Creates a new {@link UrlCredentials} instance.
+ *
+ * @param type the authentication type to use for the authentication of the URL, cannot be <code>null</code>;
+ * @param baseURL the base URL for which to apply the credentials, cannot be <code>null</code>;
+ * @param credentials the credentials to use, cannot be <code>null</code>, but may be empty.
+ */
+ public UrlCredentials(AuthType type, URL baseURL, Object... credentials) {
+ m_type = type;
+ m_baseURL = baseURL;
+ m_credentials = (credentials == null) ? new Object[0] : credentials.clone();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+
+ UrlCredentials other = (UrlCredentials) obj;
+ if (m_type != other.m_type) {
+ return false;
+ }
+ if (!m_baseURL.equals(other.m_baseURL)) {
+ return false;
+ }
+ if (!Arrays.equals(m_credentials, other.m_credentials)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether or not the given URL can be mapped to our own base URL.
+ *
+ * @param url the URL to map, may be <code>null</code> in which case <code>false</code> will be returned.
+ * @return <code>true</code> if the given URL maps to our base URL, <code>false</code> otherwise.
+ */
+ public boolean matches(URL url) {
+ if (url == null) {
+ return false;
+ }
+
+ String baseURL = m_baseURL.toExternalForm();
+ return url.toExternalForm().startsWith(baseURL);
+ }
+
+ /**
+ * Returns the credentials for a URL.
+ *
+ * @return the credentials, never <code>null</code>.
+ */
+ public Object[] getCredentials() {
+ return m_credentials.clone();
+ }
+
+ /**
+ * Returns the authentication type.
+ *
+ * @return the type of authentication to use.
+ */
+ public AuthType getType() {
+ return m_type;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((m_type == null) ? 0 : m_type.hashCode());
+ result = prime * result + ((m_baseURL == null) ? 0 : m_baseURL.hashCode());
+ result = prime * result + Arrays.hashCode(m_credentials);
+ return result;
+ }
+}
Propchange: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java?rev=1329199&view=auto
==============================================================================
--- ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java (added)
+++ ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java Mon Apr 23 12:15:01 2012
@@ -0,0 +1,147 @@
+/*
+ * 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.connectionfactory.impl;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Dictionary;
+
+import org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType;
+
+/**
+ * Provides a helper class for obtaining access credentials from a dictionary.
+ */
+final class UrlCredentialsFactory {
+
+ public static final class MissingValueException extends RuntimeException {
+ private final String m_property;
+
+ /**
+ * @param property the name of the missing property;
+ * @param message the message explaining the missing property.
+ */
+ public MissingValueException(String property) {
+ this(property, "No value for " + property + " given!");
+ }
+
+ /**
+ * @param property the name of the missing property;
+ * @param message the message explaining the missing property.
+ */
+ public MissingValueException(String property, String message) {
+ super(message);
+ m_property = property;
+ }
+
+ /**
+ * Returns the name of the missing property.
+ * @return the property name, never <code>null</code>.
+ */
+ public String getProperty() {
+ return m_property;
+ }
+ }
+
+ public static final String KEY_AUTH_BASE_URL = "authentication.baseURL";
+ public static final String KEY_AUTH_TYPE = "authentication.type";
+ public static final String KEY_AUTH_USER_NAME = "authentication.user.name";
+ public static final String KEY_AUTH_USER_PASSWORD = "authentication.user.password";
+
+ /**
+ * Not used.
+ */
+ private UrlCredentialsFactory() {
+ // Nop
+ }
+
+ /**
+ * @param props the properties to take the access credentials from.
+ * @throws MissingValueException in case the given properties is missing values.
+ */
+ public static UrlCredentials getCredentials(Dictionary props) throws MissingValueException {
+ return getCredentials(props, "");
+ }
+
+ /**
+ * @param props the properties to take the access credentials from;
+ * @param prefix the prefix to use to lookup the correct values in the given dictionary.
+ * @throws MissingValueException in case the given properties is missing values.
+ */
+ public static UrlCredentials getCredentials(Dictionary props, String prefix) throws MissingValueException {
+ AuthType type;
+ URL baseURL;
+ Object[] creds;
+
+ String baseUrlValue = getStringProperty(props, prefix.concat(KEY_AUTH_BASE_URL));
+ if (baseUrlValue == null) {
+ throw new MissingValueException(KEY_AUTH_BASE_URL);
+ }
+
+ try {
+ baseURL = new URL(baseUrlValue);
+ }
+ catch (MalformedURLException e) {
+ throw new MissingValueException(KEY_AUTH_BASE_URL, "Invalid base URL!");
+ }
+
+ String authType = getStringProperty(props, prefix.concat(KEY_AUTH_TYPE), "none");
+ try {
+ type = AuthType.valueOf(authType.toUpperCase());
+ }
+ catch (Exception e) {
+ throw new IllegalArgumentException("Unsupported authentication type: " + authType);
+ }
+
+ if (AuthType.NONE.equals(type)) {
+ creds = new Object[0];
+ } else if (AuthType.BASIC.equals(type)) {
+ String userName = getStringProperty(props, prefix.concat(KEY_AUTH_USER_NAME));
+ if (userName == null) {
+ throw new MissingValueException(prefix.concat(KEY_AUTH_USER_NAME));
+ }
+
+ String password = getStringProperty(props, prefix.concat(KEY_AUTH_USER_PASSWORD));
+ if (password == null) {
+ throw new MissingValueException(prefix.concat(KEY_AUTH_USER_PASSWORD));
+ }
+
+ creds = new Object[] { userName, password };
+ } else {
+ throw new IllegalArgumentException("Invalid/unhandled authentication type: " + authType);
+ }
+
+ return new UrlCredentials(type, baseURL, creds);
+ }
+
+ private static String getStringProperty(Dictionary dict, String key) {
+ Object value = dict.get(key);
+ if (value instanceof String) {
+ return (String) value;
+ } else if (value instanceof byte[]) {
+ return new String((byte[]) value);
+ }
+ return null;
+ }
+
+ private static String getStringProperty(Dictionary dict, String key, String defaultValue) {
+ String value = getStringProperty(dict, key);
+ return (value == null) ? defaultValue : value;
+ }
+}
Propchange: ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java
------------------------------------------------------------------------------
svn:eol-style = native