Return-Path: Delivered-To: apmail-felix-commits-archive@www.apache.org Received: (qmail 37016 invoked from network); 28 Oct 2009 14:30:25 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 28 Oct 2009 14:30:25 -0000 Received: (qmail 26278 invoked by uid 500); 28 Oct 2009 14:30:25 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 26221 invoked by uid 500); 28 Oct 2009 14:30:25 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 26212 invoked by uid 99); 28 Oct 2009 14:30:25 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Oct 2009 14:30:25 +0000 X-ASF-Spam-Status: No, hits=-2.6 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Oct 2009 14:30:22 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id E313D238890A; Wed, 28 Oct 2009 14:30:01 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r830559 - in /felix/trunk/sigil/common/runtime: ./ src/org/apache/felix/sigil/common/runtime/ src/org/apache/felix/sigil/common/runtime/io/ Date: Wed, 28 Oct 2009 14:30:01 -0000 To: commits@felix.apache.org From: dsavage@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091028143001.E313D238890A@eris.apache.org> Author: dsavage Date: Wed Oct 28 14:30:01 2009 New Revision: 830559 URL: http://svn.apache.org/viewvc?rev=830559&view=rev Log: Patches related to FELIX-1324 create BundleForm class to encapsulate a certain bundle configuration - Client.apply(BundleForm) merges the specified form into the currently running framework configuration (i.e. applies delta to currently running bundles) Added: felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/RefreshAction.java Modified: felix/trunk/sigil/common/runtime/sigil.properties felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Runtime.java felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Server.java felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/Constants.java felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/StatusAction.java Modified: felix/trunk/sigil/common/runtime/sigil.properties URL: http://svn.apache.org/viewvc/felix/trunk/sigil/common/runtime/sigil.properties?rev=830559&r1=830558&r2=830559&view=diff ============================================================================== --- felix/trunk/sigil/common/runtime/sigil.properties (original) +++ felix/trunk/sigil/common/runtime/sigil.properties Wed Oct 28 14:30:01 2009 @@ -14,7 +14,8 @@ -imports: \ org.apache.felix.sigil.common.runtime,\ org.osgi.framework, \ - org.osgi.framework.launch;resolve=compile;version=1.0.0, \ + org.osgi.framework.launch, \ + org.osgi.service.packageadmin, \ header;Main-Class: org.apache.felix.sigil.common.runtime.Main Added: felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java URL: http://svn.apache.org/viewvc/felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java?rev=830559&view=auto ============================================================================== --- felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java (added) +++ felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/BundleForm.java Wed Oct 28 14:30:01 2009 @@ -0,0 +1,197 @@ +/* + * 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.felix.sigil.common.runtime; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; + +import org.osgi.framework.Bundle; +import org.osgi.framework.Constants; + +public class BundleForm +{ + public static class BundleStatus + { + private String location; + private String bundleSymbolicName; + private String version; + private long id; + private int status; + + public String getLocation() + { + return location; + } + + public void setLocation(String location) + { + this.location = location; + } + + public String getBundleSymbolicName() + { + return bundleSymbolicName; + } + + public void setBundleSymbolicName(String bundleSymbolicName) + { + this.bundleSymbolicName = bundleSymbolicName; + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public long getId() + { + return id; + } + + public void setId(long id) + { + this.id = id; + } + + public void setStatus(int status) + { + this.status = status; + } + + public int getStatus() { + return status; + } + + public boolean isMatch(BundleStatus n) + { + return bundleSymbolicName.equals( n.bundleSymbolicName ) && version.equals(n.version); + } + } + + private String[] bundles; + private Set startMap = new HashSet(); + + public BundleForm() { + } + + public static BundleForm resolve(URL formURL) throws IOException, URISyntaxException { + InputStream in = formURL.openStream(); + try { + BundleForm f = new BundleForm(); + BufferedReader r = new BufferedReader(new InputStreamReader(in)); + LinkedList locs = new LinkedList(); + for(;;) { + String l = r.readLine(); + if ( l == null ) break; + URI uri = URI.create(l); + String status = uri.getScheme(); + uri = URI.create(uri.getSchemeSpecificPart()); + String loc = uri.toString(); + locs.add( loc ); + f.setStarted(loc, "start".equalsIgnoreCase(status) ); + } + f.setBundles(locs.toArray(new String[locs.size()])); + return f; + } + finally { + try + { + in.close(); + } + catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + public void setBundles(String[] bundles) { + this.bundles = bundles; + } + + public String[] getBundles() + { + return bundles; + } + + public boolean isStarted(String url) + { + return startMap.contains(url); + } + + public void setStarted(String url, boolean started) { + if ( started ) { + startMap.add(url); + } + else { + startMap.remove(url); + } + } + + public BundleStatus[] toStatus() throws IOException { + ArrayList ret = new ArrayList(bundles.length); + for ( String loc : bundles ) { + URL url = new URL(loc); + InputStream in = url.openStream(); + try { + JarInputStream jin = new JarInputStream(in); + Manifest mf = jin.getManifest(); + Attributes attr = mf.getMainAttributes(); + String bsn = attr.getValue(Constants.BUNDLE_SYMBOLICNAME); + String ver = attr.getValue(Constants.BUNDLE_VERSION); + BundleStatus st = new BundleStatus(); + st.setBundleSymbolicName(bsn); + st.setVersion(ver); + st.setLocation(loc); + st.setStatus(isStarted(loc) ? Bundle.ACTIVE : Bundle.INSTALLED); + ret.add(st); + } + finally { + try + { + in.close(); + } + catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + return ret.toArray(new BundleStatus[ret.size()] ); + } +} Modified: felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java URL: http://svn.apache.org/viewvc/felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java?rev=830559&r1=830558&r2=830559&view=diff ============================================================================== --- felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java (original) +++ felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Client.java Wed Oct 28 14:30:01 2009 @@ -26,16 +26,18 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; -import java.util.Map; import java.util.Properties; +import org.apache.felix.sigil.common.runtime.BundleForm.BundleStatus; import org.apache.felix.sigil.common.runtime.io.InstallAction; +import org.apache.felix.sigil.common.runtime.io.RefreshAction; import org.apache.felix.sigil.common.runtime.io.StartAction; import org.apache.felix.sigil.common.runtime.io.StatusAction; import org.apache.felix.sigil.common.runtime.io.StopAction; import org.apache.felix.sigil.common.runtime.io.UninstallAction; import org.apache.felix.sigil.common.runtime.io.UpdateAction; import org.apache.felix.sigil.common.runtime.io.UpdateAction.Update; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; import static org.apache.felix.sigil.common.runtime.Runtime.PORT_PROPERTY; @@ -90,6 +92,27 @@ out = null; } + public void apply(BundleForm form) throws IOException, BundleException { + BundleStatus[] newStatus = form.toStatus(); + + BundleStatus[] currentStatus = status(); + + stopOldBundles(currentStatus, newStatus); + + boolean change = uninstallOldBundles(currentStatus, newStatus); + change |= installNewBundles(currentStatus, newStatus); + + if ( change ) + refresh(); + + startNewBundles(newStatus); + } + + public void refresh() throws IOException, BundleException + { + if ( socket == null ) throw new IllegalStateException( "Not connected" ); + new RefreshAction( in, out ).client(); + } public long install( String url ) throws IOException, BundleException { @@ -135,9 +158,84 @@ } - public Map status() throws IOException, BundleException + public BundleStatus[] status() throws IOException, BundleException { if ( socket == null ) throw new IllegalStateException( "Not connected" ); return new StatusAction( in, out ).client(); } + + private boolean installNewBundles(BundleStatus[] status, BundleStatus[] newStatus) throws IOException, BundleException + { + boolean change = false; + for (BundleStatus n : newStatus) { + boolean found = false; + for ( BundleStatus o : status ) { + if ( o.isMatch(n) ) { + update(o.getId(), n.getLocation()); + found = true; + change = true; + break; + } + } + + if ( !found ) { + install(n.getLocation()); + change = true; + } + } + + return change; + } + + private void startNewBundles(BundleStatus[] newStatus) throws IOException, BundleException + { + BundleStatus[] status = status(); + for (BundleStatus n : newStatus) { + if ( n.getStatus() == Bundle.ACTIVE ) { + for ( BundleStatus o : status ) { + if ( o.isMatch(n) ) { + start(o.getId()); + } + } + } + } + } + + private void stopOldBundles(BundleStatus[] status, BundleStatus[] newStatus) throws IOException, BundleException + { + for (BundleStatus n : newStatus) { + if ( n.getStatus() == Bundle.INSTALLED ) { + for ( BundleStatus o : status ) { + if ( o.getId() != 0 ) { + if ( o.isMatch(n) ) { + stop(o.getId()); + } + } + } + } + } + } + + private boolean uninstallOldBundles(BundleStatus[] status, BundleStatus[] newStatus) throws IOException, BundleException + { + boolean change = false; + for ( BundleStatus o : status ) { + if ( o.getId() != 0 ) { + boolean found = false; + + for (BundleStatus n : newStatus) { + if ( o.isMatch(n) ) { + found = true; + break; + } + } + + if ( !found ) { + change = true; + uninstall(o.getId()); + } + } + } + return change; + } } Modified: felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Runtime.java URL: http://svn.apache.org/viewvc/felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Runtime.java?rev=830559&r1=830558&r2=830559&view=diff ============================================================================== --- felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Runtime.java (original) +++ felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Runtime.java Wed Oct 28 14:30:01 2009 @@ -19,7 +19,7 @@ package org.apache.felix.sigil.common.runtime; -public class Runtime +public interface Runtime { public static final String PORT_PROPERTY = "port"; public static final String ADDRESS_PROPERTY = "address"; Modified: felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Server.java URL: http://svn.apache.org/viewvc/felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Server.java?rev=830559&r1=830558&r2=830559&view=diff ============================================================================== --- felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Server.java (original) +++ felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/Server.java Wed Oct 28 14:30:01 2009 @@ -35,6 +35,7 @@ import org.apache.felix.sigil.common.runtime.io.Action; import org.apache.felix.sigil.common.runtime.io.InstallAction; +import org.apache.felix.sigil.common.runtime.io.RefreshAction; import org.apache.felix.sigil.common.runtime.io.StartAction; import org.apache.felix.sigil.common.runtime.io.StatusAction; import org.apache.felix.sigil.common.runtime.io.StopAction; @@ -164,6 +165,9 @@ case STATUS: task = new StatusAction( in, out ); break; + case REFRESH: + task = new RefreshAction(in, out); + break; } if ( task == null ) { Modified: felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/Constants.java URL: http://svn.apache.org/viewvc/felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/Constants.java?rev=830559&r1=830558&r2=830559&view=diff ============================================================================== --- felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/Constants.java (original) +++ felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/Constants.java Wed Oct 28 14:30:01 2009 @@ -31,4 +31,5 @@ public static final int UNINSTALL = 4; public static final int UPDATE = 5; public static final int STATUS = 6; + public static final int REFRESH = 7; } Added: felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/RefreshAction.java URL: http://svn.apache.org/viewvc/felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/RefreshAction.java?rev=830559&view=auto ============================================================================== --- felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/RefreshAction.java (added) +++ felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/RefreshAction.java Wed Oct 28 14:30:01 2009 @@ -0,0 +1,75 @@ +/* + * 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.felix.sigil.common.runtime.io; + +import static org.apache.felix.sigil.common.runtime.io.Constants.REFRESH; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.osgi.framework.BundleException; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.launch.Framework; +import org.osgi.service.packageadmin.PackageAdmin; + +public class RefreshAction extends Action +{ + + public RefreshAction(DataInputStream in, DataOutputStream out) throws IOException + { + super(in, out); + } + + @Override + public Void client(Void input) throws IOException, BundleException + { + writeInt( REFRESH ); + flush(); + if ( checkOk() ) + { + return null; + } + else + { + String msg = readString(); + throw new BundleException( msg ); + } + } + + @Override + public void server(Framework fw) throws IOException + { + ServiceReference ref = fw.getBundleContext().getServiceReference(PackageAdmin.class.getName()); + if ( ref != null ) { + PackageAdmin pa = (PackageAdmin) fw.getBundleContext().getService(ref); + if ( pa != null ) { + try { + pa.refreshPackages(null); + } + finally { + fw.getBundleContext().ungetService(ref); + } + } + } + writeOk(); + flush(); + } + +} Modified: felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/StatusAction.java URL: http://svn.apache.org/viewvc/felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/StatusAction.java?rev=830559&r1=830558&r2=830559&view=diff ============================================================================== --- felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/StatusAction.java (original) +++ felix/trunk/sigil/common/runtime/src/org/apache/felix/sigil/common/runtime/io/StatusAction.java Wed Oct 28 14:30:01 2009 @@ -21,23 +21,25 @@ import java.io.DataInputStream; + import java.io.DataOutputStream; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import org.apache.felix.sigil.common.runtime.BundleForm.BundleStatus; import org.osgi.framework.Bundle; import org.osgi.framework.launch.Framework; import static org.apache.felix.sigil.common.runtime.io.Constants.STATUS; import static org.osgi.framework.Constants.BUNDLE_VERSION; +import static org.osgi.framework.Constants.BUNDLE_NAME; /** * @author dave * */ -public class StatusAction extends Action> +public class StatusAction extends Action { public StatusAction( DataInputStream in, DataOutputStream out ) throws IOException @@ -47,20 +49,24 @@ @Override - public Map client( Void in ) throws IOException + public BundleStatus[] client( Void in ) throws IOException { writeInt(STATUS); flush(); int num = readInt(); - HashMap map = new HashMap(num); + ArrayList ret = new ArrayList(num); for (int i = 0; i < num; i++) { - long id = readLong(); - String symbol = readString(); - map.put( id, symbol ); + BundleStatus s = new BundleStatus(); + s.setId(readLong()); + s.setBundleSymbolicName(readString()); + s.setVersion(readString()); + s.setLocation(readString()); + s.setStatus(readInt()); + ret.add(s); } - return map; + return ret.toArray(new BundleStatus[num]); } @@ -72,25 +78,17 @@ writeInt( bundles.length ); for ( Bundle b : bundles ) { writeLong(b.getBundleId()); - String symbol = b.getSymbolicName() + ":" + b.getHeaders().get( BUNDLE_VERSION ) + ":" + state(b); - writeString(symbol); + System.out.println( "Written " + b.getBundleId()); + String bsn = b.getSymbolicName(); + if ( bsn == null ) + bsn = (String) b.getHeaders().get(BUNDLE_NAME); + + writeString(bsn); + writeString((String) b.getHeaders().get( BUNDLE_VERSION )); + writeString(b.getLocation()); + writeInt(b.getState()); + flush(); } - - flush(); + flush(); } - - - private String state( Bundle b ) - { - switch ( b.getState() ) { - case Bundle.ACTIVE: return "active"; - case Bundle.INSTALLED: return "installed"; - case Bundle.RESOLVED: return "resolved"; - case Bundle.STARTING: return "starting"; - case Bundle.STOPPING: return "stopping"; - case Bundle.UNINSTALLED: return "uninstalled"; - default: return "unknown"; - } - } - }