Return-Path: Delivered-To: apmail-felix-commits-archive@www.apache.org Received: (qmail 61490 invoked from network); 26 Jun 2008 07:29:39 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 26 Jun 2008 07:29:39 -0000 Received: (qmail 40526 invoked by uid 500); 26 Jun 2008 07:29:40 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 40502 invoked by uid 500); 26 Jun 2008 07:29:40 -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 40493 invoked by uid 99); 26 Jun 2008 07:29:40 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 26 Jun 2008 00:29:40 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED 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; Thu, 26 Jun 2008 07:28:58 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id D76E32388A06; Thu, 26 Jun 2008 00:29:17 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r671815 - in /felix/trunk/bundlerepository/src: main/java/org/apache/felix/bundlerepository/ test/ test/java/ test/java/org/ test/java/org/apache/ test/java/org/apache/felix/ test/java/org/apache/felix/bundlerepository/ test/resources/ Date: Thu, 26 Jun 2008 07:29:17 -0000 To: commits@felix.apache.org From: fmeschbe@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080626072917.D76E32388A06@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: fmeschbe Date: Thu Jun 26 00:29:16 2008 New Revision: 671815 URL: http://svn.apache.org/viewvc?rev=671815&view=rev Log: FELIX-399 Implement Referral with hop count support Added: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Referral.java felix/trunk/bundlerepository/src/test/ felix/trunk/bundlerepository/src/test/java/ felix/trunk/bundlerepository/src/test/java/org/ felix/trunk/bundlerepository/src/test/java/org/apache/ felix/trunk/bundlerepository/src/test/java/org/apache/felix/ felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java felix/trunk/bundlerepository/src/test/resources/ felix/trunk/bundlerepository/src/test/resources/referral1_repository.xml felix/trunk/bundlerepository/src/test/resources/referred.xml Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java Added: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Referral.java URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Referral.java?rev=671815&view=auto ============================================================================== --- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Referral.java (added) +++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Referral.java Thu Jun 26 00:29:16 2008 @@ -0,0 +1,52 @@ +/* + * 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.bundlerepository; + +public class Referral +{ + private int m_depth = 1; + private String m_url; + + public int getDepth() + { + return m_depth; + } + + public String getUrl() + { + return m_url; + } + + public void setUrl(String url) + { + m_url = url; + } + + public void setDepth(String depth) + { + try + { + m_depth = Integer.parseInt(depth); + } + catch (NumberFormatException nfe) + { + // don't care, and don't change current value + } + } +} \ No newline at end of file Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java?rev=671815&r1=671814&r2=671815&view=diff ============================================================================== --- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java (original) +++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdminImpl.java Thu Jun 26 00:29:16 2008 @@ -20,10 +20,21 @@ import java.net.MalformedURLException; import java.net.URL; -import java.util.*; - -import org.osgi.framework.*; -import org.osgi.service.obr.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Filter; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.service.obr.Repository; +import org.osgi.service.obr.RepositoryAdmin; +import org.osgi.service.obr.Resolver; +import org.osgi.service.obr.Resource; public class RepositoryAdminImpl implements RepositoryAdmin { @@ -35,8 +46,7 @@ // Reusable comparator for sorting resources by name. private Comparator m_nameComparator = new ResourceComparator(); - private static final String DEFAULT_REPOSITORY_URL = - "http://oscar-osgi.sourceforge.net/obr2/repository.xml"; + private static final String DEFAULT_REPOSITORY_URL = "http://oscar-osgi.sourceforge.net/obr2/repository.xml"; public static final String REPOSITORY_URL_PROP = "obr.repository.url"; public static final String EXTERN_REPOSITORY_TAG = "extern-repositories"; @@ -45,7 +55,12 @@ m_context = context; } - public synchronized Repository addRepository(URL url) throws Exception + public Repository addRepository(URL url) throws Exception + { + return addRepository(url, Integer.MAX_VALUE); + } + + public synchronized Repository addRepository(URL url, int hopCount) throws Exception { if (!m_urlList.contains(url)) { @@ -55,7 +70,7 @@ // If the repository URL is a duplicate, then we will just // replace the existing repository object with a new one, // which is effectively the same as refreshing the repository. - Repository repo = new RepositoryImpl(url); + Repository repo = new RepositoryImpl(this, url, hopCount); m_repoMap.put(url, repo); return repo; } @@ -98,7 +113,7 @@ initialize(); } - Filter filter = null; + Filter filter = null; try { filter = m_context.createFilter(filterExpr); @@ -181,7 +196,7 @@ URL url = (URL) m_urlList.get(i); try { - Repository repo = new RepositoryImpl(url); + Repository repo = new RepositoryImpl(this, url); if (repo != null) { m_repoMap.put(url, repo); @@ -189,10 +204,8 @@ } catch (Exception ex) { - System.err.println( - "RepositoryAdminImpl: Exception creating repository - " + ex); - System.err.println( - "RepositoryAdminImpl: Ignoring repository " + url); + System.err.println("RepositoryAdminImpl: Exception creating repository - " + ex); + System.err.println("RepositoryAdminImpl: Ignoring repository " + url); } } } Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java?rev=671815&r1=671814&r2=671815&view=diff ============================================================================== --- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java (original) +++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryImpl.java Thu Jun 26 00:29:16 2008 @@ -1,4 +1,4 @@ -/* +/* * 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 @@ -18,19 +18,28 @@ */ package org.apache.felix.bundlerepository; -import java.io.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.lang.reflect.Method; -import java.net.*; +import java.net.URL; +import java.net.URLConnection; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import java.security.*; import org.apache.felix.bundlerepository.metadataparser.XmlCommonHandler; import org.apache.felix.bundlerepository.metadataparser.kxmlsax.KXml2SAXParser; -import org.osgi.service.obr.*; +import org.osgi.service.obr.Capability; +import org.osgi.service.obr.Repository; +import org.osgi.service.obr.Requirement; +import org.osgi.service.obr.Resource; public class RepositoryImpl implements Repository { @@ -38,13 +47,20 @@ private long m_lastmodified = 0; private URL m_url = null; private Resource[] m_resources = null; - private int m_hopCount = 1; + private Referral[] m_referrals = null; + private RepositoryAdminImpl m_repoAdmin = null; // Reusable comparator for sorting resources by name. private ResourceComparator m_nameComparator = new ResourceComparator(); - public RepositoryImpl(URL url) throws Exception + public RepositoryImpl(RepositoryAdminImpl repoAdmin, URL url) throws Exception { + this(repoAdmin, url, Integer.MAX_VALUE); + } + + public RepositoryImpl(RepositoryAdminImpl repoAdmin, URL url, final int hopCount) throws Exception + { + m_repoAdmin = repoAdmin; m_url = url; try { @@ -52,12 +68,12 @@ { public Object run() throws Exception { - parseRepositoryFile(m_hopCount); + parseRepositoryFile(hopCount); return null; } }); - } - catch (PrivilegedActionException ex) + } + catch (PrivilegedActionException ex) { throw (Exception) ex.getCause(); } @@ -86,7 +102,8 @@ // Add to resource array. if (m_resources == null) { - m_resources = new Resource[] { resource }; + m_resources = new Resource[] + { resource }; } else { @@ -99,6 +116,28 @@ Arrays.sort(m_resources, m_nameComparator); } + public Referral[] getReferrals() + { + return m_referrals; + } + + public void addReferral(Referral referral) throws Exception + { + // Add to resource array. + if (m_referrals == null) + { + m_referrals = new Referral[] + { referral }; + } + else + { + Referral[] newResources = new Referral[m_referrals.length + 1]; + System.arraycopy(m_referrals, 0, newResources, 0, m_referrals.length); + newResources[m_referrals.length] = referral; + m_referrals = newResources; + } + } + public String getName() { return m_name; @@ -128,7 +167,7 @@ /** * Default setter method when setting parsed data from the XML file, - * which currently ignores everything. + * which currently ignores everything. **/ protected Object put(Object key, Object value) { @@ -138,26 +177,23 @@ private void parseRepositoryFile(int hopCount) throws Exception { -// TODO: OBR - Implement hop count. InputStream is = null; BufferedReader br = null; try { - // Do it the manual way to have a chance to + // Do it the manual way to have a chance to // set request properties as proxy auth (EW). - URLConnection conn = m_url.openConnection(); + URLConnection conn = m_url.openConnection(); // Support for http proxy authentication String auth = System.getProperty("http.proxyAuth"); if ((auth != null) && (auth.length() > 0)) { - if ("http".equals(m_url.getProtocol()) || - "https".equals(m_url.getProtocol())) + if ("http".equals(m_url.getProtocol()) || "https".equals(m_url.getProtocol())) { String base64 = Util.base64Encode(auth); - conn.setRequestProperty( - "Proxy-Authorization", "Basic " + base64); + conn.setRequestProperty("Proxy-Authorization", "Basic " + base64); } } @@ -178,13 +214,14 @@ else { is = conn.getInputStream(); - } + } if (is != null) { // Create the parser Kxml XmlCommonHandler handler = new XmlCommonHandler(); - Object factory = new Object() { + Object factory = new Object() + { public RepositoryImpl newInstance() { return RepositoryImpl.this; @@ -192,15 +229,16 @@ }; // Get default setter method for Repository. - Method repoSetter = RepositoryImpl.class.getDeclaredMethod( - "put", new Class[] { Object.class, Object.class }); + Method repoSetter = RepositoryImpl.class.getDeclaredMethod("put", new Class[] + { Object.class, Object.class }); // Get default setter method for Resource. - Method resSetter = ResourceImpl.class.getDeclaredMethod( - "put", new Class[] { Object.class, Object.class }); + Method resSetter = ResourceImpl.class.getDeclaredMethod("put", new Class[] + { Object.class, Object.class }); // Map XML tags to types. handler.addType("repository", factory, Repository.class, repoSetter); + handler.addType("referral", Referral.class, null, null); handler.addType("resource", ResourceImpl.class, Resource.class, resSetter); handler.addType("category", CategoryImpl.class, null, null); handler.addType("require", RequirementImpl.class, Requirement.class, null); @@ -212,6 +250,21 @@ KXml2SAXParser parser; parser = new KXml2SAXParser(br); parser.parseXML(handler); + + // resolve referrals + hopCount--; + if (hopCount > 0 && m_referrals != null) + { + for (int i = 0; i < m_referrals.length; i++) + { + Referral referral = m_referrals[i]; + + URL url = new URL(getURL(), referral.getUrl()); + hopCount = (referral.getDepth() > hopCount) ? hopCount : referral.getDepth(); + + m_repoAdmin.addRepository(url, hopCount); + } + } } else { @@ -223,7 +276,8 @@ { try { - if (is != null) is.close(); + if (is != null) + is.close(); } catch (IOException ex) { @@ -231,4 +285,4 @@ } } } -} +} \ No newline at end of file Added: felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java?rev=671815&view=auto ============================================================================== --- felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java (added) +++ felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/RepositoryImplTest.java Thu Jun 26 00:29:16 2008 @@ -0,0 +1,244 @@ +/* + * 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.bundlerepository; + +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.Dictionary; + +import junit.framework.TestCase; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleListener; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.obr.Repository; +import org.osgi.service.obr.Resource; + +public class RepositoryImplTest extends TestCase +{ + + public void testReferral1() throws Exception + { + + URL url = getClass().getResource("/referral1_repository.xml"); + + RepositoryAdminImpl repoAdmin = createRepositoryAdmin(); + RepositoryImpl repo = (RepositoryImpl) repoAdmin.addRepository(url); + Referral[] refs = repo.getReferrals(); + + assertNotNull("Expect referrals", refs); + assertTrue("Expect one referral", refs.length == 1); + + // + assertEquals(1, refs[0].getDepth()); + assertEquals("referred.xml", refs[0].getUrl()); + + // expect two resources + Resource[] res = repoAdmin.discoverResources(null); + assertNotNull("Expect Resource", res); + assertEquals("Expect two resources", 2, res.length); + + // first resource is from the referral1_repository.xml + assertEquals("6", res[0].getId()); + assertEquals("referral1_repository", res[0].getRepository().getName()); + + // second resource is from the referred.xml + assertEquals("99", res[1].getId()); + assertEquals("referred", res[1].getRepository().getName()); + } + + public void testReferral2() throws Exception + { + + URL url = getClass().getResource("/referral1_repository.xml"); + + RepositoryAdminImpl repoAdmin = createRepositoryAdmin(); + RepositoryImpl repo = (RepositoryImpl) repoAdmin.addRepository(url, 1); + Referral[] refs = repo.getReferrals(); + + assertNotNull("Expect referrals", refs); + assertTrue("Expect one referral", refs.length == 1); + + // + assertEquals(1, refs[0].getDepth()); + assertEquals("referred.xml", refs[0].getUrl()); + + // expect one resource (referral is not followed + Resource[] res = repoAdmin.discoverResources(null); + assertNotNull("Expect Resource", res); + assertEquals("Expect one resource", 1, res.length); + + // first resource is from the referral1_repository.xml + assertEquals("6", res[0].getId()); + assertEquals("referral1_repository", res[0].getRepository().getName()); + } + + private RepositoryAdminImpl createRepositoryAdmin() + { + RepositoryAdminImpl repoAdmin = new RepositoryAdminImpl(new MockBundleContext()); + + // force initialization && remove all initial repositories + Repository[] repos = repoAdmin.listRepositories(); + for (int i = 0; repos != null && i < repos.length; i++) + { + repoAdmin.removeRepository(repos[i].getURL()); + } + + return repoAdmin; + } + + private static class MockBundleContext implements BundleContext + { + + public void addBundleListener(BundleListener arg0) + { + } + + public void addFrameworkListener(FrameworkListener arg0) + { + } + + public void addServiceListener(ServiceListener arg0) + { + } + + public void addServiceListener(ServiceListener arg0, String arg1) + { + } + + public Filter createFilter(String arg0) + { + // returns a match-all filter always + return new Filter() + { + public boolean matchCase(Dictionary arg0) + { + return true; + } + + public boolean match(Dictionary arg0) + { + return true; + } + + public boolean match(ServiceReference arg0) + { + return true; + } + }; + } + + public ServiceReference[] getAllServiceReferences(String arg0, String arg1) + { + return null; + } + + public Bundle getBundle() + { + return null; + } + + public Bundle getBundle(long arg0) + { + return null; + } + + public Bundle[] getBundles() + { + return null; + } + + public File getDataFile(String arg0) + { + return null; + } + + public String getProperty(String name) + { + if (RepositoryAdminImpl.REPOSITORY_URL_PROP.equals(name)) + { + URL url = getClass().getResource("/referred.xml"); + if (url != null) + { + return url.toExternalForm(); + } + } + + return null; + } + + public Object getService(ServiceReference arg0) + { + return null; + } + + public ServiceReference getServiceReference(String arg0) + { + return null; + } + + public ServiceReference[] getServiceReferences(String arg0, String arg1) + { + return null; + } + + public Bundle installBundle(String arg0) + { + return null; + } + + public Bundle installBundle(String arg0, InputStream arg1) + { + return null; + } + + public ServiceRegistration registerService(String[] arg0, Object arg1, Dictionary arg2) + { + return null; + } + + public ServiceRegistration registerService(String arg0, Object arg1, Dictionary arg2) + { + return null; + } + + public void removeBundleListener(BundleListener arg0) + { + } + + public void removeFrameworkListener(FrameworkListener arg0) + { + } + + public void removeServiceListener(ServiceListener arg0) + { + } + + public boolean ungetService(ServiceReference arg0) + { + return false; + } + } +} Added: felix/trunk/bundlerepository/src/test/resources/referral1_repository.xml URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/test/resources/referral1_repository.xml?rev=671815&view=auto ============================================================================== --- felix/trunk/bundlerepository/src/test/resources/referral1_repository.xml (added) +++ felix/trunk/bundlerepository/src/test/resources/referral1_repository.xml Thu Jun 26 00:29:16 2008 @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file Added: felix/trunk/bundlerepository/src/test/resources/referred.xml URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/test/resources/referred.xml?rev=671815&view=auto ============================================================================== --- felix/trunk/bundlerepository/src/test/resources/referred.xml (added) +++ felix/trunk/bundlerepository/src/test/resources/referred.xml Thu Jun 26 00:29:16 2008 @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file