001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.system.plugin;
018    
019    import java.io.BufferedReader;
020    import java.io.File;
021    import java.io.IOException;
022    import java.io.InputStreamReader;
023    import java.net.MalformedURLException;
024    import java.net.URI;
025    import java.net.URISyntaxException;
026    import java.net.URL;
027    import java.util.ArrayList;
028    import java.util.List;
029    
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import org.apache.geronimo.gbean.AbstractName;
033    import org.apache.geronimo.gbean.GBeanInfo;
034    import org.apache.geronimo.gbean.GBeanInfoBuilder;
035    import org.apache.geronimo.kernel.Kernel;
036    
037    /**
038     * An implementation of PluginRepositoryList that downloads plugins from
039     * an Apache web site.
040     *
041     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
042     */
043    public class PluginRepositoryDownloader implements PluginRepositoryList {
044        private final static Log log = LogFactory.getLog(PluginRepositoryDownloader.class);
045        private List<String> downloadRepositories = new ArrayList<String>();
046        private List<String> userRepositories = new ArrayList<String>();
047        private Kernel kernel;
048        private AbstractName name;
049        private URL repositoryList;
050    
051        public PluginRepositoryDownloader(List<String> downloadRepositories, List<String> userRepositories, URL repositoryList, Kernel kernel, AbstractName name) {
052            if (downloadRepositories != null) this.downloadRepositories = downloadRepositories;
053            if (userRepositories != null) this.userRepositories = userRepositories;
054            this.repositoryList = repositoryList;
055            this.kernel = kernel;
056            this.name = name;
057        }
058    
059        /**
060         * The list of repositories that were downloaded from central.
061         */
062        public void setDownloadRepositories(List<String> downloadRepositories) {
063            this.downloadRepositories = downloadRepositories;
064            if (this.downloadRepositories == null) this.downloadRepositories = new ArrayList<String>();
065        }
066    
067        /**
068         * Any repositories that the user added manually
069         */
070        public void setUserRepositories(List<String> userRepositories) {
071            this.userRepositories = userRepositories;
072            if (this.userRepositories == null) this.userRepositories = new ArrayList<String>();
073        }
074    
075        /**
076         * Gets the union of centrally-listed repositories and user-added repositories.
077         */
078        public List<URL> getRepositories() {
079            List<URL> list = new ArrayList<URL>();
080            for (String url : downloadRepositories) {
081                url = url.trim();
082                if (!url.endsWith("/")) {
083                    url = url + "/";
084                }
085                try {
086                    list.add(new URL(url));
087                } catch (MalformedURLException e) {
088                    log.error("Unable to format plugin repository URL " + url, e);
089                }
090            }
091            for (String userRepository : userRepositories) {
092                userRepository = userRepository.trim();
093                URL url = null;
094                try {
095                    url = resolveRepository(userRepository).toURL();
096                } catch (MalformedURLException e) {
097                    log.error("Unable to format plugin repository URL " + userRepository, e);
098                }
099                if (url != null) {
100                    list.add(url);
101                }
102            }
103            return list;
104        }
105    
106        static URI resolveRepository(String userRepository) {
107            if (!userRepository.endsWith("/")) {
108               userRepository = userRepository + "/";
109            }
110            try {
111                URI uri = new URI(userRepository);
112                if (!uri.isAbsolute()) {
113                    if (userRepository.startsWith("/")) {
114                        return new URI("file", userRepository, null);
115                    } else if (userRepository.startsWith("~")) {
116                        return new File(System.getProperty("user.home")).getAbsoluteFile().toURI().resolve(userRepository.substring(2));
117                    } else {
118                        log.error("Can't interpret path: " + userRepository);
119                    }
120                } else {
121                    return uri;
122                }
123            } catch (URISyntaxException e) {
124                log.error("Unable to format plugin repository URL " + userRepository, e);
125            }
126            return null;
127        }
128    
129        /**
130         * Go download a fresh copy of the repository list.
131         */
132        public void refresh() {
133            BufferedReader in = null;
134            try {
135                in = new BufferedReader(new InputStreamReader(repositoryList.openStream()));
136                String line;
137                List<String> list = new ArrayList<String>();
138                while ((line = in.readLine()) != null) {
139                    line = line.trim();
140                    if (!line.equals("") && !line.startsWith("#")) {
141                        list.add(line);
142                    }
143                }
144                in.close();
145                in = null;
146                //this saves the new value in config.xml
147                kernel.setAttribute(name, "downloadRepositories", list);
148            } catch (Exception e) {
149                log.error("Unable to save download repositories", e);
150            } finally {
151                if (in != null) {
152                    try {
153                        in.close();
154                    } catch (IOException ignored) {
155                    }
156                }
157            }
158        }
159    
160        /**
161         * Adds a new repository that the user put in manually.
162         */
163        public void addUserRepository(URL repo) {
164            userRepositories.add(repo.toString());
165            try {
166                kernel.setAttribute(name, "userRepositories", userRepositories);
167            } catch (Exception e) {
168                log.error("Unable to save user repositories", e);
169            }
170        }
171    
172        public static final GBeanInfo GBEAN_INFO;
173    
174        static {
175            GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(PluginRepositoryDownloader.class);
176    
177            infoFactory.addAttribute("downloadRepositories", List.class, true);
178            infoFactory.addAttribute("userRepositories", List.class, true);
179            infoFactory.addAttribute("repositoryList", URL.class, true);
180            infoFactory.addAttribute("kernel", Kernel.class, false);
181            infoFactory.addAttribute("abstractName", AbstractName.class, false);
182            infoFactory.addInterface(PluginRepositoryList.class);
183            infoFactory.setConstructor(new String[]{"downloadRepositories", "userRepositories", "repositoryList", "kernel", "abstractName"});
184    
185            GBEAN_INFO = infoFactory.getBeanInfo();
186        }
187    
188        public static GBeanInfo getGBeanInfo() {
189            return GBEAN_INFO;
190        }
191    }