Skip to Content.
Sympa Menu

notify-dpml - svn commit: r2143 - in development/main/transit/core/handler: etc/main etc/setup etc/setup/authority etc/setup/authority/hosts etc/test etc/test/hosts src/main/net/dpml/io src/main/net/dpml/lang src/main/net/dpml/transit src/main/net/dpml/transit/adapter src/main/net/dpml/transit/artifact src/main/net/dpml/transit/cache src/main/net/dpml/transit/host src/main/net/dpml/transit/layout src/main/net/dpml/transit/link src/main/net/dpml/transit/monitors src/main/net/dpml/transit/network src/main/net/dpml/transit/repository src/main/net/dpml/transit/util src/test/net/dpml/transit/artifact src/test/net/dpml/transit/repository src/test/net/dpml/transit/test

notify-dpml AT lists.ibiblio.org

Subject: DPML Notify

List archive

Chronological Thread  
  • From: niclas AT hedhman.org
  • To: notify-dpml AT lists.ibiblio.org
  • Subject: svn commit: r2143 - in development/main/transit/core/handler: etc/main etc/setup etc/setup/authority etc/setup/authority/hosts etc/test etc/test/hosts src/main/net/dpml/io src/main/net/dpml/lang src/main/net/dpml/transit src/main/net/dpml/transit/adapter src/main/net/dpml/transit/artifact src/main/net/dpml/transit/cache src/main/net/dpml/transit/host src/main/net/dpml/transit/layout src/main/net/dpml/transit/link src/main/net/dpml/transit/monitors src/main/net/dpml/transit/network src/main/net/dpml/transit/repository src/main/net/dpml/transit/util src/test/net/dpml/transit/artifact src/test/net/dpml/transit/repository src/test/net/dpml/transit/test
  • Date: Sat, 26 Mar 2005 13:22:11 -0500

Author: niclas AT hedhman.org
Date: Sat Mar 26 13:22:09 2005
New Revision: 2143

Added:

development/main/transit/core/handler/src/main/net/dpml/transit/SecuredTransitContext.java
(contents, props changed)
development/main/transit/core/handler/src/main/net/dpml/transit/cache/

development/main/transit/core/handler/src/main/net/dpml/transit/cache/CacheHandler.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/cache/FileCacheHandler.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/cache/RemoteCacheHandler.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/cache/ZipCache.java
(contents, props changed)
development/main/transit/core/handler/src/main/net/dpml/transit/host/

development/main/transit/core/handler/src/main/net/dpml/transit/host/ClassicResourceHost.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceHost.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceHostFactory.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceManager.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/host/StandardResourceManager.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/host/XMLHostsBuilder.java
(contents, props changed)
development/main/transit/core/handler/src/main/net/dpml/transit/layout/

development/main/transit/core/handler/src/main/net/dpml/transit/layout/ClassicResolver.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/layout/EclipseResolver.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/layout/LocationResolver.java
(contents, props changed)
development/main/transit/core/handler/src/main/net/dpml/transit/link/
development/main/transit/core/handler/src/main/net/dpml/transit/network/

development/main/transit/core/handler/src/main/net/dpml/transit/network/ConnectionCache.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/network/DelegatingAuthenticator.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/network/NetworkLoader.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/network/RequestIdentifier.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/network/TransitAuthenticator.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/network/TransitAuthenticatorImpl.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/util/MimeTypeHandler.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/util/StreamUtils.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/util/Util.java
(contents, props changed)
development/main/transit/core/handler/src/test/net/dpml/transit/test/

development/main/transit/core/handler/src/test/net/dpml/transit/test/ArtifactTestCase.java
(contents, props changed)

development/main/transit/core/handler/src/test/net/dpml/transit/test/MimeHandlerTestCase.java
(contents, props changed)

development/main/transit/core/handler/src/test/net/dpml/transit/test/OfflineTestCase.java
(contents, props changed)

development/main/transit/core/handler/src/test/net/dpml/transit/test/OnlineTestCase.java
(contents, props changed)
Removed:
development/main/transit/core/handler/etc/main/

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/CacheHandler.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ClassicResolver.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ClassicResourceHost.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ConnectionCache.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/DelegatingAuthenticator.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/EclipseResolver.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/FileCacheHandler.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/LocationResolver.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/MimeTypeHandler.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/NetworkLoader.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/RemoteCacheHandler.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/RequestIdentifier.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ResourceHost.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ResourceHostFactory.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ResourceManager.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/SecuredTransitContext.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/StandardResourceManager.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/StreamUtils.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/TransitAuthenticator.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/TransitAuthenticatorImpl.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Util.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/XMLHostsBuilder.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ZipCache.java

development/main/transit/core/handler/src/test/net/dpml/transit/artifact/ArtifactTestCase.java

development/main/transit/core/handler/src/test/net/dpml/transit/artifact/MimeHandlerTestCase.java

development/main/transit/core/handler/src/test/net/dpml/transit/artifact/OfflineTestCase.java

development/main/transit/core/handler/src/test/net/dpml/transit/artifact/OnlineTestCase.java
Modified:
development/main/transit/core/handler/etc/setup/README.TXT
development/main/transit/core/handler/etc/setup/authority/cache.properties
development/main/transit/core/handler/etc/setup/authority/hosts/local.host

development/main/transit/core/handler/etc/setup/authority/hosts/repository.dpml.net.host

development/main/transit/core/handler/etc/setup/authority/hosts/www.apache.org.host

development/main/transit/core/handler/etc/setup/authority/hosts/www.ibiblio.org.host
development/main/transit/core/handler/etc/test/cache.properties
development/main/transit/core/handler/etc/test/hosts/test.repo

development/main/transit/core/handler/src/main/net/dpml/io/CascadingIOException.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/io/ResourceHelper.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/io/ResourceNotFoundException.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/lang/NullArgumentException.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/Environment.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/EnvironmentException.java
(contents, props changed)
development/main/transit/core/handler/src/main/net/dpml/transit/Main.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/Transit.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/TransitException.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/adapter/AbstractAdapter.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/adapter/Adapter.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/adapter/CacheMonitorAdapter.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ConnectionMonitorAdapter.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ConsoleAdapter.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ExceptionHelper.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/adapter/NetworkMonitorAdapter.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/adapter/RepositoryMonitorAdapter.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Artifact.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactAlreadyExistsException.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactException.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactNotFoundException.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactURLConnection.java

development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Handler.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/AbstractMonitorRouter.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/CacheMonitor.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/CacheMonitorRouter.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/ConnectionMonitor.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/ConnectionMonitorRouter.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/ConsoleMonitor.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/Monitor.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/NetworkMonitor.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/NetworkMonitorRouter.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/NullMonitor.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/RepositoryMonitor.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/RepositoryMonitorRouter.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/Router.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/monitors/SystemMonitor.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/repository/Plugin.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/repository/PropertiesPlugin.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/repository/Repository.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/repository/RepositoryException.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/repository/StandardLoader.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/util/Dictionary.java
(contents, props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/util/ElementHelper.java
(props changed)

development/main/transit/core/handler/src/main/net/dpml/transit/util/PropertyResolver.java
(props changed)

development/main/transit/core/handler/src/test/net/dpml/transit/repository/PropertiesPluginTestCase.java
(contents, props changed)
Log:
Fixed the issue created last night where a single file was committed which
had changes relative to a larger refactoring session. Now committing the
entire refactor. This includes the separation of packages and therefor
increasing the number of public fields and methods.

Modified: development/main/transit/core/handler/etc/setup/README.TXT
==============================================================================
--- development/main/transit/core/handler/etc/setup/README.TXT (original)
+++ development/main/transit/core/handler/etc/setup/README.TXT Sat Mar 26
13:22:09 2005
@@ -9,7 +9,7 @@
<priority>20</priority>
<policy>fast</policy>
<trusted>false</trusted>
- <class>net.dpml.transit.artifact.ClassicResourceHost</class>
+ <class>net.dpml.transit.host.ClassicResourceHost</class>
<index href="index.idx">
<credentials>
<username>fred</username>

Modified:
development/main/transit/core/handler/etc/setup/authority/cache.properties
==============================================================================
---
development/main/transit/core/handler/etc/setup/authority/cache.properties
(original)
+++
development/main/transit/core/handler/etc/setup/authority/cache.properties
Sat Mar 26 13:22:09 2005
@@ -2,6 +2,6 @@
dpml.transit.cache.location=${dpml.data}/cache

# The class that implements the cache handler
-dpml.transit.cache.class=net.dpml.transit.artifact.FileCacheHandler
+dpml.transit.cache.class=net.dpml.transit.cache.FileCacheHandler

-dpml.transit.cache.locationresolver.class=net.dpml.transit.artifact.ClassicResolver
+dpml.transit.cache.locationresolver.class=net.dpml.transit.layout.ClassicResolver

Modified:
development/main/transit/core/handler/etc/setup/authority/hosts/local.host
==============================================================================
---
development/main/transit/core/handler/etc/setup/authority/hosts/local.host
(original)
+++
development/main/transit/core/handler/etc/setup/authority/hosts/local.host
Sat Mar 26 13:22:09 2005
@@ -1,5 +1,5 @@
dpml.transit.resourcehost.enabled=true
-dpml.transit.resourcehost.class=net.dpml.transit.artifact.ClassicResourceHost
+dpml.transit.resourcehost.class=net.dpml.transit.host.ClassicResourceHost
dpml.transit.resourcehost.base=file:${dpml.system}/local
dpml.transit.resourcehost.knowngroups=
dpml.transit.resourcehost.priority=10

Modified:
development/main/transit/core/handler/etc/setup/authority/hosts/repository.dpml.net.host
==============================================================================
---
development/main/transit/core/handler/etc/setup/authority/hosts/repository.dpml.net.host
(original)
+++
development/main/transit/core/handler/etc/setup/authority/hosts/repository.dpml.net.host
Sat Mar 26 13:22:09 2005
@@ -1,5 +1,5 @@
dpml.transit.resourcehost.enabled=true
-dpml.transit.resourcehost.class=net.dpml.transit.artifact.ClassicResourceHost
+dpml.transit.resourcehost.class=net.dpml.transit.host.ClassicResourceHost
dpml.transit.resourcehost.base=http://repository.dpml.net/classic
dpml.transit.resourcehost.knowngroups=
dpml.transit.resourcehost.priority=40

Modified:
development/main/transit/core/handler/etc/setup/authority/hosts/www.apache.org.host
==============================================================================
---
development/main/transit/core/handler/etc/setup/authority/hosts/www.apache.org.host
(original)
+++
development/main/transit/core/handler/etc/setup/authority/hosts/www.apache.org.host
Sat Mar 26 13:22:09 2005
@@ -1,5 +1,5 @@
dpml.transit.resourcehost.enabled=true
-dpml.transit.resourcehost.class=net.dpml.transit.artifact.ClassicResourceHost
+dpml.transit.resourcehost.class=net.dpml.transit.host.ClassicResourceHost
dpml.transit.resourcehost.base=http://www.apache.org/dist/java-repository
dpml.transit.resourcehost.priority=100
dpml.transit.resourcehost.trusted=false

Modified:
development/main/transit/core/handler/etc/setup/authority/hosts/www.ibiblio.org.host
==============================================================================
---
development/main/transit/core/handler/etc/setup/authority/hosts/www.ibiblio.org.host
(original)
+++
development/main/transit/core/handler/etc/setup/authority/hosts/www.ibiblio.org.host
Sat Mar 26 13:22:09 2005
@@ -1,5 +1,5 @@
dpml.transit.resourcehost.enabled=true
-dpml.transit.resourcehost.class=net.dpml.transit.artifact.ClassicResourceHost
+dpml.transit.resourcehost.class=net.dpml.transit.host.ClassicResourceHost
dpml.transit.resourcehost.base=http://www.ibiblio.org/maven
dpml.transit.resourcehost.priority=70
dpml.transit.resourcehost.trusted=false

Modified: development/main/transit/core/handler/etc/test/cache.properties
==============================================================================
--- development/main/transit/core/handler/etc/test/cache.properties
(original)
+++ development/main/transit/core/handler/etc/test/cache.properties Sat
Mar 26 13:22:09 2005
@@ -3,5 +3,5 @@
dpml.transit.cache.location=${user.dir}/target/test/cache

# The class that implements the cache handler
-dpml.transit.cache.class=net.dpml.transit.artifact.FileCacheHandler
+dpml.transit.cache.class=net.dpml.transit.cache.FileCacheHandler


Modified: development/main/transit/core/handler/etc/test/hosts/test.repo
==============================================================================
--- development/main/transit/core/handler/etc/test/hosts/test.repo
(original)
+++ development/main/transit/core/handler/etc/test/hosts/test.repo Sat
Mar 26 13:22:09 2005
@@ -1,6 +1,6 @@

dpml.transit.resourcehost.enabled=true
-dpml.transit.resourcehost.class=net.dpml.transit.artifact.ClassicResourceHost
+dpml.transit.resourcehost.class=net.dpml.transit.host.ClassicResourceHost
dpml.transit.resourcehost.base=file:${user.dir}/target/test/trusted
dpml.transit.resourcehost.knowngroups=
dpml.transit.resourcehost.priority=10

Modified:
development/main/transit/core/handler/src/main/net/dpml/io/CascadingIOException.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/io/CascadingIOException.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/io/CascadingIOException.java
Sat Mar 26 13:22:09 2005
@@ -23,7 +23,7 @@
* Exception to indicate that there was a IO exception.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: CascadingIOException.java 259 2004-10-30 07:24:40Z
mcconnell $
+ * @version $Id$
*/
public class CascadingIOException extends IOException
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/io/ResourceNotFoundException.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/io/ResourceNotFoundException.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/io/ResourceNotFoundException.java
Sat Mar 26 13:22:09 2005
@@ -23,7 +23,7 @@
* Exception to indicate that a request resource was not found.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: CascadingIOException.java 259 2004-10-30 07:24:40Z
mcconnell $
+ * @version $Id$
*/
public class ResourceNotFoundException extends IOException
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/Environment.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/Environment.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/Environment.java
Sat Mar 26 13:22:09 2005
@@ -33,7 +33,7 @@
* variables.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: Environment.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public class Environment extends Properties
{
@@ -238,7 +238,8 @@
* 'nidump passwd /'
* @throws EnvironmentException if os information is not resolvable
*/
- private static String getMacUserShell() throws EnvironmentException
+ private static String getMacUserShell()
+ throws EnvironmentException
{
Process process = null;
BufferedReader reader = null;

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/EnvironmentException.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/EnvironmentException.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/EnvironmentException.java
Sat Mar 26 13:22:09 2005
@@ -23,7 +23,7 @@
* environment parameters.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: EnvironmentException.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public class EnvironmentException extends RuntimeException
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/Main.java
==============================================================================
--- development/main/transit/core/handler/src/main/net/dpml/transit/Main.java
(original)
+++ development/main/transit/core/handler/src/main/net/dpml/transit/Main.java
Sat Mar 26 13:22:09 2005
@@ -18,34 +18,27 @@

package net.dpml.transit;

-import java.io.File;
-import java.io.FileInputStream;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Hashtable;
-
import net.dpml.transit.adapter.Adapter;
-import net.dpml.transit.adapter.RepositoryMonitorAdapter;
import net.dpml.transit.adapter.CacheMonitorAdapter;
-import net.dpml.transit.adapter.NetworkMonitorAdapter;
import net.dpml.transit.adapter.ConsoleAdapter;
-
+import net.dpml.transit.adapter.NetworkMonitorAdapter;
+import net.dpml.transit.adapter.RepositoryMonitorAdapter;
import net.dpml.transit.artifact.Artifact;
-import net.dpml.transit.artifact.ResourceManager;
-import net.dpml.transit.artifact.SecuredTransitContext;
-
-import net.dpml.transit.monitors.Monitor;
-import net.dpml.transit.monitors.RepositoryMonitor;
import net.dpml.transit.monitors.CacheMonitor;
-import net.dpml.transit.monitors.NetworkMonitor;
-import net.dpml.transit.monitors.SystemMonitor;
import net.dpml.transit.monitors.ConsoleMonitor;
+import net.dpml.transit.monitors.Monitor;
+import net.dpml.transit.monitors.NetworkMonitor;
+import net.dpml.transit.monitors.RepositoryMonitor;
import net.dpml.transit.monitors.SystemMonitor;
-
import net.dpml.transit.util.Dictionary;

+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Map;
+
/**
* CLI hander for the transit package.
*
@@ -245,15 +238,15 @@
String arg = args[i];
if( "-Xdebug".equals( arg ) )
{
- final boolean ignorable = true;
+ continue;
}
- else if( arg.startsWith( "-Xbootstrap=" ) )
+ if( arg.startsWith( "-Xbootstrap=" ) )
{
- final boolean ignorable = true;
+ continue;
}
- else if( arg.startsWith( "-Xmanager=" ) )
+ if( arg.startsWith( "-Xmanager=" ) )
{
- final boolean ignorable = true;
+ continue;
}
else
{

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/SecuredTransitContext.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/SecuredTransitContext.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,750 @@
+/*
+ * Copyright 2004 Niclas Hedhman
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit;
+
+import net.dpml.io.ResourceHelper;
+import net.dpml.lang.NullArgumentException;
+import net.dpml.transit.cache.CacheHandler;
+import net.dpml.transit.cache.RemoteCacheHandler;
+import net.dpml.transit.host.ResourceManager;
+import net.dpml.transit.monitors.SystemMonitor;
+import net.dpml.transit.network.DelegatingAuthenticator;
+import net.dpml.transit.network.RequestIdentifier;
+import net.dpml.transit.network.TransitAuthenticator;
+import net.dpml.transit.network.TransitAuthenticatorImpl;
+import net.dpml.transit.util.Util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Properties;
+
+/**
+ * The initial context of the transit system.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ * @version $Id$
+ */
+public final class SecuredTransitContext
+{
+ //------------------------------------------------------------------
+ // static
+ //------------------------------------------------------------------
+
+ /**
+ * The namespace string for transit related properties.
+ */
+ static public final String DOMAIN = "dpml.transit";
+
+ /**
+ * The authority file filename.
+ */
+ static public final String AUTHORITY_FILENAME = DOMAIN +
".authority";
+
+ /**
+ * The authority key.
+ */
+ static public final String AUTHORITY_KEY = DOMAIN +
".authority";
+
+ /**
+ * The proxy host name key.
+ */
+ static public final String PROXY_HOST_KEY = DOMAIN +
".proxy.host";
+
+ /**
+ * The proxy host port key.
+ */
+ static public final String PROXY_PORT_KEY = DOMAIN +
".proxy.port";
+
+ /**
+ * The exluded proxy host names.
+ */
+ static public final String PROXY_EXCLUDES_KEY = DOMAIN +
".proxy.excludes";
+
+ /**
+ * The proxy username key.
+ */
+ static public final String PROXY_USERNAME_KEY = DOMAIN +
".proxy.username";
+
+ /**
+ * The proxy password key.
+ */
+ static public final String PROXY_PASSWORD_KEY = DOMAIN +
".proxy.password";
+
+ /**
+ * The proxy protocol key.
+ */
+ static public final String PROXY_PROTOCOL_KEY = DOMAIN +
".proxy.protocol";
+
+ /**
+ * The proxy scheme key.
+ */
+ static public final String PROXY_SCHEME_KEY = DOMAIN +
".proxy.scheme";
+
+ /**
+ * The proxy prompt/realm key.
+ */
+ static public final String PROXY_PROMPT_KEY = DOMAIN +
".proxy.prompt";
+
+ /**
+ * The transit properties filename.
+ */
+ static public final String TRANSIT_PROPERTIES_FILENAME =
"transit.properties";
+
+ /**
+ * The singleton transit context.
+ */
+ private static SecuredTransitContext m_CONTEXT;
+
+ /**
+ * The fallback remote authority.
+ */
+ private static final String DEFAULT_REMOTE_AUTHORITY =
"http://repository.dpml.net";;
+
+ /**
+ * Transit cache handler service name.
+ */
+ private static final String TRANSIT_NAME = "transit";
+
+
+ //------------------------------------------------------------------
+ // state
+ //------------------------------------------------------------------
+
+ /**
+ * The cache handler.
+ */
+ private CacheHandler m_cacheHandler;
+
+ /**
+ * The authoritive anchor url.
+ */
+ private URL m_authorativeHost;
+
+ private boolean m_server;
+
+ /**
+ * Return the singleton context.
+ * @return the secure context
+ */
+ public static SecuredTransitContext getInstance()
+ {
+ synchronized( SecuredTransitContext.class )
+ {
+ return m_CONTEXT;
+ }
+ }
+
+ //------------------------------------------------------------------
+ // implementation
+ //------------------------------------------------------------------
+
+ /**
+ * Creation of the transit context. If the transit context has already
+ * been established the method returns the singeton context otherwise a
new context
+ * is created relative to the authoritve url and returned.
+ *
+ * @return the secured transit context
+ * @exception TransitException if an error occurs during context creation
+ */
+ public static SecuredTransitContext create()
+ throws TransitException
+ {
+ synchronized( SecuredTransitContext.class )
+ {
+ return SecuredTransitContext.create( new SystemMonitor() );
+ }
+ }
+
+ /** Set the Transit instance into Server mode.
+ * @param serverMode true to operate Transit in Server mode.
+ * @exception TransitException if not possible to make this Transit into
a server.
+ */
+ public void setServer( boolean serverMode )
+ throws TransitException
+ {
+ m_server = serverMode;
+ if( m_server ^ serverMode ) // Is there a change?
+ {
+ if( m_server )
+ {
+ bindServer();
+ }
+ else
+ {
+ unbindServer();
+ }
+ }
+ }
+
+ public boolean isServer()
+ {
+ return m_server;
+ }
+
+ /**
+ * Creation of the transit context. If the transit context has already
+ * been established the method returns the singeton context otherwise a
new context
+ * is created relative to the authoritve url and returned.
+ *
+ * @param monitor the bootstrap monitor
+ * @return the secured transit context
+ * @exception TransitException if an error occurs during context creation
+ * @exception NullArgumentException if the supplied monitor is null and
an instance
+ * of this class has not been created already.
+ */
+ public static SecuredTransitContext create( final SystemMonitor monitor )
+ throws TransitException, NullArgumentException
+ {
+ synchronized( SecuredTransitContext.class )
+ {
+ if( m_CONTEXT != null )
+ {
+ return m_CONTEXT;
+ }
+ if( null == monitor )
+ {
+ throw new NullArgumentException( "monitor" );
+ }
+ if( monitor.isTraceEnabled() )
+ {
+ monitor.trace( "creating secure transit context" );
+ }
+
+ // if the cache service is available on localhost then use it
otherwise
+ // continue with the classic per jvm approach
+ try
+ {
+ Registry reg = LocateRegistry.getRegistry( 1099 );
+ CacheHandler handler = (CacheHandler) reg.lookup(
TRANSIT_NAME );
+ if( monitor.isTraceEnabled() )
+ {
+ monitor.trace( "binding to shared cache handler" );
+ }
+ m_CONTEXT = new SecuredTransitContext( handler );
+ return m_CONTEXT;
+ }
+ catch( NotBoundException e )
+ {
+ // Ignore and continue
+ }
+ catch( java.rmi.ConnectException e )
+ {
+ // Ignore and continue
+ }
+ catch( RemoteException e )
+ {
+ // Ignore and continue
+ System.out.println( "SJM: Could not find the
RemoteCacheHandler." );
+ }
+
+ // proceed with context establishment
+
+
+ try
+ {
+ URL authorative = establishAuthority( monitor );
+ monitor.notifyAuthority( authorative );
+ Properties props = getTransitProperties( authorative );
+ String classname = getResourceManagerClassname( props );
+ ResourceManager manager = createResourceManager( classname,
authorative, monitor );
+ CacheHandler ch = manager.createCacheHandler();
+ monitor.notifyCacheHandlerCreation( ch );
+ m_CONTEXT = new SecuredTransitContext( authorative, ch,
props );
+ }
+ catch( IOException e )
+ {
+ String error = "Unable to establish the
SecuredTransitContext.";
+ throw new TransitException( error, e );
+ }
+
+ return m_CONTEXT;
+ }
+ }
+
+ /**
+ * Create the resource manager that will be responsible for the
establishment
+ * of the transit cache handler. The class implementating the resource
manager
+ * is resolved relative to the transit property
+ * 'dpml.transit.authority.resourcemanager.classname'. If undefined the
+ * default implementation used in the StandardResourceManager class.
+ *
+ * @param classname the classname of the ResourceManager to be created.
+ * @param authorative the URL to the authorative host.
+ * @param monitor the SystemMonitor to receive notifications.
+ *
+ * @return the resource manager
+ */
+ private static ResourceManager createResourceManager(
+ String classname, URL authorative, SystemMonitor monitor ) throws
TransitException
+ {
+ try
+ {
+ Class cls = ResourceManager.class.getClassLoader().loadClass(
classname );
+ Class[] params = new Class[]{
+ URL.class,
+ SystemMonitor.class};
+ Object[] args = new Object[]{
+ authorative,
+ monitor};
+ Constructor cons = cls.getConstructor( params );
+ return (ResourceManager) cons.newInstance( args );
+ }
+ catch( Throwable e )
+ {
+ String error =
+ "Unable to establish the ResourceManager using the class ["
+ + classname
+ + "].";
+ throw new TransitException( error, e );
+ }
+ }
+
+ /**
+ * Return the classname of the class implementating the resource manager.
+ * Resolved relative to the transit property
'dpml.transit.authority.resourcemanager.classname'.
+ * If undefined the default classname is returned.
+ *
+ * @param props the transit properties
+ * @return the resource manager classname
+ */
+ private static String getResourceManagerClassname( Properties props )
+ {
+ return System.getProperty(
+ ResourceManager.TRANSIT_RESOURCE_MANAGER_CLASSNAME_KEY,
+ props.getProperty(
+ ResourceManager.TRANSIT_RESOURCE_MANAGER_CLASSNAME_KEY,
+ ResourceManager.TRANSIT_RESOURCE_MANAGER_CLASSNAME ) );
+ }
+
+ /**
+ * Creation of a new secured transit context using a remote service.
+ * @param handler the cache handler
+ */
+ private SecuredTransitContext( CacheHandler handler )
+ {
+ m_authorativeHost = null;
+ m_cacheHandler = handler;
+ }
+
+ /**
+ * Creation of a new secured transit context.
+ * @param authorative the authorative url.
+ * @param props the properties for the secured transit context.
+ * @param handler the cache handler.
+ * @exception TransitException if a context creation error occurs.
+ */
+ private SecuredTransitContext( URL authorative, CacheHandler handler,
Properties props )
+ throws TransitException
+ {
+ m_authorativeHost = authorative;
+ m_cacheHandler = handler;
+ try
+ {
+ setupAuthenticator( props );
+ }
+ catch( IOException e )
+ {
+ throw new TransitException( "Unable to read Transit
configuration at " + authorative, e );
+ }
+ }
+
+ private static Properties getTransitProperties( URL authorative ) throws
IOException
+ {
+ try
+ {
+ URL conf = new URL( authorative, TRANSIT_PROPERTIES_FILENAME );
+ return Util.readProps( conf );
+ }
+ catch( FileNotFoundException fnfe )
+ {
+ URL url =
SecuredTransitContext.class.getClassLoader().getResource(
+ "transit/authority/" + TRANSIT_PROPERTIES_FILENAME );
+ return Util.readProps( url );
+ }
+ }
+
+ /**
+ * Return cache handler directory.
+ *
+ * @return the cache handler
+ */
+ public CacheHandler getCacheHandler()
+ {
+ return m_cacheHandler;
+ }
+
+ /**
+ * Return the authorative host URL.
+ * @return the authorative host url
+ */
+ public URL getAuthorativeHost()
+ {
+ return m_authorativeHost;
+ }
+
+ /**
+ * Resolve the authorative url. The implementation will check for a
+ * system property named "dpml.transit.authority.file". If the value
+ * refers to a file then the file will be used to resolve the authority
+ * url by reading the property "dpml.transit.authority". If no system
+ * property is defined then a attempt will be made to locate the file
+ * ${dpml.prefs}/transit/dpml.transit.authority. If this file does not
exist the
+ * implementation will attempt to locate an authority file in the
directory
+ * referenced by the system property "java.ext.dirs". If no file is found
+ * the implementation will be establised using a bundled default.
+ *
+ * @param monitor the bootstrap monitor
+ * @return the authorative url
+ * @exception TransitException if an error occurs during authority url
creation
+ */
+ private static URL establishAuthority( final SystemMonitor monitor )
+ throws TransitException
+ {
+ try
+ {
+ //
+ // System property declaration of an authority file takes
precedence.
+ //
+
+ String path = System.getProperty( "dpml.transit.authority.file"
);
+ if( null != path )
+ {
+ File authorativeFile = getCanonicalFile( new File( path ) );
+ if( !authorativeFile.exists() )
+ {
+ final String error =
+ "The System property 'dpml.transit.authority.file'
referes to the path: ["
+ + authorativeFile
+ + "] which does not exist.";
+ throw new TransitException( error );
+ }
+ else
+ {
+ if( monitor.isTraceEnabled() )
+ {
+ final String message =
+ "using system property
'dpml.transit.authority.file' ["
+ + path
+ + "]";
+ monitor.trace( message );
+ }
+ return useForAuthority( authorativeFile );
+ }
+ }
+
+ //
+ // Otherwise check for a authoritive file in the
${dpml.prefs}/transit
+ // directory.
+ //
+
+ File transitDir = new File( Transit.DPML_PREFS, "transit" );
+ File artifactAuthFile = new File( transitDir, AUTHORITY_FILENAME
);
+ if( artifactAuthFile.exists() )
+ {
+ if( monitor.isTraceEnabled() )
+ {
+ final String message =
+ "using authority file ["
+ + artifactAuthFile
+ + "]";
+ monitor.trace( message );
+ }
+ return useForAuthority( artifactAuthFile );
+ }
+
+ //
+ // Otherwise fallback to checking for the authority file in the
+ // java extensions directory.
+ //
+
+ File extlib = new File( System.getProperty( "java.ext.dirs" ) );
+ File javaAuthFile = new File( extlib, AUTHORITY_FILENAME );
+ if( javaAuthFile .exists() )
+ {
+ if( monitor.isTraceEnabled() )
+ {
+ final String message =
+ "using extension authority file ["
+ + javaAuthFile
+ + "]";
+ monitor.trace( message );
+ }
+ return useForAuthority( javaAuthFile );
+ }
+
+ //
+ // create it based on packaged defaults
+ //
+
+ File authority = new File( transitDir, "authority" );
+ File hosts = new File( authority, "hosts" );
+
+ try
+ {
+ authority.mkdirs();
+ ClassLoader classloader = Transit.class.getClassLoader();
+ ResourceHelper.unpack( classloader, "transit/" +
AUTHORITY_FILENAME, artifactAuthFile );
+ ResourceHelper.unpack( classloader,
"transit/authority/cache.properties", new File( authority, "cache.properties"
) );
+ ResourceHelper.unpack( classloader,
"transit/authority/hosts.xml.example", new File( authority,
"hosts.xml.example" ) );
+ ResourceHelper.unpack( classloader,
"transit/authority/transit.properties", new File( authority,
"transit.properties" ) );
+ ResourceHelper.unpack(
+ classloader, "transit/authority/hosts/local.host", new
File( hosts, "local.host" ) );
+ ResourceHelper.unpack(
+ classloader,
"transit/authority/hosts/repository.dpml.net.host", new File( hosts,
"repository.dpml.net.host" ) );
+ ResourceHelper.unpack(
+ classloader,
"transit/authority/hosts/www.ibiblio.org.host", new File( hosts,
"www.ibiblio.org.host" ) );
+ ResourceHelper.unpack(
+ classloader,
"transit/authority/hosts/www.apache.org.host", new File( hosts,
"www.apache.org.host" ) );
+
+ if( monitor.isTraceEnabled() )
+ {
+ final String message =
+ "using bundled defaults ["
+ + artifactAuthFile
+ + "]";
+ monitor.trace( message );
+ }
+
+ return useForAuthority( artifactAuthFile );
+
+ }
+ catch( SecurityException se )
+ {
+ if( monitor.isTraceEnabled() )
+ {
+ final String message =
+ "using http://repository.dpml.net/ as authorative
source";
+ monitor.trace( message );
+ }
+ return new URL( DEFAULT_REMOTE_AUTHORITY );
+ }
+ }
+ catch( Exception e )
+ {
+ throw new TransitException( "Artifact AUTHORITY cannot be
established.", e );
+ }
+ }
+
+ /**
+ * Return the cononical form of a file.
+ * @param file the file to convert to its cononical form
+ * @return the converted file
+ * @exception TransitException if the file could not be converted
+ */
+ private static File getCanonicalFile( final File file ) throws
TransitException
+ {
+ try
+ {
+ return file.getCanonicalFile();
+ }
+ catch( IOException e )
+ {
+ final String error =
+ "Internal error while attempting to convert the supplied file
["
+ + file.toString()
+ + "] to its canonical form.";
+ throw new TransitException( error );
+ }
+ }
+
+ /**
+ * Parse an authorative file for the "dpml.transit.authority" property
+ * value and resolve from this value the authorative url.
+ * @param authFile the authorative file
+ * @return the authorative url
+ * @exception IOException if a file read error occurs
+ * @exception MalformedURLException if the value assigned to the property
+ * dpml.transit.authority could not be resolved to a url.
+ * @exception TransitException if the dpml.transit.authority property is
undefined
+ */
+ private static URL useForAuthority( File authFile )
+ throws IOException, MalformedURLException, TransitException
+ {
+ FileInputStream stream = new FileInputStream( authFile );
+ try
+ {
+ Properties p = new Properties();
+ p.setProperty( Transit.HOME_KEY, Transit.DPML_HOME.toString() );
+ p.setProperty( Transit.PREFS_KEY, Transit.DPML_PREFS.toString()
);
+ p.setProperty( Transit.DATA_KEY, Transit.DPML_DATA.toString() );
+ p.setProperty( Transit.SYSTEM_KEY,
Transit.DPML_SYSTEM.toString() );
+ p.load( stream );
+
+ String authority = Util.getProperty( p, AUTHORITY_KEY, null );
+ if( authority == null )
+ {
+ throw new TransitException( "No " + AUTHORITY_KEY + " could
be found in " + authFile );
+ }
+ if( ! authority.endsWith( "/" ) )
+ {
+ authority = authority + "/";
+ }
+
+ File f = new File( authority );
+ if( !f.isAbsolute() )
+ {
+ f = new File( Transit.DPML_PREFS, "transit/" + authority );
+ }
+ if( f.exists() )
+ {
+ URL url = f.toURL();
+ return url;
+ }
+ else
+ {
+ URL url = new URL( authority );
+ return url;
+ }
+ }
+ finally
+ {
+ stream.close();
+ }
+ }
+
+ /**
+ * Setup the transit authenticator.
+ * @param properties the transit properties
+ * @exception UnknownHostException if a proxy host is declared but is
unknown
+ */
+ private void setupAuthenticator( Properties properties )
+ throws UnknownHostException
+ {
+ TransitAuthenticator ta = createProxyAuthenticator( properties );
+ if( ta != null )
+ {
+ RequestIdentifier id = createProxyRequestIdentifier( properties
);
+ DelegatingAuthenticator da =
DelegatingAuthenticator.getInstance();
+ da.addTransitAuthenticator( ta, id );
+ }
+ }
+
+ /**
+ * Creation of a new transit authenticator.
+ * @param properties the transit properties
+ * @return the transit authenticator
+ */
+ private TransitAuthenticator createProxyAuthenticator( Properties
properties )
+ {
+ String username = Util.getProperty( properties, PROXY_USERNAME_KEY,
null );
+ String password = Util.getProperty( properties, PROXY_PASSWORD_KEY,
null );
+ if( null == username )
+ {
+ return null;
+ }
+ return new TransitAuthenticatorImpl( username, password );
+ }
+
+ /**
+ * Creation of a new request identifier.
+ * @param properties the transit properties
+ * @return the request identifier
+ * @exception UnknownHostException if a proxy host is declared but is
unknown
+ * @exception IllegalArgumentException if a proxy host is declared and
+ * either the proxy scheme or proxy prompt property values are undefined
+ */
+ private RequestIdentifier createProxyRequestIdentifier( Properties
properties )
+ throws UnknownHostException, IllegalArgumentException
+ {
+ String proxy = Util.getProperty( properties, PROXY_HOST_KEY, null );
+ if( null == proxy )
+ {
+ return null;
+ }
+
+ String protocol = Util.getProperty( properties, PROXY_PROTOCOL_KEY,
"http" );
+ String scheme = Util.getProperty( properties, PROXY_SCHEME_KEY, null
);
+ if( scheme == null )
+ {
+ throw new IllegalArgumentException( "Missing " +
PROXY_SCHEME_KEY + " in properties." );
+ }
+ String prompt = Util.getProperty( properties, PROXY_PROMPT_KEY, null
);
+ if( prompt == null )
+ {
+ throw new IllegalArgumentException( "Missing " +
PROXY_PROMPT_KEY + " in properties." );
+ }
+
+ InetAddress host = InetAddress.getByName( proxy );
+ String portText = Util.getProperty( properties, PROXY_PORT_KEY, "0"
);
+ int port = Integer.parseInt( portText );
+ Properties system = System.getProperties();
+ system.put( "http.proxyHost", proxy );
+ system.put( "http.proxyPort", "" + port );
+ String excludes = Util.getProperty( properties, PROXY_EXCLUDES_KEY,
null );
+ if( null != excludes )
+ {
+ system.put( "http.nonProxyHosts", excludes );
+ }
+ RequestIdentifier id = new RequestIdentifier( host, port, protocol,
scheme, prompt );
+ return id;
+ }
+
+ private void unbindServer()
+ throws TransitException
+ {
+ try
+ {
+ Registry reg = LocateRegistry.getRegistry( 1099 );
+ reg.unbind( TRANSIT_NAME );
+ }
+ catch( Throwable e )
+ {
+ String error = "Could not remove the cache handler as a remote
service.";
+ throw new TransitException( error, e );
+ }
+ }
+
+ private void bindServer()
+ throws TransitException
+ {
+ // publish the cache handler as a remotely accessible
+ // service on localhost
+ try
+ {
+ try
+ {
+ LocateRegistry.createRegistry( 1099 );
+ } catch( Throwable t )
+ {} // ignore
+
+ CacheHandler lch = m_CONTEXT.getCacheHandler();
+ RemoteCacheHandler rch = new RemoteCacheHandler( lch );
+ Registry reg = LocateRegistry.getRegistry( 1099 );
+ reg.bind( TRANSIT_NAME, rch );
+ System.out.println( "# server registered on port 1099 as: " +
TRANSIT_NAME );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Could not establish the cache handler as a remote service.";
+ throw new TransitException( error, e );
+ }
+ }
+}

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/Transit.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/Transit.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/Transit.java
Sat Mar 26 13:22:09 2005
@@ -30,8 +30,6 @@

import net.dpml.lang.NullArgumentException;

-import net.dpml.transit.artifact.SecuredTransitContext;
-
import net.dpml.transit.monitors.Monitor;
import net.dpml.transit.monitors.SystemMonitor;
import net.dpml.transit.monitors.RepositoryMonitorRouter;

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/TransitException.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/TransitException.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/TransitException.java
Sat Mar 26 13:22:09 2005
@@ -25,7 +25,7 @@
* Exception to indicate that there was a transit artifact related error.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: RepositoryException.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public class TransitException extends IOException
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/Adapter.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/Adapter.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/Adapter.java
Sat Mar 26 13:22:09 2005
@@ -28,7 +28,7 @@
* action.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: Monitor.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public interface Adapter
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/CacheMonitorAdapter.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/CacheMonitorAdapter.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/CacheMonitorAdapter.java
Sat Mar 26 13:22:09 2005
@@ -29,7 +29,7 @@
* Adapts cache events to logging messages.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: DownloadMonitor.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
* @see net.dpml.transit.monitors.Monitor
*/
public class CacheMonitorAdapter extends AbstractAdapter

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ConnectionMonitorAdapter.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ConnectionMonitorAdapter.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ConnectionMonitorAdapter.java
Sat Mar 26 13:22:09 2005
@@ -29,7 +29,7 @@
* The NetworkMonitor must be thread safe.
* </p>
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: DownloadMonitor.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
* @see net.dpml.transit.monitors.Monitor
*/
public class ConnectionMonitorAdapter extends AbstractAdapter

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ConsoleAdapter.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ConsoleAdapter.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/adapter/ConsoleAdapter.java
Sat Mar 26 13:22:09 2005
@@ -24,7 +24,7 @@
* Console montor for download messages.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: ConsoleMonitor.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public class ConsoleAdapter implements Adapter
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Artifact.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Artifact.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Artifact.java
Sat Mar 26 13:22:09 2005
@@ -34,7 +34,7 @@
* specifications.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: Artifact.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public final class Artifact
implements Serializable, Comparable

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactException.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactException.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactException.java
Sat Mar 26 13:22:09 2005
@@ -25,7 +25,7 @@
* Exception to indicate that there was an Artifact related error.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: ArtifactException.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public class ArtifactException extends TransitException
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactNotFoundException.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactNotFoundException.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactNotFoundException.java
Sat Mar 26 13:22:09 2005
@@ -22,7 +22,7 @@
* Exception to indicate that ther Artifact could not be located.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: ArtifactException.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public class ArtifactNotFoundException extends ArtifactException
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactURLConnection.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactURLConnection.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/ArtifactURLConnection.java
Sat Mar 26 13:22:09 2005
@@ -194,6 +194,8 @@
File destFile = new File( tempDir, name );
if( destFile.exists() )
return destFile;
+ File parent = destFile.getParentFile();
+ parent.mkdirs();
FileOutputStream output = new FileOutputStream( destFile );
StreamUtils.copyStream( content, output, true );
return destFile;

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Handler.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Handler.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/artifact/Handler.java
Sat Mar 26 13:22:09 2005
@@ -28,6 +28,7 @@

import net.dpml.transit.Transit;
import net.dpml.transit.TransitException;
+import net.dpml.transit.SecuredTransitContext;

/**
* Repository artifact: URL protocol handler.

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/cache/CacheHandler.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/cache/CacheHandler.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2004-2005 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.cache;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import java.util.Map;
+
+import net.dpml.lang.NullArgumentException;
+
+import net.dpml.transit.TransitException;
+import net.dpml.transit.SecuredTransitContext;
+import net.dpml.transit.SecuredTransitContext;
+import net.dpml.transit.artifact.Artifact;
+import net.dpml.transit.artifact.ArtifactAlreadyExistsException;
+
+/**
+ * The CacheHandler interface defines the contract for classes capable of
+ * supporting the cache mentement aspects of a transit system. Cache
management
+ * encompasses the retreval of resources based on artifact identifiers.
Cache
+ * manager implementations may provide varying levels of quality-of-services.
+ * Selection of a cache manager is defined under the transit cache
configuration
+ * properties.
+ */
+public interface CacheHandler extends Remote
+{
+ /**
+ * The domain identifier.
+ */
+ static final String DOMAIN = SecuredTransitContext.DOMAIN;
+
+ /**
+ * Cache property key.
+ */
+ static final String CACHE_KEY = DOMAIN + ".cache.location";
+
+ /**
+ * Cache handler classname key.
+ */
+ static final String CACHE_CLASS_KEY = DOMAIN + ".cache.class";
+
+ /**
+ * Cache location resolver classname key.
+ */
+ static final String RESOLVER_CLASS_KEY = DOMAIN +
".cache.locationresolver.class";
+
+ /**
+ * Attempts to download and cache a remote artifact using a set of remote
+ * repositories.
+ *
+ * @param artifact the artifact to retrieve and cache
+ * @return a file referencing the local resource
+ * @exception IOException if an IO error occurs
+ * @exception TransitException is a transit system error occurs
+ */
+ InputStream getResource( Artifact artifact )
+ throws IOException, TransitException, RemoteException;
+
+ /**
+ * Attempts to download and cache a remote artifact using a set of remote
+ * repositories.
+ * <p>
+ * This method allows an internal reference to be passed to the
+ * cache handler and it is expected to return the InputStream of the
+ * internal item inside Jar/Zip files. If this method is called, the
+ * implementation can assume that the artifact is a Zip file.
+ * </p>
+ *
+ * @param artifact the artifact to retrieve and cache
+ * @param internalReference referencing a item within the artifact. This
+ * argument may start with "!" or "!/", which should be ignored.
+ * @return a file referencing the local resource
+ * @exception IOException if an IO error occurs
+ * @exception TransitException is a transit system error occurs
+ */
+ InputStream getResource( Artifact artifact, String internalReference )
+ throws IOException, TransitException, RemoteException;
+
+ /** Creates an output stream to where the artifact content can be written
+ * to.
+ * <p>
+ * If the artifact already exists, a
<code>ArtifactAlreadyExistsException</code>
+ * will be thrown. If the directory doesn't exists, it will be created.
+ * The CacheHandler is responsible to recognize the completion of the
+ * writes through the <code>close()</code> method in the output stream,
+ * and do any post-processing there.
+ * </p>
+ * @exception NullArgumentException if the artifact argument is null.
+ * @exception net.dpml.transit.artifact.ArtifactAlreadyExistsException
if the artifact already exists
+ * in the cache.
+ */
+ OutputStream createOutputStream( Artifact artifact )
+ throws NullArgumentException, ArtifactAlreadyExistsException,
IOException, RemoteException;
+
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/cache/FileCacheHandler.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/cache/FileCacheHandler.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,421 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.cache;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.TreeMap;
+
+import java.util.zip.ZipFile;
+import java.util.zip.ZipEntry;
+
+import net.dpml.lang.NullArgumentException;
+
+import net.dpml.transit.Transit;
+import net.dpml.transit.TransitException;
+import net.dpml.transit.util.StreamUtils;
+import net.dpml.transit.util.Util;
+import net.dpml.transit.host.ResourceHost;
+import net.dpml.transit.layout.LocationResolver;
+import net.dpml.transit.artifact.*;
+import net.dpml.transit.cache.CacheHandler;
+import net.dpml.transit.monitors.Monitor;
+
+import net.dpml.transit.monitors.CacheMonitorRouter;
+
+/**
+ * Default cache handler that maintains a file based cache.
+ */
+public class FileCacheHandler
+ implements CacheHandler
+{
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ /**
+ * The base directory of the cache.
+ */
+ private File m_cacheDir;
+
+ /**
+ * The resource hosts.
+ */
+ private TreeMap m_resourceHosts;
+
+ private LocationResolver m_resolver;
+
+ private ZipCache m_zipCache;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new file based cache handler.
+ * @param monitor the assigned monitor
+ * @param hosts the assigned hosts
+ * @param props the properties against which this instance will be
configured
+ */
+ public FileCacheHandler( Monitor monitor, ResourceHost[] hosts,
Properties props, LocationResolver resolver )
+ {
+ m_zipCache = new ZipCache();
+
+ m_resolver = resolver;
+ m_resourceHosts = new TreeMap();
+ for( int i=0; i < hosts.length; i++ )
+ {
+ // We need to ensure that no other host already have the same
+ // priority, in which case we increase the priority until we find
+ // an available spot.
+
+ int priority = hosts[i].getPriority();
+ Integer key;
+ while ( true )
+ {
+ key = new Integer( priority );
+ if( !m_resourceHosts.containsKey( key ) )
+ {
+ break;
+ }
+ priority = priority + 1;
+ }
+ m_resourceHosts.put( key, hosts[i] );
+ }
+ m_cacheDir = createCacheDirectory( props );
+ monitor.trace( "created file based cache on: " + m_cacheDir );
+ }
+
+ /**
+ * Set the local cache directory.
+ *
+ */
+ protected void setLocalCacheDirectory( File file )
+ {
+ synchronized( m_cacheDir )
+ {
+ m_cacheDir = file;
+ }
+ }
+
+ /**
+ * Return a directory established to provide the local cache.
+ *
+ * @return the feature collection
+ */
+ protected File getLocalCacheDirectory()
+ {
+ return m_cacheDir;
+ }
+
+ //
------------------------------------------------------------------------
+ // CacheHandler
+ //
------------------------------------------------------------------------
+
+ /**
+ * Attempts to download and cache a remote artifact using a set of remote
+ * repositories. The operation is not fail fast and so it keeps trying
if
+ * the first repository does not have the artifact in question.
+ *
+ * @param artifact the artifact to retrieve and cache
+ * @return input stream containing the artifact content.
+ * @exception IOException if an IO error occurs.
+ * @exception TransitException if a transit system error occurs.
+ * @exception NullArgumentException if the artifact argument is null.
+ */
+ public InputStream getResource( Artifact artifact )
+ throws IOException, TransitException, NullArgumentException
+ {
+ CacheMonitorRouter monitor =
Transit.getInstance().getCacheMonitorRouter();
+ if( monitor != null )
+ {
+ monitor.resourceRequested( artifact );
+ }
+
+ if( null == artifact )
+ {
+ throw new NullArgumentException( "artifact" );
+ }
+ String path = m_resolver.resolvePath( artifact );
+ File destination = new File( m_cacheDir, path );
+ File parentDir = destination.getParentFile();
+ parentDir.mkdirs();
+ boolean exist = destination.exists();
+ boolean success;
+ if( exist )
+ {
+ success = true;
+ }
+ else
+ {
+ ResourceHost known = findKnownGroupHost( artifact );
+ success = download( known, artifact, destination );
+ if( !success )
+ {
+ ResourceHost any = findAnyPresence( artifact );
+ success = download( any, artifact, destination );
+ }
+ }
+ if( success )
+ {
+ checkInternalConsistency( artifact, destination );
+ endNotifyMonitor( monitor, exist, artifact, destination );
+ }
+ if( destination.exists() )
+ {
+ FileInputStream stream = new FileInputStream( destination );
+ return new BufferedInputStream( stream );
+ }
+
+ if( monitor != null )
+ {
+ monitor.failedDownload( artifact );
+ }
+
+ String error = "Unresolvable artifact: [" + artifact + "].";
+ throw new ArtifactNotFoundException( error, artifact );
+ }
+
+ /**
+ * Attempts to download and cache a remote artifact using a set of remote
+ * repositories.
+ * <p>
+ * This method allows an internal reference to be passed to the
+ * cache handler and it is expected to return the InputStream of the
+ * internal item inside Jar/Zip files. If this method is called, the
+ * implementation can assume that the artifact is a Zip file.
+ * </p>
+ *
+ * @param artifact the artifact to retrieve and cache
+ * @param internalReference referencing a item within the artifact. This
+ * argument may start with "!" or "!/", which should be ignored.
+ * @return a file referencing the local resource
+ * @exception IOException if an IO error occurs
+ * @exception TransitException is a transit system error occurs
+ */
+ public InputStream getResource( Artifact artifact, String
internalReference )
+ throws IOException, TransitException
+ {
+ synchronized( this )
+ {
+ if( internalReference.startsWith( "!" ) )
+ internalReference = internalReference.substring( 1 );
+ if( internalReference.startsWith( "/" ) )
+ internalReference = internalReference.substring( 1 );
+
+ ZipFile zip = m_zipCache.get( artifact );
+ if( zip == null )
+ {
+ InputStream artifactStream = getResource( artifact );
+ File tmpFile = File.createTempFile( "~dpml", ".tmp" );
+ tmpFile.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream( tmpFile );
+ StreamUtils.copyStream( artifactStream, fos, true );
+ zip = new ZipFile( tmpFile );
+ m_zipCache.put( artifact, zip );
+ }
+ ZipEntry entry = zip.getEntry( internalReference );
+ InputStream stream = zip.getInputStream( entry );
+ return new BufferedInputStream( stream );
+ }
+
+ }
+
+ /** Creates an output stream to where the artifact content can be written
+ * to.
+ * <p>
+ * If the artifact already exists, a
<code>ArtifactAlreadyExistsException</code>
+ * will be thrown. If the directory doesn't exists, it will be created.
+ * </p>
+ * @exception IOException if an IO error occurs.
+ * @exception NullArgumentException if the artifact argument is null.
+ * @exception ArtifactAlreadyExistsException if the artifact already
exists
+ * in the cache.
+ */
+ public OutputStream createOutputStream( Artifact artifact )
+ throws NullArgumentException, ArtifactAlreadyExistsException,
IOException
+ {
+ if( null == artifact )
+ {
+ throw new NullArgumentException( "artifact" );
+ }
+ ResourceHost any = findAnyPresence( artifact );
+ if( any != null )
+ throw new ArtifactAlreadyExistsException( "Artifact found on
server.", artifact );
+ String path = m_resolver.resolvePath( artifact );
+ File destination = new File( m_cacheDir, path );
+ if( destination.exists() )
+ throw new ArtifactAlreadyExistsException( "Artifact found in
cache.", artifact );
+ File parentDir = destination.getParentFile();
+ if( !parentDir.exists() )
+ parentDir.mkdirs();
+ return new FileOutputStream( destination );
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Return a resource host.
+ * @param artifact the artifact
+ * @return the resource host (possibly null)
+ */
+ private ResourceHost findKnownGroupHost( Artifact artifact )
+ {
+ Iterator list = m_resourceHosts.values().iterator();
+ while ( list.hasNext() )
+ {
+ ResourceHost host = (ResourceHost) list.next();
+ if( host.isEnabled() )
+ {
+ if( host.checkPresence( artifact, true ) )
+ {
+ return host;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find any host.
+ * @param artifact the artifact
+ * @return the resource host (possibly null)
+ */
+ private ResourceHost findAnyPresence( Artifact artifact )
+ {
+ Iterator list = m_resourceHosts.values().iterator();
+ while ( list.hasNext() )
+ {
+ ResourceHost host = (ResourceHost) list.next();
+ if( host.isEnabled() )
+ {
+ if( host.checkPresence( artifact, false ) )
+ {
+ return host;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Download an artifact from a host to the cache.
+ * @param host the remote host
+ * @param artifact the artifact being retrieved
+ * @param destination the cached destination
+ * @return TRUE if downloaded
+ * @exception IOException if an IO error occurs
+ * @exception TransitException if a transit system error occurs
+ */
+ private boolean download( ResourceHost host, Artifact artifact, File
destination )
+ throws IOException, TransitException
+ {
+ if( host == null )
+ {
+ return false;
+ }
+ File parentDir = destination.getParentFile();
+ File tempFile = File.createTempFile( "~dpml", ".tmp", parentDir );
+ tempFile.deleteOnExit(); // safety harness in case we abort
abnormally
+ // like a Ctrl-C.
+ FileOutputStream tempOut = new FileOutputStream( tempFile );
+
+ CacheMonitorRouter monitor =
Transit.getInstance().getCacheMonitorRouter();
+ try
+ {
+ Date lastModified = host.download( artifact, tempOut );
+ // An atomic operation and no risk of a corrupted
+ // artifact content.
+ tempFile.renameTo( destination );
+ destination.setLastModified( lastModified.getTime() );
+ return true;
+ }
+ catch( IOException e )
+ {
+ tempFile.delete();
+ if( monitor != null )
+ {
+ monitor.failedDownloadFromHost( host.toString(), artifact, e
);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Create the file to the root of the cache directory. If the cache key is
+ * declared as a system property, the value will take precidence over the
+ * cache configuration properties.
+ *
+ * @param props the configuration properties
+ * @return the cache root directory
+ */
+ private File createCacheDirectory( Properties props )
+ {
+ String defaultCache = "cache";
+ String fallback = Util.getProperty( props, CACHE_KEY, defaultCache );
+ String cache = System.getProperty( CACHE_KEY, fallback );
+ File cachedir = new File( cache );
+ if( !cachedir.isAbsolute() )
+ {
+ cachedir = new File( Transit.DPML_DATA, cache );
+ }
+ cachedir.mkdirs();
+ return cachedir;
+ }
+
+ private void endNotifyMonitor( CacheMonitorRouter monitor, boolean
existed,
+ Artifact artifact, File destination )
+ {
+ if( monitor != null )
+ {
+ if( existed )
+ {
+ monitor.updatedLocalCache( artifact.toURL(), destination );
+ }
+ else
+ {
+ monitor.addedToLocalCache( artifact.toURL(), destination );
+ }
+ }
+ }
+
+ private void checkInternalConsistency( Artifact artifact, File
destination )
+ {
+ if( destination.exists() )
+ return;
+ String error = "Download reported [success], but the destination
does not exist: "
+ + artifact + ", " + destination;
+ throw new InternalError( error );
+ }
+
+
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/cache/RemoteCacheHandler.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/cache/RemoteCacheHandler.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2004-2005 Stephen J. McConnell.
+ * Copyright 2004-2005 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.cache;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.TreeMap;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+import net.dpml.lang.NullArgumentException;
+
+import net.dpml.transit.Transit;
+import net.dpml.transit.TransitException;
+import net.dpml.transit.artifact.Artifact;
+import net.dpml.transit.artifact.ArtifactAlreadyExistsException;
+import net.dpml.transit.cache.CacheHandler;
+import net.dpml.transit.monitors.Monitor;
+
+import net.dpml.transit.monitors.CacheMonitorRouter;
+
+/**
+ * Default cache handler that maintains a file based cache.
+ */
+public class RemoteCacheHandler extends UnicastRemoteObject
+ implements CacheHandler
+{
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ /**
+ * The base directory of the cache.
+ */
+ private CacheHandler m_delegate;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new file based cache handler.
+ * @param monitor the assigned monitor
+ * @param hosts the assigned hosts
+ * @param props the properties against which this instance will be
configured
+ */
+ public RemoteCacheHandler( CacheHandler delegate )
+ throws RemoteException
+ {
+ super();
+ m_delegate = delegate;
+ }
+
+ //
------------------------------------------------------------------------
+ // CacheHandler
+ //
------------------------------------------------------------------------
+
+ /**
+ * Attempts to download and cache a remote artifact using a set of remote
+ * repositories. The operation is not fail fast and so it keeps trying
if
+ * the first repository does not have the artifact in question.
+ *
+ * @param artifact the artifact to retrieve and cache
+ * @return file referencing the local resource
+ * @exception IOException if an IO error occurs.
+ * @exception TransitException if a transit system error occurs.
+ * @exception NullArgumentException if the artifact argument is null.
+ */
+ public InputStream getResource( Artifact artifact )
+ throws IOException, TransitException, NullArgumentException
+ {
+ return m_delegate.getResource( artifact );
+ }
+
+ /**
+ * Attempts to download and cache a remote artifact using a set of remote
+ * repositories. The operation is not fail fast and so it keeps trying
if
+ * the first repository does not have the artifact in question.
+ *
+ * @param artifact the artifact to retrieve and cache
+ * @return file referencing the local resource
+ * @exception IOException if an IO error occurs.
+ * @exception TransitException if a transit system error occurs.
+ * @exception NullArgumentException if the artifact argument is null.
+ */
+ public InputStream getResource( Artifact artifact, String internalRef )
+ throws IOException, TransitException, NullArgumentException
+ {
+ return m_delegate.getResource( artifact, internalRef );
+ }
+
+ /** Creates an output stream to where the artifact content can be written
+ * to.
+ * <p>
+ * If the artifact already exists, a
<code>ArtifactAlreadyExistsException</code>
+ * will be thrown. If the directory doesn't exists, it will be created.
+ * The CacheHandler is responsible to recognize the completion of the
+ * writes through the <code>close()</code> method in the output stream,
+ * and do any post-processing there.
+ * </p>
+ * @exception NullArgumentException if the artifact argument is null.
+ * @exception net.dpml.transit.artifact.ArtifactAlreadyExistsException
if the artifact already exists
+ * in the cache.
+ */
+ public OutputStream createOutputStream( Artifact artifact )
+ throws NullArgumentException, ArtifactAlreadyExistsException,
IOException, RemoteException
+ {
+ return m_delegate.createOutputStream( artifact );
+ }
+
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/cache/ZipCache.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/cache/ZipCache.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.cache;
+
+import net.dpml.transit.artifact.Artifact;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import java.util.zip.ZipFile;
+
+class ZipCache
+ implements Runnable
+{
+ private HashMap m_store;
+ private long m_timeToLive;
+ private Thread m_thread;
+
+ ZipCache()
+ {
+ m_store = new HashMap();
+ m_timeToLive = 30000;
+ }
+
+ ZipFile get( Artifact key )
+ {
+ synchronized( this ) // ensure no ConcurrentModificationException
can occur.
+ {
+ Entry entry = (Entry) m_store.get( key );
+ if( entry == null )
+ return null;
+ ZipFile zip = entry.m_file;
+ return zip;
+ }
+ }
+
+ void put( Artifact key, ZipFile file )
+ {
+ synchronized( this ) // ensure no ConcurrentModificationException
can occur.
+ {
+ Entry entry = new Entry( file );
+ m_store.put( key, entry );
+ if( m_thread == null )
+ {
+ m_thread = new Thread( this, "ZipCache-cleaner" );
+ m_thread.setDaemon( true );
+ m_thread.start();
+ }
+ }
+ }
+
+ public void run()
+ {
+ while( true )
+ {
+ try
+ {
+ synchronized( this )
+ {
+ long now = System.currentTimeMillis();
+ Iterator list = m_store.values().iterator();
+ while( list.hasNext() )
+ {
+ Entry entry = (Entry) list.next();
+ if( entry.m_collectTime < now )
+ {
+ entry.m_file.close();
+ list.remove();
+ }
+ }
+ if( m_store.size() == 0 )
+ {
+ m_thread = null;
+ break;
+ }
+ wait( 10000 );
+ }
+ } catch( Exception e )
+ {
+ // Can not happen?
+ // Just ignore and it will be handled in the next round.
+ e.printStackTrace();
+ }
+ }
+ }
+
+ class Entry
+ {
+ private ZipFile m_file;
+ private long m_collectTime;
+
+ Entry( ZipFile file )
+ {
+ m_file = file;
+ m_collectTime = System.currentTimeMillis() + m_timeToLive;
+ }
+
+ public boolean equals( Object obj )
+ {
+ if( obj == null )
+ return false;
+ if( obj.getClass().equals( Entry.class ) == false )
+ return false;
+ Entry other = (Entry) obj;
+
+ if( m_file.equals( other.m_file ) == false )
+ return false;
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ return m_file.hashCode();
+ }
+
+ public String toString()
+ {
+ return "Entry[" + m_file + ", " + m_collectTime + "]";
+ }
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/host/ClassicResourceHost.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/host/ClassicResourceHost.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,539 @@
+/*
+ * Copyright 2004 Niclas Hedhman.
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.host;
+
+import net.dpml.transit.Transit;
+
+import net.dpml.transit.artifact.Artifact;
+
+import net.dpml.transit.layout.ClassicResolver;
+import net.dpml.transit.layout.LocationResolver;
+
+import net.dpml.transit.network.ConnectionCache;
+import net.dpml.transit.network.DelegatingAuthenticator;
+import net.dpml.transit.network.NetworkLoader;
+import net.dpml.transit.network.RequestIdentifier;
+import net.dpml.transit.network.TransitAuthenticator;
+import net.dpml.transit.network.TransitAuthenticatorImpl;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.UnknownHostException;
+
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+
+import java.security.cert.X509Certificate;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+
+
+/** This class represents a single host where resources are stored at.
+ * <p>
+ * <strong>NOTE:</strong> This ResourceHost does NOT currently support
+ * realm/domain authentication. It may be introduced in the future.
+ * </p>
+ */
+public class ClassicResourceHost
+ implements ResourceHost
+{
+ //
------------------------------------------------------------------------
+ // static
+ //
------------------------------------------------------------------------
+
+ /**
+ * HTTP port number.
+ */
+ private static final int HTTP_PORT = 80;
+
+ /**
+ * FTP port number.
+ */
+ private static final int FTP_PORT = 21;
+
+ /**
+ * HTTPS port number.
+ */
+ private static final int HTTPS_PORT = 443;
+
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ /**
+ * Host base url.
+ */
+ private URL m_baseUrl;
+
+ /**
+ * Known groups.
+ */
+ private HashSet m_knownGroups;
+
+ /**
+ * locks.
+ * The key is the Artifact one wants to lock against, and the value is an
+ * anonymously lock object.
+ */
+ private HashMap m_locks;
+
+ /**
+ * Host priority.
+ */
+ private int m_priority;
+
+ /**
+ * Enabled state.
+ */
+ private boolean m_enabled;
+
+ /**
+ * Trusted state.
+ */
+ private boolean m_trusted;
+
+ /**
+ * Connections.
+ */
+ private ConnectionCache m_connections;
+
+ private LocationResolver m_resolver;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /** Constructor for a resource host.
+ *
+ * The <i>base</i> argument is the location of the root level of the
+ * group hierarchy.
+ *
+ * @param base the host base url
+ * @param knownGroups known groups within the host
+ * @param priority host priority
+ * @param enabled the enabled state
+ * @param trusted the trusted state
+ * @param username an authentication username
+ * @param password the authentication password
+ * @param scheme the authentication scheme
+ * @param prompt the authentication prompt/realm
+ * @param resolver the LocationResolver to use.
+ * @exception UnknownHostException if the supplied base url references
an unknown host
+ */
+ public ClassicResourceHost(
+ URL base, String[] knownGroups, int priority, boolean enabled,
+ boolean trusted, String username, String password, String scheme,
+ String prompt, LocationResolver resolver )
+ throws UnknownHostException
+ {
+ if( resolver != null )
+ m_resolver = resolver;
+ else
+ m_resolver = new ClassicResolver();
+ m_locks = new HashMap();
+ m_connections = ConnectionCache.getInstance();
+ m_baseUrl = base;
+ m_priority = priority;
+ m_knownGroups = new HashSet();
+ m_trusted = trusted;
+ m_enabled = enabled;
+
+ for( int i = 0; i < knownGroups.length; i++ )
+ {
+ String group = knownGroups[ i ];
+ m_knownGroups.add( group );
+ }
+
+ String protocol = base.getProtocol();
+ InetAddress host = InetAddress.getByName( base.getHost() );
+ int port = base.getPort();
+ if( port == 0 )
+ {
+ if( protocol.equals( "http" ) )
+ {
+ port = HTTP_PORT;
+ }
+ else if( protocol.equals( "ftp" ) )
+ {
+ port = FTP_PORT;
+ }
+ else if( protocol.equals( "https" ) )
+ {
+ port = HTTPS_PORT;
+ }
+ }
+ RequestIdentifier id = new RequestIdentifier( host, port, protocol,
scheme, prompt );
+ TransitAuthenticator ta = new TransitAuthenticatorImpl( username,
password );
+ DelegatingAuthenticator da = DelegatingAuthenticator.getInstance();
+ da.addTransitAuthenticator( ta, id );
+ }
+
+ //
------------------------------------------------------------------------
+ // ResourceHost
+ //
------------------------------------------------------------------------
+
+ /**
+ * Return the host name.
+ * @return the hostname
+ */
+ public String getHostName()
+ {
+ return m_baseUrl.getHost();
+ }
+
+ /**
+ * Returns the full host url.
+ *
+ * @return the host url
+ */
+ public URL getURL()
+ {
+ return m_baseUrl;
+ }
+
+ /**
+ * Return the host priority.
+ * @return the priority
+ */
+ public int getPriority()
+ {
+ return m_priority;
+ }
+
+ /** Downloads the given artifact to the directory indicated.
+ * <p>
+ * The cachedir argument is the root cache directory, and the
ResourceHost
+ * class is responsible for the creation of the directory structure of
the
+ * group if nonexistent.
+ * </p>
+ * <p>
+ * If the knownOnly argument is true, then only attempt download if the
+ * group is known to exist on this resource host.
+ * </p>
+ * @param artifact the artifact that is requested to be downloaded.
+ * @param dest The output stream where to write the downloaded content.
+ * @exception IOException if an IO related error occurs
+ */
+ public Date download( Artifact artifact, OutputStream dest )
+ throws IOException
+ {
+ Object lock = obtainLock( artifact );
+ synchronized ( lock )
+ {
+ NetworkLoader loader = new NetworkLoader();
+ URL url = createRemoteUrl( artifact );
+
+ URLConnection connection;
+ synchronized ( m_connections )
+ {
+ connection = m_connections.get( artifact );
+ if( connection == null )
+ {
+ // Not in cache. Why not? ---> Garbage Collection has
occurred.
+ String message = this + " - Info: Connection no longer
in cache. Reconnecting.";
+ Transit.getInstance().getLogWriter().println( message );
+ URL remote = createRemoteUrl( artifact );
+ connection = remote.openConnection();
+ connection.connect();
+ }
+ }
+
+ return loader.loadResource( url, connection, dest );
+ }
+ }
+
+ /** Uploads the given file to the resource host as an artifact.
+ *
+ * @param artifact the artifact destination specification.
+ * @param source The input stream from where to read the content to be
uploaded.
+ * @exception IOException if an IO related error occurs
+ */
+ public void upload( Artifact artifact, InputStream source )
+ throws IOException
+ {
+ // TODO: implement upload through HTTP POST requests.
+ }
+
+ /** Checks if the Artifact is present on the resource host.
+ *
+ * <p>
+ * Performs a check to see if the artifact exists on the resource
host. If
+ * <i>knownOnly</i> is set to true, then the implementation will only
+ * consult the knownGroups table, and if found there, it is considered
+ * found without checking at the resource host itself. If
<i>knownOnly</i>
+ * is false, however, a connection will be established to the resource
+ * host and a check of the actual resource existence.
+ * </p>
+ *
+ * @param artifact the artifact for which the method checks its presence.
+ * @param knownOnly does not perform a remote connection, and instead
lookup
+ * the group table, and if not found there it will return false.
+ *
+ * @return true if the artifact can be located, false otherwise.
+ */
+ public boolean checkPresence( Artifact artifact, boolean knownOnly )
+ {
+ if( "file".equals( m_baseUrl.getProtocol() ) )
+ {
+ return checkAtServer( artifact );
+ }
+ else if( knownOnly )
+ {
+ return checkKnown( artifact );
+ }
+ else
+ {
+ return checkAtServer( artifact );
+ }
+ }
+
+ /**
+ * Return true if the reosurce host is enabled and online.
+ *
+ * @return true if the reosurce host is enabled and online.
+ */
+ public boolean isEnabled()
+ {
+ return m_enabled;
+ }
+
+ /** Returns true if the ResourceHost is considered trusted.
+ *
+ * @return true if the ResourceHost is considered trusted.
+ */
+ public boolean isTrusted()
+ {
+ return m_trusted;
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Check if the supplied artifact group is known.
+ * @param artifact the subject artifact to check
+ * @return TRUE if known else FALSE
+ */
+ private boolean checkKnown( Artifact artifact )
+ {
+ String group = artifact.getGroup();
+ return m_knownGroups.contains( group );
+ }
+
+ /**
+ * Ckeck if the server conection is available.
+ * @param artifact the subject artifact
+ * @return TRUE if a connection is available
+ */
+ private boolean checkAtServer( Artifact artifact )
+ {
+ try
+ {
+ URL remote = createRemoteUrl( artifact );
+ String protocol = remote.getProtocol();
+ if( protocol.startsWith( "file" ) )
+ {
+ String path = remote.getPath();
+ File f = new File( path );
+ return f.exists();
+ }
+ else
+ {
+ return openRemoteConnection( artifact );
+ }
+ }
+ catch( IOException e )
+ {
+ return false;
+ }
+ catch( NoSuchAlgorithmException e )
+ {
+ return false;
+ }
+ catch( KeyManagementException e )
+ {
+ return false;
+ }
+ catch( RuntimeException e )
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Obtain a lock on the supplied artifact.
+ * @param artifact the artifact to obtain a lock on
+ * @return the lock
+ */
+ private Object obtainLock( Artifact artifact )
+ {
+ synchronized ( this )
+ {
+ Object lock = m_locks.get( artifact );
+ if( lock == null )
+ {
+ lock = new Object();
+ m_locks.put( artifact, lock );
+ }
+ return lock;
+ }
+ }
+
+ /**
+ * Open a remote connection relative to a supplied artifact.
+ * @param artifact the artifact against which a connection will be
established
+ * @exception IOException if an IO error occurs
+ * @exception KeyManagementException if a key management error occurs
+ * @exception NoSuchAlgorithmException if no such algorithm exists?
+ * @return true if the atrifact was found and could be opened, false if
not
+ * available at this resource host.
+ */
+ private boolean openRemoteConnection( Artifact artifact )
+ throws IOException, KeyManagementException, NoSuchAlgorithmException
+ {
+ PrintWriter log = Transit.getInstance().getLogWriter();
+ log.println( this + " - opening connection: " + artifact );
+ URL remote = createRemoteUrl( artifact );
+ URLConnection conn = remote.openConnection();
+ if( conn instanceof HttpsURLConnection )
+ {
+ log.println( this + " - HTTPS connection opened." );
+ if( m_trusted )
+ {
+ log.println( this + " - Using NullTrustManager." );
+ HttpsURLConnection ssl = (HttpsURLConnection) conn;
+ TrustManager nullTrustManager = new NullTrustManager();
+ SSLContext ctx = SSLContext.getInstance( "SSLv3" );
+ ctx.init( null, new TrustManager[]{nullTrustManager}, null );
+ log.println( this + " - Setting SSLv3 socket factory." );
+ SSLSocketFactory factory = ctx.getSocketFactory();
+ ssl.setSSLSocketFactory( factory );
+ }
+ }
+ conn.connect();
+ if( conn instanceof HttpURLConnection )
+ {
+ int code = ( (HttpURLConnection) conn ).getResponseCode();
+ log.println( this + " - ResponseCode: " + code );
+ if( code == HttpURLConnection.HTTP_UNAUTHORIZED )
+ {
+ throw new IOException( "Unauthorized request." );
+ }
+ else if( code == HttpURLConnection.HTTP_NOT_FOUND )
+ {
+ return false;
+ }
+ else if( code != HttpURLConnection.HTTP_OK )
+ {
+ throw new IOException( "Unexpected Result: " + code );
+ }
+ }
+ synchronized ( m_connections )
+ {
+ log.println( this + " - caching connection: " + conn );
+ m_connections.put( artifact, conn );
+ }
+ return true;
+ }
+
+ /**
+ * Create a remote urtl from an artifact.
+ *
+ * @param artifact the subject artifact
+ * @return the remote url connection
+ * @exception MalformedURLException if the artifact path is not
resolvable to a url
+ */
+ private URL createRemoteUrl( Artifact artifact )
+ throws MalformedURLException
+ {
+ String path = m_resolver.resolvePath( artifact );
+ URL url = new URL( m_baseUrl, path );
+ return url;
+ }
+
+ /**
+ * Return a string representation of this host.
+ * @return the representation
+ */
+ public String toString()
+ {
+ return "[HOST: " + m_baseUrl + "]";
+ }
+
+ /**
+ * A null trust manager that will accept any certificate. I.e. this
+ * class performs NO TRUST MANAGEMENT and simply serves as a mechanism
+ * through which https connections can be established with the same notion
+ * of trust as a http connection (i.e. none).
+ */
+ private static final class NullTrustManager
+ implements X509TrustManager
+ {
+ /**
+ * Empty certificate sequence.
+ */
+ private static final X509Certificate[] EMPTY_CERTS = new
X509Certificate[0];
+
+ /**
+ * Null implementation.
+ * @param certs the supplied certs (ignored)
+ * @param authType the supplied type (ignored)
+ */
+ public void checkServerTrusted( final X509Certificate[] certs, final
String authType )
+ {
+ }
+
+ /**
+ * Null implementation.
+ * @param certs the supplied certs (ignored)
+ * @param authType the supplied type (ignored)
+ */
+ public void checkClientTrusted( final X509Certificate[] certs, final
String authType )
+ {
+ }
+
+ /**
+ * Null implementation.
+ * @return an empty certificate array
+ */
+ public X509Certificate[] getAcceptedIssuers()
+ {
+ return EMPTY_CERTS;
+ }
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceHost.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceHost.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.host;
+
+import net.dpml.transit.artifact.Artifact;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+import java.net.URL;
+
+import java.util.Date;
+
+/**
+ * An interface that represents locations where the artifacts can be
+ * downloaded.
+ */
+public interface ResourceHost
+{
+ /** Downloa ds the given artifact to the directory indicated.
+ * <p>
+ * The cachedir argument is the root cache directory, and the
ResourceHost
+ * class is responsible for the creation of the directory structure of
the
+ * group if nonexistent.
+ * </p>
+ * <p>
+ * If the knownOnly argument is true, then only attempt download if the
+ * group is known to exist on this resource host.
+ * </p>
+ * @param artifact the artifact that is requested to be downloaded.
+ * @param dest The output stream where to write the downloaded content.
+ * @exception IOException if an IO related error occurs
+ * @return the lastModified date of the downloaded artifact.
+ */
+ Date download( Artifact artifact, OutputStream dest )
+ throws IOException;
+
+ /** Uploads the given file to the resource host as an artifact.
+ *
+ * @param artifact the artifact destination specification.
+ * @param source The input stream from where to read the content to be
uploaded.
+ * @exception IOException if an IO related error occurs
+ */
+ void upload( Artifact artifact, InputStream source )
+ throws IOException;
+
+ /** Checks if the Artifact is present on the resource host.
+ *
+ * <p>
+ * Performs a check to see if the artifact exists on the resource
host. If
+ * <i>knownOnly</i> is set to true, then the implementation will only
+ * consult the knownGroups table, and if found there, it is considered
+ * found without checking at the resource host itself. If
<i>knownOnly</i>
+ * is false, however, a connection will be established to the resource
+ * host and a check of the actual resource existence.
+ * </p>
+ *
+ * @param artifact the artifact for which the method checks its presence.
+ * @param knownOnly does not perform a remote connection, and instead
lookup
+ * the group table, and if not found there it will return false.
+ *
+ * @return true if the artifact can be located, false otherwise.
+ */
+ boolean checkPresence( Artifact artifact, boolean knownOnly );
+
+ /** Returns the hostname of the resource host.
+ *
+ * <p>
+ * This does not include any of the path, but do include any port
number
+ * of this resource host.
+ * </p>
+ * @return the hostname
+ */
+ String getHostName();
+
+ /**
+ * Returns the full host url.
+ *
+ * @return the host url
+ */
+ URL getURL();
+
+ /**
+ * Return true if the resource host has been enabled.
+ *
+ * @return true if the resource host is enabled, false if not.
+ */
+ boolean isEnabled();
+
+ /** Returns true if the ResourceHost is considered trusted.
+ * @return true if the host is trusted
+ */
+ boolean isTrusted();
+
+ /** Returns the priority of the resource host.
+ *
+ * A high number indicates a more important host that should take
precendence
+ * over a host with lower number.
+ * @return the host priority
+ */
+ int getPriority();
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceHostFactory.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceHostFactory.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,647 @@
+/*
+ * Copyright 2004 Niclas Hedhman
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.host;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import java.net.URL;
+import java.net.MalformedURLException;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Properties;
+
+import net.dpml.lang.NullArgumentException;
+
+import net.dpml.transit.Transit;
+import net.dpml.transit.TransitException;
+
+import net.dpml.transit.util.Util;
+
+import net.dpml.transit.layout.LocationResolver;
+
+import net.dpml.transit.monitors.SystemMonitor;
+
+/**
+ * Internal class that handles the creation of resource hosts based on an
XML host
+ * destriptor or property files.
+ */
+class ResourceHostFactory
+{
+ //
------------------------------------------------------------------------
+ // static
+ //
------------------------------------------------------------------------
+
+ /**
+ * True.
+ */
+ private static final String TRUE_VALUE = "true";
+
+ /**
+ * Filename of the remote file index.
+ */
+ private static final String REMOTE_LIST_FILENAME = "index.lst";
+
+ /**
+ * File protocol name length.
+ */
+ private static final int FILE_PROTOCOL_LENGTH = 5;
+
+ /**
+ * Default priority.
+ */
+ static final int DEFAULT_HOST_PRIORITY = 10;
+
+ /**
+ * Default priority string.
+ */
+ private static final String DEFAULT_PRIORITY_STRING = "10";
+
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ /**
+ * Authorative anchor url.
+ */
+ private URL m_authorative;
+
+ /**
+ * Monitor
+ */
+ private SystemMonitor m_monitor;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new resource host factory using a supplied authoriative
+ * anchor url.
+ * @param authorative the authorative anchor
+ * @param monitor the bootstrap monitor
+ */
+ ResourceHostFactory( URL authorative, SystemMonitor monitor )
+ {
+ m_authorative = authorative;
+ m_monitor = monitor;
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Create a set of resource hosts relative to the information optained at
the
+ * authorative anchor.
+ * <p>
+ * The implementation will attempt to locate a hosts.xml
+ * at the authorative location and if available will resolve host
defintions
+ * and return. Otherwise the behaviour is dependent on the type of
authority - if
+ * the authority url protocol is "file:" then property based host
descriptors will
+ * be read from the [authorative]/hosts direrectory. All files in the
directory
+ * will be considered. If the a property based host file does not contain
the property
+ * declaration "dpml.transit.resourcehost.base" the file not be
processed. If the
+ * authorative url is not the "file:" protocol then the implementation
will attempt
+ * to locate a resource named "index.lst" containing a set of host
descriptor filenames
+ * to evaluation.
+ * </p>
+ *
+ * @return the resolve set of resource hosts
+ * @exception IOException if an io error occurs
+ * @exception TransitException if a transit related error occurs
+ */
+ ResourceHost[] createResourceHosts()
+ throws IOException, TransitException
+ {
+ ArrayList result = new ArrayList();
+
+ URL hosts = new URL( m_authorative, "hosts.xml" );
+ InputStream input = null;
+ try
+ {
+ input = hosts.openStream();
+ new XMLHostsBuilder( this ).buildResourceHosts( result, input );
+ }
+ catch( IOException ioe )
+ {
+ if( null != input )
+ {
+ input.close();
+ }
+ }
+
+ String protocol = m_authorative.getProtocol();
+ if( "file".equals( protocol ) )
+ {
+ String authorative = m_authorative.toExternalForm().substring(
FILE_PROTOCOL_LENGTH );
+ while ( authorative.startsWith( "//" ) )
+ {
+ authorative = authorative.substring( 1 );
+ }
+
+ File base = new File( authorative );
+ if( !base.exists() )
+ {
+ final String error =
+ "Authority base directory ["
+ + base
+ + "] does not exist.";
+ throw new FileNotFoundException( error );
+ }
+ createResourceHostsFromDirectory( result, base );
+ }
+ else
+ {
+ URL index = new URL( m_authorative, REMOTE_LIST_FILENAME );
+ String[] files = Util.readListFile( index );
+ createResourceHosts( result, files );
+ }
+ ResourceHost[] hostArray = new ResourceHost[ result.size() ];
+ result.toArray( hostArray );
+ return hostArray;
+ }
+
+ /**
+ * Creates the ResourceHosts defined in the properties for the
ResourceHost.
+ *
+ * <pre>
+ * dpml.transit.resourcehost.class=[classname]
+ * dpml.transit.resourcehost.base=[baseurl]
+ * dpml.transit.resourcehost.knowngroups=[groupsurl]
+ * dpml.transit.resourcehost.priority=[priority]
+ * dpml.transit.resourcehost.username=[username]
+ * dpml.transit.resourcehost.password=[password]
+ * dpml.transit.resourcehost.scheme=[authentication scheme]
+ * dpml.transit.resourcehost.prompt=[prompt/realm]
+ * dpml.transit.resourcehost.resolver=[resolver-classname]
+ * </pre>
+ * @param result the list of established hosts
+ * @param files the set of filesname to scan
+ * @exception TransitException if an error occurs in resource host
construction
+ */
+ private void createResourceHosts( List result, String[] files )
+ throws TransitException
+ {
+ for( int i=0; i < files.length; i++ )
+ {
+ URL file;
+ try
+ {
+ file = new URL( m_authorative, files[i] );
+ ResourceHost host = createResourceHostFromDescriptor( file );
+ if( host != null )
+ {
+ result.add( host );
+ }
+ }
+ catch( MalformedURLException e )
+ {
+ final String error =
+ "Unable to construct a URL from " + m_authorative + " and
" + files[i];
+ throw new TransitException( error );
+ }
+ catch( IOException e )
+ {
+ throw new TransitException( "Unable to read : " +
m_authorative + ", " + files[i], e );
+ }
+ }
+ }
+
+
+ /** Creates the ResourceHosts defined in the properties.
+ *
+ * <pre>
+ * dpml.transit.resourcehost.class=[classname]
+ * dpml.transit.resourcehost.base=[baseurl]
+ * dpml.transit.resourcehost.knowngroups=[groupsurl]
+ * dpml.transit.resourcehost.priority=[priority]
+ * dpml.transit.resourcehost.username=[username]
+ * dpml.transit.resourcehost.password=[password]
+ * dpml.transit.resourcehost.scheme=[authentication scheme]
+ * dpml.transit.resourcehost.prompt=[prompt/realm]
+ * dpml.transit.resourcehost.resolver=[resolver-classname]
+ * </pre>
+ * @param result the list of established hosts
+ * @param base the base directory from within which host files will be
located
+ * @exception TransitException if an error occurs while reading host
descriptors
+ */
+ private void createResourceHostsFromDirectory( List result, File base )
+ throws TransitException
+ {
+ File hosts = new File( base, "hosts" );
+ if( hosts.exists() )
+ {
+ File[] files = hosts.listFiles();
+ createResourceHostsFromFiles( result, files );
+ }
+ }
+
+ /** Creates the ResourceHosts defined in the properties.
+ *
+ * <pre>
+ * dpml.transit.resourcehost.class=[classname]
+ * dpml.transit.resourcehost.base=[baseurl]
+ * dpml.transit.resourcehost.knowngroups=[groupsurl]
+ * dpml.transit.resourcehost.priority=[priority]
+ * dpml.transit.resourcehost.username=[username]
+ * dpml.transit.resourcehost.password=[password]
+ * dpml.transit.resourcehost.scheme=[authentication scheme]
+ * dpml.transit.resourcehost.prompt=[prompt/realm]
+ * dpml.transit.resourcehost.resolver=[resolver-classname]
+ * </pre>
+ * @param result the list of established hosts
+ * @param files the set of host descriptors to read
+ * @exception TransitException if an error occurs while reading host
descriptors
+ * @exception NullArgumentException if the files argument or the result
argument is null.
+ */
+ private void createResourceHostsFromFiles( List result, File[] files )
+ throws TransitException, NullArgumentException
+ {
+ if( null == files )
+ {
+ throw new NullArgumentException( "files" );
+ }
+
+ if( null == result )
+ {
+ throw new NullArgumentException( "result" );
+ }
+
+ for( int i=0; i < files.length; i++ )
+ {
+ try
+ {
+ URL url = fileToURL( files[i] );
+ ResourceHost host = createResourceHostFromDescriptor( url );
+ if( host != null )
+ {
+ result.add( host );
+ }
+ }
+ catch( MalformedURLException e )
+ {
+ throw new TransitException( "# Unable to construct a URL
from " + files[i] );
+ }
+ catch( IOException e )
+ {
+ throw new TransitException( "Unable to read : " + files[i],
e );
+ }
+ }
+ }
+
+ /**
+ * Return the url of a file.
+ * @param file the file to convert
+ * @return the equivalent url
+ * @exception TransitException if a error occurs in file to url conversion
+ */
+ private URL fileToURL( File file ) throws TransitException
+ {
+ try
+ {
+ return file.toURL();
+ }
+ catch( MalformedURLException mue )
+ {
+ final String error =
+ "The file ["
+ + file
+ + "] ("
+ + file.exists()
+ + ") raised a malformed url exception with the message '"
+ + mue.getMessage()
+ + "'.";
+ throw new TransitException( error );
+ }
+ }
+
+ /**
+ * Return a resource host relative to a url.
+ * @param hostDef the url of the host descriptor
+ * @return the resource host
+ * @exception TransitException if an error occurs related to content
parsing
+ * @exception IOException if an error occurs due to content reading
+ */
+ private ResourceHost createResourceHostFromDescriptor( URL hostDef )
+ throws TransitException, IOException
+ {
+ if( null == hostDef )
+ {
+ throw new NullArgumentException( "hostDef" );
+ }
+
+ Properties props = Util.readProps( hostDef );
+ URL baseUrl;
+ String base = Util.getProperty( props,
"dpml.transit.resourcehost.base", null );
+ if( base == null )
+ {
+ return null;
+ }
+
+ try
+ {
+ if( !base.endsWith( "/" ) )
+ {
+ base = base + "/";
+ }
+ baseUrl = new URL( base );
+ }
+ catch( MalformedURLException e )
+ {
+ final String error =
+ "The value assigned to the base host property within a host
definition file is invalid."
+ + "\n Source: "
+ + hostDef
+ + "\n Property: dpml.transit.resourcehost.base"
+ + "\n Value: "
+ + base;
+ throw new TransitException( error, e );
+ }
+
+ if( base.startsWith( "file:" ) )
+ {
+ base = base.substring( FILE_PROTOCOL_LENGTH );
+
+ File f = new File( base );
+ if( !f.isAbsolute() )
+ {
+ f = new File( Transit.DPML_SYSTEM, base );
+ }
+ base = f.toURL().toExternalForm();
+ }
+
+ String key = "dpml.transit.resourcehost.class";
+ String def = "net.dpml.transit.host.ClassicResourceHost";
+ String classname = Util.getProperty( props, key, def );
+
+ String known = Util.getProperty( props,
"dpml.transit.resourcehost.knowngroups", "" );
+
+ URL groupFile = getRelativeURL( hostDef, known );
+
+ String priorityText =
+ Util.getProperty( props, "dpml.transit.resourcehost.priority",
DEFAULT_PRIORITY_STRING );
+ if( "".equals( priorityText ) )
+ {
+ priorityText = DEFAULT_PRIORITY_STRING;
+ }
+ int priority = Integer.parseInt( priorityText );
+ String username = Util.getProperty( props,
"dpml.transit.resourcehost.username", "" );
+ String password = Util.getProperty( props,
"dpml.transit.resourcehost.password", "" );
+ String prompt = Util.getProperty( props,
"dpml.transit.resourcehost.prompt", "" );
+ String scheme = Util.getProperty( props,
"dpml.transit.resourcehost.scheme", "" );
+ String resolverclass = Util.getProperty( props,
"dpml.transit.resourcehost.resolver",
"net.dpml.transit.layout.ClassicResolver" );
+
+ boolean enabled =
+ Util.getProperty(
+ props, "dpml.transit.resourcehost.enabled", TRUE_VALUE
).equalsIgnoreCase( TRUE_VALUE );
+ boolean trusted =
+ Util.getProperty(
+ props, "dpml.transit.resourcehost.trusted", "false"
).equalsIgnoreCase( TRUE_VALUE );
+
+ try
+ {
+ return createResourceHost(
+ classname, baseUrl, groupFile, priority, enabled, trusted,
+ username, password, scheme, prompt, resolverclass );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Could not construct a resource hosts from the host
descriptor: "
+ + hostDef;
+ throw new TransitException( error, e );
+ }
+ }
+
+ /**
+ * Return a url using the supplied url as anchor for the supplied path.
+ * @param anchor the anchor url
+ * @param path the relative path
+ * @return the resolved absolute url
+ * @exception TransitException if an error occurs in url creation
+ */
+ private URL getRelativeURL( URL anchor, String path ) throws
TransitException
+ {
+ try
+ {
+ return new URL( anchor, path );
+ }
+ catch( MalformedURLException mue )
+ {
+ final String error =
+ "An error occured while attempting to construct a new url
using the path ["
+ + path
+ + "] and base url ["
+ + anchor
+ + "].";
+ throw new TransitException( error, mue );
+ }
+ }
+
+ /**
+ * Return the class relative a supplied filename using this class as the
+ * reference classloader.
+ * @param classname the classname of the class to load
+ * @return the class
+ * @exception ClassNotFoundException if the class cannot be found
+ */
+ private Class getHostClass( String classname ) throws
ClassNotFoundException
+ {
+ return ResourceHostFactory.class.getClassLoader().loadClass(
classname );
+ }
+
+ /**
+ * Return a set of known groups froma host.
+ * @param href the host against which the request is to be made
+ * @return the set of known group names
+ * @exception TransitException if an error occurs while attempting to
read the
+ * remote address
+ */
+ private String[] getKnownGroups( URL href ) throws TransitException
+ {
+ if( href != null )
+ {
+ try
+ {
+ return Util.readListFile( href );
+ }
+ catch( Exception e )
+ {
+ final String error =
+ "Unable to extract the groups from "
+ + href;
+ throw new TransitException( error, e );
+ }
+ }
+ else
+ {
+ return new String[0];
+ }
+ }
+
+ /**
+ * Utility method used to construct a new resource host instance.
+ * @param classname the classname of the resource host provider
+ * @param base the base url of the host
+ * @param index the url of group index resource
+ * @param priority the assigned host priority
+ * @param enabled if true the created host is enabled else disabled
+ * @param trusted if the host is trusted
+ * @param username the authentication username
+ * @param password the authentication password
+ * @param scheme the authentication request scheme
+ * @param prompt the authentication prompt (should be HTTP realm)
+ * @return the resource host
+ * @exception TransitException if a construction error occurs
+ * @exception IOException if an IO related error occurs
+ */
+ ResourceHost createResourceHost(
+ String classname, URL base, URL index, int priority,
+ boolean enabled, boolean trusted, String username, String password,
+ String scheme, String prompt, String resolverClassname )
+ throws TransitException, IOException
+ {
+ LocationResolver resolver = createResolver( resolverClassname );
+ String[] groups = getKnownGroups( index );
+ Class[] types = new Class[]
+ {
+ URL.class,
+ String[].class,
+ Integer.TYPE,
+ Boolean.TYPE,
+ Boolean.TYPE,
+ String.class,
+ String.class,
+ String.class,
+ String.class,
+ LocationResolver.class
+ };
+
+ Object[] args = new Object[]
+ {
+ base,
+ groups,
+ new Integer( priority ),
+ enabled ? Boolean.TRUE : Boolean.FALSE,
+ trusted ? Boolean.TRUE : Boolean.FALSE,
+ username,
+ password,
+ scheme,
+ prompt,
+ resolver
+ };
+
+ try
+ {
+ Class clazz = getHostClass( classname );
+ Constructor cons = clazz.getConstructor( types );
+ Object instance = cons.newInstance( args );
+ if( instance instanceof ResourceHost )
+ {
+ ResourceHost host = (ResourceHost) instance;
+ m_monitor.notifyHostCreation( host );
+ return host;
+ }
+ else
+ {
+ final String error =
+ "Class "
+ + classname
+ + " does not implement "
+ + ResourceHost.class.getName() + ".";
+ throw new TransitException( error );
+ }
+ }
+ catch( ClassNotFoundException e )
+ {
+ final String error =
+ "The resource host factory classname ["
+ + classname
+ + "] is unknown.";
+ throw new TransitException( error );
+ }
+ catch( NoSuchMethodException e )
+ {
+ final String error =
+ "The resource host factory class ["
+ + classname
+ + "] does not declare the required constructor.";
+ throw new TransitException( error );
+ }
+ catch( IllegalAccessException e )
+ {
+ final String error =
+ "The resource host factory class ["
+ + classname
+ + "] is not accessible.";
+ throw new TransitException( error );
+ }
+ catch( IllegalArgumentException e )
+ {
+ final String error =
+ "The resource host factory class ["
+ + classname
+ + "] could not be established due to an internal error.";
+ throw new TransitException( error, e );
+ }
+ catch( InstantiationException e )
+ {
+ final String error =
+ "The resource host factory class ["
+ + classname
+ + "] could not be instantiated.";
+ throw new TransitException( error, e );
+ }
+ catch( InvocationTargetException e )
+ {
+ final String error =
+ "The resource host factory class ["
+ + classname
+ + "] raised an unexpected error during instantiation.";
+ throw new TransitException( error, e.getTargetException() );
+ }
+ }
+
+ private LocationResolver createResolver( String classname )
+ throws TransitException
+ {
+ try
+ {
+ Class cls = getClass().getClassLoader().loadClass( classname );
+ return (LocationResolver) cls.newInstance();
+ } catch( ClassNotFoundException e )
+ {
+ throw new TransitException( "Specified resolver class can not be
found: " + classname );
+ } catch( ClassCastException e )
+ {
+ throw new TransitException( "Specified resolver classname does
not implement net.dpml.transit.handler.LocationResolver : " + classname );
+ } catch( Exception e )
+ {
+ throw new TransitException( "Unknown exception: " + classname, e
);
+ }
+
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceManager.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/host/ResourceManager.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.host;
+
+import net.dpml.transit.TransitException;
+import net.dpml.transit.cache.CacheHandler;
+
+import java.io.IOException;
+
+/**
+ * Interface implemented by a resource manager responsible for the
establishment
+ * of a transit cache handler.
+ */
+public interface ResourceManager
+{
+ /**
+ * The default resource manager classname key.
+ */
+ String TRANSIT_RESOURCE_MANAGER_CLASSNAME_KEY =
+ "dpml.transit.authority.resourcemanager.classname";
+
+ /**
+ * The default resource manager classname key.
+ */
+ String TRANSIT_RESOURCE_MANAGER_CLASSNAME =
+ "net.dpml.transit.host.StandardResourceManager";
+
+ /**
+ * Return the cache handler.
+ * @exception IOException if an io error occurs
+ * @exception TransitException if a transit system error occurs
+ */
+ CacheHandler createCacheHandler() throws TransitException, IOException;
+
+
+}
\ No newline at end of file

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/host/StandardResourceManager.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/host/StandardResourceManager.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2004-2005 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.host;
+
+import net.dpml.transit.TransitException;
+import net.dpml.transit.cache.CacheHandler;
+import net.dpml.transit.layout.ClassicResolver;
+import net.dpml.transit.layout.LocationResolver;
+import net.dpml.transit.monitors.Monitor;
+import net.dpml.transit.monitors.SystemMonitor;
+import net.dpml.transit.util.Util;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.util.Properties;
+
+/**
+ * Internal resource manager that establishes a CacheHandler implementation
using
+ * the property 'dpml.transit.cache.class' from the file cache.properties.
+ *
+ * The CacheHandler constructor MUST have the signature of;
+ * <code><pre>
+ * MyCacheHandler( Monitor monitor, ResourceHost[] hosts, Properties
props, LocationResolver resolver )
+ * </pre></code>
+ */
+public class StandardResourceManager implements ResourceManager
+{
+ //
------------------------------------------------------------------------
+ // static
+ //
------------------------------------------------------------------------
+
+ /**
+ * The cache properties filename.
+ */
+ private static final String TRANSIT_CACHE_PROPERTIES_FILENAME =
"cache.properties";
+
+ /**
+ * The default cache handler classname.
+ */
+ private static final String TRANSIT_CACHE_DEFAULT_HANDLER_CLASSNAME =
+ "net.dpml.transit.cache.FileCacheHandler";
+
+ /**
+ * The default cache handler classname.
+ */
+ private static final String TRANSIT_CACHE_DEFAULT_RESOLVER_CLASSNAME =
+ "net.dpml.transit.layout.ClassicResolver";
+
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ private final URL m_authorative;
+ private final SystemMonitor m_monitor;
+ private final ResourceHost[] m_hosts;
+ private final Properties m_properties;
+ private final LocationResolver m_resolver;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new resource manager.
+ * @param authorative the authorative base url
+ * @param monitor the internal monitor
+ * @exception IOException if an io error occurs
+ * @exception TransitException if a transit system error occurs
+ */
+ public StandardResourceManager( URL authorative, SystemMonitor monitor )
+ throws TransitException, IOException
+ {
+ m_authorative = authorative;
+ m_monitor = monitor;
+
+ ResourceHostFactory factory = new ResourceHostFactory(
m_authorative, m_monitor );
+ m_hosts = factory.createResourceHosts();
+
+ m_properties = getCacheProperties( m_authorative );
+ m_resolver = createResolver( m_properties );
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new cache handler.
+ * @return the cache handler
+ * @exception IOException if an io error occurs
+ * @exception TransitException if a transit system error occurs
+ */
+ public CacheHandler createCacheHandler()
+ throws TransitException, IOException
+ {
+ String classname =
+ m_properties.getProperty( CacheHandler.CACHE_CLASS_KEY,
TRANSIT_CACHE_DEFAULT_HANDLER_CLASSNAME );
+ return createCacheHandler( classname );
+ }
+
+ /**
+ * Creation of a new cache handler using a supplied class.
+ * @param classname the CacheHandler classname.
+ * @return the cache handler
+ * @exception IOException if an io error occurs
+ * @exception TransitException if a transit system error occurs
+ */
+ protected CacheHandler createCacheHandler( String classname )
+ throws TransitException, IOException
+ {
+ try
+ {
+ Class cls = getClass().getClassLoader().loadClass( classname );
+ Class[] params = new Class[]{
+ Monitor.class,
+ ResourceHost[].class,
+ Properties.class,
+ LocationResolver.class};
+ Object[] args = new Object[]{
+ m_monitor,
+ m_hosts,
+ m_properties,
+ m_resolver};
+ Constructor cons = cls.getConstructor( params );
+ return (CacheHandler) cons.newInstance( args );
+ }
+ catch( Exception e )
+ {
+ final String error =
+ "Unable to create CacheHandler using ["
+ + classname
+ + "].";
+ throw new TransitException( error, e );
+ }
+ }
+
+
+ private LocationResolver createResolver( Properties props )
+ {
+ String classname =
+ props.getProperty( CacheHandler.RESOLVER_CLASS_KEY,
TRANSIT_CACHE_DEFAULT_RESOLVER_CLASSNAME );
+ try
+ {
+ Class cls = getClass().getClassLoader().loadClass( classname );
+ return (LocationResolver) cls.newInstance();
+ } catch( Exception e )
+ {
+ // Niclas: Should we throw exception instead???
+ return new ClassicResolver();
+ }
+ }
+
+ private Properties getCacheProperties( URL authorative ) throws
IOException
+ {
+ try
+ {
+ URL url = new URL( authorative,
TRANSIT_CACHE_PROPERTIES_FILENAME );
+ return Util.readProps( url );
+ }
+ catch( FileNotFoundException fnfe )
+ {
+ String resource = "transit/authority/" +
TRANSIT_CACHE_PROPERTIES_FILENAME;
+ ClassLoader classloader = getClass().getClassLoader();
+ URL url = classloader.getResource( resource );
+ return Util.readProps( url );
+ }
+ }
+}
\ No newline at end of file

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/host/XMLHostsBuilder.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/host/XMLHostsBuilder.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,391 @@
+/*
+ * Copyright 2004 Stephen McConnell
+ * Copyright 2004 Niclas Hedhman
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.host;
+
+import net.dpml.transit.Transit;
+import net.dpml.transit.TransitException;
+import net.dpml.transit.util.ElementHelper;
+
+import org.w3c.dom.Element;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+
+/**
+ * Utility class supporting the translation of an XML based hosts file to a
+ * set of ResourceHost descriptors.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ * @version $Revision: 1.2 $ $Date: 2004/03/17 10:30:09 $
+ */
+final class XMLHostsBuilder
+{
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ /**
+ * The factory used to create resource hosts based on the data collected
+ * from xml based specifications.
+ */
+ private final ResourceHostFactory m_resourceHostFactory;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ * @param factory the resource host factory
+ */
+ XMLHostsBuilder( ResourceHostFactory factory )
+ {
+ m_resourceHostFactory = factory;
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Build a set of resource hosts using a supplied input stream.
+ * @param result a list containing the acculated host definitions
+ * @param input the input stream of an XML document
+ * @exception IOException if an IO related error occurs
+ * @exception TransitException if an error occurs in constructing the
+ * host defintions
+ */
+ void buildResourceHosts( List result, InputStream input )
+ throws IOException, TransitException
+ {
+ try
+ {
+ Element root = ElementHelper.getRootElement( input );
+ Element[] elements = ElementHelper.getChildren( root, "host" );
+ for( int i=0; i < elements.length; i++ )
+ {
+ Element element = elements[i];
+ ResourceHost host = buildResourceHost( element );
+ result.add( host );
+ }
+ }
+ catch( Exception e )
+ {
+ final String error =
+ "Unabled to construct host defintions from source.";
+ throw new TransitException( error, e );
+ }
+ }
+
+ /**
+ * Build a single resource host from a host Element.
+ * @param element the XML host element
+ * @return the resource host
+ * @exception IOException if an IO related error occurs
+ * @exception TransitException if an error occurs in constructing the
+ * host defintions
+ */
+ private ResourceHost buildResourceHost( Element element )
+ throws IOException, TransitException
+ {
+ String classname = getClassname( element );
+ String resolverclass = getResolverClass( element );
+ URL base = getBaseURL( element );
+ URL index = getKnownGroupsURL( element );
+ int priority = getPriority( element );
+ boolean enabled = getEnabled( element );
+ boolean trusted = getTrusted( element );
+ String username = getUsername( element );
+ String password = getPassword( element );
+ String scheme = getScheme( element );
+ String prompt = getPrompt( element );
+
+ return m_resourceHostFactory.createResourceHost(
+ classname, base, index, priority, enabled, trusted,
+ username, password, scheme, prompt, resolverclass );
+ }
+
+ /**
+ * Get the base url from the supplied host element.
+ * @param root the XML host element
+ * @return the resource host base url
+ * @exception IOException if an IO related error occurs
+ */
+ private URL getBaseURL( Element root )
+ throws IOException
+ {
+ String base = ElementHelper.getAttribute( root, "href", null );
+ if( null == base )
+ {
+ String dir = ElementHelper.getAttribute( root, "dir", null );
+ if( null == dir )
+ {
+ final String error =
+ "The host element does not contain an 'href' or 'dir'
attribute:\n"
+ + root.toString();
+ throw new IllegalArgumentException( error );
+ }
+ else
+ {
+ return resolveLocalRepositoryURL( dir );
+ }
+ }
+
+ if( !base.endsWith( "/" ) )
+ {
+ base = base + "/";
+ }
+ return new URL( base );
+ }
+
+ /**
+ * Resolve a base url to a local file repository using a supplied path.
If the path
+ * resolves to an absolute filename a local repository will be created at
that location
+ * otherwise a repository will be created relative to ${dpml.home}.
+ *
+ * @param path the repository path
+ * @return the repository url
+ * @exception IOException if an IO related error occurs
+ */
+ private URL resolveLocalRepositoryURL( String path )
+ throws IOException
+ {
+ File base = new File( path );
+ if( base.isAbsolute() )
+ {
+ base.mkdirs();
+ return base.toURL();
+ }
+ else
+ {
+ File dir = new File( Transit.DPML_SYSTEM, path );
+ dir.mkdirs();
+ return dir.toURL();
+ }
+ }
+
+ /**
+ * Get the index url from the supplied host element using a child element
+ * named 'index' with an href attribute.
+ * @param root the XML host element
+ * @return the index url (possibly null)
+ * @exception IOException if an IO related error occurs
+ */
+ private URL getKnownGroupsURL( Element root )
+ throws IOException
+ {
+ Element element = ElementHelper.getChild( root, "index" );
+ if( null == element )
+ {
+ return null;
+ }
+
+ String href = ElementHelper.getAttribute( element, "href", null );
+ if( null == href )
+ {
+ final String error =
+ "The index element does not contain the required 'href'
attribute.";
+ throw new IllegalArgumentException( error );
+ }
+ return new URL( href );
+ }
+
+ /**
+ * Get the host classname from the supplied host element using a child
element
+ * named 'class' with an 'name' attribute.
+ * @param root the XML host element
+ * @return the host classname
+ */
+ private String getClassname( Element root )
+ {
+ String defaultClass = "net.dpml.transit.host.ClassicResourceHost";
+ Element element = ElementHelper.getChild( root, "class" );
+ if( null == element )
+ {
+ return defaultClass;
+ }
+
+ String classname = ElementHelper.getAttribute( root, "name", null );
+ if( null == classname )
+ {
+ classname = ElementHelper.getValue( element );
+ if( classname == null )
+ {
+ classname = defaultClass;
+ }
+ }
+ return classname;
+ }
+
+
+ /**
+ * Get the host priority from the supplied host element using the value of
+ * the child element named 'priority'.
+ * @param root the XML host element
+ * @return the priority
+ */
+ private int getPriority( Element root )
+ {
+ Element element = ElementHelper.getChild( root, "priority" );
+ if( null == element )
+ {
+ return ResourceHostFactory.DEFAULT_HOST_PRIORITY;
+ }
+ String priority = ElementHelper.getValue( element );
+ if( null == priority )
+ {
+ return ResourceHostFactory.DEFAULT_HOST_PRIORITY;
+ }
+ return Integer.parseInt( priority );
+ }
+
+ /**
+ * Get the host enabled status from the supplied host element using the
enabled
+ * attribute.
+ * @param root the XML host element
+ * @return the enabled status
+ */
+ private boolean getEnabled( Element root )
+ {
+ String enabled = ElementHelper.getAttribute( root, "enabled", "true"
);
+ return new Boolean( enabled ).booleanValue();
+ }
+
+ /**
+ * Get the host trusted status from the supplied host element using the
+ * value of a child element named 'trusted'.
+ * @param root the XML host element
+ * @return the trusted status
+ */
+ private boolean getTrusted( Element root )
+ {
+ Element element = ElementHelper.getChild( root, "trusted" );
+ if( null == element )
+ {
+ return false;
+ }
+ String trusted = ElementHelper.getValue( element );
+ return new Boolean( trusted ).booleanValue();
+ }
+
+ /**
+ * Get the username from the supplied host element's credentials element
using the
+ * value of a child element named 'username'.
+ * @param root the XML host element
+ * @return the username
+ */
+ private String getUsername( Element root )
+ {
+ Element credentials = ElementHelper.getChild( root, "credentials" );
+ if( null == credentials )
+ {
+ return "";
+ }
+
+ Element element = ElementHelper.getChild( credentials, "username" );
+ if( null == element )
+ {
+ return "";
+ }
+ else
+ {
+ return ElementHelper.getValue( element );
+ }
+ }
+
+ /**
+ * Get the password from the supplied host element's credentials element
using the
+ * value of a child element named 'password'.
+ * @param root the XML host element
+ * @return the password
+ */
+ private String getPassword( Element root )
+ {
+ Element credentials = ElementHelper.getChild( root, "credentials" );
+ if( null == credentials )
+ {
+ return "";
+ }
+
+ Element element = ElementHelper.getChild( credentials, "password" );
+ if( null == element )
+ {
+ return "";
+ }
+ else
+ {
+ return ElementHelper.getValue( element );
+ }
+ }
+
+ /**
+ * Get the scheme from the supplied host element using the
+ * value of a child element named 'scheme'.
+ * @param root the XML host element
+ * @return the scheme
+ */
+ private String getScheme( Element root )
+ {
+ Element element = ElementHelper.getChild( root, "scheme" );
+ if( null == element )
+ {
+ return "";
+ }
+ else
+ {
+ return ElementHelper.getValue( element );
+ }
+ }
+
+ /**
+ * Get the prompt/realm from the supplied host element using the
+ * value of a child element named 'prompt'.
+ * @param root the XML host element
+ * @return the prompt/realm
+ */
+ private String getPrompt( Element root )
+ {
+ Element element = ElementHelper.getChild( root, "prompt" );
+ if( null == element )
+ {
+ return "";
+ }
+ else
+ {
+ return ElementHelper.getValue( element );
+ }
+ }
+
+ private String getResolverClass( Element root )
+ {
+ Element element = ElementHelper.getChild( root, "resolver" );
+ if( null == element )
+ {
+ return "";
+ }
+ else
+ {
+ return ElementHelper.getValue( element );
+ }
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/layout/ClassicResolver.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/layout/ClassicResolver.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.layout;
+
+import net.dpml.transit.artifact.Artifact;
+
+/** The ClassicResolver decodes artifacts into the Classic/Maven layout
+ * of artifacts on a file system or http server.
+ * This format says that for an artifact
<code>artifact:[type]:[group]/[name]#[version]</code>
+ * the location of such artifact would be;
+ * <code>[group]/[type]s/[name]-[version].[type]</code>.
+ * Example; <code>artifact:jar:metro/cache/dpml-cache-main#1.0.0</code>
+ * would return the path
<code>metro/cache/jars/dpml-cache-main-1.0.0.jar</code>.
+ */
+public class ClassicResolver
+ implements LocationResolver
+{
+ /**
+ * Return the base path for an artifact. The base path is derived from
+ * the artifact group and type. For an artifact group of "metro/cache"
and a
+ * type equal to "jar", the base value will be translated using the
pattern
+ * "[group]/[type]s" to form "metro/cache/jars". The base path value
represents
+ * the directory path relative to a repository root of the directory
containing
+ * this artifact.
+ *
+ * @return the base path
+ */
+ public final String resolveBase( Artifact artifact )
+ {
+ return artifact.getGroup() + "/" + artifact.getType() + "s";
+ }
+
+ /**
+ * Returns the full path of the artifact relative to a logical root
directory.
+ * The full path is equivalent to the base path and artifact filename
using the
+ * pattern "[base]/[filename]". Path values may be used to resolve an
artifact
+ * from a remote repository or local cache relative to the repository or
cache
+ * root. An artifact such as
<code>artifact:jar:metro/cache/dpml-cache-main#1.0.0</code>
+ * would return the path
<code>metro/cache/jars/dpml-cache-main-1.0.0.jar</code>.
+ *
+ * @see #resolveBase
+ * @see #resolveFilename
+ * @return the logical artifact path
+ */
+ public final String resolvePath( Artifact artifact )
+ {
+ return resolveBase( artifact ) + "/" + resolveFilename( artifact );
+ }
+
+ /**
+ * Return the expanded filename of the artifact. The filename is
expressed
+ * as [name]-[version].[type] or in case of a null version simply
[name].[type].
+ *
+ * @return the artifact expanded filename
+ */
+ public String resolveFilename( Artifact artifact )
+ {
+ String ver = artifact.getVersion();
+ if( null == ver )
+ {
+ return artifact.getName() + "." + artifact.getType();
+ }
+ else
+ {
+ return artifact.getName() + "-" + ver + "." + artifact.getType();
+ }
+ }
+
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/layout/EclipseResolver.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/layout/EclipseResolver.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.layout;
+
+import net.dpml.transit.artifact.Artifact;
+
+/** The EclipseResolver decodes artifacts into the Eclipse specified layout
+ * of artifacts on a file system or http server.
+ * This format says that for an artifact
<code>artifact:[type]:[group]/[name]#[version]</code>
+ * the location of such artifact would be;
+ * <code>[group]-[version]/[name].[type]</code>.
+ * Example;
<code>artifact:jar:eclipse/plugins/eclipse-osgi-runtime/core#3.1.0</code>
+ * would return the path
<code>eclipse/plugins/eclipse-osgi-runtime-3.1.0/core.jar</code>.
+ */
+public class EclipseResolver
+ implements LocationResolver
+{
+ /**
+ * Return the base path for an artifact. The base path is derived from
+ * the artifact group and version. For an artifact group of
"metro/cache" and a
+ * version equal to "1.3", the base value will be translated using the
pattern
+ * "[group]-[version]" to form "metro/cache-1.3". The base path value
represents
+ * the directory path relative to a repository root of the directory
containing
+ * this artifact.
+ *
+ * @return the base path
+ */
+ public final String resolveBase( Artifact artifact )
+ {
+ return artifact.getGroup() + "-" + artifact.getVersion();
+ }
+
+ /**
+ * Returns the full path of the artifact relative to a logical root
directory.
+ * The full path is equivalent to the base path and artifact filename
using the
+ * pattern "[base]/[filename]". Path values may be used to resolve an
artifact
+ * from a remote repository or local cache relative to the repository or
cache
+ * root. An artifact such as
+ *
<code>artifact:jar:eclipse/plugins/eclipse-osgi-runtime/core#3.1.0</code>
+ * would return the path
+ * <code>eclipse/plugins/eclipse-osgi-runtime-3.1.0/core.jar</code>.
+ *
+ * @see #resolveBase
+ * @see #resolveFilename
+ * @return the logical artifact path
+ */
+ public final String resolvePath( Artifact artifact )
+ {
+ return resolveBase( artifact ) + "/" + resolveFilename( artifact );
+ }
+
+ /**
+ * Return the expanded filename of the artifact.
+ * The filename is expressed as <code>[name].[type]</code>.
+ *
+ * @return the artifact expanded filename
+ */
+ public String resolveFilename( Artifact artifact )
+ {
+ return artifact.getName() + "." + artifact.getType();
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/layout/LocationResolver.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/layout/LocationResolver.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.layout;
+
+import net.dpml.transit.artifact.Artifact;
+
+/** The LocationResolver abstracts the decoding process of the location
+ * of artifacts in various filesystems.
+ */
+public interface LocationResolver
+{
+ /**
+ * Return the base path for an artifact. The base path is the location
+ * where the file will be found. The base + "/" filename is equal to the
+ * full path.
+ *
+ * @param artifact the Artifact to resolve.
+ * @return the base path
+ */
+ String resolveBase( Artifact artifact );
+
+ /**
+ * Returns the full path of the artifact relative to a logical root
directory.
+ * The base + "/" filename is equal to the full path.
+ *
+ * @see #resolveBase
+ * @see #resolveFilename
+ * @param artifact the Artifact to resolve.
+ * @return the logical artifact path
+ */
+ String resolvePath( Artifact artifact );
+
+ /**
+ * Return the filename for an artifact. The base + "/" filename is equal
+ * to the full path.
+ *
+ * @see #resolveBase
+ * @see #resolveFilename
+ * @param artifact the Artifact to resolve.
+ * @return the logical artifact path
+ */
+ String resolveFilename( Artifact artifact );
+}

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/CacheMonitor.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/CacheMonitor.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/CacheMonitor.java
Sat Mar 26 13:22:09 2005
@@ -31,7 +31,7 @@
* The CacheMonitor must be thread safe.
* </p>
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: DownloadMonitor.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
* @see Monitor
*/
public interface CacheMonitor extends Monitor

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/ConnectionMonitor.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/ConnectionMonitor.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/ConnectionMonitor.java
Sat Mar 26 13:22:09 2005
@@ -28,7 +28,7 @@
* The NetworkMonitor must be thread safe.
* </p>
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: DownloadMonitor.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
* @see Monitor
*/
public interface ConnectionMonitor extends Monitor

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/NetworkMonitor.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/NetworkMonitor.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/NetworkMonitor.java
Sat Mar 26 13:22:09 2005
@@ -25,7 +25,7 @@
* A monitor of a download activity or activities.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: DownloadMonitor.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
* @see Monitor
*/
public interface NetworkMonitor extends Monitor

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/SystemMonitor.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/SystemMonitor.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/monitors/SystemMonitor.java
Sat Mar 26 13:22:09 2005
@@ -23,8 +23,10 @@
import java.util.ArrayList;
import java.util.Map;

-import net.dpml.transit.artifact.CacheHandler;
-import net.dpml.transit.artifact.ResourceHost;
+import net.dpml.transit.cache.CacheHandler;
+import net.dpml.transit.host.ResourceHost;
+import net.dpml.transit.cache.CacheHandler;
+import net.dpml.transit.host.ResourceHost;

/**
* Monitor used to handle debug level trace messages

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/network/ConnectionCache.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/network/ConnectionCache.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.network;
+
+import net.dpml.transit.artifact.Artifact;
+
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.WeakHashMap;
+
+public class ConnectionCache
+ implements Runnable
+{
+ static private Object DUMMY = new Object();
+ static private ConnectionCache m_instance;
+
+ private HashMap m_hardStore;
+ private WeakHashMap m_weakStore;
+
+ private long m_timeToLive;
+ private Thread m_thread;
+
+ static
+ {
+ m_instance = new ConnectionCache();
+ }
+
+ static public ConnectionCache getInstance()
+ {
+ return m_instance;
+ }
+
+ private ConnectionCache()
+ {
+ m_hardStore = new HashMap();
+ m_weakStore = new WeakHashMap();
+ m_timeToLive = 30000;
+ }
+
+ public URLConnection get( Artifact key )
+ {
+ synchronized( this ) // ensure no ConcurrentModificationException
can occur.
+ {
+ Entry entry = (Entry) m_hardStore.get( key );
+ if( entry == null )
+ return null;
+ URLConnection conn = entry.m_connection;
+ return conn;
+ }
+ }
+
+ public void put( Artifact key, URLConnection conn )
+ {
+ synchronized( this ) // ensure no ConcurrentModificationException
can occur.
+ {
+ Entry entry = new Entry( conn );
+ m_hardStore.put( key, entry );
+ if( m_thread == null )
+ {
+ m_thread = new Thread( this, "ConnectionCache-cleaner" );
+ m_thread.setDaemon( true );
+ m_thread.start();
+ }
+ }
+ }
+
+ public void run()
+ {
+ while( true )
+ {
+ try
+ {
+ synchronized( this )
+ {
+ long now = System.currentTimeMillis();
+ Iterator list = m_hardStore.values().iterator();
+ while( list.hasNext() )
+ {
+ Entry entry = (Entry) list.next();
+ if( entry.m_collectTime < now )
+ {
+ m_weakStore.put( entry.m_connection, DUMMY );
+ list.remove();
+ }
+ }
+ if( m_hardStore.size() == 0 )
+ {
+ m_thread = null; // mark to start a new thread
next time.
+ break; // Exit the thread
+ }
+ wait( 10000 );
+ }
+ } catch( Exception e )
+ {
+ // Can not happen?
+ // Just ignore and it will be handled in the next round.
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private class Entry
+ {
+ private URLConnection m_connection;
+ private long m_collectTime;
+
+ Entry( URLConnection conn )
+ {
+ m_connection = conn;
+ m_collectTime = System.currentTimeMillis() + m_timeToLive;
+ }
+
+ public boolean equals( Object obj )
+ {
+ if( obj == null )
+ return false;
+ if( obj.getClass().equals( Entry.class ) == false )
+ return false;
+ Entry other = (Entry) obj;
+
+ if( m_connection.equals( other.m_connection ) == false )
+ return false;
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ return m_connection.hashCode();
+ }
+
+ public String toString()
+ {
+ return "Entry[" + m_connection + ", " + m_collectTime + "]";
+ }
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/network/DelegatingAuthenticator.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/network/DelegatingAuthenticator.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2004 Niclas Hedhman, DPML
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.network;
+
+import java.net.Authenticator;
+import java.net.InetAddress;
+import java.net.PasswordAuthentication;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:dev AT avalon.apache.org";>Avalon Development Team</a>
+ * @version $Id$
+ */
+public final class DelegatingAuthenticator extends Authenticator
+{
+ //
------------------------------------------------------------------------
+ // static
+ //
------------------------------------------------------------------------
+
+ /**
+ * The singleton delegating authenticator instance.
+ */
+ private static DelegatingAuthenticator m_INSTANCE;
+
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ /**
+ * The set of registered authenticators keyed by id.
+ */
+ private Map m_authenticators;
+
+ /**
+ * Return the singleton authenticator.
+ * @return the authenticator
+ */
+ static public DelegatingAuthenticator getInstance()
+ {
+ synchronized( DelegatingAuthenticator.class )
+ {
+ if( m_INSTANCE == null )
+ {
+ m_INSTANCE = new DelegatingAuthenticator();
+ Authenticator.setDefault( m_INSTANCE );
+ }
+ return m_INSTANCE;
+ }
+ }
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new delegating authenticator.
+ */
+ private DelegatingAuthenticator()
+ {
+ m_authenticators = new HashMap();
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Add an authenticator to the set of authenticators managed by the
+ * singleton delegating authenticator.
+ * @param authenticator the authenticator to add
+ * @param id the request identifier
+ */
+ public void addTransitAuthenticator( TransitAuthenticator authenticator,
RequestIdentifier id )
+ {
+ synchronized( m_authenticators )
+ {
+ m_authenticators.put( id, authenticator );
+ }
+ }
+
+ /**
+ * Remove an authenticator from the set of authenticators managed by the
+ * singleton delegating authenticator.
+ * @param authenticator the authenticator to remove
+ */
+ public void removeTransitAuthenticator( TransitAuthenticator
authenticator )
+ {
+ synchronized( m_authenticators )
+ {
+ Iterator list = m_authenticators.values().iterator();
+ while( list.hasNext() )
+ {
+ Authenticator item = (Authenticator) list.next();
+ if( item.equals( authenticator ) )
+ {
+ list.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the password authenticator.
+ * @return the password authenticator
+ */
+ protected PasswordAuthentication getPasswordAuthentication()
+ {
+ try
+ {
+ String host = getRequestingHost();
+ String protocol = getRequestingProtocol();
+ String prompt = getRequestingPrompt();
+ String scheme = getRequestingScheme();
+ int port = getRequestingPort();
+ InetAddress addr = getRequestingSite();
+ if( addr == null )
+ {
+ addr = InetAddress.getByName( host );
+ }
+ RequestIdentifier id = new RequestIdentifier( addr, port,
protocol, scheme, prompt );
+ synchronized( m_authenticators )
+ {
+ TransitAuthenticator auth = (TransitAuthenticator)
m_authenticators.get( id );
+ if( auth == null )
+ {
+ return null;
+ }
+ return auth.resolvePasswordAuthentication( this );
+ }
+ }
+ catch( UnknownHostException e )
+ {
+ return null;
+ }
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/network/NetworkLoader.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/network/NetworkLoader.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.network;
+
+import net.dpml.transit.Transit;
+import net.dpml.transit.TransitException;
+import net.dpml.transit.artifact.ArtifactException;
+import net.dpml.transit.monitors.NetworkMonitorRouter;
+import net.dpml.transit.util.StreamUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Date;
+
+/**
+ * Nework loader utility.
+ */
+public class NetworkLoader
+{
+ /**
+ * Network monitor router.
+ */
+ private NetworkMonitorRouter m_monitor;
+
+ /**
+ * Creation of a new network loader.
+ * @exception TransitException if an error in transit system
establishment occurs
+ */
+ public NetworkLoader()
+ throws TransitException
+ {
+ m_monitor = Transit.getInstance().getNetworkMonitorRouter();
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Retrieve a remote resource.
+ *
+ * @param url the of the file to retrieve
+ * @param connection the url connection
+ * @param destination where to store it
+ * @return the lastModified date of the downloaded artifact.
+ * @exception net.dpml.transit.artifact.ArtifactException if an artifact
related errror occurs
+ * @exception IOException if an IO error occurs
+ */
+ public Date loadResource( URL url, URLConnection connection,
OutputStream destination )
+ throws ArtifactException, IOException
+ {
+ if( connection instanceof HttpURLConnection )
+ {
+ HttpURLConnection httpConnection = (HttpURLConnection)
connection;
+ int code = httpConnection.getResponseCode();
+ // test for 401 result (HTTP only)
+ if ( code == HttpURLConnection.HTTP_UNAUTHORIZED )
+ {
+ throw new IOException( "Not authorized." );
+ }
+ }
+ InputStream in = connection.getInputStream();
+ int expected = connection.getContentLength();
+ StreamUtils.copyStream( m_monitor, url, expected, in, destination,
true );
+ long remoteTimestamp = connection.getLastModified();
+ return new Date( remoteTimestamp );
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/network/RequestIdentifier.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/network/RequestIdentifier.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2004 Niclas Hedhman, DPML
+ * Copyright 2005 Stephen McConnell, DPML
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.network;
+
+import java.net.InetAddress;
+
+import net.dpml.lang.NullArgumentException;
+
+/**
+ * A request identifier.
+ */
+public final class RequestIdentifier
+{
+ //
------------------------------------------------------------------------
+ // static
+ //
------------------------------------------------------------------------
+
+ /**
+ * Used in hashcode calculation.
+ */
+ private static final int MAGIC_NUMBER = 72349724;
+
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ /**
+ * The internet address.
+ */
+ private final InetAddress m_address;
+
+ /**
+ * The port.
+ */
+ private final int m_port;
+
+ /**
+ * The prompt.
+ */
+ private final String m_prompt;
+
+ /**
+ * The protocol.
+ */
+ private final String m_protocol;
+
+ /**
+ * The scheme.
+ */
+ private final String m_scheme;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new request identifier.
+ * @param address the address
+ * @param port the port
+ * @param protocol the protocol
+ * @param scheme the scheme
+ * @param prompt the prompt
+ * @exception NullArgumentException if any of the address, protocol,
scheme
+ * or prompt arguments is null.
+ */
+ public RequestIdentifier( InetAddress address, int port, String protocol,
+ String scheme, String prompt )
+ throws NullArgumentException
+ {
+ if( address == null )
+ {
+ throw new NullArgumentException( "address" );
+ }
+ if( protocol == null )
+ {
+ throw new NullArgumentException( "protocol" );
+ }
+ if( scheme == null )
+ {
+ throw new NullArgumentException( "scheme" );
+ }
+ if( prompt == null )
+ {
+ throw new NullArgumentException( "prompt" );
+ }
+ m_address = address;
+ m_port = port;
+ m_protocol = protocol;
+ m_prompt = prompt;
+ m_scheme = scheme;
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Test for equality.
+ * @param obj the object to test against
+ * @return true if this object is the same as the supplied object
+ */
+ public boolean equals( Object obj )
+ {
+ if( !( obj instanceof RequestIdentifier ) )
+ {
+ return false;
+ }
+ RequestIdentifier other = (RequestIdentifier) obj;
+
+ if( m_port != other.m_port )
+ {
+ return false;
+ }
+
+ if( !m_address.equals( other.m_address ) )
+ {
+ return false;
+ }
+ if( !m_protocol.equals( other.m_protocol ) )
+ {
+ return false;
+ }
+ if( !m_prompt.equals( other.m_prompt ) )
+ {
+ return false;
+ }
+ if( !m_scheme.equals( other.m_scheme ) )
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return the hascode for this instance.
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ int hash = MAGIC_NUMBER * m_port;
+ hash = hash ^ m_address.hashCode();
+ hash = hash ^ m_protocol.hashCode();
+ hash = hash ^ m_prompt.hashCode();
+ hash = hash ^ m_scheme.hashCode();
+ return hash;
+ }
+
+ /**
+ * Return the string representation of this instance.
+ * @return the string value
+ */
+ public String toString()
+ {
+ StringBuffer b = new StringBuffer();
+ b.append( "ID[ " );
+ b.append( m_protocol );
+ b.append( ", " );
+ b.append( m_address );
+ b.append( ", " );
+ b.append( m_port );
+ b.append( ", " );
+ b.append( m_scheme );
+ b.append( ", " );
+ b.append( m_prompt );
+ b.append( " ]" );
+ return b.toString();
+ }
+}
+

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/network/TransitAuthenticator.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/network/TransitAuthenticator.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2004 Stephen McConnell, DPML
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.network;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+
+/**
+ * Transit authenticator contract.
+ * @author <a href="mailto:dev AT avalon.apache.org";>Avalon Development Team</a>
+ * @version $Id$
+ */
+public interface TransitAuthenticator
+{
+ /**
+ * Returns the password authenticator.
+ * @param authenticator the default authenticator
+ * @return the password authenticator
+ */
+ PasswordAuthentication resolvePasswordAuthentication( Authenticator
authenticator );
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/network/TransitAuthenticatorImpl.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/network/TransitAuthenticatorImpl.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2004-2005 Stephen McConnell, DPML
+ * Copyright 2004 Niclas Hedhman, DPML
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.network;
+
+import net.dpml.lang.NullArgumentException;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+
+/**
+ * Default authenticator that provides support for username password
+ * based authentication in conjunction with the repository proxy settings.
+ *
+ * @version $Id$
+ */
+public final class TransitAuthenticatorImpl
+ implements TransitAuthenticator
+{
+ //
------------------------------------------------------------------------
+ // state
+ //
------------------------------------------------------------------------
+
+ /**
+ * Proxy username.
+ */
+ private final PasswordAuthentication m_authentication;
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Creation of a new simple authenticator.
+ * @param username the username
+ * @param password the password
+ * @exception NullArgumentException if either the username or password
argument is null
+ */
+ public TransitAuthenticatorImpl( String username, String password )
+ throws NullArgumentException
+ {
+ if( username == null )
+ {
+ throw new NullArgumentException( "username" );
+ }
+ if( password == null )
+ {
+ throw new NullArgumentException( "password" );
+ }
+ m_authentication = new PasswordAuthentication( username,
password.toCharArray() );
+ }
+
+ //
------------------------------------------------------------------------
+ // implementation
+ //
------------------------------------------------------------------------
+
+ /**
+ * Returns the password authenticator.
+ * @param authenticator an default authenticator
+ * @return the password authenticator
+ */
+ public PasswordAuthentication resolvePasswordAuthentication(
Authenticator authenticator )
+ {
+ return m_authentication;
+ }
+}

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/repository/Plugin.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/repository/Plugin.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/repository/Plugin.java
Sat Mar 26 13:22:09 2005
@@ -26,7 +26,7 @@
* from a 'plugin' artifact.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: Plugin.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public interface Plugin
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/repository/PropertiesPlugin.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/repository/PropertiesPlugin.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/repository/PropertiesPlugin.java
Sat Mar 26 13:22:09 2005
@@ -49,11 +49,6 @@
//-----------------------------------------------------------

/**
- * used in has calculation.
- */
- private static final int THIRTEEN = 13;
-
- /**
* key to designate the namespace of the plugin descriptor.
*/
static final String PP_NAMESPACE_KEY = "dpml.plugin.meta.namespace";
@@ -317,8 +312,7 @@
*/
public int hashCode()
{
- int hash = 112380413;
- hash ^= m_specificationNamespace.hashCode();
+ int hash = m_specificationNamespace.hashCode();
hash ^= m_specificationVersion.hashCode();
hash ^= m_group.hashCode();
hash ^= m_version.hashCode();

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/repository/Repository.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/repository/Repository.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/repository/Repository.java
Sat Mar 26 13:22:09 2005
@@ -26,7 +26,7 @@
* A service that provides support for the establishment of classloaders and
plugin
* instances based on plugin descriptor describing a classloader chain.
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: Repository.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public interface Repository
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/repository/RepositoryException.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/repository/RepositoryException.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/repository/RepositoryException.java
Sat Mar 26 13:22:09 2005
@@ -25,7 +25,7 @@
* Exception to indicate that there was a repository related error.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: RepositoryException.java 183 2004-10-23 16:53:31Z niclas $
+ * @version $Id$
*/
public class RepositoryException extends IOException
{

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/repository/StandardLoader.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/repository/StandardLoader.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/repository/StandardLoader.java
Sat Mar 26 13:22:09 2005
@@ -19,37 +19,30 @@

package net.dpml.transit.repository;

-import java.io.File;
-import java.io.IOException;
-
-import java.net.URI;
-import java.net.URL;
-import java.net.URLClassLoader;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Array;
-
-import java.util.ArrayList;
-import java.util.Properties;
-
import net.dpml.lang.NullArgumentException;
-
import net.dpml.transit.Transit;
import net.dpml.transit.TransitException;
-
import net.dpml.transit.artifact.Artifact;
import net.dpml.transit.artifact.ArtifactNotFoundException;
import net.dpml.transit.artifact.Handler;
-
import net.dpml.transit.monitors.RepositoryMonitorRouter;

+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Properties;
+
/**
* Utility class supporting downloading of resources based on
* artifact references.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: StandardLoader.java 224 2004-10-27 03:53:05Z mcconnell $
+ * @version $Id$
*/
public class StandardLoader
implements Repository
@@ -669,23 +662,6 @@
}

/**
- * Test is the supplied file is a sanpshot file.
- * @param file the file to test
- * @return true if its a snapshot file
- */
- private static boolean isSnapshot( File file )
- {
- String name = file.getName();
- int i = name.lastIndexOf( "." );
- if( i > -1 )
- {
- String sub = name.substring( 0, i );
- return sub.endsWith( "SNAPSHOT" );
- }
- return file.getName().endsWith( "SNAPSHOT" );
- }
-
- /**
* Convert a uri to an artifact.
* @param uri the uri to convert
* @return the artifact

Modified:
development/main/transit/core/handler/src/main/net/dpml/transit/util/Dictionary.java
==============================================================================
---
development/main/transit/core/handler/src/main/net/dpml/transit/util/Dictionary.java
(original)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/util/Dictionary.java
Sat Mar 26 13:22:09 2005
@@ -28,7 +28,7 @@
* The dictionary class is a read-only map of keyed values.
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: Criteria.java 259 2004-10-30 07:24:40Z mcconnell $
+ * @version $Id$
*/
public class Dictionary implements Map
{

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/util/MimeTypeHandler.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/util/MimeTypeHandler.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.util;
+
+import java.util.HashMap;
+
+/**
+ * Mimetype utility hanlder.
+ */
+public final class MimeTypeHandler
+{
+ //
------------------------------------------------------------------------
+ // static
+ //
------------------------------------------------------------------------
+
+ /**
+ * Static mime type table of artifact types to mimetype strings.
+ */
+ private static final HashMap MIME_TYPES = new HashMap();
+
+ static
+ {
+ MIME_TYPES.put( "block", "text/x-dpml-block" );
+ MIME_TYPES.put( "plugin", "text/x-dpml-plugin" );
+ MIME_TYPES.put( "conf", "text/x-dpml-conf" );
+ MIME_TYPES.put( "jar", "application/x-jar" );
+ MIME_TYPES.put( "zip", "application/x-zip" );
+ MIME_TYPES.put( "pdf", "application/pdf" );
+ MIME_TYPES.put( "png", "image/png" );
+ MIME_TYPES.put( "gif", "image/gif" );
+ MIME_TYPES.put( "jpg", "image/jpg" );
+ }
+
+ /**
+ * Return the mimetype given a artifact type.
+ * @param artifactType the artifact type such as "block", "jar", etc.
+ * @return the matching mimetype of null if unknown
+ */
+ static public String getMimeType( String artifactType )
+ {
+ return (String) MIME_TYPES.get( artifactType );
+ }
+
+ /**
+ * Returns the number of MimeTypes that has been defined.
+ *
+ * Only for use with testcases.
+ * @return the known mimetype count
+ */
+ static public int getMimeTypesSize()
+ {
+ return MIME_TYPES.size();
+ }
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Disabled constructor.
+ */
+ private MimeTypeHandler()
+ {
+ // disable
+ }
+}
\ No newline at end of file

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/util/StreamUtils.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/util/StreamUtils.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.net.URL;
+
+import net.dpml.lang.NullArgumentException;
+
+import net.dpml.transit.monitors.NetworkMonitor;
+
+public class StreamUtils
+{
+ /**
+ * Buffer size.
+ */
+ private static final int BUFFER_SIZE = 102400;
+
+
+ /** Copy a stream.
+ * @param src the source input stream
+ * @param dest the destination output stream
+ * @param closeStreams TRUE if the streams should be closed on completion
+ * @exception IOException if an IO error occurs
+ */
+ static public void copyStream( InputStream src, OutputStream dest,
boolean closeStreams )
+ throws IOException, NullArgumentException
+ {
+ copyStream( null, null, 0, src, dest, closeStreams );
+ }
+
+ /** Copy a stream.
+ * @param source the source url
+ * @param expected the expected size in bytes
+ * @param src the source input stream
+ * @param dest the destination output stream
+ * @param closeStreams TRUE if the streams should be closed on completion
+ * @exception IOException if an IO error occurs
+ */
+ static public void copyStream( NetworkMonitor monitor, URL source, int
expected,
+ InputStream src, OutputStream dest, boolean
closeStreams )
+ throws IOException, NullArgumentException
+ {
+ if( src == null )
+ {
+ throw new NullArgumentException( "src" );
+ }
+
+ if( dest == null )
+ {
+ throw new NullArgumentException( "dest" );
+ }
+
+ int length;
+ int count = 0; // cumulative total read
+ byte[] buffer = new byte[BUFFER_SIZE];
+ if( dest instanceof BufferedOutputStream == false )
+ {
+ dest = new BufferedOutputStream( dest );
+ }
+ if( src instanceof BufferedInputStream == false )
+ {
+ src = new BufferedInputStream( src );
+ }
+
+ try
+ {
+ while ( ( length = src.read( buffer ) ) >= 0 )
+ {
+ count = count + length;
+ dest.write( buffer, 0, length );
+ if( null != monitor )
+ {
+ monitor.notifyUpdate( source, expected, count );
+ }
+ }
+ }
+ finally
+ {
+ if( closeStreams )
+ {
+ try
+ {
+ src.close();
+ }
+ catch( Throwable e )
+ {
+ e.printStackTrace();
+ }
+
+ try
+ {
+ dest.close();
+ }
+ catch( Throwable e )
+ {
+ e.printStackTrace();
+ }
+ }
+ if( null != monitor )
+ {
+ monitor.notifyCompletion( source );
+ }
+ }
+ }
+}

Added:
development/main/transit/core/handler/src/main/net/dpml/transit/util/Util.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/main/net/dpml/transit/util/Util.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2004 Niclas Hedhman
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.util;
+
+import net.dpml.transit.Transit;
+
+import java.util.Properties;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ArrayList;
+import java.net.URL;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+
+/**
+ * Utility class supporting operations related to property retrival.
+ */
+public final class Util
+{
+ //
------------------------------------------------------------------------
+ // static
+ //
------------------------------------------------------------------------
+
+ /**
+ * Read a set of properties from a property file specificed by a url.
+ * Property files may reference symbolic properties in the form ${name}.
+ * @param propsUrl the url of the property file to read
+ * @return the resolved properties
+ * @exception IOException if an io error occurs
+ */
+ static public Properties readProps( URL propsUrl )
+ throws IOException
+ {
+ InputStream stream = propsUrl.openStream();
+ try
+ {
+ Properties p = new Properties();
+ p.setProperty( Transit.HOME_KEY, Transit.DPML_HOME.toString() );
+ p.load( stream );
+ Iterator list = p.entrySet().iterator();
+ while ( list.hasNext() )
+ {
+ Map.Entry entry = (Map.Entry) list.next();
+ String value = (String) entry.getValue();
+ value = resolveProperty( p, value );
+ entry.setValue( value );
+ }
+ return p;
+ }
+ finally
+ {
+ stream.close();
+ }
+ }
+
+ /**
+ * Resolve symbols in a supplied value against supplied known properties.
+ * @param props a set of know properties
+ * @param value the string to parse for tokens
+ * @return the resolved string
+ */
+ static public String resolveProperty( Properties props, String value )
+ {
+ value = PropertyResolver.resolve( props, value );
+ return value;
+ }
+
+ /**
+ * Return the value of a property.
+ * @param props the property file
+ * @param key the property key to lookup
+ * @param def the default value
+ * @return the resolve value
+ */
+ static public String getProperty( Properties props, String key, String
def )
+ {
+ String value = props.getProperty( key, def );
+ if( value == null )
+ {
+ return null;
+ }
+ if( "".equals( value ) )
+ {
+ return value;
+ }
+ value = PropertyResolver.resolve( props, value );
+ return value;
+ }
+
+ /**
+ * Read a file and return the list of lines in an array of strings.
+ * @param listFile the url to read from
+ * @return the lines
+ * @exception IOException if a read error occurs
+ */
+ static public String[] readListFile( URL listFile )
+ throws IOException
+ {
+ ArrayList list = new ArrayList();
+ InputStream stream = listFile.openStream();
+ try
+ {
+ InputStreamReader isr = new InputStreamReader( stream, "UTF-8" );
+ BufferedReader reader = new BufferedReader( isr );
+ String line = reader.readLine();
+ while ( line != null )
+ {
+ list.add( line );
+ line = reader.readLine();
+ }
+ String[] items = new String[ list.size() ];
+ list.toArray( items );
+ return items;
+ }
+ finally
+ {
+ stream.close();
+ }
+ }
+
+ //
------------------------------------------------------------------------
+ // constructor
+ //
------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ private Util()
+ {
+ }
+}

Modified:
development/main/transit/core/handler/src/test/net/dpml/transit/repository/PropertiesPluginTestCase.java
==============================================================================
---
development/main/transit/core/handler/src/test/net/dpml/transit/repository/PropertiesPluginTestCase.java
(original)
+++
development/main/transit/core/handler/src/test/net/dpml/transit/repository/PropertiesPluginTestCase.java
Sat Mar 26 13:22:09 2005
@@ -30,7 +30,7 @@

/**
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
- * @version $Id: SystemContextFactoryTestCase.java 183 2004-10-23 16:53:31Z
niclas $
+ * @version $Id$
*/
public class PropertiesPluginTestCase extends TestCase
{

Added:
development/main/transit/core/handler/src/test/net/dpml/transit/test/ArtifactTestCase.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/test/net/dpml/transit/test/ArtifactTestCase.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.test;
+
+import junit.framework.TestCase;
+import net.dpml.transit.layout.ClassicResolver;
+import net.dpml.transit.layout.LocationResolver;
+import net.dpml.transit.artifact.Artifact;
+
+/**
+ * Create of a new Artifact test case.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ * @version $Id$
+ */
+public class ArtifactTestCase extends TestCase
+{
+ /**
+ * Constructor for ArtifactReferenceTest.
+ * @param name the test name
+ */
+ public ArtifactTestCase( String name )
+ {
+ super( name );
+ }
+
+ public void testNullPathConstructor() throws Exception
+ {
+ try
+ {
+ Artifact artifact = Artifact.createArtifact( (String) null );
+ fail( "No IllegalArgumentException thrown for null uri spec: " +
artifact );
+ }
+ catch( IllegalArgumentException e )
+ {
+ assertTrue( true );
+ }
+ }
+
+ public void testMissingProtocol() throws Exception
+ {
+ try
+ {
+ Artifact artifact = Artifact.createArtifact(
"jar:/group/sub-group/name#version" );
+ fail( "Illegal argument exception not thrown for missing
protocol: " + artifact );
+ }
+ catch( IllegalArgumentException e )
+ {
+ assertTrue( true );
+ }
+ }
+
+ public void testBadGroup() throws Exception
+ {
+ try
+ {
+ Artifact artifact = Artifact.createArtifact(
"artifact:jar://sub-group/name#version" );
+ fail( "Illegal argument exception not thrown for bad group: " +
artifact );
+ }
+ catch( IllegalArgumentException e )
+ {
+ assertTrue( true );
+ }
+ }
+
+ public void testAnotherBadGroup() throws Exception
+ {
+ try
+ {
+ Artifact artifact = Artifact.createArtifact(
"artifact:jar:group//name#version" );
+ fail( "Illegal argument exception not thrown for bad group: " +
artifact );
+ }
+ catch( IllegalArgumentException e )
+ {
+ assertTrue( true );
+ }
+ }
+
+ public void testBadVersion() throws Exception
+ {
+ try
+ {
+ Artifact artifact = Artifact.createArtifact(
"artifact:jar:group/name#version/xxx" );
+ list( artifact );
+ fail( "Illegal argument exception not thrown for bad version: "
+ artifact );
+ }
+ catch( IllegalArgumentException e )
+ {
+ assertTrue( true );
+ }
+ }
+
+ public void testFullSpec() throws Exception
+ {
+ Artifact artifact = Artifact.createArtifact(
"artifact:jar:group/sub-group/name#version");
+ verify( artifact, "group/sub-group", "name", "jar", "version" );
+ }
+
+ public void testLeadingSlash() throws Exception
+ {
+ try
+ {
+ String form = "artifact:jar:/group/sub-group/name#version";
+ Artifact artifact = Artifact.createArtifact( form );
+ fail( "illegal format not caught: " + artifact );
+ } catch( IllegalArgumentException e )
+ {}
+ }
+
+ public void testMissingType() throws Exception
+ {
+ String form = "artifact:group/sub-group/name#version";
+ try
+ {
+ Artifact artifact = Artifact.createArtifact( form );
+ fail( "illegal format not caught: " + artifact );
+ } catch( IllegalArgumentException e )
+ {}
+ }
+
+ public void testNullVersion() throws Exception
+ {
+ Artifact artifact = Artifact.createArtifact(
"artifact:jar:group/sub-group/name");
+ verify( artifact, "group/sub-group", "name", "jar", null );
+ }
+
+ public void testNullVersionAndNullType() throws Exception
+ {
+ String form = "artifact:group/sub-group/name";
+ try
+ {
+ Artifact artifact = Artifact.createArtifact( form );
+ fail( "illegal format not caught: " + artifact );
+ } catch( IllegalArgumentException e )
+ {}
+ }
+
+ public void testMissingGroup() throws Exception
+ {
+ try
+ {
+ Artifact artifact = Artifact.createArtifact(
"artifact:jar:name#version" );
+ fail( "Illegal argument exception not thrown:" + artifact );
+ }
+ catch( Throwable e )
+ {
+ assertTrue( true );
+ }
+ }
+
+ public void testMissingGroupWithoutType() throws Exception
+ {
+ try
+ {
+ Artifact artifact = Artifact.createArtifact(
"artifact:name#version" );
+ fail( "Illegal argument exception not thrown: " + artifact );
+ }
+ catch( Throwable e )
+ {
+ assertTrue( true );
+ }
+ }
+
+ public void testZeroLengthVersion() throws Exception
+ {
+ Artifact artifact = Artifact.createArtifact(
"artifact:jar:group/sub-group/name#");
+ verify( artifact, "group/sub-group", "name", "jar", null );
+ }
+
+ public void testExternalForm() throws Exception
+ {
+ final String spec = "artifact:jar:group/sub-group/name#version";
+ Artifact artifact = Artifact.createArtifact( spec );
+ assertEquals( artifact.toString(), spec );
+ }
+
+ public void testInternalReference1() throws Exception
+ {
+ final String spec = "artifact:jar:group/sub-group/name#version";
+ final String url = spec + "!/some/resource.abc";
+ Artifact artifact = Artifact.createArtifact( url );
+ assertEquals( spec, artifact.toString() );
+ }
+
+ public void testInternalReference2() throws Exception
+ {
+ final String spec = "artifact:jar:group/sub-group/name#version";
+ final String url =
"artifact:jar:group/sub-group/name!/some/resource.abc#version";
+ Artifact artifact = Artifact.createArtifact( url );
+ assertEquals( spec, artifact.toString() );
+ }
+
+ public void testExternalFormWithNonDefaultType() throws Exception
+ {
+ final String spec = "artifact:block:group/sub-group/name#version";
+ Artifact artifact = Artifact.createArtifact( spec );
+ assertEquals( spec, spec, artifact.toString() );
+ }
+
+ public void testEquality() throws Exception
+ {
+ final String spec = "artifact:jar:group/sub-group/name#version";
+ Artifact artifact1 = Artifact.createArtifact( spec );
+ Artifact artifact2 = Artifact.createArtifact( spec );
+ assertTrue( spec, artifact1.equals( artifact2 ) );
+ }
+
+ public void testInequality() throws Exception
+ {
+ final String spec1 = "artifact:jar:group/sub-group/name#version";
+ final String spec2 = "artifact:jar:group/sub-group/name";
+ Artifact artifact1 = Artifact.createArtifact( spec1 );
+ Artifact artifact2 = Artifact.createArtifact( spec2 );
+ assertFalse( artifact1.equals( artifact2 ) );
+ }
+
+ public void testInequalityOnType() throws Exception
+ {
+ final String spec1 = "artifact:jar:group/sub-group/name#version";
+ final String spec2 = "artifact:block:group/sub-group/name#version";
+ Artifact artifact1 = Artifact.createArtifact( spec1 );
+ Artifact artifact2 = Artifact.createArtifact( spec2 );
+ assertFalse( artifact1.equals( artifact2 ) );
+ }
+
+ public void testComparability1() throws Exception
+ {
+ final String spec1 = "artifact:jar:aaa/name";
+ final String spec2 = "artifact:jar:bbb/name";
+ Artifact artifact1 = Artifact.createArtifact( spec1 );
+ Artifact artifact2 = Artifact.createArtifact( spec2 );
+
+ assertTrue( artifact1.compareTo( artifact2 ) < 0 );
+ assertTrue( artifact2.compareTo( artifact1 ) > 0 );
+ assertTrue( artifact1.compareTo( artifact1 ) == 0 );
+ assertTrue( artifact2.compareTo( artifact2 ) == 0 );
+ }
+
+ public void testComparability2() throws Exception
+ {
+ final String spec1 = "artifact:jar:aaa/name";
+ final String spec2 = "artifact:block:bbb/name";
+ Artifact artifact1 = Artifact.createArtifact( spec1 );
+ Artifact artifact2 = Artifact.createArtifact( spec2 );
+ Artifact artifact3 = Artifact.createArtifact( spec1 );
+ Artifact artifact4 = Artifact.createArtifact( spec2 );
+
+ assertTrue( artifact1.compareTo( artifact2 ) > 0 );
+ assertTrue( artifact2.compareTo( artifact1 ) < 0 );
+ assertTrue( artifact1.compareTo( artifact3 ) == 0 );
+ assertTrue( artifact2.compareTo( artifact4 ) == 0 );
+ }
+
+ public void verify( Artifact artifact, String group, String name, String
type, String version )
+ {
+ assertEquals( "group", group, artifact.getGroup() );
+ assertEquals( "name", name, artifact.getName() );
+ assertEquals( "version", version, artifact.getVersion() );
+ assertEquals( "type", type, artifact.getType() );
+
+ LocationResolver resolver = new ClassicResolver();
+
+ String base = group + "/" + type + "s";
+ assertEquals( "base", base, resolver.resolveBase( artifact ) );
+
+ if( null == version )
+ {
+ String path = base + "/" + name + "." + type;
+ assertEquals( "path", path, resolver.resolvePath( artifact ) );
+ }
+ else
+ {
+ String path = base + "/" + name + "-" + version + "." + type;
+ assertEquals( "path", path, resolver.resolvePath( artifact ) );
+ }
+ }
+
+ public void list( Artifact artifact )
+ {
+ System.out.println( "GROUP: " + artifact.getGroup() );
+ System.out.println( "NAME: " + artifact.getName() );
+ System.out.println( "TYPE: " + artifact.getType() );
+ System.out.println( "VERSION: " + artifact.getVersion() );
+ }
+}

Added:
development/main/transit/core/handler/src/test/net/dpml/transit/test/MimeHandlerTestCase.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/test/net/dpml/transit/test/MimeHandlerTestCase.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import net.dpml.transit.util.MimeTypeHandler;
+
+public class MimeHandlerTestCase extends TestCase
+{
+ static private String[][] TESTS = new String[][]
+ {
+ { "block", "text/x-dpml-block" },
+ { "plugin", "text/x-dpml-plugin" },
+ { "conf", "text/x-dpml-conf" },
+ { "jar", "application/x-jar" },
+ { "zip", "application/x-zip" },
+ { "pdf", "application/pdf" },
+ { "png", "image/png" },
+ { "jpg", "image/jpg" },
+ { "gif", "image/gif" }
+ };
+
+ static public Test suite()
+ {
+ TestSuite tests = new TestSuite();
+
+ for( int i = 0 ; i < TESTS.length ; i++ )
+ {
+ String lookup = TESTS[i][0];
+ String expected = TESTS[i][1];
+ String name = "testLookup";
+ TestCase testcase = new MimeHandlerTestCase( name, lookup,
expected );
+ tests.addTest( testcase );
+ }
+ String name = "testSize";
+ TestCase testcase = new MimeHandlerTestCase( name, null, null );
+ tests.addTest( testcase );
+ return tests;
+ }
+
+ private String m_Lookup;
+ private String m_Expected;
+
+ private MimeHandlerTestCase( String name, String lookup, String expected
)
+ {
+ super( name );
+ m_Lookup = lookup;
+ m_Expected = expected;
+ }
+
+ public void testLookup()
+ throws Exception
+ {
+ String mime = MimeTypeHandler.getMimeType( m_Lookup );
+ assertEquals( m_Lookup, m_Expected, mime );
+ }
+
+ public void testSize()
+ {
+ assertEquals( "Map Size", TESTS.length,
MimeTypeHandler.getMimeTypesSize() );
+ }
+}

Added:
development/main/transit/core/handler/src/test/net/dpml/transit/test/OfflineTestCase.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/test/net/dpml/transit/test/OfflineTestCase.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2004 Niclas Hedhman.
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.test;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import junit.framework.TestCase;
+
+/**
+ * URL Handler TestCase for Offline operations.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ * @version $Id$
+ */
+public class OfflineTestCase extends TestCase
+{
+ protected void setUp()
+ throws Exception
+ {
+ System.setProperty( "java.protocol.handler.pkgs", "net.dpml.transit"
);
+ System.setProperty( "dpml.transit.secured.disable", "true" );
+ System.setProperty( "dpml.transit.authority.file",
"target/test/test.authority" );
+ }
+
+ public void testDownloadNoVersion()
+ throws Exception
+ {
+ URL url = new URL( "artifact:testfile:dpml/test/1" );
+ String content = getContent( url );
+ assertEquals( "Content not retrieved.", "abc\n", content );
+ }
+
+ public void testDownloadWithVersion()
+ throws Exception
+ {
+ URL url = new URL( "artifact:testfile:dpml/test/abc#1.0.1" );
+ String content = getContent( url );
+ assertEquals( "Content not retrieved.", "abc\ndef\n", content );
+ }
+
+ public void testClassLoader1()
+ throws Exception
+ {
+ URL url = new URL( "artifact:jar:dpml/test/dpml-test-testa" );
+ ClassLoader classloader = new URLClassLoader( new URL[]{ url } );
+ classloader.loadClass( "net.dpml.test.testa.A" );
+ }
+
+ public void testClassLoader2()
+ throws Exception
+ {
+ URL url = new URL( "artifact:jar:dpml/test/dpml-test-testb" );
+ ClassLoader classloader = new URLClassLoader( new URL[]{ url } );
+ classloader.loadClass( "net.dpml.test.testb.B" );
+ }
+
+ public void testContentConversionA()
+ throws Exception
+ {
+ URL url = new URL( "artifact:jar:dpml/test/dpml-test-testa" );
+ Object content = url.getContent();
+ assertTrue( "Content type not correct.", content instanceof
InputStream );
+ }
+
+ public void testContentConversionB()
+ throws Exception
+ {
+ URL url = new URL( "artifact:png:dpml/test/sample" );
+ Object content = url.getContent();
+ assertTrue( "Content type not correct.", content instanceof
java.awt.image.ImageProducer );
+ }
+
+ public void testWriteExistingArtifact()
+ throws Exception
+ {
+ URL url = new URL( "artifact:png:dpml/test/sample" );
+ try
+ {
+ OutputStream out = url.openConnection().getOutputStream();
+ for( int i = 65 ; i < 91 ; i++ )
+ {
+ out.write( i );
+ }
+ out.write( 10 );
+ out.close();
+ fail( "Able to write to an existing artifact." );
+ } catch( java.io.IOException e )
+ {
+ // A "Artifact on server" exception should be thrown.
+ }
+ }
+
+ public void testWriteNewArtifact()
+ throws Exception
+ {
+ URL url = new URL( "artifact:txt:dpml/test/sample" );
+ OutputStream out = url.openConnection().getOutputStream();
+ for( int i = 65 ; i < 91 ; i++ )
+ {
+ out.write( i );
+ }
+ out.write( 10 );
+ out.close();
+
+ url = new URL( "artifact:txt:dpml/test/sample" );
+ InputStream in = url.openStream();
+ StringBuffer result = new StringBuffer();
+ while( true )
+ {
+ int value = in.read();
+ if( value == -1 )
+ break;
+ char ch = (char) value;
+ result.append( ch );
+ }
+ assertEquals( "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", result.toString() );
+ }
+
+ private String getContent( URL url )
+ throws Exception
+ {
+ InputStream stream = url.openStream();
+ try
+ {
+ InputStreamReader isr = new InputStreamReader( stream,
"ISO8859-1" );
+ BufferedReader in = new BufferedReader( isr );
+ StringBuffer buf = new StringBuffer( 100 );
+ String line = in.readLine();
+ while( line != null )
+ {
+ buf.append( line );
+ buf.append( '\n' );
+ line = in.readLine();
+ }
+ return buf.toString();
+ } finally
+ {
+ stream.close();
+ }
+ }
+/* TODO: not used
+ private void print( URL url )
+ {
+ System.out.println( "URL: " + url );
+ System.out.println( "Authority: " + url.getAuthority() );
+ System.out.println( "File: " + url.getFile() );
+ System.out.println( "Host: " + url.getHost() );
+ System.out.println( "Path: " + url.getPath() );
+ System.out.println( "Port: " + url.getPort() );
+ System.out.println( "Protocol: " + url.getProtocol() );
+ System.out.println( "Query: " + url.getQuery() );
+ System.out.println( "Ref: " + url.getRef() );
+ System.out.println( "Userinfo: " + url.getUserInfo() );
+ System.out.println( "--------------" );
+ }
+*/
+}

Added:
development/main/transit/core/handler/src/test/net/dpml/transit/test/OnlineTestCase.java
==============================================================================
--- (empty file)
+++
development/main/transit/core/handler/src/test/net/dpml/transit/test/OnlineTestCase.java
Sat Mar 26 13:22:09 2005
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2004 Niclas Hedhman.
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.transit.test;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import junit.framework.TestCase;
+
+/**
+ * URL Handler TestCase for Offline operations.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ * @version $Id$
+ */
+public class OnlineTestCase extends TestCase
+{
+ protected void setUp() throws Exception
+ {
+ System.setProperty( "java.protocol.handler.pkgs", "net.dpml.transit"
);
+ }
+
+ public void testStackedJarUrl() throws Exception
+ {
+ URL url = new URL(
"jar:artifact:jar:testcasegroup/dpml-test-testb!/net/dpml/test/testb/B.class"
);
+ Object obj = url.getContent();
+ System.out.println( obj.getClass() );
+ }
+
+ public void testDownloadNoVersion() throws Exception
+ {
+ URL url = new URL( "artifact:testfile:testcasegroup/1" );
+ String content = getContent( url );
+ assertEquals( "Content not retrieved.", "abc\n", content );
+ }
+
+ public void testDownloadWithVersion() throws Exception
+ {
+ URL url = new URL( "artifact:testfile:testcasegroup/abc#1.0.1" );
+ String content = getContent( url );
+ assertEquals( "Content not retrieved.", "abc\ndef\n", content );
+ }
+
+ public void testClassLoader1() throws Exception
+ {
+ URL url = new URL( "artifact:jar:testcasegroup/dpml-test-testa" );
+ ClassLoader classloader = new URLClassLoader( new URL[]{ url } );
+ classloader.loadClass( "net.dpml.test.testa.A" );
+ }
+
+ public void testClassLoader2() throws Exception
+ {
+ URL url = new URL( "artifact:jar:testcasegroup/dpml-test-testb" );
+ ClassLoader classloader = new URLClassLoader( new URL[]{ url } );
+ classloader.loadClass( "net.dpml.test.testb.B" );
+ }
+
+ public void testInternalResource() throws Exception
+ {
+ URL url = new URL( "artifact:jar:testcasegroup/dpml-test-testb" );
+ ClassLoader classloader = new URLClassLoader( new URL[]{ url } );
+ Class clazz = classloader.loadClass( "net.dpml.test.testb.B" );
+ URL resourceUrl = clazz.getResource( "TestB.xinfo" );
+ String external =
+
"artifact:jar:testcasegroup/dpml-test-testb!/net/dpml/test/testb/TestB.xinfo";
+ assertEquals( "external", external, resourceUrl.toExternalForm() );
+ resourceUrl.openStream();
+ }
+
+ public void testContentConversionA() throws Exception
+ {
+ URL url = new URL( "artifact:jar:testcasegroup/dpml-test-testa" );
+ Object content = url.getContent();
+ assertTrue( "Content type not correct.", content instanceof
InputStream );
+ }
+
+ public void testContentConversionB() throws Exception
+ {
+ URL url = new URL( "artifact:png:testcasegroup/sample" );
+ Object content = url.getContent();
+ assertTrue( "Content type not correct.", content instanceof
java.awt.image.ImageProducer );
+ }
+
+ private String getContent( URL url )
+ throws Exception
+ {
+ InputStream stream = url.openStream();
+ try
+ {
+ InputStreamReader isr = new InputStreamReader( stream,
"ISO8859-1" );
+ BufferedReader in = new BufferedReader( isr );
+ StringBuffer buf = new StringBuffer( 100 );
+ String line = in.readLine();
+ while( line != null )
+ {
+ buf.append( line );
+ buf.append( '\n' );
+ line = in.readLine();
+ }
+ return buf.toString();
+ } finally
+ {
+ stream.close();
+ }
+ }
+
+/* TODO: Not used.
+ private void print( URL url )
+ {
+ System.out.println( "URL: " + url );
+ System.out.println( "Authority: " + url.getAuthority() );
+ System.out.println( "File: " + url.getFile() );
+ System.out.println( "Host: " + url.getHost() );
+ System.out.println( "Path: " + url.getPath() );
+ System.out.println( "Port: " + url.getPort() );
+ System.out.println( "Protocol: " + url.getProtocol() );
+ System.out.println( "Query: " + url.getQuery() );
+ System.out.println( "Ref: " + url.getRef() );
+ System.out.println( "Userinfo: " + url.getUserInfo() );
+ System.out.println( "--------------" );
+ }
+*/
+}



  • svn commit: r2143 - in development/main/transit/core/handler: etc/main etc/setup etc/setup/authority etc/setup/authority/hosts etc/test etc/test/hosts src/main/net/dpml/io src/main/net/dpml/lang src/main/net/dpml/transit src/main/net/dpml/transit/adapter src/main/net/dpml/transit/artifact src/main/net/dpml/transit/cache src/main/net/dpml/transit/host src/main/net/dpml/transit/layout src/main/net/dpml/transit/link src/main/net/dpml/transit/monitors src/main/net/dpml/transit/network src/main/net/dpml/transit/repository src/main/net/dpml/transit/util src/test/net/dpml/transit/artifact src/test/net/dpml/transit/repository src/test/net/dpml/transit/test, niclas, 03/26/2005

Archive powered by MHonArc 2.6.24.

Top of Page