You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by da...@apache.org on 2011/03/23 15:39:58 UTC
svn commit: r1084603 - in /aries/trunk/spi-fly: ./
spi-fly-core/src/main/java/org/apache/aries/spifly/
spi-fly-core/src/test/java/org/apache/aries/spifly/ spi-fly-dynamic-bundle/
spi-fly-dynamic-bundle/src/ spi-fly-dynamic-bundle/src/main/ spi-fly-dyna...
Author: davidb
Date: Wed Mar 23 14:39:56 2011
New Revision: 1084603
URL: http://svn.apache.org/viewvc?rev=1084603&view=rev
Log:
First step of major SPI-Fly refactoring.
It introduces a dynamic bundle (which uses weaving hooks) and two static modules, a static weaver and a runtime support bundle for it.
Tests are broken - will work on those soon. Hudson should not be affected since spifly is currently not part of the overall build.
Added:
aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/BaseActivator.java
aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ClientWeavingHookTest.java.todo
- copied unchanged from r1084567, aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ClientWeavingHookTest.java
aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java.todo
- copied, changed from r1084567, aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java
aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/UnaffectedTestClient.java.todo
- copied unchanged from r1084567, aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/UnaffectedTestClient.java
aries/trunk/spi-fly/spi-fly-dynamic-bundle/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/DynamicWeavingActivator.java
aries/trunk/spi-fly/spi-fly-static-bundle/
aries/trunk/spi-fly/spi-fly-static-bundle/pom.xml
aries/trunk/spi-fly/spi-fly-static-bundle/src/
aries/trunk/spi-fly/spi-fly-static-bundle/src/main/
aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/
aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/
aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/
aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/aries/
aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/aries/spifly/
aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/aries/spifly/staticbundle/
aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/aries/spifly/staticbundle/StaticWeavingActivator.java
aries/trunk/spi-fly/spi-fly-static-tool/
aries/trunk/spi-fly/spi-fly-static-tool/pom.xml
aries/trunk/spi-fly/spi-fly-static-tool/src/
aries/trunk/spi-fly/spi-fly-static-tool/src/main/
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/DirTree.java
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java
aries/trunk/spi-fly/spi-fly-static-tool/src/test/
aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/
aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/
aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/
aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/aries/
aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/aries/spifly/
aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/aries/spifly/statictool/
aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/aries/spifly/statictool/MainTest.java
aries/trunk/spi-fly/spi-fly-static-tool/src/test/resources/
aries/trunk/spi-fly/spi-fly-static-tool/src/test/resources/testjar.jar (with props)
Removed:
aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/Activator.java
aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ClientWeavingHook.java
aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ClientWeavingHookTest.java
aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java
aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/UnaffectedTestClient.java
aries/trunk/spi-fly/spi-fly-static/
aries/trunk/spi-fly/spi-fly-static-support-bundle/
Modified:
aries/trunk/spi-fly/pom.xml
aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ConsumerHeaderProcessor.java
aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizer.java
aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/TCCLSetterVisitor.java
aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/Util.java
Modified: aries/trunk/spi-fly/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/pom.xml?rev=1084603&r1=1084602&r2=1084603&view=diff
==============================================================================
--- aries/trunk/spi-fly/pom.xml (original)
+++ aries/trunk/spi-fly/pom.xml Wed Mar 23 14:39:56 2011
@@ -56,7 +56,8 @@
<modules>
<module>spi-fly-deps</module>
<module>spi-fly-core</module>
- <module>spi-fly-static</module>
- <module>spi-fly-static-support-bundle</module>
+ <module>spi-fly-dynamic-bundle</module>
+ <module>spi-fly-static-tool</module>
+ <module>spi-fly-static-bundle</module>
</modules>
</project>
Added: aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/BaseActivator.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/BaseActivator.java?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/BaseActivator.java (added)
+++ aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/BaseActivator.java Wed Mar 23 14:39:56 2011
@@ -0,0 +1,238 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.spifly;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.aries.spifly.api.SpiFlyConstants;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.ServiceTracker;
+
+public abstract class BaseActivator implements BundleActivator {
+ private static final Set<WeavingData> NON_WOVEN_BUNDLE = Collections.emptySet();
+
+ // Static access to the activator used by the woven code, therefore
+ // this bundle must be a singleton.
+ // TODO see if we can get rid of the static access.
+ static BaseActivator activator;
+
+ private BundleContext bundleContext;
+ private LogServiceTracker logServiceTracker;
+ private List<LogService> logServices = new CopyOnWriteArrayList<LogService>();
+ private BundleTracker<Object> consumerBundleTracker;
+ private BundleTracker<List<ServiceRegistration<?>>> providerBundleTracker;
+
+ private final ConcurrentMap<Bundle, Set<WeavingData>> bundleWeavingData =
+ new ConcurrentHashMap<Bundle, Set<WeavingData>>();
+
+ private final ConcurrentMap<String, SortedMap<Long, Bundle>> registeredProviders =
+ new ConcurrentHashMap<String, SortedMap<Long, Bundle>>();
+
+ private final ConcurrentMap<Bundle, Map<ConsumerRestriction, List<BundleDescriptor>>> consumerRestrictions =
+ new ConcurrentHashMap<Bundle, Map<ConsumerRestriction, List<BundleDescriptor>>>();
+
+ public synchronized void start(BundleContext context, final String consumerHeaderName) throws Exception {
+ bundleContext = context;
+
+ logServiceTracker = new LogServiceTracker(context);
+ logServiceTracker.open();
+
+ providerBundleTracker = new BundleTracker<List<ServiceRegistration<?>>>(context,
+ Bundle.ACTIVE, new ProviderBundleTrackerCustomizer(this, context.getBundle()));
+ providerBundleTracker.open();
+
+ consumerBundleTracker = new BundleTracker<Object>(context, Bundle.INSTALLED, null) {
+ @Override
+ public Object addingBundle(Bundle bundle, BundleEvent event) {
+ processBundle(bundle, consumerHeaderName);
+
+ return super.addingBundle(bundle, event);
+ }
+
+ @Override
+ public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+ removedBundle(bundle, event, object);
+ addingBundle(bundle, event);
+ }
+
+ @Override
+ public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+ bundleWeavingData.remove(bundle);
+ }
+ };
+ consumerBundleTracker.open();
+
+ for (Bundle bundle : context.getBundles()) {
+ processBundle(bundle, consumerHeaderName);
+ }
+
+ activator = this;
+ }
+
+ private void processBundle(Bundle bundle, String consumerHeaderName) {
+ if (bundleWeavingData.containsKey(bundle)) {
+ // This bundle was already processed
+ return;
+ }
+
+ String consumerHeader = bundle.getHeaders().get(consumerHeaderName);
+ if (consumerHeader != null) {
+ Set<WeavingData> wd = ConsumerHeaderProcessor.processHeader(consumerHeader);
+ bundleWeavingData.put(bundle, Collections.unmodifiableSet(wd));
+
+ for (WeavingData w : wd) {
+ registerConsumerBundle(bundle, w.getArgRestrictions(), w.getAllowedBundles());
+ }
+ } else {
+ bundleWeavingData.put(bundle, NON_WOVEN_BUNDLE);
+ }
+ }
+
+ @Override
+ public synchronized void stop(BundleContext context) throws Exception {
+ activator = null;
+
+ consumerBundleTracker.close();
+ providerBundleTracker.close();
+ logServiceTracker.close();
+ }
+
+ public void log(int level, String message) {
+ synchronized (logServices) {
+ for (LogService log : logServices) {
+ log.log(level, message);
+ }
+ }
+ }
+
+ public void log(int level, String message, Throwable th) {
+ synchronized (logServices) {
+ for (LogService log : logServices) {
+ log.log(level, message, th);
+ }
+ }
+ }
+
+ public Set<WeavingData> getWeavingData(Bundle b) {
+ // Simply return the value as it's already an unmovable set.
+ Set<WeavingData> wd = bundleWeavingData.get(b);
+ if (wd == null)
+ return null;
+
+ if (wd.size() == 0)
+ return null;
+
+ return wd;
+ }
+
+ public void registerProviderBundle(String registrationClassName, Bundle bundle) {
+ registeredProviders.putIfAbsent(registrationClassName, Collections.synchronizedSortedMap(new TreeMap<Long, Bundle>()));
+ SortedMap<Long, Bundle> map = registeredProviders.get(registrationClassName);
+ map.put(bundle.getBundleId(), bundle);
+ }
+
+ public Collection<Bundle> findProviderBundles(String name) {
+ SortedMap<Long, Bundle> map = registeredProviders.get(name);
+ return map == null ? Collections.<Bundle>emptyList() : map.values();
+ }
+
+ // TODO unRegisterProviderBundle();
+ public void registerConsumerBundle( Bundle consumerBundle,
+ Set<ConsumerRestriction> restrictions, List<BundleDescriptor> allowedBundles) {
+ consumerRestrictions.putIfAbsent(consumerBundle, new HashMap<ConsumerRestriction, List<BundleDescriptor>>());
+ Map<ConsumerRestriction, List<BundleDescriptor>> map = consumerRestrictions.get(consumerBundle);
+ for (ConsumerRestriction restriction : restrictions) {
+ map.put(restriction, allowedBundles);
+ }
+ }
+
+ public Collection<Bundle> findConsumerRestrictions(Bundle consumer, String className, String methodName,
+ Map<Pair<Integer, String>, String> args) {
+ Map<ConsumerRestriction, List<BundleDescriptor>> restrictions = consumerRestrictions.get(consumer);
+ if (restrictions == null) {
+ // Null means: no restrictions
+ return null;
+ }
+
+ for (Map.Entry<ConsumerRestriction, List<BundleDescriptor>> entry : restrictions.entrySet()) {
+ if (entry.getKey().matches(className, methodName, args)) {
+ return getBundles(entry.getValue());
+ }
+ }
+
+ // Empty collection: nothing matches
+ return Collections.emptySet();
+ }
+
+ private Collection<Bundle> getBundles(List<BundleDescriptor> descriptors) {
+ if (descriptors == null) {
+ return null;
+ }
+
+ List<Bundle> bundles = new ArrayList<Bundle>();
+ for (Bundle b : bundleContext.getBundles()) {
+ for (BundleDescriptor desc : descriptors) {
+ if (b.getSymbolicName().equals(desc.getSymbolicName())) {
+ if (desc.getVersion() == null || b.getVersion().equals(desc.getVersion())) {
+ bundles.add(b);
+ }
+ }
+ }
+ }
+ return bundles;
+ }
+
+ // TODO unRegisterConsumerBundle();
+
+ private class LogServiceTracker extends ServiceTracker<LogService, LogService> {
+ public LogServiceTracker(BundleContext context) {
+ super(context, LogService.class, null);
+ }
+
+ public LogService addingService(ServiceReference<LogService> reference) {
+ LogService svc = super.addingService(reference);
+ if (svc != null)
+ logServices.add(svc);
+ return svc;
+ }
+
+ @Override
+ public void removedService(ServiceReference<LogService> reference, LogService service) {
+ logServices.remove(service);
+ }
+ }
+}
Modified: aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ConsumerHeaderProcessor.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ConsumerHeaderProcessor.java?rev=1084603&r1=1084602&r2=1084603&view=diff
==============================================================================
--- aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ConsumerHeaderProcessor.java (original)
+++ aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ConsumerHeaderProcessor.java Wed Mar 23 14:39:56 2011
@@ -56,7 +56,7 @@ public class ConsumerHeaderProcessor {
* @param consumerHeader the <tt>SPI-Consumer</tt> header.
* @return an instance of the {@link WeavingData} class.
*/
- public static WeavingData[] processHeader(/* Bundle consumerBundle, */String consumerHeader) {
+ public static Set<WeavingData> processHeader(/* Bundle consumerBundle, */String consumerHeader) {
Set<WeavingData> weavingData = new HashSet<WeavingData>();
for (PathElement element : HeaderParser.parseHeader(consumerHeader)) {
@@ -169,6 +169,6 @@ public class ConsumerHeaderProcessor {
weavingData.add(new WeavingData(className, methodName, argClasses, restrictions,
allowedBundles.size() == 0 ? null : allowedBundles));
}
- return weavingData.toArray(new WeavingData [weavingData.size()]);
+ return weavingData;
}
}
Modified: aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizer.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizer.java?rev=1084603&r1=1084602&r2=1084603&view=diff
==============================================================================
--- aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizer.java (original)
+++ aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizer.java Wed Mar 23 14:39:56 2011
@@ -37,10 +37,10 @@ import org.osgi.util.tracker.BundleTrack
* Listens for new bundles being installed and registers them as service providers if applicable.
*/
public class ProviderBundleTrackerCustomizer implements BundleTrackerCustomizer<List<ServiceRegistration<?>>> {
- final Activator activator;
+ final BaseActivator activator;
final Bundle spiBundle;
- public ProviderBundleTrackerCustomizer(Activator a, Bundle b) {
+ public ProviderBundleTrackerCustomizer(BaseActivator a, Bundle b) {
activator = a;
spiBundle = b;
Modified: aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/TCCLSetterVisitor.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/TCCLSetterVisitor.java?rev=1084603&r1=1084602&r2=1084603&view=diff
==============================================================================
--- aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/TCCLSetterVisitor.java (original)
+++ aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/TCCLSetterVisitor.java Wed Mar 23 14:39:56 2011
@@ -20,6 +20,7 @@ package org.apache.aries.spifly;
import java.util.Arrays;
import java.util.ServiceLoader;
+import java.util.Set;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
@@ -39,13 +40,13 @@ public class TCCLSetterVisitor extends C
private static final String VOID_RETURN_TYPE = "()V";
private final String targetClass;
- private final WeavingData [] weavingData;
+ private final Set<WeavingData> weavingData;
// Set to true when the weaving code has changed the client such that an additional import
// (to the Util.class.getPackage()) is needed.
private boolean additionalImportRequired = false;
- public TCCLSetterVisitor(ClassVisitor cv, String className, WeavingData [] weavingData) {
+ public TCCLSetterVisitor(ClassVisitor cv, String className, Set<WeavingData> weavingData) {
super(cv);
this.targetClass = className.replace('.', '/');
this.weavingData = weavingData;
Modified: aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/Util.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/Util.java?rev=1084603&r1=1084602&r2=1084603&view=diff
==============================================================================
--- aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/Util.java (original)
+++ aries/trunk/spi-fly/spi-fly-core/src/main/java/org/apache/aries/spifly/Util.java Wed Mar 23 14:39:56 2011
@@ -49,7 +49,7 @@ public class Util {
public static void fixContextClassloader(String cls, String method, Class<?> clsArg, ClassLoader bundleLoader) {
if (!(bundleLoader instanceof BundleReference)) {
- Activator.activator.log(LogService.LOG_WARNING, "Classloader of consuming bundle doesn't implement BundleReference: " + bundleLoader);
+ BaseActivator.activator.log(LogService.LOG_WARNING, "Classloader of consuming bundle doesn't implement BundleReference: " + bundleLoader);
return;
}
@@ -58,15 +58,15 @@ public class Util {
ClassLoader cl = findContextClassloader(br.getBundle(), cls, method, clsArg);
if (cl != null) {
- Activator.activator.log(LogService.LOG_INFO, "Temporarily setting Thread Context Classloader to: " + cl);
+ BaseActivator.activator.log(LogService.LOG_INFO, "Temporarily setting Thread Context Classloader to: " + cl);
Thread.currentThread().setContextClassLoader(cl);
} else {
- Activator.activator.log(LogService.LOG_WARNING, "No classloader found for " + cls + ":" + method + "(" + clsArg + ")");
+ BaseActivator.activator.log(LogService.LOG_WARNING, "No classloader found for " + cls + ":" + method + "(" + clsArg + ")");
}
}
private static ClassLoader findContextClassloader(Bundle consumerBundle, String className, String methodName, Class<?> clsArg) {
- Activator activator = Activator.activator;
+ BaseActivator activator = BaseActivator.activator;
String requestedClass;
Map<Pair<Integer, String>, String> args;
Copied: aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java.todo (from r1084567, aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java)
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java.todo?p2=aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java.todo&p1=aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java&r1=1084567&r2=1084603&rev=1084603&view=diff
==============================================================================
--- aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java (original)
+++ aries/trunk/spi-fly/spi-fly-core/src/test/java/org/apache/aries/spifly/ProviderBundleTrackerCustomizerTest.java.todo Wed Mar 23 14:39:56 2011
@@ -40,7 +40,7 @@ public class ProviderBundleTrackerCustom
public void testAddingRemovedBundle() throws Exception {
Bundle spiBundle = EasyMock.createMock(Bundle.class);
EasyMock.replay(spiBundle);
- Activator a = new Activator();
+ BaseActivator a = new BaseActivator();
ProviderBundleTrackerCustomizer customizer = new ProviderBundleTrackerCustomizer(a, spiBundle);
Added: aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java (added)
+++ aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java Wed Mar 23 14:39:56 2011
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.spifly.dynamic;
+
+import java.util.Set;
+
+import org.apache.aries.spifly.TCCLSetterVisitor;
+import org.apache.aries.spifly.Util;
+import org.apache.aries.spifly.WeavingData;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.hooks.weaving.WeavingHook;
+import org.osgi.framework.hooks.weaving.WovenClass;
+import org.osgi.service.log.LogService;
+
+public class ClientWeavingHook implements WeavingHook {
+ private final String addedImport;
+ private final DynamicWeavingActivator activator;
+
+ ClientWeavingHook(BundleContext context, DynamicWeavingActivator dwActivator) {
+ activator = dwActivator;
+
+ Bundle b = context.getBundle();
+ String bver = b.getVersion().toString();
+ String bsn = b.getSymbolicName();
+
+ addedImport = Util.class.getPackage().getName() +
+ ";bundle-symbolic-name=" + bsn +
+ ";bundle-version=" + bver;
+ }
+
+ @Override
+ public void weave(WovenClass wovenClass) {
+ Bundle consumerBundle = wovenClass.getBundleWiring().getBundle();
+ Set<WeavingData> wd = activator.getWeavingData(consumerBundle);
+ if (wd != null) {
+ activator.log(LogService.LOG_DEBUG, "Weaving class " + wovenClass.getClassName());
+
+// WeavingData[] wd = ConsumerHeaderProcessor.processHeader(consumerBundle, consumerHeader);
+
+ ClassReader cr = new ClassReader(wovenClass.getBytes());
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ TCCLSetterVisitor tsv = new TCCLSetterVisitor(cw, wovenClass.getClassName(), wd);
+ cr.accept(tsv, 0);
+ wovenClass.setBytes(cw.toByteArray());
+ if (tsv.additionalImportRequired())
+ wovenClass.getDynamicImports().add(addedImport);
+ }
+ }
+}
Added: aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/DynamicWeavingActivator.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/DynamicWeavingActivator.java?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/DynamicWeavingActivator.java (added)
+++ aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/DynamicWeavingActivator.java Wed Mar 23 14:39:56 2011
@@ -0,0 +1,27 @@
+package org.apache.aries.spifly.dynamic;
+
+import org.apache.aries.spifly.BaseActivator;
+import org.apache.aries.spifly.api.SpiFlyConstants;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.hooks.weaving.WeavingHook;
+
+public class DynamicWeavingActivator extends BaseActivator implements BundleActivator {
+ private ServiceRegistration<WeavingHook> weavingHookService;
+
+ @Override
+ public synchronized void start(BundleContext context) throws Exception {
+ WeavingHook wh = new ClientWeavingHook(context, this);
+ weavingHookService = context.registerService(WeavingHook.class, wh, null);
+
+ super.start(context, SpiFlyConstants.SPI_CONSUMER_HEADER);
+ }
+
+ @Override
+ public synchronized void stop(BundleContext context) throws Exception {
+ weavingHookService.unregister();
+
+ super.stop(context);
+ }
+}
Added: aries/trunk/spi-fly/spi-fly-static-bundle/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-static-bundle/pom.xml?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-static-bundle/pom.xml (added)
+++ aries/trunk/spi-fly/spi-fly-static-bundle/pom.xml Wed Mar 23 14:39:56 2011
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.aries.spifly</groupId>
+ <artifactId>spifly</artifactId>
+ <version>0.4-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.apache.aries.spifly.static.bundle</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Aries SPI Fly Static Weaving Bundle</name>
+ <description>
+ This bundle contains support classes used at runtime by bundles
+ woven using the static weaving done through the org.apache.aries.spifly.static
+ component.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.aries.spifly</groupId>
+ <artifactId>org.apache.aries.spifly.core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ *
+ </Import-Package>
+ <Export-Package>
+ org.apache.aries.spifly;version=${project.version},
+ org.apache.aries.spifly.api;version=${project.version}
+ </Export-Package>
+ <Private-Package>
+ org.apache.aries.spifly.staticbundle
+ </Private-Package>
+ <Bundle-Activator>org.apache.aries.spifly.staticbundle.StaticWeavingActivator</Bundle-Activator>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
Added: aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/aries/spifly/staticbundle/StaticWeavingActivator.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/aries/spifly/staticbundle/StaticWeavingActivator.java?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/aries/spifly/staticbundle/StaticWeavingActivator.java (added)
+++ aries/trunk/spi-fly/spi-fly-static-bundle/src/main/java/org/apache/aries/spifly/staticbundle/StaticWeavingActivator.java Wed Mar 23 14:39:56 2011
@@ -0,0 +1,18 @@
+package org.apache.aries.spifly.staticbundle;
+
+import org.apache.aries.spifly.BaseActivator;
+import org.apache.aries.spifly.api.SpiFlyConstants;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class StaticWeavingActivator extends BaseActivator implements BundleActivator {
+ @Override
+ public synchronized void start(BundleContext context) throws Exception {
+ super.start(context, SpiFlyConstants.PROCESSED_SPI_CONSUMER_HEADER);
+ }
+
+ @Override
+ public synchronized void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ }
+}
Added: aries/trunk/spi-fly/spi-fly-static-tool/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-static-tool/pom.xml?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-static-tool/pom.xml (added)
+++ aries/trunk/spi-fly/spi-fly-static-tool/pom.xml Wed Mar 23 14:39:56 2011
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.aries.spifly</groupId>
+ <artifactId>spifly</artifactId>
+ <version>0.4-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.apache.aries.spifly.static.tool</artifactId>
+ <packaging>jar</packaging>
+ <name>Apache Aries SPI Fly Static Weaving Tool</name>
+ <description>
+ This tool does the weaving to support SPI ServiceLoader statically.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>3.3.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.aries.spifly</groupId>
+ <artifactId>org.apache.aries.spifly.core</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.apache.aries.spifly.statictool.Main</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
Added: aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/DirTree.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/DirTree.java?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/DirTree.java (added)
+++ aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/DirTree.java Wed Mar 23 14:39:56 2011
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.spifly.statictool;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class DirTree {
+ List<File> fileList = new ArrayList<File>();
+
+ public DirTree(File f) {
+ String[] names = f.list();
+
+ if (names == null) {
+ fileList.add(f);
+ return;
+ }
+
+ for (String name : names) {
+ File curFile = new File(f, name);
+
+ if (curFile.isDirectory()) {
+ fileList.addAll(new DirTree(curFile).getFiles());
+ } else {
+ fileList.add(curFile);
+ }
+ }
+ fileList.add(f);
+ }
+
+ public List<File> getFiles() {
+ return fileList;
+ }
+}
Added: aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java (added)
+++ aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java Wed Mar 23 14:39:56 2011
@@ -0,0 +1,282 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.spifly.statictool;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.aries.spifly.ConsumerHeaderProcessor;
+import org.apache.aries.spifly.Streams;
+import org.apache.aries.spifly.TCCLSetterVisitor;
+import org.apache.aries.spifly.Util;
+import org.apache.aries.spifly.WeavingData;
+import org.apache.aries.spifly.api.SpiFlyConstants;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+
+public class Main {
+ private static final String IMPORT_PACKAGE = "Import-Package";
+
+ public static void usage() {
+ System.err.println();
+ System.err.println("Usage: java " + Main.class.getName() + " bundle1.jar bundle2.jar ...");
+ System.exit(-1);
+ }
+
+ public static void main(String ... args) throws Exception {
+ for (String arg : args) {
+ weaveJar(arg);
+ }
+ }
+
+ private static void weaveJar(String jarPath) throws IOException {
+ String spiFlyVersion = getMyVersion();
+
+ File jarFile = new File(jarPath);
+ File tempDir = new File(System.getProperty("java.io.tmpdir") + File.separator + jarFile.getName() + "_" + System.currentTimeMillis());
+ Manifest manifest = unJar(jarFile, tempDir);
+ String consumerHeader = manifest.getMainAttributes().getValue(SpiFlyConstants.SPI_CONSUMER_HEADER);
+ if (consumerHeader != null) {
+ weaveDir(tempDir, consumerHeader);
+
+ manifest.getMainAttributes().remove(new Attributes.Name(SpiFlyConstants.SPI_CONSUMER_HEADER));
+ manifest.getMainAttributes().putValue(SpiFlyConstants.PROCESSED_SPI_CONSUMER_HEADER, consumerHeader);
+ // TODO if new packages needed then...
+ extendImportPackage(spiFlyVersion, manifest);
+
+ File newJar = getNewJarFile(jarFile);
+ jar(newJar, tempDir, manifest);
+ }
+ delTree(tempDir);
+ }
+
+ private static void extendImportPackage(String spiFlyVersion, Manifest manifest) {
+ String ip = manifest.getMainAttributes().getValue(IMPORT_PACKAGE);
+ StringBuilder sb = new StringBuilder(ip);
+ sb.append(",");
+ sb.append(Util.class.getPackage().getName());
+ sb.append(";version=\"[");
+ sb.append(spiFlyVersion);
+ sb.append(",");
+ sb.append(spiFlyVersion);
+ sb.append("]\"");
+ manifest.getMainAttributes().putValue(IMPORT_PACKAGE, sb.toString());
+ }
+
+ private static String getMyVersion() throws IOException {
+ // Should be able to leverage the aries.osgi.version file that appears in the target directory here.
+ // Need to figure that out...
+ return "0.4.0.SNAPSHOT";
+
+// String classResource = "/" + Main.class.getName().replace(".", "/") + ".class";
+// URL jarUrl = Main.class.getResource(classResource);
+// if (jarUrl != null) {
+// String jarLoc = jarUrl.toExternalForm();
+// Manifest mf = null;
+// if (jarLoc.startsWith("jar:")) {
+// jarLoc.substring("jar:".length());
+// int idx = jarLoc.indexOf("!/");
+// if (idx >= 0) {
+// jarLoc = jarLoc.substring(0, idx);
+// }
+//
+// JarFile jr = new JarFile(jarLoc);
+// mf = jr.getManifest();
+// } else if (jarLoc.startsWith("file:") && jarLoc.endsWith(classResource)) {
+// String rootDir = jarLoc.substring(0, jarLoc.length() - classResource.length());
+// File manifestFile = new File(rootDir + "/META-INF/MANIFEST.MF");
+// if (manifestFile.exists()) {
+// mf = new Manifest(new FileInputStream(manifestFile));
+// }
+// }
+//
+// if (mf != null) {
+// String version = mf.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+// if (version == null)
+// throw new IOException("Could not obtain the implementation version of this jar file from the manifest");
+// return version.trim();
+// }
+// }
+// throw new IOException("This class can only be executed from inside a jar or an exploded jar file.");
+ }
+
+ private static File getNewJarFile(File jarFile) {
+ String s = jarFile.getAbsolutePath();
+ int idx = s.lastIndexOf('.');
+ s = s.substring(0, idx);
+ s += "_spifly.jar";
+ return new File(s);
+ }
+
+ private static void weaveDir(File dir, String consumerHeader) throws IOException {
+ String dirName = dir.getAbsolutePath();
+
+ DirTree dt = new DirTree(dir);
+ for (File f : dt.getFiles()) {
+ if (!f.getName().endsWith(".class"))
+ continue;
+
+ String className = f.getAbsolutePath().substring(dirName.length());
+ if (className.startsWith(File.separator))
+ className = className.substring(1);
+ className = className.substring(0, className.length() - ".class".length());
+ className = className.replace(File.separator, ".");
+
+ Set<WeavingData> wd = ConsumerHeaderProcessor.processHeader(consumerHeader);
+ InputStream is = new FileInputStream(f);
+ byte[] b;
+ try {
+ ClassReader cr = new ClassReader(is);
+ ClassWriter cw = new ClassWriter(0);
+ ClassVisitor cv = new TCCLSetterVisitor(cw, className, wd);
+ cr.accept(cv, 0);
+ b = cw.toByteArray();
+ } finally {
+ is.close();
+ }
+
+ OutputStream os = new FileOutputStream(f);
+ try {
+ os.write(b);
+ } finally {
+ os.close();
+ }
+ }
+ }
+
+ static Manifest unJar(File jarFile, File tempDir) throws IOException {
+ ensureDirectory(tempDir);
+
+ JarInputStream jis = new JarInputStream(new FileInputStream(jarFile));
+ JarEntry je = null;
+ while((je = jis.getNextJarEntry()) != null) {
+ if (je.isDirectory()) {
+ File outDir = new File(tempDir, je.getName());
+ ensureDirectory(outDir);
+
+ continue;
+ }
+
+ File outFile = new File(tempDir, je.getName());
+ File outDir = outFile.getParentFile();
+ ensureDirectory(outDir);
+
+ OutputStream out = new FileOutputStream(outFile);
+ try {
+ Streams.pump(jis, out);
+ } finally {
+ out.flush();
+ out.close();
+ jis.closeEntry();
+ }
+ outFile.setLastModified(je.getTime());
+ }
+
+ Manifest manifest = jis.getManifest();
+ if (manifest != null) {
+ File mf = new File(tempDir, "META-INF/MANIFEST.MF");
+ File mfDir = mf.getParentFile();
+ ensureDirectory(mfDir);
+
+ OutputStream out = new FileOutputStream(mf);
+ try {
+ manifest.write(out);
+ } finally {
+ out.flush();
+ out.close();
+ }
+ }
+
+ jis.close();
+ return manifest;
+ }
+
+ static void jar(File jarFile, File rootFile, Manifest manifest) throws IOException {
+ JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile), manifest);
+ try {
+ addToJarRecursively(jos, rootFile.getAbsoluteFile(), rootFile.getAbsolutePath());
+ } finally {
+ jos.close();
+ }
+ }
+
+ static void addToJarRecursively(JarOutputStream jar, File source, String rootDirectory) throws IOException {
+ String sourceName = source.getAbsolutePath().replace("\\", "/");
+ sourceName = sourceName.substring(rootDirectory.length());
+
+ if (sourceName.startsWith("/")) {
+ sourceName = sourceName.substring(1);
+ }
+
+ if ("META-INF/MANIFEST.MF".equals(sourceName))
+ return;
+
+ if (source.isDirectory()) {
+ /* Is there any point in adding a directory beyond just taking up space?
+ if (!sourceName.isEmpty()) {
+ if (!sourceName.endsWith("/")) {
+ sourceName += "/";
+ }
+ JarEntry entry = new JarEntry(sourceName);
+ jar.putNextEntry(entry);
+ jar.closeEntry();
+ }
+ */
+ for (File nested : source.listFiles()) {
+ addToJarRecursively(jar, nested, rootDirectory);
+ }
+ return;
+ }
+
+ JarEntry entry = new JarEntry(sourceName);
+ jar.putNextEntry(entry);
+ InputStream is = new FileInputStream(source);
+ try {
+ Streams.pump(is, jar);
+ } finally {
+ jar.closeEntry();
+ is.close();
+ }
+ }
+
+ static void delTree(File tempDir) throws IOException {
+ for (File f : new DirTree(tempDir).getFiles()) {
+ if (!f.delete())
+ throw new IOException("Problem deleting file: " + tempDir.getAbsolutePath());
+ }
+ }
+
+ private static void ensureDirectory(File outDir) throws IOException {
+ if (!outDir.isDirectory())
+ if (!outDir.mkdirs())
+ throw new IOException("Unable to create directory " + outDir.getAbsolutePath());
+ }
+}
+
Added: aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/aries/spifly/statictool/MainTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/aries/spifly/statictool/MainTest.java?rev=1084603&view=auto
==============================================================================
--- aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/aries/spifly/statictool/MainTest.java (added)
+++ aries/trunk/spi-fly/spi-fly-static-tool/src/test/java/org/apache/aries/spifly/statictool/MainTest.java Wed Mar 23 14:39:56 2011
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.spifly.statictool;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.jar.Manifest;
+
+import org.apache.aries.spifly.Streams;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.internal.ArrayComparisonFailure;
+
+public class MainTest {
+ @Test
+ public void testUnJarReJar() throws Exception {
+ URL jarURL = getClass().getResource("/testjar.jar");
+ File jarFile = new File(jarURL.getFile());
+ File tempDir = new File(System.getProperty("java.io.tmpdir") + "/testjar_" + System.currentTimeMillis());
+
+ try {
+ Manifest manifest = Main.unJar(jarFile, tempDir);
+
+ assertStreams(new File(tempDir, "META-INF/MANIFEST.MF"),
+ "jar:" + jarURL + "!/META-INF/MANIFEST.MF");
+
+ assertStreams(new File(tempDir, "A text File with no content"),
+ "jar:" + jarURL + "!/A text File with no content");
+ assertStreams(new File(tempDir, "dir/Main.class"),
+ "jar:" + jarURL + "!/dir/Main.class");
+ assertStreams(new File(tempDir, "dir/dir 2/a.txt"),
+ "jar:" + jarURL + "!/dir/dir 2/a.txt");
+ assertStreams(new File(tempDir, "dir/dir 2/b.txt"),
+ "jar:" + jarURL + "!/dir/dir 2/b.txt");
+
+ Assert.assertTrue(new File(tempDir, "dir/dir.3").exists());
+
+ // Create a second jar from the exploded directory
+ File copiedFile = new File(jarFile.getAbsolutePath() + ".copy");
+ Main.jar(copiedFile, tempDir, manifest);
+ URL copyURL = copiedFile.toURI().toURL();
+
+ assertStreams("jar:" + copyURL + "!/META-INF/MANIFEST.MF",
+ "jar:" + jarURL + "!/META-INF/MANIFEST.MF");
+
+ assertStreams("jar:" + copyURL + "!/A text File with no content",
+ "jar:" + jarURL + "!/A text File with no content");
+ assertStreams("jar:" + copyURL + "!/dir/Main.class",
+ "jar:" + jarURL + "!/dir/Main.class");
+ assertStreams("jar:" + copyURL + "!/dir/dir 2/a.txt",
+ "jar:" + jarURL + "!/dir/dir 2/a.txt");
+ assertStreams("jar:" + copyURL + "!/dir/dir 2/b.txt",
+ "jar:" + jarURL + "!/dir/dir 2/b.txt");
+ } finally {
+ Main.delTree(tempDir);
+ }
+ }
+
+ @Test
+ public void testDelTree() throws IOException {
+ URL jarURL = getClass().getResource("/testjar.jar");
+ File jarFile = new File(jarURL.getFile());
+ File tempDir = new File(System.getProperty("java.io.tmpdir") + "/testjar_" + System.currentTimeMillis());
+
+ assertFalse("Precondition", tempDir.exists());
+ Main.unJar(jarFile, tempDir);
+ assertTrue(tempDir.exists());
+
+ Main.delTree(tempDir);
+ assertFalse(tempDir.exists());
+ }
+
+ private void assertStreams(String url1, String url2) throws Exception {
+ InputStream is1 = new URL(url1).openStream();
+ InputStream is2 = new URL(url2).openStream();
+ assertStreams(is1, is2);
+ }
+
+ private void assertStreams(File file, String url) throws Exception {
+ InputStream is1 = new FileInputStream(file);
+ InputStream is2 = new URL(url).openStream();
+ assertStreams(is1, is2);
+ }
+
+ private void assertStreams(InputStream is1, InputStream is2)
+ throws IOException, ArrayComparisonFailure {
+ try {
+ byte[] bytes1 = Streams.suck(is1);
+ byte[] bytes2 = Streams.suck(is2);
+ Assert.assertArrayEquals("Files not equal", bytes1, bytes2);
+ } finally {
+ is1.close();
+ is2.close();
+ }
+ }
+}
+
+
Added: aries/trunk/spi-fly/spi-fly-static-tool/src/test/resources/testjar.jar
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-static-tool/src/test/resources/testjar.jar?rev=1084603&view=auto
==============================================================================
Binary file - no diff available.
Propchange: aries/trunk/spi-fly/spi-fly-static-tool/src/test/resources/testjar.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream